mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+3
@@ -513,6 +513,9 @@
|
||||
<constraint name="MethodCall" target="true" within="" contains="" />
|
||||
<constraint name="Parameter" minCount="0" maxCount="2147483647" within="" contains="" />
|
||||
</searchConfiguration>
|
||||
<replaceConfiguration name="StringUtil.stripQuotesAroundValue" text="com.intellij.openapi.util.text.StringUtil.stripQuotesAroundValue($Parameter$)" recursive="false" caseInsensitive="false" type="JAVA" reformatAccordingToStyle="true" shortenFQN="true" replacement="com.intellij.openapi.util.text.StringUtil.unquoteString($Parameter$)">
|
||||
<constraint name="Parameter" within="" contains="" />
|
||||
</replaceConfiguration>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SessionScopedInjectsRequestScoped" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SetReplaceableByEnumSet" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
target(nsis: 'Build nsis windows installer') {
|
||||
nsis_installer()
|
||||
}
|
||||
|
||||
String p(String key) {
|
||||
return getProperty(key)
|
||||
}
|
||||
|
||||
def nsis_installer(pathsToInclude, stringsFile, pathsFile, outNamePrefix, includeToolsJar = true, associateIpr = true,
|
||||
system_selector = getProperty("system_selector"), failOnSignError = false, outFileName = null,
|
||||
boolean hasBundledJRE = false) {
|
||||
// p.s: Groovy reevaluates default value of system_selector on each call, so it always uses actual property value.
|
||||
|
||||
if (outFileName == null) {
|
||||
outFileName = "${outNamePrefix}${buildNumber}"
|
||||
}
|
||||
|
||||
ant.taskdef(name: "nsis", classname: "com.intellij.internalUtilities.ant.NsiFiles", classpath: "${home}/community/build/lib/NsiFiles.jar")
|
||||
|
||||
def box = paths.sandbox
|
||||
ant.mkdir(dir: "$box/bin")
|
||||
ant.mkdir(dir: "$box/nsiconf")
|
||||
|
||||
if (!hasBundledJRE) {
|
||||
ant.mkdir(dir: "$box/jre")
|
||||
requireProperty("jdk_bundled_win", "1.7")
|
||||
def jdk_bundled_version = p("jdk_bundled_win") == "1.8" ? "${home}/build/jdk/jdk8_redist.zip" : "${home}/build/jdk/jdk_redist.zip"
|
||||
getBundledJDK(new File("${home}/build/jdk/win"), "jdk"+ p("jdk_bundled_win"), "x32.zip", jdk_bundled_version)
|
||||
ant.unzip(dest: "$box/jre", src: "${jdk_bundled_version}")
|
||||
|
||||
ant.copy(todir: "$box/bin") {
|
||||
fileset(dir: "$box/jre/jre/bin") {
|
||||
include(name: "msvcr71.dll")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ant.copy(todir: "$box/nsiconf") {
|
||||
fileset(dir: "$home/community/build/conf/nsis") {
|
||||
include(name: "*")
|
||||
exclude(name: "version*")
|
||||
exclude(name: "strings*")
|
||||
exclude(name: "paths*")
|
||||
}
|
||||
}
|
||||
|
||||
if (isEap()) {
|
||||
ant.copy(file: "$home/community/build/conf/nsis/version.eap.nsi",
|
||||
tofile: "$box/nsiconf/version.nsi", overwrite: true)
|
||||
}
|
||||
else {
|
||||
ant.copy(file: "$home/community/build/conf/nsis/version.nsi",
|
||||
tofile: "$box/nsiconf/version.nsi", overwrite: true)
|
||||
}
|
||||
ant.copy(file: pathsFile, toFile: "$box/nsiconf/paths.nsi", overwrite: true)
|
||||
|
||||
ant.nsis(instfile: "$box/nsiconf/idea_win.nsh", uninstfile: "$box/nsiconf/unidea_win.nsh") {
|
||||
pathsToInclude.each {
|
||||
fileset(dir: it, includes: "**/*") {
|
||||
exclude(name: "**/idea.properties")
|
||||
exclude(name: "**/*.vmoptions")
|
||||
}
|
||||
}
|
||||
fileset(dir: box, includes: "bin/msvcr71.dll")
|
||||
if (!hasBundledJRE) {
|
||||
fileset(dir: box, includes: "jre/**/*")
|
||||
if (includeToolsJar) {
|
||||
fileset(dir: box) {
|
||||
include(name: "jre/lib/tools.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ant.replace(file: "$stringsFile") {
|
||||
replacefilter(token: "__VERSION_MAJOR__", value: p("component.version.major"))
|
||||
replacefilter(token: "__VERSION_MINOR__", value: p("component.version.minor"))
|
||||
}
|
||||
ant.copy(file: stringsFile, toFile: "$box/nsiconf/strings.nsi", overwrite: true)
|
||||
|
||||
ant.replace(file: "$box/nsiconf/version.nsi") {
|
||||
replacefilter(token: "__BUILD_NUMBER__", value: buildNumber)
|
||||
replacefilter(token: "__VERSION_MAJOR__", value: p("component.version.major"))
|
||||
replacefilter(token: "__VERSION_MINOR__", value: p("component.version.minor"))
|
||||
replacefilter(token: "__MIN_UPGRADE_BUILD__", value: p("component.install-over.minbuild"))
|
||||
replacefilter(token: "__MAX_UPGRADE_BUILD__", value: p("component.install-over.maxbuild"))
|
||||
replacefilter(token: "__UPGRADE_VERSION__", value: p("component.install-over.version"))
|
||||
replacefilter(token: "__PRODUCT_PATHS_SELECTOR__", value: system_selector)
|
||||
}
|
||||
|
||||
ant.unzip(src: "$home/build/tools/NSIS.zip", dest: box)
|
||||
ant.exec(command: "$box/NSIS/makensis.exe" +
|
||||
" /DBASE_DIR=\"$home\"" +
|
||||
" /DCOMMUNITY_DIR=\"$home/community\"" +
|
||||
" /DIPR=\"${associateIpr}\"" +
|
||||
" /DOUT_FILE=\"${outFileName}\"" +
|
||||
" /DOUT_DIR=\"$paths.artifacts\"" +
|
||||
" $box/nsiconf/idea.nsi")
|
||||
|
||||
projectBuilder.stage("Signing binaries")
|
||||
executeExternalAnt(["dirName": "${paths.artifacts}", "fileName": "${outFileName}.exe"], "$home/build/signBuild.xml")
|
||||
projectBuilder.stage("Signing done")
|
||||
|
||||
return "${paths.artifacts}/${outFileName}.exe"
|
||||
}
|
||||
+11
-10
@@ -754,17 +754,18 @@ private List<File> getChildren(File file) {
|
||||
return file.listFiles().sort { File f -> f.name.toLowerCase() }
|
||||
}
|
||||
|
||||
binding.setVariable("getCustomJDK", { File customJdkDir ->
|
||||
getChildren(customJdkDir).each {
|
||||
if (it.getName().endsWith(".tar.gz")) {
|
||||
def customJdkFileName = it.getAbsolutePath().substring(0, it.getAbsolutePath().length() - 3)
|
||||
if (new File(customJdkFileName).exists()){ ant.delete(file: customJdkFileName) }
|
||||
if (new File("${home}/build/jdk/custom_jdk_${buildNumber}.tar").exists()){
|
||||
ant.delete(file: "${home}/build/jdk/custom_jdk_${buildNumber}.tar")
|
||||
binding.setVariable("getBundledJDK", { File jdkDir, String prefix, String ext, String bundledJDKFileName ->
|
||||
getChildren(jdkDir).each {
|
||||
if (it.getName().startsWith(prefix) && it.getName().endsWith(ext)) {
|
||||
if (new File(bundledJDKFileName).exists()) { ant.delete(file: bundledJDKFileName) }
|
||||
def JdkFileName = it.getAbsolutePath()
|
||||
if (ext == ".tar.gz") {
|
||||
JdkFileName = JdkFileName.substring(0, JdkFileName.length() - 3)
|
||||
if (new File(JdkFileName).exists()) { ant.delete(file: JdkFileName) }
|
||||
ant.gunzip(src: it.getAbsolutePath())
|
||||
}
|
||||
ant.gunzip(src: it.getAbsolutePath())
|
||||
projectBuilder.info("customJdkFileName: " + customJdkFileName)
|
||||
ant.copy(file: customJdkFileName, tofile: "${home}/build/jdk/custom_jdk_${buildNumber}.tar")
|
||||
projectBuilder.info("JdkFileName: " + JdkFileName)
|
||||
ant.copy(file: JdkFileName, tofile: bundledJDKFileName)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -240,7 +240,14 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent
|
||||
}
|
||||
});
|
||||
DebuggerSession session = new DebuggerSession(environment.getSessionName(), debugProcess);
|
||||
final ExecutionResult executionResult = session.attach(environment);
|
||||
ExecutionResult executionResult;
|
||||
try {
|
||||
executionResult = session.attach(environment);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
session.dispose();
|
||||
throw e;
|
||||
}
|
||||
if (executionResult == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
@@ -195,6 +196,11 @@ public abstract class JavaTestFrameworkRunnableState<T extends ModuleBasedConfig
|
||||
JavaSdkUtil.addRtJar(javaParameters.getClassPath());
|
||||
|
||||
configureClasspath(javaParameters);
|
||||
|
||||
if (!StringUtil.isEmptyOrSpaces(parameters)) {
|
||||
javaParameters.getProgramParametersList().add("@name" + parameters);
|
||||
}
|
||||
|
||||
return javaParameters;
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -30,6 +30,7 @@ import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class JavaAwareTestConsoleProperties<T extends ModuleBasedConfiguration<JavaRunConfigurationModule> & CommonJavaRunConfigurationParameters> extends SMTRunnerConsoleProperties {
|
||||
@@ -48,6 +49,11 @@ public abstract class JavaAwareTestConsoleProperties<T extends ModuleBasedConfig
|
||||
return (T)super.getConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSelectionMode() {
|
||||
return TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixEmptySuite() {
|
||||
return ResetConfigurationModuleAdapter.tryWithAnotherModule(getConfiguration(), isDebug());
|
||||
|
||||
+11
-25
@@ -47,25 +47,21 @@ public class JavaTestLocationProvider implements TestLocationProvider {
|
||||
public List<Location> getLocation(@NotNull String protocolId, @NotNull String locationData, Project project) {
|
||||
List<Location> results = Collections.emptyList();
|
||||
|
||||
final int idx = locationData.indexOf("[");
|
||||
final String paramName = idx >= 0 ? locationData.substring(idx) : null;
|
||||
if (idx >= 0) {
|
||||
locationData = locationData.substring(0, idx);
|
||||
}
|
||||
|
||||
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
|
||||
if (SUITE_PROTOCOL.equals(protocolId)) {
|
||||
locationData = StringUtil.trimEnd(locationData, ".");
|
||||
PsiClass[] classes = javaPsiFacade.findClasses(locationData, myScope);
|
||||
if (classes.length > 0) {
|
||||
results = ContainerUtil.newSmartList();
|
||||
for (PsiClass aClass : classes) {
|
||||
results.add(new PsiLocation<PsiClass>(project, aClass));
|
||||
}
|
||||
}
|
||||
else {
|
||||
//parameter root for parameterized tests: ClassName.[paramName]
|
||||
final String className = StringUtil.getPackageName(locationData);
|
||||
classes = javaPsiFacade.findClasses(className, myScope);
|
||||
if (classes.length > 0) {
|
||||
final String paramName = StringUtil.getShortName(locationData);
|
||||
results = ContainerUtil.newSmartList();
|
||||
for (PsiClass aClass : classes) {
|
||||
results.add(PsiMemberParameterizedLocation.getParameterizedLocation(aClass, paramName));
|
||||
}
|
||||
results.add(paramName != null ? PsiMemberParameterizedLocation.getParameterizedLocation(aClass, paramName)
|
||||
: new PsiLocation<PsiClass>(project, aClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,18 +76,8 @@ public class JavaTestLocationProvider implements TestLocationProvider {
|
||||
PsiMethod[] methods = aClass.findMethodsByName(methodName, true);
|
||||
if (methods.length > 0) {
|
||||
for (PsiMethod method : methods) {
|
||||
results.add(MethodLocation.elementInClass(method, aClass));
|
||||
}
|
||||
}
|
||||
else {
|
||||
//parameterized tests: ClassName.testName[paramName]
|
||||
final int paramIdx = methodName.indexOf("[");
|
||||
if (paramIdx > -1 && methodName.endsWith("]")) {
|
||||
final String paramName = methodName.substring(paramIdx);
|
||||
methods = aClass.findMethodsByName(methodName.substring(0, paramIdx), true);
|
||||
for (PsiMethod method : methods) {
|
||||
results.add(new PsiMemberParameterizedLocation(project, method, aClass, paramName));
|
||||
}
|
||||
results.add(paramName != null ? new PsiMemberParameterizedLocation(project, method, aClass, paramName)
|
||||
: MethodLocation.elementInClass(method, aClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class ImportModuleAction extends AnAction {
|
||||
}
|
||||
|
||||
public static List<Module> createFromWizard(@Nullable Project project, AbstractProjectWizard wizard) {
|
||||
if (project == null && wizard.getStepCount() > 0) {
|
||||
if (project == null) {
|
||||
Project newProject = NewProjectUtil.createFromWizard(wizard, null);
|
||||
return newProject == null ? Collections.<Module>emptyList() : Arrays.asList(ModuleManager.getInstance(newProject).getModules());
|
||||
}
|
||||
@@ -94,7 +94,6 @@ public class ImportModuleAction extends AnAction {
|
||||
return Collections.singletonList(module);
|
||||
}
|
||||
else {
|
||||
assert project != null;
|
||||
return projectBuilder.commit(project);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +331,9 @@ public class SdkEditor implements Configurable, Place.Navigator {
|
||||
}
|
||||
sdkModificator = dummySdk.getSdkModificator();
|
||||
for (OrderRootType type : myPathEditors.keySet()) {
|
||||
myPathEditors.get(type).addPaths(sdkModificator.getRoots(type));
|
||||
SdkPathEditor pathEditor = myPathEditors.get(type);
|
||||
pathEditor.setAddBaseDir(dummySdk.getHomeDirectory());
|
||||
pathEditor.addPaths(sdkModificator.getRoots(type));
|
||||
}
|
||||
mySdkModel.getMulticaster().sdkHomeSelected(dummySdk, homePath);
|
||||
}
|
||||
|
||||
+19
-65
@@ -53,7 +53,6 @@ import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -211,7 +210,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
ContainerUtil.addIfNotNull(fixes, ReplaceOptionalOfWithOfNullableFix.registerReplaceOptionalOfWithOfNullableFix(qualifier));
|
||||
ContainerUtil.addIfNotNull(fixes, DfaOptionalSupport.registerReplaceOptionalOfWithOfNullableFix(qualifier));
|
||||
return fixes.isEmpty() ? null : fixes.toArray(new LocalQuickFix[fixes.size()]);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
@@ -272,11 +271,29 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
reportNullableArgumentsPassedToNonAnnotated(visitor, holder, reportedAnchors);
|
||||
}
|
||||
|
||||
reportOptionalOfNullableImprovements(holder, visitor, reportedAnchors);
|
||||
|
||||
|
||||
if (REPORT_CONSTANT_REFERENCE_VALUES) {
|
||||
reportConstantReferenceValues(holder, visitor, reportedAnchors);
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportOptionalOfNullableImprovements(ProblemsHolder holder,
|
||||
DataFlowInstructionVisitor visitor,
|
||||
HashSet<PsiElement> reportedAnchors) {
|
||||
for (PsiElement expr : visitor.getProblems(NullabilityProblem.passingNullToOptional)) {
|
||||
if (!reportedAnchors.add(expr)) continue;
|
||||
holder.registerProblem(expr, "Passing <code>null</code> argument to Optional",
|
||||
DfaOptionalSupport.createReplaceOptionalOfNullableWithEmptyFix(expr));
|
||||
}
|
||||
for (PsiElement expr : visitor.getProblems(NullabilityProblem.passingNotNullToOptional)) {
|
||||
if (!reportedAnchors.add(expr)) continue;
|
||||
holder.registerProblem(expr, "Passing a non-null argument to Optional",
|
||||
DfaOptionalSupport.createReplaceOptionalOfNullableWithOfFix());
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportConstantReferenceValues(ProblemsHolder holder, StandardInstructionVisitor visitor, Set<PsiElement> reportedAnchors) {
|
||||
for (Pair<PsiReferenceExpression, DfaConstValue> pair : visitor.getConstantReferenceValues()) {
|
||||
PsiReferenceExpression ref = pair.first;
|
||||
@@ -764,67 +781,4 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
boolean normalOk;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReplaceOptionalOfWithOfNullableFix implements LocalQuickFix {
|
||||
|
||||
private static final String GUAVA_OPTIONAL = "com.google.common.base.Optional";
|
||||
private final String myTargetMethodName;
|
||||
|
||||
public ReplaceOptionalOfWithOfNullableFix(final String targetMethodName) {
|
||||
myTargetMethodName = targetMethodName;
|
||||
}
|
||||
|
||||
private static LocalQuickFix registerReplaceOptionalOfWithOfNullableFix(PsiExpression qualifier) {
|
||||
final PsiElement argList = PsiUtil.skipParenthesizedExprUp(qualifier).getParent();
|
||||
if (argList instanceof PsiExpressionList) {
|
||||
final PsiElement parent = argList.getParent();
|
||||
if (parent instanceof PsiMethodCallExpression) {
|
||||
final PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
|
||||
if (method != null) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if ("of".equals(method.getName()) && containingClass != null) {
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
if (CommonClassNames.JAVA_UTIL_OPTIONAL.equals(qualifiedName)) {
|
||||
return new ReplaceOptionalOfWithOfNullableFix("ofNullable");
|
||||
}
|
||||
else if (GUAVA_OPTIONAL.equals(qualifiedName)) {
|
||||
return new ReplaceOptionalOfWithOfNullableFix("fromNullable");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getFamilyName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Replace with '." + myTargetMethodName + "()'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiMethodCallExpression
|
||||
methodCallExpression = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethodCallExpression.class);
|
||||
if (methodCallExpression != null) {
|
||||
final PsiElement ofNullableExprName =
|
||||
((PsiMethodCallExpression)JavaPsiFacade.getElementFactory(project)
|
||||
.createExpressionFromText("Optional.ofNullable(null)", null)).getMethodExpression();
|
||||
final PsiElement referenceNameElement = methodCallExpression.getMethodExpression().getReferenceNameElement();
|
||||
if (referenceNameElement != null) {
|
||||
final PsiElement ofNullableNameElement = ((PsiReferenceExpression)ofNullableExprName).getReferenceNameElement();
|
||||
LOG.assertTrue(ofNullableNameElement != null);
|
||||
referenceNameElement.replace(ofNullableNameElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author anet, peter
|
||||
*/
|
||||
class DfaOptionalSupport {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DfaOptionalSupport");
|
||||
private static final String GUAVA_OPTIONAL = "com.google.common.base.Optional";
|
||||
|
||||
@Nullable
|
||||
static LocalQuickFix registerReplaceOptionalOfWithOfNullableFix(@NotNull PsiExpression qualifier) {
|
||||
final PsiElement call = findCallExpression(qualifier);
|
||||
final PsiMethod method = call == null ? null : ((PsiMethodCallExpression)call).resolveMethod();
|
||||
final PsiClass containingClass = method == null ? null : method.getContainingClass();
|
||||
if (containingClass != null && "of".equals(method.getName())) {
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
if (CommonClassNames.JAVA_UTIL_OPTIONAL.equals(qualifiedName)) {
|
||||
return new ReplaceOptionalCallFix("ofNullable", false);
|
||||
}
|
||||
if (GUAVA_OPTIONAL.equals(qualifiedName)) {
|
||||
return new ReplaceOptionalCallFix("fromNullable", false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PsiMethodCallExpression findCallExpression(@NotNull PsiElement anchor) {
|
||||
final PsiElement argList = PsiUtil.skipParenthesizedExprUp(anchor).getParent();
|
||||
if (argList instanceof PsiExpressionList) {
|
||||
final PsiElement parent = argList.getParent();
|
||||
if (parent instanceof PsiMethodCallExpression) {
|
||||
return (PsiMethodCallExpression)parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static boolean isJdkOptional(@NotNull PsiElement anchor) {
|
||||
final PsiElement parent = findCallExpression(anchor);
|
||||
PsiMethod method = parent == null ? null : resolveOfNullable(findCallExpression(anchor));
|
||||
return method != null && "ofNullable".equals(method.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static LocalQuickFix createReplaceOptionalOfNullableWithEmptyFix(@NotNull PsiElement anchor) {
|
||||
return new ReplaceOptionalCallFix(isJdkOptional(anchor) ? "empty" : "absent", true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static LocalQuickFix createReplaceOptionalOfNullableWithOfFix() {
|
||||
return new ReplaceOptionalCallFix("of", false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiMethod resolveOfNullable(PsiCallExpression expression) {
|
||||
String name = ((PsiMethodCallExpression)expression).getMethodExpression().getReferenceName();
|
||||
if ("ofNullable".equals(name) || "fromNullable".equals(name)) {
|
||||
PsiMethod method = expression.resolveMethod();
|
||||
PsiClass psiClass = method == null ? null : method.getContainingClass();
|
||||
String qname = psiClass == null ? null : psiClass.getQualifiedName();
|
||||
if (CommonClassNames.JAVA_UTIL_OPTIONAL.equals(qname) || GUAVA_OPTIONAL.equals(qname)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ReplaceOptionalCallFix implements LocalQuickFix {
|
||||
private final String myTargetMethodName;
|
||||
private final boolean myClearArguments;
|
||||
|
||||
public ReplaceOptionalCallFix(final String targetMethodName, boolean clearArguments) {
|
||||
myTargetMethodName = targetMethodName;
|
||||
myClearArguments = clearArguments;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getFamilyName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Replace with '." + myTargetMethodName + "()'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiMethodCallExpression
|
||||
methodCallExpression = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethodCallExpression.class);
|
||||
if (methodCallExpression != null) {
|
||||
final PsiElement ofNullableExprName =
|
||||
((PsiMethodCallExpression)JavaPsiFacade.getElementFactory(project)
|
||||
.createExpressionFromText("Optional." + myTargetMethodName + "(null)", null)).getMethodExpression();
|
||||
final PsiElement referenceNameElement = methodCallExpression.getMethodExpression().getReferenceNameElement();
|
||||
if (referenceNameElement != null) {
|
||||
final PsiElement ofNullableNameElement = ((PsiReferenceExpression)ofNullableExprName).getReferenceNameElement();
|
||||
LOG.assertTrue(ofNullableNameElement != null);
|
||||
referenceNameElement.replace(ofNullableNameElement);
|
||||
}
|
||||
if (myClearArguments) {
|
||||
PsiExpressionList argList = methodCallExpression.getArgumentList();
|
||||
PsiExpression[] args = argList.getExpressions();
|
||||
if (args.length > 0) {
|
||||
argList.deleteChildRange(args[0], args[args.length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -11,4 +11,6 @@ public enum NullabilityProblem {
|
||||
nullableReturn,
|
||||
passingNullableToNotNullParameter,
|
||||
passingNullableArgumentToNonAnnotatedParameter,
|
||||
passingNullToOptional,
|
||||
passingNotNullToOptional
|
||||
}
|
||||
|
||||
+20
-1
@@ -57,6 +57,15 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
return callExpression != null ? DfaPsiUtil.getElementNullability(key.getResultType(), callExpression.resolveMethod()) : null;
|
||||
}
|
||||
};
|
||||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
private final FactoryMap<MethodCallInstruction, Boolean> myOptionOfNullable = new FactoryMap<MethodCallInstruction, Boolean>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected Boolean create(MethodCallInstruction key) {
|
||||
PsiCallExpression expression = key.getCallExpression();
|
||||
return expression instanceof PsiMethodCallExpression && DfaOptionalSupport.resolveOfNullable(expression) != null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public DfaInstructionState[] visitAssign(AssignInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
||||
@@ -231,6 +240,10 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
forceNotNull(runner, memState, arg);
|
||||
}
|
||||
}
|
||||
else if (myOptionOfNullable.get(instruction)) {
|
||||
checkNotNullable(memState, arg, NullabilityProblem.passingNotNullToOptional, expr);
|
||||
checkNotNullable(memState, arg, NullabilityProblem.passingNullToOptional, expr);
|
||||
}
|
||||
else if (requiredNullability == Nullness.UNKNOWN) {
|
||||
checkNotNullable(memState, arg, NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter, expr);
|
||||
}
|
||||
@@ -371,8 +384,14 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
protected boolean checkNotNullable(DfaMemoryState state,
|
||||
DfaValue value, NullabilityProblem problem,
|
||||
PsiElement anchor) {
|
||||
if (problem == NullabilityProblem.passingNotNullToOptional) {
|
||||
return !state.isNotNull(value);
|
||||
}
|
||||
|
||||
boolean notNullable = state.checkNotNullable(value);
|
||||
if (notNullable && problem != NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter) {
|
||||
if (notNullable &&
|
||||
problem != NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter &&
|
||||
problem != NullabilityProblem.passingNullToOptional) {
|
||||
DfaValueFactory factory = ((DfaMemoryStateImpl)state).getFactory();
|
||||
state.applyCondition(factory.getRelationFactory().createRelation(value, factory.getConstFactory().getNull(), NE, false));
|
||||
}
|
||||
|
||||
+15
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.ExtensionPoint;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
@@ -31,6 +32,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
@@ -43,7 +45,6 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -52,6 +53,7 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -107,16 +109,17 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void loadForbiddenApi(@NonNls String fileName, Set<String> set) {
|
||||
private static void loadForbiddenApi(String fileName, Set<String> set) {
|
||||
URL resource = Java15APIUsageInspectionBase.class.getResource(fileName);
|
||||
if (resource == null) {
|
||||
Logger.getInstance(Java15APIUsageInspectionBase.class).warn("not found: " + fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> aClass = Java15APIUsageInspectionBase.class;
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(aClass.getResourceAsStream(fileName), CharsetToolkit.UTF8_CHARSET));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream(), CharsetToolkit.UTF8_CHARSET));
|
||||
try {
|
||||
do {
|
||||
String line = reader.readLine();
|
||||
if (line == null) break;
|
||||
set.add(line);
|
||||
} while(true);
|
||||
set.addAll(FileUtil.loadLines(reader));
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
@@ -330,6 +333,7 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
|
||||
private void registerError(PsiJavaCodeReferenceElement reference, LanguageLevel api) {
|
||||
if (reference != null && isInProject(reference)) {
|
||||
//noinspection DialogTitleCapitalization
|
||||
myHolder.registerProblem(reference, InspectionsBundle.message("inspection.1.5.problem.descriptor", getShortName(api)));
|
||||
}
|
||||
}
|
||||
@@ -382,7 +386,7 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
/**
|
||||
* please leave public for {@link #com.intellij.codeInspection.JavaAPIUsagesInspectionTest#testCollectSinceApiUsages}
|
||||
* please leave public for JavaAPIUsagesInspectionTest#testCollectSinceApiUsages
|
||||
*/
|
||||
@Nullable
|
||||
public static String getSignature(@Nullable PsiMember member) {
|
||||
|
||||
@@ -160,20 +160,23 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
|
||||
(psiType instanceof PsiClassReferenceType ? ((PsiClassReferenceType)psiType).getReference().getClass() : ""));
|
||||
return null;
|
||||
}
|
||||
final PsiStatement statement = elementFactory
|
||||
.createStatementFromText(canonicalText + " v = new " + erasedText + "<>()", parameters.getOriginalFile());
|
||||
final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0];
|
||||
final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer();
|
||||
final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondTypeImpl.hasDefaultConstructor(psiClass) ||
|
||||
!PsiDiamondTypeImpl.haveConstructorsGenericsParameters(psiClass);
|
||||
if (hasDefaultConstructorOrNoGenericsOne) {
|
||||
final PsiDiamondTypeImpl.DiamondInferenceResult inferenceResult = PsiDiamondTypeImpl.resolveInferredTypes(initializer);
|
||||
if (inferenceResult.getErrorMessage() == null &&
|
||||
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
|
||||
areInferredTypesApplicable(inferenceResult.getTypes(), parameters.getPosition())) {
|
||||
psiType = initializer.getType();
|
||||
try {
|
||||
final PsiStatement statement = elementFactory
|
||||
.createStatementFromText(canonicalText + " v = new " + erasedText + "<>()", parameters.getOriginalFile());
|
||||
final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0];
|
||||
final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer();
|
||||
final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondTypeImpl.hasDefaultConstructor(psiClass) ||
|
||||
!PsiDiamondTypeImpl.haveConstructorsGenericsParameters(psiClass);
|
||||
if (hasDefaultConstructorOrNoGenericsOne) {
|
||||
final PsiDiamondTypeImpl.DiamondInferenceResult inferenceResult = PsiDiamondTypeImpl.resolveInferredTypes(initializer);
|
||||
if (inferenceResult.getErrorMessage() == null &&
|
||||
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
|
||||
areInferredTypesApplicable(inferenceResult.getTypes(), parameters.getPosition())) {
|
||||
psiType = initializer.getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException ignore) {}
|
||||
}
|
||||
}
|
||||
final PsiTypeLookupItem item = PsiTypeLookupItem.createLookupItem(psiType, position);
|
||||
|
||||
+2
-8
@@ -26,7 +26,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorFontType;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -226,7 +225,8 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
|
||||
@Override
|
||||
protected ParametersListTable createParametersListTable() {
|
||||
return new ParametersListTable() {
|
||||
private final EditorTextFieldJBTableRowRenderer myRowRenderer = new EditorTextFieldJBTableRowRenderer(getProject(), myDisposable) {
|
||||
private final EditorTextFieldJBTableRowRenderer myRowRenderer =
|
||||
new EditorTextFieldJBTableRowRenderer(getProject(), JavaChangeSignatureDialog.this.getFileType(), myDisposable) {
|
||||
@Override
|
||||
protected String getText(JTable table, int row) {
|
||||
ParameterTableModelItemBase<ParameterInfoImpl> item = getRowItem(row);
|
||||
@@ -249,12 +249,6 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
|
||||
}
|
||||
return " " + text;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected FileType getFileType() {
|
||||
return JavaChangeSignatureDialog.this.getFileType();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
|
||||
@@ -260,6 +260,11 @@ public class RefactoringConflictsUtil {
|
||||
!CommonRefactoringUtil.isAncestor(resolved, scopes) &&
|
||||
!PsiSearchScopeUtil.isInScope(resolveScope, resolved) &&
|
||||
!(resolved instanceof LightElement)) {
|
||||
if (resolved instanceof PsiMethod) {
|
||||
for (PsiMethod superMethod : ((PsiMethod)resolved).findDeepestSuperMethods()) {
|
||||
if (PsiSearchScopeUtil.isInScope (resolveScope, superMethod)) return;
|
||||
}
|
||||
}
|
||||
final String scopeDescription = RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(reference), true);
|
||||
final String message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.in.module.2",
|
||||
RefactoringUIUtil.getDescription(resolved, true),
|
||||
|
||||
+4
-3
@@ -1252,7 +1252,7 @@ public class InferenceSession {
|
||||
|
||||
if (methodContainingClass != null) {
|
||||
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(methodContainingClass, containingClass, psiSubstitutor);
|
||||
LOG.assertTrue(psiSubstitutor != null);
|
||||
LOG.assertTrue(psiSubstitutor != null, "derived: " + containingClass + "; super: " + methodContainingClass);
|
||||
}
|
||||
|
||||
for (int i = 0; i < functionalMethodParameters.length; i++) {
|
||||
@@ -1447,7 +1447,8 @@ public class InferenceSession {
|
||||
if (arg instanceof PsiMethodReferenceExpression && ((PsiMethodReferenceExpression)arg).isExact()) {
|
||||
final PsiParameter[] sParameters = sInterfaceMethod.getParameterList().getParameters();
|
||||
final PsiParameter[] tParameters = tInterfaceMethod.getParameterList().getParameters();
|
||||
LOG.assertTrue(sParameters.length == tParameters.length);
|
||||
LOG.assertTrue(sParameters.length == tParameters.length,
|
||||
"s: " + sInterfaceMethod.getParameterList().getText() + "; t: " + tInterfaceMethod.getParameterList().getText());
|
||||
for (int i = 0; i < tParameters.length; i++) {
|
||||
final PsiType tSubstituted = tSubstitutor.substitute(tParameters[i].getType());
|
||||
final PsiType sSubstituted = sSubstitutor.substitute(sParameters[i].getType());
|
||||
@@ -1471,7 +1472,7 @@ public class InferenceSession {
|
||||
|
||||
if (sPrimitive ^ tPrimitive) {
|
||||
final PsiMember member = ((PsiMethodReferenceExpression)arg).getPotentiallyApplicableMember();
|
||||
LOG.assertTrue(member != null);
|
||||
LOG.assertTrue(member != null, arg);
|
||||
if (member instanceof PsiMethod) {
|
||||
final PsiType methodReturnType = ((PsiMethod)member).getReturnType();
|
||||
if (sPrimitive && methodReturnType instanceof PsiPrimitiveType && methodReturnType != PsiType.VOID ||
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.of()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
com.google.common.base.Optional.of(1<caret>1);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.absent()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
com.google.common.base.Optional.absent(<caret>);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.of()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
java.util.Optional.of(1<caret>1);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Replace with '.of()'" "true"
|
||||
|
||||
class A{
|
||||
void test(String s){
|
||||
assert s != null;
|
||||
java.util.Optional.of(<caret>s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Replace with '.empty()'" "true"
|
||||
class A {
|
||||
void test() {
|
||||
String s = null;
|
||||
java.util.Optional.empty(<caret>);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Replace with '.empty()'" "true"
|
||||
class A {
|
||||
void test() {
|
||||
String s = null;
|
||||
java.util.Optional.empty(<caret>);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.of()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
com.google.common.base.Optional.fromNullable(1<caret>1);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.absent()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
com.google.common.base.Optional.fromNullable(n<caret>ull);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.of()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
java.util.Optional.ofNullable(1<caret>1);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Replace with '.of()'" "true"
|
||||
|
||||
class A{
|
||||
void test(String s){
|
||||
assert s != null;
|
||||
java.util.Optional.ofNullable(<caret>s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Replace with '.empty()'" "true"
|
||||
class A {
|
||||
void test() {
|
||||
String s = null;
|
||||
java.util.Optional.ofNullable(n<caret>ull);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Replace with '.empty()'" "true"
|
||||
class A {
|
||||
void test() {
|
||||
String s = null;
|
||||
java.util.Optional.ofNullable(<caret>s);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.of()'" "false"
|
||||
class A{
|
||||
void test(String s){
|
||||
java.util.Optional.ofNullable(<caret>s);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.fromNullable()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
com.google.common.base.Optional.fromNullable(n<caret>ull);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Replace with '.fromNullable()'" "true"
|
||||
class A{
|
||||
void test(){
|
||||
com.google.common.base.Optional.of(n<caret>ull);
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.codeInsight.daemon.quickFix
|
||||
import com.intellij.codeInspection.LocalInspectionTool
|
||||
import com.intellij.codeInspection.dataFlow.DataFlowInspection
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
public class ReplaceFromOfNullableFixTest extends LightQuickFixParameterizedTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return [new DataFlowInspection()] as LocalInspectionTool[]
|
||||
}
|
||||
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/replaceFromOfNullable";
|
||||
}
|
||||
|
||||
static void addGuavaOptional(Disposable parent) {
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
VirtualFile optional = getSourceRoot()
|
||||
.createChildDirectory(this, "com")
|
||||
.createChildDirectory(this, "google")
|
||||
.createChildDirectory(this, "common")
|
||||
.createChildDirectory(this, "base")
|
||||
.createChildData(this, "Optional.java");
|
||||
VfsUtil.saveText(optional, """
|
||||
package com.google.common.base;
|
||||
public abstract class Optional<T> {
|
||||
public static <T> Optional<T> absent() { }
|
||||
|
||||
public static <T> Optional<T> of(@org.jetbrains.annotations.NotNull T reference) { }
|
||||
|
||||
public static <T> Optional<T> fromNullable(T nullableReference) { }
|
||||
}
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanupGuava() {
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
getSourceRoot().findChild("com")?.delete(this)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActionStarted(String testName, String contents) {
|
||||
if (testName.contains("Guava")) {
|
||||
addGuavaOptional(testRootDisposable)
|
||||
}
|
||||
super.beforeActionStarted(testName, contents)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterActionCompleted(String testName, String contents) {
|
||||
cleanupGuava()
|
||||
super.afterActionCompleted(testName, contents)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
+14
@@ -42,6 +42,20 @@ public class ReplaceWithOfNullableFixTest extends LightQuickFixParameterizedTest
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/replaceWithOfNullable";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActionStarted(String testName, String contents) {
|
||||
if (testName.contains("Guava")) {
|
||||
ReplaceFromOfNullableFixTest.addGuavaOptional(myTestRootDisposable);
|
||||
}
|
||||
super.beforeActionStarted(testName, contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterActionCompleted(String testName, String contents) {
|
||||
ReplaceFromOfNullableFixTest.cleanupGuava();
|
||||
super.afterActionCompleted(testName, contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
|
||||
@@ -17,6 +17,9 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.completion.NormalCompletionDfaTest;
|
||||
import com.intellij.codeInsight.completion.SmartTypeCompletionDfaTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.AddAssertStatementFixTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.ReplaceFromOfNullableFixTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.ReplaceWithOfNullableFixTest;
|
||||
import com.intellij.slicer.SliceBackwardTest;
|
||||
import com.intellij.slicer.SliceTreeTest;
|
||||
import junit.framework.Test;
|
||||
@@ -25,20 +28,29 @@ import junit.framework.TestSuite;
|
||||
public class DataFlowInspectionTestSuite {
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
suite.addTestSuite(DataFlowInspectionTest.class);
|
||||
suite.addTestSuite(DataFlowInspection8Test.class);
|
||||
suite.addTestSuite(DataFlowInspectionAncientTest.class);
|
||||
suite.addTestSuite(ContractCheckTest.class);
|
||||
|
||||
suite.addTestSuite(ContractInferenceFromSourceTest.class);
|
||||
suite.addTestSuite(NullityInferenceFromSourceTestCase.DfaInferenceTest.class);
|
||||
suite.addTestSuite(NullityInferenceFromSourceTestCase.LightInferenceTest.class);
|
||||
suite.addTestSuite(PurityInferenceFromSourceTest.class);
|
||||
|
||||
suite.addTestSuite(SliceTreeTest.class);
|
||||
suite.addTestSuite(SliceBackwardTest.class);
|
||||
|
||||
suite.addTestSuite(SmartTypeCompletionDfaTest.class);
|
||||
suite.addTestSuite(NormalCompletionDfaTest.class);
|
||||
|
||||
suite.addTestSuite(NullableStuffInspectionTest.class);
|
||||
suite.addTestSuite(NullableStuffInspection14Test.class);
|
||||
|
||||
suite.addTestSuite(AddAssertStatementFixTest.class);
|
||||
suite.addTestSuite(ReplaceWithOfNullableFixTest.class);
|
||||
suite.addTestSuite(ReplaceFromOfNullableFixTest.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +136,9 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
|
||||
JUnitConfiguration configuration = createConfiguration(testA);
|
||||
JavaParameters parameters = checkCanRun(configuration);
|
||||
CHECK.empty(parameters.getVMParametersList().getList());
|
||||
final SegmentedOutputStream notifications = new SegmentedOutputStream(System.out);
|
||||
assertTrue(JUnitStarter.checkVersion(parameters.getProgramParametersList().getArray(),
|
||||
new SegmentedOutputStream(System.out)));
|
||||
new PrintStream(notifications)));
|
||||
assertTrue(parameters.getProgramParametersList().getList().contains(testA.getQualifiedName()));
|
||||
assertEquals(JUnitStarter.class.getName(), parameters.getMainClass());
|
||||
assertEquals(myJdk.getHomeDirectory().getPresentableUrl(), parameters.getJdkPath());
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@ package com.intellij.execution.configurations;
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.ExecutionBundle;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.process.DefaultJavaProcessHandler;
|
||||
import com.intellij.execution.process.KillableColoredProcessHandler;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||
@@ -101,7 +101,7 @@ public class JavaCommandLineTest extends LightIdeaTestCase {
|
||||
|
||||
public void testCreateProcess() {
|
||||
try {
|
||||
new DefaultJavaProcessHandler(new GeneralCommandLine());
|
||||
new KillableColoredProcessHandler(new GeneralCommandLine());
|
||||
fail("ExecutionException (executable is not specified) expected");
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
|
||||
+5
-7
@@ -61,16 +61,14 @@ public class MissingFinalNewlineInspection extends LocalInspectionTool {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class AddNewlineQuickFix implements LocalQuickFix {
|
||||
private final Section mySection;
|
||||
|
||||
private static class AddNewlineQuickFix extends LocalQuickFixOnPsiElement {
|
||||
private AddNewlineQuickFix(Section section) {
|
||||
mySection = section;
|
||||
super(section);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
public String getText() {
|
||||
return ManifestBundle.message("inspection.newline.fix");
|
||||
}
|
||||
|
||||
@@ -81,8 +79,8 @@ public class MissingFinalNewlineInspection extends LocalInspectionTool {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement lastChild = mySection.getLastChild();
|
||||
public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
|
||||
PsiElement lastChild = startElement.getLastChild();
|
||||
if (lastChild instanceof Header) {
|
||||
lastChild.getNode().addLeaf(ManifestTokenType.NEWLINE, "\n", null);
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@ package org.jetbrains.lang.manifest;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import junit.framework.Assert;
|
||||
import org.jetbrains.lang.manifest.highlighting.MissingFinalNewlineInspection;
|
||||
|
||||
public class MissingFinalNewlineInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
@@ -29,12 +28,12 @@ public class MissingFinalNewlineInspectionTest extends LightCodeInsightFixtureTe
|
||||
|
||||
public void testEmptyFile() {
|
||||
myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "");
|
||||
Assert.assertEquals(0, myFixture.getAvailableIntentions().size());
|
||||
assertEquals(0, myFixture.getAvailableIntentions().size());
|
||||
}
|
||||
|
||||
public void testNoProblem() {
|
||||
myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Manifest-Version: 1.0\n");
|
||||
Assert.assertEquals(0, myFixture.getAvailableIntentions().size());
|
||||
assertEquals(0, myFixture.getAvailableIntentions().size());
|
||||
}
|
||||
|
||||
public void testFix() {
|
||||
|
||||
@@ -54,7 +54,7 @@ public class JsonLiteralAnnotator implements Annotator {
|
||||
final int length = text.length();
|
||||
|
||||
// Check that string literal is closed properly
|
||||
if (length <= 1 || text.charAt(0) != text.charAt(length - 1) || quoteEscaped(text, length - 1)) {
|
||||
if (length <= 1 || text.charAt(0) != text.charAt(length - 1) || JsonPsiUtil.isEscapedChar(text, length - 1)) {
|
||||
holder.createErrorAnnotation(element, JsonBundle.message("msg.missing.closing.quote"));
|
||||
}
|
||||
|
||||
@@ -79,12 +79,4 @@ public class JsonLiteralAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean quoteEscaped(String text, int quotePos) {
|
||||
int count = 0;
|
||||
for (int i = quotePos - 1; i >= 0 && text.charAt(i) == '\\'; i--) {
|
||||
count++;
|
||||
}
|
||||
return count % 2 != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
|
||||
import com.intellij.json.JsonBundle;
|
||||
import com.intellij.json.JsonElementTypes;
|
||||
import com.intellij.json.psi.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
@@ -139,13 +139,42 @@ public class JsonStandardComplianceInspection extends LocalInspectionTool {
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final String rawText = element.getText();
|
||||
if (element instanceof JsonLiteral || element instanceof JsonReferenceExpression) {
|
||||
final String content = StringUtil.stripQuotesAroundValue(element.getText());
|
||||
element.replace(new JsonElementGenerator(project).createStringLiteral(content));
|
||||
String content = JsonPsiUtil.stripQuotes(rawText);
|
||||
if (element instanceof JsonStringLiteral && rawText.startsWith("'")) {
|
||||
content = escapeSingleQuotedStringContent(content);
|
||||
}
|
||||
// TODO: find out better way to replace element and skip reformatting step afterwards
|
||||
final ASTNode replacement = new JsonElementGenerator(project).createValue("\"" + content + "\"").getNode();
|
||||
element.getParent().getNode().replaceChild(element.getNode(), replacement);
|
||||
}
|
||||
else if (element != null) {
|
||||
LOG.error("Quick fix was applied to unexpected element", element.getText(), element.getParent().getText());
|
||||
LOG.error("Quick fix was applied to unexpected element", rawText, element.getParent().getText());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String escapeSingleQuotedStringContent(@NotNull String content) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
boolean nextCharEscaped = false;
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
final char c = content.charAt(i);
|
||||
if ((nextCharEscaped && c != '\'') || (!nextCharEscaped && c == '"')) {
|
||||
result.append('\\');
|
||||
}
|
||||
if (c != '\\' || nextCharEscaped) {
|
||||
result.append(c);
|
||||
nextCharEscaped = false;
|
||||
}
|
||||
else {
|
||||
nextCharEscaped = true;
|
||||
}
|
||||
}
|
||||
if (nextCharEscaped) {
|
||||
result.append('\\');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,10 @@ public class JsonBlock implements ASTBlock {
|
||||
mySpacingBuilder = JsonFormattingBuilderModel.createSpacingBuilder(settings);
|
||||
|
||||
if (myPsiElement instanceof JsonObject) {
|
||||
myChildWrap = Wrap.createWrap(getCustomSettings().OBJECT_WRAPPING, false);
|
||||
myChildWrap = Wrap.createWrap(getCustomSettings().OBJECT_WRAPPING, true);
|
||||
}
|
||||
else if (myPsiElement instanceof JsonArray) {
|
||||
myChildWrap = Wrap.createWrap(getCustomSettings().ARRAY_WRAPPING, false);
|
||||
myChildWrap = Wrap.createWrap(getCustomSettings().ARRAY_WRAPPING, true);
|
||||
}
|
||||
else {
|
||||
myChildWrap = null;
|
||||
@@ -113,7 +113,10 @@ public class JsonBlock implements ASTBlock {
|
||||
|
||||
final JsonCodeStyleSettings customSettings = getCustomSettings();
|
||||
if (hasElementType(myNode, JSON_CONTAINERS)) {
|
||||
if (!hasElementType(childNode, COMMA) && !hasElementType(childNode, JSON_ALL_BRACES)) {
|
||||
if (hasElementType(childNode, COMMA)) {
|
||||
wrap = Wrap.createWrap(WrapType.NONE, true);
|
||||
}
|
||||
else if (!hasElementType(childNode, JSON_ALL_BRACES)) {
|
||||
assert myChildWrap != null;
|
||||
wrap = myChildWrap;
|
||||
indent = Indent.getNormalIndent();
|
||||
|
||||
@@ -137,4 +137,46 @@ public class JsonPsiUtil {
|
||||
return element.getText();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns content of the string literal (without escaping) striving to preserve as much of user data as possible.
|
||||
* <ul>
|
||||
* <li>If literal length is greater than one and it starts and ends with the same quote and the last quote is not escaped, returns
|
||||
* text without first and last characters.</li>
|
||||
* <li>Otherwise if literal still begins with a quote, returns text without first character only.</li>
|
||||
* <li>Returns unmodified text in all other cases.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param text presumably result of {@link JsonStringLiteral#getText()}
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
public static String stripQuotes(@NotNull String text) {
|
||||
if (text.length() > 0) {
|
||||
final char firstChar = text.charAt(0);
|
||||
final char lastChar = text.charAt(text.length() - 1);
|
||||
if (firstChar == '\'' || firstChar == '"') {
|
||||
if (text.length() > 1 && firstChar == lastChar && !isEscapedChar(text, text.length() - 1)) {
|
||||
return text.substring(1, text.length() - 1);
|
||||
}
|
||||
return text.substring(1);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that character in given position is escaped with backslashes.
|
||||
*
|
||||
* @param text text character belongs to
|
||||
* @param position position of the character
|
||||
* @return whether character at given position is escaped, i.e. preceded by odd number of backslashes
|
||||
*/
|
||||
public static boolean isEscapedChar(@NotNull String text, int position) {
|
||||
int count = 0;
|
||||
for (int i = position - 1; i >= 0 && text.charAt(i) == '\\'; i--) {
|
||||
count++;
|
||||
}
|
||||
return count % 2 != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class JsonPsiImplUtils {
|
||||
|
||||
@NotNull
|
||||
public static String getName(@NotNull JsonProperty property) {
|
||||
return StringUtil.stripQuotesAroundValue(property.getNameElement().getText());
|
||||
return StringUtil.unescapeStringCharacters(JsonPsiUtil.stripQuotes(property.getNameElement().getText()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,7 +210,7 @@ public class JsonPsiImplUtils {
|
||||
|
||||
@NotNull
|
||||
public static String getValue(@NotNull JsonStringLiteral literal) {
|
||||
return StringUtil.unescapeStringCharacters(StringUtil.unquoteString(literal.getText()));
|
||||
return StringUtil.unescapeStringCharacters(JsonPsiUtil.stripQuotes(literal.getText()));
|
||||
}
|
||||
|
||||
public static boolean getValue(@NotNull JsonBooleanLiteral literal) {
|
||||
|
||||
@@ -101,6 +101,16 @@ public class JsonFormattingTest extends FormatterTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
// IDEA-138902
|
||||
public void testObjectsWithSingleProperty() throws Exception {
|
||||
withPreservedSettings(new ThrowableRunnable<Exception>() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Moved from JavaScript
|
||||
|
||||
public void testWeb3830() throws Exception {
|
||||
|
||||
@@ -27,8 +27,10 @@ public class JsonQuickFixTest extends JsonTestCase {
|
||||
checkWrapInDoubleQuotes("{4<caret>2: false}", "{\"42\": false}");
|
||||
checkWrapInDoubleQuotes("{fo<caret>o: false}", "{\"foo\": false}");
|
||||
checkWrapInDoubleQuotes("{'fo<caret>o': false}", "{\"foo\": false}");
|
||||
checkWrapInDoubleQuotes("'foo\\\"", "\"foo\\\"\"");
|
||||
checkWrapInDoubleQuotes("{\"foo\": b<caret>ar}", "{\"foo\": \"bar\"}");
|
||||
checkWrapInDoubleQuotes("{\"foo\": 'b<caret>ar'}", "{\"foo\": \"bar\"}");
|
||||
checkWrapInDoubleQuotes("'foo\\n\\'\"\\\\\\\"bar", "\"foo\\n'\\\"\\\\\\\"bar\"");
|
||||
}
|
||||
|
||||
private void checkWrapInDoubleQuotes(@NotNull String before, @NotNull String after) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"level0": {"level1": {"level2": "someValue"}}}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"level0": {
|
||||
"level1": {
|
||||
"level2": "someValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,5 +8,7 @@
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
["this line is long too"]
|
||||
[
|
||||
"this line is long too"
|
||||
]
|
||||
]
|
||||
@@ -1,3 +1,5 @@
|
||||
{
|
||||
"<selection>property</selection>": [null]
|
||||
"<selection>property</selection>": [
|
||||
null
|
||||
]
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.List;
|
||||
|
||||
public class FCTSBackedLighterAST extends LighterAST {
|
||||
@@ -53,6 +54,38 @@ public class FCTSBackedLighterAST extends LighterAST {
|
||||
}
|
||||
LighterASTNode[] elements = into.get();
|
||||
assert elements != null : myTreeStructure +" ("+parent+")";
|
||||
return ContainerUtil.newArrayList(elements, 0, numKids);
|
||||
return new LighterASTNodeList(numKids, elements);
|
||||
}
|
||||
|
||||
public void disposeChildren(@NotNull List<LighterASTNode> children) {
|
||||
if (children instanceof LighterASTNodeList) {
|
||||
LighterASTNodeList nodes = (LighterASTNodeList)children;
|
||||
|
||||
myTreeStructure.disposeChildren(nodes.myElements, nodes.mySize);
|
||||
} else {
|
||||
LighterASTNode[] astNodes = new LighterASTNode[children.size()];
|
||||
myTreeStructure.disposeChildren(children.toArray(astNodes), astNodes.length);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LighterASTNodeList extends AbstractList<LighterASTNode> {
|
||||
private final int mySize;
|
||||
private final LighterASTNode[] myElements;
|
||||
|
||||
public LighterASTNodeList(int size, LighterASTNode[] elements) {
|
||||
mySize = size;
|
||||
myElements = elements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LighterASTNode get(final int index) {
|
||||
if (index < 0 || index >= mySize) throw new IndexOutOfBoundsException("index:" + index + " size:" + mySize);
|
||||
return myElements[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return mySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,4 +44,6 @@ public abstract class LighterAST {
|
||||
|
||||
@NotNull
|
||||
public abstract List<LighterASTNode> getChildren(@NotNull final LighterASTNode parent);
|
||||
|
||||
public abstract void disposeChildren(@NotNull List<LighterASTNode> children);
|
||||
}
|
||||
@@ -45,9 +45,8 @@ public class TreeBackedLighterAST extends LighterAST {
|
||||
@Override
|
||||
public List<LighterASTNode> getChildren(@NotNull final LighterASTNode parent) {
|
||||
final ASTNode[] children = ((NodeWrapper)parent).myNode.getChildren(null);
|
||||
if (children == null || children.length == 0) {
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
if (children.length == 0) return ContainerUtil.emptyList();
|
||||
|
||||
List<LighterASTNode> result = new ArrayList<LighterASTNode>(children.length);
|
||||
for (final ASTNode child : children) {
|
||||
result.add(wrap(child));
|
||||
@@ -55,6 +54,9 @@ public class TreeBackedLighterAST extends LighterAST {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void disposeChildren(@NotNull List<LighterASTNode> children) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static LighterASTNode wrap(@NotNull ASTNode node) {
|
||||
return node.getFirstChildNode() == null && node.getTextLength() > 0 ? new TokenNodeWrapper(node) : new NodeWrapper(node);
|
||||
|
||||
@@ -19,6 +19,8 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.PossiblyDumbAware;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.Stack;
|
||||
@@ -38,7 +40,7 @@ import java.util.Set;
|
||||
public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements PossiblyDumbAware {
|
||||
|
||||
private CustomFoldingProvider myDefaultProvider;
|
||||
private static final int MAX_LOOKUP_DEPTH = 10;
|
||||
private final RegistryValue myMaxLookupDepth = Registry.get("custom.folding.max.lookup.depth");
|
||||
private static final ThreadLocal<Set<ASTNode>> ourCustomRegionElements = new ThreadLocal<Set<ASTNode>>();
|
||||
|
||||
@NotNull
|
||||
@@ -103,7 +105,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements P
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (currDepth < MAX_LOOKUP_DEPTH) {
|
||||
if (currDepth < myMaxLookupDepth.asInteger()) {
|
||||
addCustomFoldingRegionsRecursively(localFoldingStack, child, descriptors, currDepth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -210,7 +210,7 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
|
||||
@Override
|
||||
public String getApiVersion() {
|
||||
if (myApiVersion != null) {
|
||||
return BuildNumber.fromString(myApiVersion, getProductPrefix()).asString();
|
||||
return BuildNumber.fromString(myApiVersion, getBuild().getProductCode()).asString();
|
||||
}
|
||||
return getBuild().asString();
|
||||
}
|
||||
|
||||
@@ -411,12 +411,19 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doScrollToChange(@NotNull SimpleDiffChange change, boolean animated) {
|
||||
private void doScrollToChange(@NotNull SimpleDiffChange change, final boolean animated) {
|
||||
if (myEditor1 == null || myEditor2 == null) return;
|
||||
assert mySyncScrollSupport != null;
|
||||
|
||||
EditorEx editor = getCurrentEditor();
|
||||
int line = change.getStartLine(getCurrentSide());
|
||||
DiffUtil.scrollEditor(editor, line, animated);
|
||||
final int line1 = change.getStartLine(Side.LEFT);
|
||||
final int line2 = change.getStartLine(Side.RIGHT);
|
||||
final int endLine1 = change.getEndLine(Side.LEFT);
|
||||
final int endLine2 = change.getEndLine(Side.RIGHT);
|
||||
|
||||
DiffUtil.moveCaret(myEditor1, line1);
|
||||
DiffUtil.moveCaret(myEditor2, line2);
|
||||
|
||||
mySyncScrollSupport.makeVisible(getCurrentSide(), line1, endLine1, line2, endLine2, animated);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -346,6 +346,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
|
||||
}
|
||||
|
||||
private void doScrollToChange(@NotNull SimpleThreesideDiffChange change, boolean animated) {
|
||||
// TODO: use anchors to fix scrolling issue at the start/end of file
|
||||
EditorEx editor = getCurrentEditor();
|
||||
int line = change.getStartLine(getCurrentSide());
|
||||
DiffUtil.scrollEditor(editor, line, animated);
|
||||
|
||||
@@ -15,15 +15,18 @@
|
||||
*/
|
||||
package com.intellij.diff.tools.util;
|
||||
|
||||
import com.intellij.diff.util.IntPair;
|
||||
import com.intellij.diff.util.Side;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.ScrollingModel;
|
||||
import com.intellij.openapi.editor.event.VisibleAreaEvent;
|
||||
import com.intellij.openapi.editor.event.VisibleAreaListener;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import gnu.trove.TIntFunction;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -82,6 +85,51 @@ public class SyncScrollSupport {
|
||||
public boolean isDuringSyncScroll() {
|
||||
return myDuringSyncScroll;
|
||||
}
|
||||
|
||||
public void makeVisible(@NotNull Side masterSide,
|
||||
int startLine1, int endLine1, int startLine2, int endLine2,
|
||||
final boolean animate) {
|
||||
Side slaveSide = masterSide.other();
|
||||
|
||||
final IntPair offsets = getTargetOffsets(myEditor1, myEditor2, startLine1, endLine1, startLine2, endLine2);
|
||||
|
||||
final Editor masterEditor = masterSide.select(myEditor1, myEditor2);
|
||||
final Editor slaveEditor = slaveSide.select(myEditor1, myEditor2);
|
||||
|
||||
final int masterOffset = masterSide.select(offsets.val1, offsets.val2);
|
||||
final int slaveOffset = slaveSide.select(offsets.val1, offsets.val2);
|
||||
|
||||
int startOffset1 = myEditor1.getScrollingModel().getVisibleArea().y;
|
||||
int startOffset2 = myEditor2.getScrollingModel().getVisibleArea().y;
|
||||
final int masterStartOffset = masterSide.select(startOffset1, startOffset2);
|
||||
|
||||
myHelper1.setAnchor(startOffset1, offsets.val1, startOffset2, offsets.val2);
|
||||
myHelper2.setAnchor(startOffset2, offsets.val2, startOffset1, offsets.val1);
|
||||
|
||||
doScrollHorizontally(masterEditor, 0, false); // animation will be canceled by "scroll vertically" anyway
|
||||
doScrollVertically(masterEditor, masterOffset, animate);
|
||||
|
||||
masterEditor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myHelper1.removeAnchor();
|
||||
myHelper2.removeAnchor();
|
||||
|
||||
if (masterOffset == masterStartOffset) { // master editor didn't scrolled
|
||||
myDuringSyncScroll = true;
|
||||
|
||||
doScrollVertically(slaveEditor, slaveOffset, animate);
|
||||
|
||||
slaveEditor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myDuringSyncScroll = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class ThreesideSyncScrollSupport {
|
||||
@@ -157,78 +205,150 @@ public class SyncScrollSupport {
|
||||
private static class MyScrollHelper implements VisibleAreaListener {
|
||||
@NotNull private final Editor myMaster;
|
||||
@NotNull private final Editor mySlave;
|
||||
|
||||
@NotNull private final TIntFunction myConvertor;
|
||||
|
||||
@Nullable private Anchor myAnchor;
|
||||
|
||||
public MyScrollHelper(@NotNull Editor master, @NotNull Editor slave, @NotNull TIntFunction convertor) {
|
||||
myMaster = master;
|
||||
mySlave = slave;
|
||||
myConvertor = convertor;
|
||||
}
|
||||
|
||||
public void setAnchor(int masterStartOffset, int masterEndOffset, int slaveStartOffset, int slaveEndOffset) {
|
||||
myAnchor = new Anchor(masterStartOffset, masterEndOffset, slaveStartOffset, slaveEndOffset);
|
||||
}
|
||||
|
||||
public void removeAnchor() {
|
||||
myAnchor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visibleAreaChanged(VisibleAreaEvent e) {
|
||||
Rectangle newRectangle = e.getNewRectangle();
|
||||
Rectangle oldRectangle = e.getOldRectangle();
|
||||
if (oldRectangle == null) return;
|
||||
|
||||
syncVerticalScroll(newRectangle, oldRectangle);
|
||||
syncHorizontalScroll(newRectangle, oldRectangle);
|
||||
if (newRectangle.x != oldRectangle.x) syncHorizontalScroll(false);
|
||||
if (newRectangle.y != oldRectangle.y) syncVerticalScroll(false);
|
||||
}
|
||||
|
||||
private void syncVerticalScroll(@NotNull Rectangle newRectangle, @NotNull Rectangle oldRectangle) {
|
||||
if (newRectangle.y == oldRectangle.y) return;
|
||||
|
||||
private void syncVerticalScroll(boolean animated) {
|
||||
if (myMaster.getDocument().getTextLength() == 0) return;
|
||||
|
||||
int masterVerticalScrollOffset = myMaster.getScrollingModel().getVerticalScrollOffset();
|
||||
|
||||
Rectangle viewRect = myMaster.getScrollingModel().getVisibleArea();
|
||||
int middleY = viewRect.height / 3;
|
||||
|
||||
LogicalPosition masterPos = myMaster.xyToLogicalPosition(new Point(viewRect.x, masterVerticalScrollOffset + middleY));
|
||||
int masterCenterLine = masterPos.line;
|
||||
int scrollToLine = myConvertor.execute(masterCenterLine);
|
||||
int offset;
|
||||
if (myAnchor == null) {
|
||||
LogicalPosition masterPos = myMaster.xyToLogicalPosition(new Point(viewRect.x, viewRect.y + middleY));
|
||||
int masterCenterLine = masterPos.line;
|
||||
int convertedCenterLine = myConvertor.execute(masterCenterLine);
|
||||
|
||||
int correction = (masterVerticalScrollOffset + middleY) % myMaster.getLineHeight();
|
||||
Point point = mySlave.logicalPositionToXY(new LogicalPosition(scrollToLine, masterPos.column));
|
||||
int offset = point.y - middleY + correction;
|
||||
Point point = mySlave.logicalPositionToXY(new LogicalPosition(convertedCenterLine, masterPos.column));
|
||||
int correction = (viewRect.y + middleY) % myMaster.getLineHeight();
|
||||
offset = point.y - middleY + correction;
|
||||
}
|
||||
else {
|
||||
double progress = myAnchor.masterStartOffset == myAnchor.masterEndOffset || viewRect.y == myAnchor.masterEndOffset ? 1 :
|
||||
((double)(viewRect.y - myAnchor.masterStartOffset)) / (myAnchor.masterEndOffset - myAnchor.masterStartOffset);
|
||||
|
||||
offset = myAnchor.slaveStartOffset + (int)((myAnchor.slaveEndOffset - myAnchor.slaveStartOffset) * progress);
|
||||
}
|
||||
|
||||
int deltaHeaderOffset = getHeaderOffset(mySlave) - getHeaderOffset(myMaster);
|
||||
doScrollVertically(mySlave.getScrollingModel(), offset + deltaHeaderOffset);
|
||||
doScrollVertically(mySlave, offset + deltaHeaderOffset, animated);
|
||||
}
|
||||
|
||||
private void syncHorizontalScroll(@NotNull Rectangle newRectangle, @NotNull Rectangle oldRectangle) {
|
||||
if (newRectangle.x == oldRectangle.x) return;
|
||||
|
||||
int offset = newRectangle.x;
|
||||
|
||||
doScrollHorizontally(mySlave.getScrollingModel(), offset);
|
||||
private void syncHorizontalScroll(boolean animated) {
|
||||
int offset = myMaster.getScrollingModel().getVisibleArea().x;
|
||||
doScrollHorizontally(mySlave, offset, animated);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doScrollVertically(@NotNull ScrollingModel model, int offset) {
|
||||
model.disableAnimation();
|
||||
try {
|
||||
model.scrollVertically(offset);
|
||||
}
|
||||
finally {
|
||||
model.enableAnimation();
|
||||
}
|
||||
private static void doScrollVertically(@NotNull Editor editor, int offset, boolean animated) {
|
||||
ScrollingModel model = editor.getScrollingModel();
|
||||
if (!animated) model.disableAnimation();
|
||||
model.scrollVertically(offset);
|
||||
if (!animated) model.enableAnimation();
|
||||
}
|
||||
|
||||
private static void doScrollHorizontally(@NotNull ScrollingModel model, int offset) {
|
||||
model.disableAnimation();
|
||||
try {
|
||||
model.scrollHorizontally(offset);
|
||||
}
|
||||
finally {
|
||||
model.enableAnimation();
|
||||
}
|
||||
private static void doScrollHorizontally(@NotNull Editor editor, int offset, boolean animated) {
|
||||
ScrollingModel model = editor.getScrollingModel();
|
||||
if (!animated) model.disableAnimation();
|
||||
model.scrollHorizontally(offset);
|
||||
if (!animated) model.enableAnimation();
|
||||
}
|
||||
|
||||
private static int getHeaderOffset(@NotNull final Editor editor) {
|
||||
final JComponent header = editor.getHeaderComponent();
|
||||
return header == null ? 0 : header.getHeight();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static IntPair getTargetOffsets(@NotNull Editor editor1, @NotNull Editor editor2,
|
||||
int startLine1, int endLine1, int startLine2, int endLine2) {
|
||||
int topOffset1 = editor1.logicalPositionToXY(new LogicalPosition(startLine1, 0)).y;
|
||||
int bottomOffset1 = editor1.logicalPositionToXY(new LogicalPosition(endLine1 + 1, 0)).y;
|
||||
int topOffset2 = editor2.logicalPositionToXY(new LogicalPosition(startLine2, 0)).y;
|
||||
int bottomOffset2 = editor2.logicalPositionToXY(new LogicalPosition(endLine2 + 1, 0)).y;
|
||||
|
||||
int rangeHeight1 = bottomOffset1 - topOffset1;
|
||||
int rangeHeight2 = bottomOffset2 - topOffset2;
|
||||
|
||||
int gapLines1 = 2 * editor1.getLineHeight();
|
||||
int gapLines2 = 2 * editor2.getLineHeight();
|
||||
|
||||
int editorHeight1 = editor1.getScrollingModel().getVisibleArea().height;
|
||||
int editorHeight2 = editor2.getScrollingModel().getVisibleArea().height;
|
||||
|
||||
int maximumOffset1 = ((EditorEx)editor1).getScrollPane().getVerticalScrollBar().getMaximum() - editorHeight1;
|
||||
int maximumOffset2 = ((EditorEx)editor1).getScrollPane().getVerticalScrollBar().getMaximum() - editorHeight2;
|
||||
|
||||
// 'shift' here - distance between editor's top and first line of range
|
||||
|
||||
// make whole range visible. If possible, locate it at 'center' (1/3 of height)
|
||||
// If can't show whole range - show as much as we can
|
||||
boolean canShow1 = 2 * gapLines1 + rangeHeight1 <= editorHeight1;
|
||||
boolean canShow2 = 2 * gapLines2 + rangeHeight2 <= editorHeight2;
|
||||
|
||||
int topShift1 = canShow1 ? Math.min(editorHeight1 - gapLines1 - rangeHeight1, editorHeight1 / 3) : gapLines1;
|
||||
int topShift2 = canShow2 ? Math.min(editorHeight2 - gapLines2 - rangeHeight2, editorHeight2 / 3) : gapLines2;
|
||||
|
||||
int topShift = Math.min(topShift1, topShift2);
|
||||
|
||||
// check if we're at the top of file
|
||||
topShift = Math.min(topShift, Math.min(topOffset1, topOffset2));
|
||||
|
||||
int offset1 = topOffset1 - topShift;
|
||||
int offset2 = topOffset2 - topShift;
|
||||
if (maximumOffset1 > offset1 && maximumOffset2 > offset2) return new IntPair(offset1, offset2);
|
||||
|
||||
// One of the ranges is at end of file - we can't scroll where we want to.
|
||||
topShift = Math.min(topOffset1 - maximumOffset1, topOffset2 - maximumOffset2);
|
||||
|
||||
// Try to show as much of range as we can (even if it breaks alignment)
|
||||
offset1 = topOffset1 - topShift + Math.max(topShift + rangeHeight1 + gapLines1 - editorHeight1, 0);
|
||||
offset2 = topOffset2 - topShift + Math.max(topShift + rangeHeight2 + gapLines2 - editorHeight2, 0);
|
||||
|
||||
// always show top of the range
|
||||
offset1 = Math.min(offset1, topOffset1 - gapLines1);
|
||||
offset2 = Math.min(offset2, topOffset2 - gapLines2);
|
||||
|
||||
return new IntPair(offset1, offset2);
|
||||
}
|
||||
|
||||
private static class Anchor {
|
||||
public final int masterStartOffset;
|
||||
public final int masterEndOffset;
|
||||
public final int slaveStartOffset;
|
||||
public final int slaveEndOffset;
|
||||
|
||||
public Anchor(int masterStartOffset, int masterEndOffset, int slaveStartOffset, int slaveEndOffset) {
|
||||
this.masterStartOffset = masterStartOffset;
|
||||
this.masterEndOffset = masterEndOffset;
|
||||
this.slaveStartOffset = slaveStartOffset;
|
||||
this.slaveEndOffset = slaveEndOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -82,7 +82,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
|
||||
@NotNull private final MyScrollToLineHelper myScrollToLineHelper = new MyScrollToLineHelper();
|
||||
|
||||
@Nullable private TwosideSyncScrollSupport mySyncScrollListener;
|
||||
@Nullable protected TwosideSyncScrollSupport mySyncScrollSupport;
|
||||
|
||||
@NotNull private Side myCurrentSide;
|
||||
|
||||
@@ -230,7 +230,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
if (myEditor1 != null && myEditor2 != null) {
|
||||
SyncScrollSupport.SyncScrollable scrollable = getSyncScrollable();
|
||||
if (scrollable != null) {
|
||||
mySyncScrollListener = new TwosideSyncScrollSupport(myEditor1, myEditor2, scrollable);
|
||||
mySyncScrollSupport = new TwosideSyncScrollSupport(myEditor1, myEditor2, scrollable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,15 +248,15 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
myEditor2.getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener);
|
||||
}
|
||||
if (myEditor1 != null && myEditor2 != null) {
|
||||
if (mySyncScrollListener != null) {
|
||||
mySyncScrollListener = null;
|
||||
if (mySyncScrollSupport != null) {
|
||||
mySyncScrollSupport = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void disableSyncScrollSupport(boolean disable) {
|
||||
if (mySyncScrollListener != null) {
|
||||
mySyncScrollListener.myDuringSyncScroll = disable;
|
||||
if (mySyncScrollSupport != null) {
|
||||
mySyncScrollSupport.myDuringSyncScroll = disable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,8 +325,8 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
@CalledInAwt
|
||||
@NotNull
|
||||
protected LogicalPosition transferPosition(@NotNull Side baseSide, @NotNull LogicalPosition position) {
|
||||
if (mySyncScrollListener == null) return position;
|
||||
int line = mySyncScrollListener.getScrollable().transfer(baseSide, position.line);
|
||||
if (mySyncScrollSupport == null) return position;
|
||||
int line = mySyncScrollSupport.getScrollable().transfer(baseSide, position.line);
|
||||
return new LogicalPosition(line, position.column);
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
private class MyVisibleAreaListener implements VisibleAreaListener {
|
||||
@Override
|
||||
public void visibleAreaChanged(VisibleAreaEvent e) {
|
||||
if (mySyncScrollListener != null) mySyncScrollListener.visibleAreaChanged(e);
|
||||
if (mySyncScrollSupport != null) mySyncScrollSupport.visibleAreaChanged(e);
|
||||
if (Registry.is("diff.divider.repainting.fix")) {
|
||||
myContentPanel.repaint();
|
||||
}
|
||||
|
||||
@@ -191,6 +191,12 @@ public class DiffUtil {
|
||||
// Scrolling
|
||||
//
|
||||
|
||||
public static void moveCaret(@Nullable final Editor editor, int line) {
|
||||
if (editor == null) return;
|
||||
editor.getCaretModel().removeSecondaryCarets();
|
||||
editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(line, 0));
|
||||
}
|
||||
|
||||
public static void scrollEditor(@Nullable final Editor editor, int line, boolean animated) {
|
||||
scrollEditor(editor, line, 0, animated);
|
||||
}
|
||||
@@ -203,11 +209,15 @@ public class DiffUtil {
|
||||
}
|
||||
|
||||
public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point) {
|
||||
scrollToPoint(editor, point, false);
|
||||
}
|
||||
|
||||
public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point, boolean animated) {
|
||||
if (editor == null) return;
|
||||
editor.getScrollingModel().disableAnimation();
|
||||
if (!animated) editor.getScrollingModel().disableAnimation();
|
||||
editor.getScrollingModel().scrollHorizontally(point.x);
|
||||
editor.getScrollingModel().scrollVertically(point.y);
|
||||
editor.getScrollingModel().enableAnimation();
|
||||
if (!animated) editor.getScrollingModel().enableAnimation();
|
||||
}
|
||||
|
||||
public static void scrollToCaret(@Nullable Editor editor, boolean animated) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,11 +37,11 @@ class FakeRerunAction extends AnAction implements DumbAware {
|
||||
if (environment != null) {
|
||||
presentation.setText(ExecutionBundle.message("rerun.configuration.action.name", environment.getRunProfile().getName()));
|
||||
presentation.setIcon(ExecutionManagerImpl.isProcessRunning(getDescriptor(event)) ? AllIcons.Actions.Restart : environment.getExecutor().getIcon());
|
||||
presentation.setEnabledAndVisible(isEnabled(event));
|
||||
presentation.setEnabled(isEnabled(event));
|
||||
return;
|
||||
}
|
||||
|
||||
presentation.setEnabledAndVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizerUtil;
|
||||
@@ -191,7 +192,7 @@ public class ProjectViewPane extends AbstractProjectViewPSIPane {
|
||||
}
|
||||
}
|
||||
|
||||
private final class ShowExcludedFilesAction extends ToggleAction {
|
||||
private final class ShowExcludedFilesAction extends ToggleAction implements DumbAware {
|
||||
private ShowExcludedFilesAction() {
|
||||
super(IdeBundle.message("action.show.excluded.files"), IdeBundle.message("action.show.hide.excluded.files"), null);
|
||||
}
|
||||
|
||||
@@ -2456,14 +2456,14 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
|
||||
private boolean isTooLarge(@NotNull VirtualFile file) {
|
||||
if (SingleRootFileViewProvider.isTooLargeForIntelligence(file)) {
|
||||
return !myNoLimitCheckTypes.contains(file.getFileType()) && !SingleRootFileViewProvider.isTooLargeForContentLoading(file);
|
||||
return !myNoLimitCheckTypes.contains(file.getFileType()) || SingleRootFileViewProvider.isTooLargeForContentLoading(file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isTooLarge(@NotNull VirtualFile file, long contentSize) {
|
||||
if (SingleRootFileViewProvider.isTooLargeForIntelligence(file, contentSize)) {
|
||||
return !myNoLimitCheckTypes.contains(file.getFileType()) && !SingleRootFileViewProvider.isTooLargeForContentLoading(file, contentSize);
|
||||
return !myNoLimitCheckTypes.contains(file.getFileType()) || SingleRootFileViewProvider.isTooLargeForContentLoading(file, contentSize);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,8 @@ public class ListUtil {
|
||||
boolean myIsEngaged = false;
|
||||
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (myIsEngaged && !UIUtil.isSelectionButtonDown(e)) {
|
||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
if (myIsEngaged && !UIUtil.isSelectionButtonDown(e) && !(focusOwner instanceof JRootPane)) {
|
||||
Point point = e.getPoint();
|
||||
int index = list.locationToIndex(point);
|
||||
list.putClientProperty(SELECTED_BY_MOUSE_EVENT, Boolean.TRUE);
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.util.EventObject;
|
||||
public class JBTable extends JTable implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
|
||||
public static final int PREFERRED_SCROLLABLE_VIEWPORT_HEIGHT_IN_ROWS = 7;
|
||||
public static final int COLUMN_RESIZE_AREA_WIDTH = 3; // same as in BasicTableHeaderUI
|
||||
private static final int DEFAULT_MIN_COLUMN_WIDTH = 15; // see TableColumn constructor javadoc
|
||||
|
||||
private final StatusText myEmptyText;
|
||||
private final ExpandableItemsHandler<TableCell> myExpandableItemsHandler;
|
||||
@@ -794,27 +795,6 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
|
||||
});
|
||||
}
|
||||
|
||||
protected int getExpandedColumnWidth(int columnToExpand) {
|
||||
int expandedWidth = getPreferredHeaderWidth(columnToExpand);
|
||||
for (int row = 0; row < getRowCount(); row++) {
|
||||
TableCellRenderer cellRenderer = getCellRenderer(row, columnToExpand);
|
||||
if (cellRenderer != null) {
|
||||
Component c = JBTable.this.prepareRenderer(cellRenderer, row, columnToExpand);
|
||||
expandedWidth = Math.max(expandedWidth, c.getPreferredSize().width);
|
||||
}
|
||||
}
|
||||
return expandedWidth;
|
||||
}
|
||||
|
||||
private int getPreferredHeaderWidth(int columnIdx) {
|
||||
TableColumn column = getColumnModel().getColumn(columnIdx);
|
||||
TableCellRenderer renderer = column.getHeaderRenderer();
|
||||
renderer = renderer == null ? getDefaultRenderer() : renderer;
|
||||
Object headerValue = column.getHeaderValue();
|
||||
Component headerCellRenderer = renderer.getTableCellRendererComponent(JBTable.this, headerValue, false, false, -1, columnIdx);
|
||||
return headerCellRenderer.getPreferredSize().width;
|
||||
}
|
||||
|
||||
private int getColumnToPack(Point p) {
|
||||
int viewColumnIdx = JBTable.this.columnAtPoint(p);
|
||||
if (viewColumnIdx == -1) return -1;
|
||||
@@ -836,6 +816,33 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
|
||||
}
|
||||
}
|
||||
|
||||
public int getExpandedColumnWidth(int columnToExpand) {
|
||||
int expandedWidth = getPreferredHeaderWidth(columnToExpand);
|
||||
for (int row = 0; row < getRowCount(); row++) {
|
||||
TableCellRenderer cellRenderer = getCellRenderer(row, columnToExpand);
|
||||
if (cellRenderer != null) {
|
||||
Component c = prepareRenderer(cellRenderer, row, columnToExpand);
|
||||
expandedWidth = Math.max(expandedWidth, c.getPreferredSize().width);
|
||||
}
|
||||
}
|
||||
return expandedWidth;
|
||||
}
|
||||
|
||||
private int getPreferredHeaderWidth(int columnIdx) {
|
||||
TableColumn column = getColumnModel().getColumn(columnIdx);
|
||||
TableCellRenderer renderer = column.getHeaderRenderer();
|
||||
if (renderer == null) {
|
||||
JTableHeader header = getTableHeader();
|
||||
if (header == null) {
|
||||
return DEFAULT_MIN_COLUMN_WIDTH;
|
||||
}
|
||||
renderer = header.getDefaultRenderer();
|
||||
}
|
||||
Object headerValue = column.getHeaderValue();
|
||||
Component headerCellRenderer = renderer.getTableCellRendererComponent(this, headerValue, false, false, -1, columnIdx);
|
||||
return headerCellRenderer.getPreferredSize().width;
|
||||
}
|
||||
|
||||
/**
|
||||
* JTable gets table data from model lazily - only for a table part to be shown.
|
||||
* JBTable loads <i>all</i> the data on initialization to calculate cell size.
|
||||
|
||||
@@ -54,7 +54,10 @@
|
||||
<constraints>
|
||||
<splitpane position="right"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<properties>
|
||||
<minimumSize width="50" height="50"/>
|
||||
<preferredSize width="300" height="200"/>
|
||||
</properties>
|
||||
<border type="none">
|
||||
<size top="2" left="4" bottom="2" right="4"/>
|
||||
</border>
|
||||
@@ -91,7 +94,10 @@
|
||||
<constraints>
|
||||
<splitpane position="left"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<properties>
|
||||
<minimumSize width="50" height="50"/>
|
||||
<preferredSize width="300" height="200"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
|
||||
@@ -124,7 +124,7 @@ public class StartupUtil {
|
||||
if (!"true".equals(System.getProperty("idea.no.jre.check"))) {
|
||||
try {
|
||||
// try to find a class from tools.jar
|
||||
Class.forName("com.sun.jdi.Field");
|
||||
Class.forName("com.sun.jdi.Field", false, StartupUtil.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
String message = "'tools.jar' seems to be not in " + ApplicationNamesInfo.getInstance().getProductName() + " classpath.\n" +
|
||||
@@ -132,6 +132,12 @@ public class StartupUtil {
|
||||
Main.showMessage("JDK Required", message, true);
|
||||
return false;
|
||||
}
|
||||
catch (LinkageError e) {
|
||||
String message = "Cannot load a class from 'tools.jar': " + e.getMessage() + "\n" +
|
||||
"Please ensure JAVA_HOME points to JDK rather than JRE.";
|
||||
Main.showMessage("JDK Required", message, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringUtil.containsIgnoreCase(System.getProperty("java.vm.name", ""), "OpenJDK") && !SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
String message = "OpenJDK 6 is not supported. Please use Oracle Java or newer OpenJDK.";
|
||||
|
||||
+37
-9
@@ -27,6 +27,7 @@ import com.intellij.ui.PopupHandler;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.speedSearch.ListWithFilter;
|
||||
import com.intellij.ui.speedSearch.NameFilteringListModel;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -80,17 +81,44 @@ public class NewRecentProjectPanel extends RecentProjectPanel {
|
||||
list.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
|
||||
FlatWelcomeFrame frame = UIUtil.getParentOfType(FlatWelcomeFrame.class, list);
|
||||
if (frame != null) {
|
||||
FocusTraversalPolicy policy = frame.getFocusTraversalPolicy();
|
||||
if (policy != null) {
|
||||
Component next = policy.getComponentAfter(frame, list);
|
||||
if (next != null) {
|
||||
next.requestFocus();
|
||||
Object selected = list.getSelectedValue();
|
||||
final ProjectGroup group;
|
||||
if (selected instanceof ProjectGroupActionGroup) {
|
||||
group = ((ProjectGroupActionGroup)selected).getGroup();
|
||||
} else {
|
||||
group = null;
|
||||
}
|
||||
|
||||
int keyCode = e.getKeyCode();
|
||||
if (keyCode == KeyEvent.VK_RIGHT) {
|
||||
if (group != null) {
|
||||
if (!group.isExpanded()) {
|
||||
group.setExpanded(true);
|
||||
ListModel model = ((NameFilteringListModel)list.getModel()).getOriginalModel();
|
||||
int index = list.getSelectedIndex();
|
||||
RecentProjectsWelcomeScreenActionBase.rebuildRecentProjectDataModel((DefaultListModel)model);
|
||||
list.setSelectedIndex(group.getProjects().isEmpty() ? index : index + 1);
|
||||
}
|
||||
} else {
|
||||
FlatWelcomeFrame frame = UIUtil.getParentOfType(FlatWelcomeFrame.class, list);
|
||||
if (frame != null) {
|
||||
FocusTraversalPolicy policy = frame.getFocusTraversalPolicy();
|
||||
if (policy != null) {
|
||||
Component next = policy.getComponentAfter(frame, list);
|
||||
if (next != null) {
|
||||
next.requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (keyCode == KeyEvent.VK_LEFT ) {
|
||||
if (group != null && group.isExpanded()) {
|
||||
group.setExpanded(false);
|
||||
int index = list.getSelectedIndex();
|
||||
ListModel model = ((NameFilteringListModel)list.getModel()).getOriginalModel();
|
||||
RecentProjectsWelcomeScreenActionBase.rebuildRecentProjectDataModel((DefaultListModel)model);
|
||||
list.setSelectedIndex(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -186,7 +214,7 @@ public class NewRecentProjectPanel extends RecentProjectPanel {
|
||||
return new JPanel() {
|
||||
{
|
||||
setLayout(new BorderLayout());
|
||||
setBackground(UIUtil.getListBackground(isSelected));
|
||||
setBackground(back);
|
||||
|
||||
boolean isGroup = value instanceof ProjectGroupActionGroup;
|
||||
boolean isInsideGroup = false;
|
||||
|
||||
+2
-1
@@ -235,7 +235,8 @@ public class RecentProjectPanel extends JPanel {
|
||||
boolean myIsEngaged = false;
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (myIsEngaged && !UIUtil.isSelectionButtonDown(e)) {
|
||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
if (myIsEngaged && !UIUtil.isSelectionButtonDown(e) && !(focusOwner instanceof JRootPane)) {
|
||||
Point point = e.getPoint();
|
||||
int index = myList.locationToIndex(point);
|
||||
myList.setSelectedIndex(index);
|
||||
|
||||
+14
-10
@@ -35,7 +35,7 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class RecentProjectsWelcomeScreenActionBase extends DumbAwareAction {
|
||||
@Nullable
|
||||
public DefaultListModel getDataModel(AnActionEvent e) {
|
||||
public static DefaultListModel getDataModel(AnActionEvent e) {
|
||||
final JList list = getList(e);
|
||||
if (list != null) {
|
||||
ListModel model = list.getModel();
|
||||
@@ -50,7 +50,7 @@ public abstract class RecentProjectsWelcomeScreenActionBase extends DumbAwareAct
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<AnAction> getSelectedElements(AnActionEvent e) {
|
||||
public static List<AnAction> getSelectedElements(AnActionEvent e) {
|
||||
final JList list = getList(e);
|
||||
final List<AnAction> actions = new ArrayList<AnAction>();
|
||||
if (list != null) {
|
||||
@@ -64,7 +64,7 @@ public abstract class RecentProjectsWelcomeScreenActionBase extends DumbAwareAct
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JList getList(AnActionEvent e) {
|
||||
public static JList getList(AnActionEvent e) {
|
||||
final Component component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT);
|
||||
if (component instanceof JList) {
|
||||
return (JList)component;
|
||||
@@ -72,7 +72,7 @@ public abstract class RecentProjectsWelcomeScreenActionBase extends DumbAwareAct
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasGroupSelected(AnActionEvent e) {
|
||||
public static boolean hasGroupSelected(AnActionEvent e) {
|
||||
for (AnAction action : getSelectedElements(e)) {
|
||||
if (action instanceof ProjectGroupActionGroup) {
|
||||
return true;
|
||||
@@ -81,14 +81,18 @@ public abstract class RecentProjectsWelcomeScreenActionBase extends DumbAwareAct
|
||||
return false;
|
||||
}
|
||||
|
||||
public void rebuildRecentProjectsList(AnActionEvent e) {
|
||||
public static void rebuildRecentProjectsList(AnActionEvent e) {
|
||||
final DefaultListModel model = getDataModel(e);
|
||||
if (model != null) {
|
||||
model.clear();
|
||||
for (AnAction action : RecentProjectsManager.getInstance().getRecentProjectsActions(false, FlatWelcomeFrame.isUseProjectGroups())) {
|
||||
//noinspection unchecked
|
||||
model.addElement(action);
|
||||
}
|
||||
rebuildRecentProjectDataModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
public static void rebuildRecentProjectDataModel(@NotNull DefaultListModel model) {
|
||||
model.clear();
|
||||
for (AnAction action : RecentProjectsManager.getInstance().getRecentProjectsActions(false, FlatWelcomeFrame.isUseProjectGroups())) {
|
||||
//noinspection unchecked
|
||||
model.addElement(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.impl.DelegateColorScheme;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.ex.*;
|
||||
@@ -58,54 +57,37 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, Disposable {
|
||||
|
||||
private static final Key<MyPanel> MY_PANEL_PROPERTY = Key.create("EditorTextFieldCellRenderer.MyEditorPanel");
|
||||
private static final Key<RendererComponent> MY_PANEL_PROPERTY = Key.create("EditorTextFieldCellRenderer.MyEditorPanel");
|
||||
|
||||
private final Project myProject;
|
||||
private final FileType myFileType;
|
||||
private final boolean myInheritFontFromLaF;
|
||||
|
||||
protected EditorTextFieldCellRenderer(@Nullable Project project, @NotNull Disposable parent) {
|
||||
this(project, true, parent);
|
||||
protected EditorTextFieldCellRenderer(@Nullable Project project, @Nullable FileType fileType, @NotNull Disposable parent) {
|
||||
this(project, fileType, true, parent);
|
||||
}
|
||||
|
||||
protected EditorTextFieldCellRenderer(@Nullable Project project, boolean inheritFontFromLaF, @NotNull Disposable parent) {
|
||||
protected EditorTextFieldCellRenderer(@Nullable Project project, @Nullable FileType fileType,
|
||||
boolean inheritFontFromLaF, @NotNull Disposable parent) {
|
||||
myProject = project;
|
||||
myFileType = fileType;
|
||||
myInheritFontFromLaF = inheritFontFromLaF;
|
||||
Disposer.register(parent, this);
|
||||
}
|
||||
|
||||
protected abstract String getText(JTable table, Object value, int row, int column);
|
||||
|
||||
@Nullable
|
||||
protected TextAttributes getTextAttributes(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Color getCellBackground(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
|
||||
return UIUtil.getTableBackground(selected);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected FileType getFileType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected EditorColorsScheme getColorScheme() {
|
||||
return EditorColorsManager.getInstance().getGlobalScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
|
||||
MyPanel panel = getEditorPanel(table);
|
||||
EditorEx editor = panel.myEditor;
|
||||
RendererComponent panel = getEditorPanel(table);
|
||||
EditorEx editor = panel.getEditor();
|
||||
editor.getColorsScheme().setEditorFontSize(table.getFont().getSize());
|
||||
String text = getText(table, value, row, column);
|
||||
TextAttributes textAttributes = getTextAttributes(table, value, selected, focused, row, column);
|
||||
panel.setText(text, textAttributes, selected);
|
||||
panel.setText(text, null, selected);
|
||||
|
||||
editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground());
|
||||
editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground());
|
||||
editor.setBackgroundColor(getCellBackground(table, value, selected, focused, row, column));
|
||||
editor.setBackgroundColor(selected ? table.getSelectionBackground() : table.getBackground());
|
||||
panel.setOpaque(!Comparing.equal(editor.getBackgroundColor(), table.getBackground()));
|
||||
|
||||
panel.setBorder(null); // prevents double border painting when ExtendedItemRendererComponentWrapper is used
|
||||
@@ -114,29 +96,15 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private MyPanel getEditorPanel(final JTable table) {
|
||||
MyPanel panel = UIUtil.getClientProperty(table, MY_PANEL_PROPERTY);
|
||||
private RendererComponent getEditorPanel(final JTable table) {
|
||||
RendererComponent panel = UIUtil.getClientProperty(table, MY_PANEL_PROPERTY);
|
||||
if (panel != null) {
|
||||
DelegateColorScheme scheme = (DelegateColorScheme)panel.myEditor.getColorsScheme();
|
||||
scheme.setDelegate(getColorScheme());
|
||||
scheme.setDelegate(EditorColorsManager.getInstance().getGlobalScheme());
|
||||
return panel;
|
||||
}
|
||||
|
||||
FileType fileType = ObjectUtils.notNull(getFileType(), FileTypes.PLAIN_TEXT);
|
||||
EditorTextField field = new EditorTextField(new MyDocument(), myProject, fileType, false, false);
|
||||
field.setSupplementary(true);
|
||||
field.setFontInheritedFromLAF(myInheritFontFromLaF);
|
||||
field.addNotify(); // creates editor
|
||||
|
||||
EditorEx editor = (EditorEx)ObjectUtils.assertNotNull(field.getEditor());
|
||||
editor.setRendererMode(true);
|
||||
|
||||
editor.setColorsScheme(editor.createBoundColorSchemeDelegate(null));
|
||||
editor.getSettings().setCaretRowShown(false);
|
||||
|
||||
editor.getScrollPane().setBorder(null);
|
||||
|
||||
panel = new MyPanel(editor);
|
||||
panel = new RendererComponent(myProject, myFileType, myInheritFontFromLaF);
|
||||
Disposer.register(this, panel);
|
||||
Disposer.register(this, new Disposable() {
|
||||
@Override
|
||||
@@ -153,7 +121,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
private static class MyPanel extends CellRendererPanel implements Disposable {
|
||||
public static class RendererComponent extends CellRendererPanel implements Disposable {
|
||||
private static final char ABBREVIATION_SUFFIX = '\u2026'; // 2026 '...'
|
||||
private static final char RETURN_SYMBOL = '\u23ce';
|
||||
|
||||
@@ -165,9 +133,13 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
|
||||
private TextAttributes myTextAttributes;
|
||||
private boolean mySelected;
|
||||
|
||||
public MyPanel(EditorEx editor) {
|
||||
add(editor.getContentComponent());
|
||||
this.myEditor = editor;
|
||||
public RendererComponent(Project project, @Nullable FileType fileType, boolean inheritFontFromLaF) {
|
||||
myEditor = createEditor(project, fileType, inheritFontFromLaF);
|
||||
add(myEditor.getContentComponent());
|
||||
}
|
||||
|
||||
public EditorEx getEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,14 +172,6 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
if (getBorder() == null || !myEditor.getContentComponent().isOpaque()) return;
|
||||
|
||||
Color oldColor = g.getColor();
|
||||
g.setColor(myEditor.getBackgroundColor());
|
||||
Insets insets = getInsets();
|
||||
g.fillRect(0, 0, insets.left, getHeight());
|
||||
g.fillRect(getWidth() - insets.left - insets.right, 0, getWidth(), getHeight());
|
||||
g.setColor(oldColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -325,6 +289,25 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
|
||||
|
||||
return abbrLength;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static EditorEx createEditor(Project project, @Nullable FileType fileType, boolean inheritFontFromLaF) {
|
||||
fileType = ObjectUtils.notNull(fileType, FileTypes.PLAIN_TEXT);
|
||||
EditorTextField field = new EditorTextField(new MyDocument(), project, fileType, false, false);
|
||||
field.setSupplementary(true);
|
||||
field.setFontInheritedFromLAF(inheritFontFromLaF);
|
||||
field.addNotify(); // creates editor
|
||||
|
||||
EditorEx editor = (EditorEx)ObjectUtils.assertNotNull(field.getEditor());
|
||||
editor.setRendererMode(true);
|
||||
|
||||
editor.setColorsScheme(editor.createBoundColorSchemeDelegate(null));
|
||||
editor.getSettings().setCaretRowShown(false);
|
||||
|
||||
editor.getScrollPane().setBorder(null);
|
||||
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyDocument extends UserDataHolderBase implements DocumentEx {
|
||||
|
||||
+3
-24
@@ -16,18 +16,17 @@
|
||||
package com.intellij.util.ui.table;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.ui.EditorTextFieldCellRenderer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class EditorTextFieldJBTableRowRenderer extends EditorTextFieldCellRenderer implements JBTableRowRenderer {
|
||||
protected EditorTextFieldJBTableRowRenderer(@Nullable Project project, @NotNull Disposable parent) {
|
||||
super(project, parent);
|
||||
protected EditorTextFieldJBTableRowRenderer(@Nullable Project project, @Nullable FileType fileType, @NotNull Disposable parent) {
|
||||
super(project, fileType, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,25 +39,5 @@ public abstract class EditorTextFieldJBTableRowRenderer extends EditorTextFieldC
|
||||
return getText(table, row);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Color getCellBackground(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
|
||||
return getRowBackground(table, selected, focused, row);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected final TextAttributes getTextAttributes(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
|
||||
return getTextAttributes(table, row);
|
||||
}
|
||||
|
||||
protected abstract String getText(JTable table, int row);
|
||||
|
||||
@Nullable
|
||||
protected TextAttributes getTextAttributes(JTable table, int row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Color getRowBackground(JTable table, boolean selected, boolean focused, int row) {
|
||||
return super.getCellBackground(table, null, selected, focused, row, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@
|
||||
</group>
|
||||
|
||||
<group id="WelcomeScreenRecentProjectActionGroup">
|
||||
<action id="WelcomeScreen.OpenSelected" class="com.intellij.openapi.wm.impl.welcomeScreen.OpenSelectedProjectsAction"/>
|
||||
<action id="WelcomeScreen.OpenSelected" class="com.intellij.openapi.wm.impl.welcomeScreen.OpenSelectedProjectsAction" text="Open Selected"/>
|
||||
<action id="WelcomeScreen.NewGroup" class="com.intellij.openapi.wm.impl.welcomeScreen.CreateNewProjectGroupAction" text="New Project Group"/>
|
||||
<group id="WelcomeScreen.MoveToGroup" class="com.intellij.openapi.wm.impl.welcomeScreen.MoveProjectToGroupActionGroup" text="Move To Group" popup="true"/>
|
||||
</group>
|
||||
|
||||
+7
-2
@@ -28,6 +28,7 @@ import com.intellij.openapi.keymap.impl.ShortcutRestrictions;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.picocontainer.MutablePicoContainer;
|
||||
@@ -208,6 +209,8 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase {
|
||||
|
||||
public void testPresentation() {
|
||||
ActionManager manager = ActionManager.getInstance();
|
||||
|
||||
List<String> failures = new SmartList<String>();
|
||||
for (String id : manager.getActionIds("")) {
|
||||
if (!ACTION_WITHOUT_TEXT_AND_DESCRIPTION.equals(id)) {
|
||||
try {
|
||||
@@ -224,8 +227,8 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase {
|
||||
if (action instanceof ActionGroup) {
|
||||
System.out.println("ignored action group: " + message);
|
||||
}
|
||||
else {
|
||||
assertFalse("no text: " + message, StringUtil.isEmpty(action.getTemplatePresentation().getText()));
|
||||
else if (StringUtil.isEmpty(action.getTemplatePresentation().getText())) {
|
||||
failures.add("no text: " + message);
|
||||
}
|
||||
}
|
||||
catch (PluginException exception) {
|
||||
@@ -233,6 +236,8 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertEmpty(failures);
|
||||
}
|
||||
|
||||
private static void checkPresentationProperty(String name, String message, Object expected, Object actual) {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.debugger;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -6,7 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface MemberFilter {
|
||||
boolean isMemberVisible(@NotNull Variable variable, boolean filterFunctions);
|
||||
boolean isMemberVisible(@NotNull Variable variable);
|
||||
|
||||
@NotNull
|
||||
Collection<Variable> getAdditionalVariables();
|
||||
|
||||
+16
-1
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.debugger;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -8,7 +23,7 @@ import java.util.Collections;
|
||||
|
||||
public abstract class MemberFilterBase implements MemberFilter {
|
||||
@Override
|
||||
public boolean isMemberVisible(@NotNull Variable variable, boolean filterFunctions) {
|
||||
public boolean isMemberVisible(@NotNull Variable variable) {
|
||||
return variable.isReadable();
|
||||
}
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ public final class VariableView extends XNamedValue implements VariableContext {
|
||||
}
|
||||
|
||||
private void computeArrayRanges(@NotNull List<Variable> properties, @NotNull XCompositeNode node) {
|
||||
final List<Variable> variables = Variables.filterAndSort(properties, memberFilter, false);
|
||||
final List<Variable> variables = Variables.filterAndSort(properties, memberFilter);
|
||||
int count = variables.size();
|
||||
int bucketSize = XCompositeNode.MAX_CHILDREN_TO_SHOW;
|
||||
if (count <= bucketSize) {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.debugger;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -65,7 +80,7 @@ public final class Variables {
|
||||
List<Variable> properties = new ArrayList<Variable>(variables.size() + additionalVariables.size());
|
||||
List<Variable> functions = new SmartList<Variable>();
|
||||
for (Variable variable : variables) {
|
||||
if (memberFilter.isMemberVisible(variable, false)) {
|
||||
if (memberFilter.isMemberVisible(variable)) {
|
||||
Value value = variable.getValue();
|
||||
if (value != null &&
|
||||
value.getType() == ValueType.FUNCTION &&
|
||||
@@ -112,7 +127,7 @@ public final class Variables {
|
||||
@NotNull MemberFilter memberFilter,
|
||||
int maxChildrenToAdd,
|
||||
boolean defaultIsLast) {
|
||||
List<Variable> list = filterAndSort(variables, memberFilter, true);
|
||||
List<Variable> list = filterAndSort(variables, memberFilter);
|
||||
if (list.isEmpty()) {
|
||||
if (defaultIsLast) {
|
||||
node.addChildren(XValueChildrenList.EMPTY, true);
|
||||
@@ -133,7 +148,7 @@ public final class Variables {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<Variable> filterAndSort(@NotNull List<Variable> variables, @NotNull MemberFilter memberFilter, boolean filterFunctions) {
|
||||
public static List<Variable> filterAndSort(@NotNull List<Variable> variables, @NotNull MemberFilter memberFilter) {
|
||||
if (variables.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -141,7 +156,7 @@ public final class Variables {
|
||||
Collection<Variable> additionalVariables = memberFilter.getAdditionalVariables();
|
||||
List<Variable> result = new ArrayList<Variable>(variables.size() + additionalVariables.size());
|
||||
for (Variable variable : variables) {
|
||||
if (memberFilter.isMemberVisible(variable, filterFunctions)) {
|
||||
if (memberFilter.isMemberVisible(variable)) {
|
||||
result.add(variable);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -52,6 +52,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
private final String myTestFrameworkName;
|
||||
private boolean myIsTestingFinished;
|
||||
private TestLocationProvider myLocator = null;
|
||||
private boolean myTreeBuildBeforeStart = false;
|
||||
|
||||
public GeneralToSMTRunnerEventsConvertor(@NotNull final SMTestProxy.SMRootTestProxy testsRootNode,
|
||||
@NotNull final String testFrameworkName) {
|
||||
@@ -117,6 +118,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
|
||||
@Override
|
||||
public void onSuiteTreeNodeAdded(final String testName, final String locationHint) {
|
||||
myTreeBuildBeforeStart = true;
|
||||
addToInvokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -132,6 +134,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
|
||||
@Override
|
||||
public void onSuiteTreeStarted(final String suiteName, final String locationHint) {
|
||||
myTreeBuildBeforeStart = true;
|
||||
addToInvokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -229,10 +232,12 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
});
|
||||
}
|
||||
|
||||
private static SMTestProxy findChildByName(SMTestProxy parentSuite, String fullName) {
|
||||
for (SMTestProxy proxy : parentSuite.getChildren()) {
|
||||
if (fullName.equals(proxy.getName())) {
|
||||
return proxy;
|
||||
private SMTestProxy findChildByName(SMTestProxy parentSuite, String fullName) {
|
||||
if (myTreeBuildBeforeStart) {
|
||||
for (SMTestProxy proxy : parentSuite.getChildren()) {
|
||||
if (fullName.equals(proxy.getName())) {
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
+7
@@ -37,9 +37,11 @@ import com.intellij.util.config.ToggleBooleanProperty;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -195,4 +197,9 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp
|
||||
Icon icon = AllIcons.RunConfigurations.IncludeNonStartedTests_Rerun;
|
||||
return new ToggleBooleanProperty(text, null, icon, this, INCLUDE_NON_STARTED_IN_RERUN_FAILED);
|
||||
}
|
||||
|
||||
@JdkConstants.TreeSelectionMode
|
||||
protected int getSelectionMode() {
|
||||
return TreeSelectionModel.SINGLE_TREE_SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
package com.intellij.execution.testframework;
|
||||
|
||||
import com.intellij.execution.Location;
|
||||
import com.intellij.execution.testframework.actions.ViewAssertEqualsDiffAction;
|
||||
import com.intellij.ide.CopyProvider;
|
||||
import com.intellij.ide.actions.CopyReferenceAction;
|
||||
import com.intellij.openapi.Disposable;
|
||||
@@ -35,12 +34,14 @@ import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.EditSourceOnDoubleClickHandler;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.plaf.TreeUI;
|
||||
import javax.swing.tree.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -68,7 +69,7 @@ public abstract class TestTreeView extends Tree implements DataProvider, CopyPro
|
||||
|
||||
public void attachToModel(final TestFrameworkRunningModel model) {
|
||||
setModel(new DefaultTreeModel(new DefaultMutableTreeNode(model.getRoot())));
|
||||
getSelectionModel().setSelectionMode(getSelectionMode());
|
||||
getSelectionModel().setSelectionMode(model.getProperties().getSelectionMode());
|
||||
myModel = model;
|
||||
Disposer.register(myModel, myModel.getRoot());
|
||||
Disposer.register(myModel, new Disposable() {
|
||||
@@ -169,9 +170,4 @@ public abstract class TestTreeView extends Tree implements DataProvider, CopyPro
|
||||
TreeUtil.installActions(this);
|
||||
PopupHandler.installPopupHandler(this, IdeActions.GROUP_TESTTREE_POPUP, ActionPlaces.TESTTREE_VIEW_POPUP);
|
||||
}
|
||||
|
||||
@JdkConstants.TreeSelectionMode
|
||||
protected int getSelectionMode() {
|
||||
return TreeSelectionModel.SINGLE_TREE_SELECTION;
|
||||
}
|
||||
}
|
||||
@@ -575,3 +575,6 @@ search.everywhere.pattern.checking.description=Avoid searching classes and symbo
|
||||
idea.concurrent.scanning.files.to.index=true
|
||||
welcome.screen.project.grouping.enabled=true
|
||||
welcome.screen.project.grouping.enabled.description=Allows to group recent projects
|
||||
|
||||
custom.folding.max.lookup.depth=50
|
||||
custom.folding.max.lookup.depth.description=Max lookup depth for custom folding comments in a PSI tree.
|
||||
@@ -21,6 +21,7 @@ import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.containers.WeakList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.management.ListenerNotFoundException;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationEmitter;
|
||||
import javax.management.NotificationListener;
|
||||
@@ -66,6 +67,21 @@ public class LowMemoryWatcher {
|
||||
}
|
||||
}
|
||||
};
|
||||
private static final NotificationListener ourLowMemoryListener = new NotificationListener() {
|
||||
@Override
|
||||
public void handleNotification(Notification n, Object hb) {
|
||||
if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(n.getType()) ||
|
||||
MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(n.getType())) {
|
||||
synchronized (ourJanitor) {
|
||||
if (!ourSubmitted) {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
ourSubmitted = true;
|
||||
ourExecutor.submit(ourJanitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable myRunnable;
|
||||
|
||||
@@ -79,20 +95,7 @@ public class LowMemoryWatcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
((NotificationEmitter)ManagementFactory.getMemoryMXBean()).addNotificationListener(new NotificationListener() {
|
||||
@Override
|
||||
public void handleNotification(Notification n, Object hb) {
|
||||
if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(n.getType()) || MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(n.getType())) {
|
||||
synchronized (ourJanitor) {
|
||||
if (!ourSubmitted) {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
ourSubmitted = true;
|
||||
ourExecutor.submit(ourJanitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null, null);
|
||||
((NotificationEmitter)ManagementFactory.getMemoryMXBean()).addNotificationListener(ourLowMemoryListener, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,6 +138,12 @@ public class LowMemoryWatcher {
|
||||
public static void stopAll() {
|
||||
ourExecutor.shutdown();
|
||||
ourInstances.clear();
|
||||
try {
|
||||
((NotificationEmitter)ManagementFactory.getMemoryMXBean()).removeNotificationListener(ourLowMemoryListener);
|
||||
}
|
||||
catch (ListenerNotFoundException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1503,14 +1503,13 @@ public class StringUtil extends StringUtilRt {
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips quotes around the value.
|
||||
* Quotes are removed even if leading and trailing quotes are different or if there is only one quote (leading or trailing).
|
||||
* @deprecated use {@link com.intellij.openapi.util.text.StringUtil#unquoteString(String)} instead
|
||||
* To be removed in IDEA 17
|
||||
* Consider using {@link StringUtil#unquoteString(String)} instead.
|
||||
* Note: this method has an odd behavior:
|
||||
* Quotes are removed even if leading and trailing quotes are different or
|
||||
* if there is only one quote (leading or trailing).
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
@Deprecated
|
||||
public static String stripQuotesAroundValue(@NotNull String text) {
|
||||
final int len = text.length();
|
||||
if (len > 0) {
|
||||
|
||||
@@ -314,13 +314,16 @@ public class UIUtil {
|
||||
}
|
||||
|
||||
try {
|
||||
isRetina = (getScaleFactorMethod == null) || ((Integer)getScaleFactorMethod.invoke(device) != 1);
|
||||
isRetina = getScaleFactorMethod == null || (Integer)getScaleFactorMethod.invoke(device) != 1;
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG.debug("CGraphicsDevice.getScaleFactor(): Access issue");
|
||||
isRetina = false;
|
||||
} catch (InvocationTargetException e) {
|
||||
LOG.debug("CGraphicsDevice.getScaleFactor(): Invocation issue");
|
||||
isRetina = false;
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.debug("object is not an instance of declaring class: " + device.getClass().getName());
|
||||
isRetina = false;
|
||||
}
|
||||
|
||||
devicesToRetinaSupportCacheMap.put(device, isRetina);
|
||||
@@ -1783,7 +1786,7 @@ public class UIUtil {
|
||||
}
|
||||
|
||||
public static BufferedImage createImageForGraphics(Graphics2D g, int width, int height, int type) {
|
||||
if (DetectRetinaKit.isMacRetina(g)) {
|
||||
if (isRetina(g)) {
|
||||
return RetinaImage.create(width, height, type);
|
||||
}
|
||||
//noinspection UndesirableClassUsage
|
||||
|
||||
+12
-5
@@ -1,5 +1,7 @@
|
||||
package com.intellij.openapi.vcs.changes.actions.diff;
|
||||
|
||||
import com.intellij.diff.actions.impl.GoToChangePopupBuilder;
|
||||
import com.intellij.diff.chains.DiffRequestChain;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -7,12 +9,11 @@ import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.diff.actions.impl.GoToChangePopupBuilder;
|
||||
import com.intellij.diff.chains.DiffRequestChain;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.update.UiNotifyConnector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -68,16 +69,22 @@ public abstract class ChangeGoToChangePopupAction<Chain extends DiffRequestChain
|
||||
//
|
||||
|
||||
private class MyChangesBrowser extends ChangesBrowser implements Runnable {
|
||||
@NotNull Ref<JBPopup> myPopup;
|
||||
@NotNull private final Ref<JBPopup> myPopup;
|
||||
|
||||
public MyChangesBrowser(@NotNull Project project,
|
||||
@NotNull List<Change> changes,
|
||||
@Nullable Change currentChange,
|
||||
@Nullable final Change currentChange,
|
||||
@NotNull Ref<JBPopup> popup) {
|
||||
super(project, null, changes, null, false, false, null, MyUseCase.LOCAL_CHANGES, null);
|
||||
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
setChangesToDisplay(changes);
|
||||
if (currentChange != null) select(Collections.singletonList(currentChange));
|
||||
|
||||
UiNotifyConnector.doWhenFirstShown(this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (currentChange != null) select(Collections.singletonList(currentChange));
|
||||
}
|
||||
});
|
||||
|
||||
myPopup = popup;
|
||||
}
|
||||
|
||||
+44
-33
@@ -48,14 +48,7 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
if (paths != null) {
|
||||
for (TreePath path : paths) {
|
||||
Object node = path.getLastPathComponent();
|
||||
if (node instanceof XValueNodeImpl) {
|
||||
if (((XValueNodeImpl)node).isComputed()) {
|
||||
e.getPresentation().setEnabled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (node instanceof WatchMessageNode) {
|
||||
e.getPresentation().setEnabled(true);
|
||||
if (isEnabled(e, node)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -63,8 +56,22 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
e.getPresentation().setEnabled(false);
|
||||
}
|
||||
|
||||
protected boolean isEnabled(@NotNull AnActionEvent event, @NotNull Object node) {
|
||||
if (node instanceof XValueNodeImpl) {
|
||||
if (((XValueNodeImpl)node).isComputed()) {
|
||||
event.getPresentation().setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (node instanceof WatchMessageNode) {
|
||||
event.getPresentation().setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull final AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
TreePath[] paths = getSelectedNodes(e.getDataContext());
|
||||
if (paths == null) {
|
||||
return;
|
||||
@@ -72,28 +79,31 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
|
||||
ValueCollector valueCollector = createCollector(e);
|
||||
for (TreePath path : paths) {
|
||||
Object node = path.getLastPathComponent();
|
||||
if (node instanceof XValueNodeImpl) {
|
||||
XValueNodeImpl valueNode = (XValueNodeImpl)node;
|
||||
XFullValueEvaluator fullValueEvaluator = valueNode.getFullValueEvaluator();
|
||||
if (paths.length > 1) { // multiselection - copy the whole node text, see IDEA-136722
|
||||
valueCollector.add(valueNode.getText().toString(), valueNode.getPath().getPathCount());
|
||||
}
|
||||
else {
|
||||
if (fullValueEvaluator == null || !fullValueEvaluator.isShowValuePopup()) {
|
||||
valueCollector.add(StringUtil.notNullize(DebuggerUIUtil.getNodeRawValue(valueNode)));
|
||||
}
|
||||
else {
|
||||
new CopyValueEvaluationCallback(valueNode, valueCollector).startFetchingValue(fullValueEvaluator);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof WatchMessageNode) {
|
||||
valueCollector.add(((WatchMessageNode)node).getExpression().getExpression());
|
||||
}
|
||||
addToCollector(paths, path.getLastPathComponent(), valueCollector);
|
||||
}
|
||||
valueCollector.processed = true;
|
||||
valueCollector.finish(e.getProject());
|
||||
valueCollector.finish();
|
||||
}
|
||||
|
||||
protected void addToCollector(@NotNull TreePath[] paths, @NotNull Object node, @NotNull ValueCollector valueCollector) {
|
||||
if (node instanceof XValueNodeImpl) {
|
||||
XValueNodeImpl valueNode = (XValueNodeImpl)node;
|
||||
XFullValueEvaluator fullValueEvaluator = valueNode.getFullValueEvaluator();
|
||||
if (paths.length > 1) { // multiselection - copy the whole node text, see IDEA-136722
|
||||
valueCollector.add(valueNode.getText().toString(), valueNode.getPath().getPathCount());
|
||||
}
|
||||
else {
|
||||
if (fullValueEvaluator == null || !fullValueEvaluator.isShowValuePopup()) {
|
||||
valueCollector.add(StringUtil.notNullize(DebuggerUIUtil.getNodeRawValue(valueNode)));
|
||||
}
|
||||
else {
|
||||
new CopyValueEvaluationCallback(valueNode, valueCollector).startFetchingValue(fullValueEvaluator);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof WatchMessageNode) {
|
||||
valueCollector.add(((WatchMessageNode)node).getExpression().getExpression());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -120,7 +130,8 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
indents.put(values.size() - 1, indent);
|
||||
}
|
||||
|
||||
public void finish(Project project) {
|
||||
public void finish() {
|
||||
Project project = myTree.getProject();
|
||||
if (processed && !values.contains(null) && !project.isDisposed()) {
|
||||
int minIndent = Integer.MAX_VALUE;
|
||||
for (int indent : indents.getValues()) {
|
||||
@@ -151,12 +162,12 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void evaluationComplete(final int index, @NotNull final String value, final Project project) {
|
||||
public void evaluationComplete(final int index, @NotNull final String value) {
|
||||
AppUIUtil.invokeOnEdt(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
values.set(index, value);
|
||||
finish(project);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -177,7 +188,7 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
|
||||
@Override
|
||||
protected void evaluationComplete(@NotNull String value, @NotNull Project project) {
|
||||
myValueCollector.evaluationComplete(myValueIndex, value, project);
|
||||
myValueCollector.evaluationComplete(myValueIndex, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +149,9 @@
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ArrayHashCode" bundle="com.siyeh.InspectionGadgetsBundle" key="array.hash.code.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.ArrayHashCodeInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ArrayObjectsEquals" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="array.objects.equals.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs"
|
||||
enabledByDefault="true" level="WARNING" implementationClass="com.siyeh.ig.bugs.ArrayObjectsEqualsInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="AssertWithSideEffects" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="assert.with.side.effects.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
|
||||
|
||||
+4
-1
@@ -2154,4 +2154,7 @@ dangling.javadoc.convert.quickfix=Replace with block comment
|
||||
dangling.javadoc.delete.quickfix=Remove dangling comment
|
||||
equals.replaceable.by.objects.call.display.name='equals()' expression replaceable by 'Objects.equals()' expression
|
||||
equals.replaceable.by.objects.call.problem.descriptor=<code>#ref</code> replaceable by 'Objects.equals()' expression #loc
|
||||
equals.replaceable.by.objects.call.quickfix=Replace with 'Objects.equals()' expression
|
||||
equals.replaceable.by.objects.call.quickfix=Replace with 'Objects.equals()' expression
|
||||
array.objects.equals.display.name='Objects.equals()' called on arrays
|
||||
array.objects.equals.problem.descriptor=<code>Objects.#ref()</code> on arrays should probably be 'Arrays.equals()' #loc
|
||||
array.objects.deep.equals.problem.descriptor=<code>Objects.#ref()</code> on arrays should probably be 'Arrays.deepEquals()' #loc
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2011-2015 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,7 +79,7 @@ public class ArrayEqualityInspection extends BaseInspection {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Replace with implicit equals";
|
||||
return InspectionGadgetsBundle.message("replace.with.arrays.equals");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.HardcodedMethodConstants;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ArrayObjectsEqualsInspection extends BaseInspection {
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message("array.objects.equals.display.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String buildErrorString(Object... infos) {
|
||||
final boolean deep = ((Boolean)infos[0]).booleanValue();
|
||||
return deep
|
||||
? InspectionGadgetsBundle.message("array.objects.deep.equals.problem.descriptor")
|
||||
: InspectionGadgetsBundle.message("array.objects.equals.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
final boolean deep = ((Boolean)infos[0]).booleanValue();
|
||||
return new ArrayObjectsEqualsFix(deep);
|
||||
}
|
||||
|
||||
private static class ArrayObjectsEqualsFix extends InspectionGadgetsFix {
|
||||
|
||||
private final boolean myDeep;
|
||||
|
||||
public ArrayObjectsEqualsFix(boolean deep) {
|
||||
myDeep = deep;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myDeep ?
|
||||
InspectionGadgetsBundle.message("replace.with.arrays.deep.equals") :
|
||||
InspectionGadgetsBundle.message("replace.with.arrays.equals");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("replace.with.arrays.equals");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement().getParent().getParent();
|
||||
if (!(element instanceof PsiMethodCallExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
|
||||
final StringBuilder newExpression = new StringBuilder("java.util.Arrays.");
|
||||
if (myDeep) {
|
||||
newExpression.append("deepEquals");
|
||||
}
|
||||
else {
|
||||
newExpression.append("equals");
|
||||
}
|
||||
newExpression.append(methodCallExpression.getArgumentList().getText());
|
||||
PsiReplacementUtil.replaceExpressionAndShorten(methodCallExpression, newExpression.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new ArrayObjectsEqualsVisitor();
|
||||
}
|
||||
|
||||
private static class ArrayObjectsEqualsVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (!HardcodedMethodConstants.EQUALS.equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
if (expressions.length != 2) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression argument1 = expressions[0];
|
||||
final PsiType type1 = argument1.getType();
|
||||
if (!(type1 instanceof PsiArrayType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression argument2 = expressions[1];
|
||||
final PsiType type2 = argument2.getType();
|
||||
if (!(type2 instanceof PsiArrayType)) {
|
||||
return;
|
||||
}
|
||||
final int dimensions = type1.getArrayDimensions();
|
||||
if (dimensions != type2.getArrayDimensions()) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null || !"java.util.Objects".equals(containingClass.getQualifiedName())) {
|
||||
return;
|
||||
}
|
||||
registerMethodCallError(expression, Boolean.valueOf(dimensions > 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any use of <b>==</b> to test for Array equality,
|
||||
rather than the <b>"java.util.Arrays.equals()"</b> method.
|
||||
Reports any use of <b>==</b> or <b>!=</b> to test for array equality,
|
||||
rather than the <b>java.util.Arrays.equals()</b> method.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports <b>java.util.Objects.equals()</b> called on two arrays.
|
||||
Calling <b>java.util.Objects.equals()</b> with array arguments compares identity and is equivalent to using <b>==</b>.
|
||||
Use <b>Arrays.equals()</b> to compare the contents of two arrays
|
||||
or <b>Arrays.deepEquals()</b> to compare the contents of two multi-dimensional arrays.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
<small>New in 15</small>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any use of <b>==</b> to test for Number equality,
|
||||
rather than the <b>".equals()"</b> method. With auto-boxing it is easy
|
||||
Reports any use of <b>==</b> or <b>!=</b> to test for Number equality,
|
||||
rather than the <b>equals()</b> method. With auto-boxing it is easy
|
||||
to make the mistake of comparing two Integer (or other subclass of java.lang.Number) objects instead
|
||||
of two ints.
|
||||
<!-- tooltip end -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any use of <b>==</b>
|
||||
to test for Object equality, rather than the <b>".equals()"</b> method.
|
||||
Reports any use of <b>==</b> or <b>!=</b>
|
||||
to test for Object equality, rather than the <b>equals()</b> method.
|
||||
Note that comparison of Strings or Numbers using <b>==</b> is not reported by this
|
||||
inspection, nor is the comparison of an object to <b>null</b> using
|
||||
<b>==</b>, or the comparison of two array objects.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any use of <b>==</b> to test for String equality,
|
||||
rather than the <b>".equals()"</b> method.
|
||||
Reports any use of <b>==</b> or <b>!=</b> to test for String equality,
|
||||
rather than the <b>equals()</b> method.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
class ArrayObjectsEquals {
|
||||
|
||||
boolean one(String[] ss1, String[] ss2) {
|
||||
return java.util.Objects.<warning descr="'Objects.equals()' on arrays should probably be 'Arrays.equals()'">equals</warning>(ss1, ss2);
|
||||
}
|
||||
|
||||
boolean two(String[][] ss1, String[][] ss2) {
|
||||
return java.util.Objects.<warning descr="'Objects.equals()' on arrays should probably be 'Arrays.deepEquals()'">equals</warning>(ss1, ss2);
|
||||
}
|
||||
|
||||
boolean noWarn(String s1, String[] ss2) {
|
||||
return java.util.Objects.equals(s1, ss2);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ArrayObjectsEqualsInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void testArrayObjectsEquals() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new ArrayObjectsEqualsInspection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getEnvironmentClasses() {
|
||||
return new String[]{
|
||||
"package java.util;" +
|
||||
"public class Objects {" +
|
||||
" public static boolean equals(Object a, Object b) {" +
|
||||
" return (a == b) || (a != null && a.equals(b));" +
|
||||
" }" +
|
||||
"}"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class LineEndingsManager extends FileDocumentManagerAdapter {
|
||||
@Override
|
||||
public void run() {
|
||||
IdeFrame frame = WindowManager.getInstance().getIdeFrame(myProject);
|
||||
StatusBar statusBar = frame.getStatusBar();
|
||||
StatusBar statusBar = frame != null ? frame.getStatusBar() : null;
|
||||
StatusBarWidget widget = statusBar != null ? statusBar.getWidget("LineSeparator") : null;
|
||||
|
||||
if (widget instanceof LineSeparatorPanel) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user