Merge remote-tracking branch 'origin/master'

This commit is contained in:
Nadya Zabrodina
2015-04-16 12:43:06 +04:00
153 changed files with 2336 additions and 795 deletions
+3
View File
@@ -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" />
+105
View File
@@ -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
View File
@@ -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;
}
@@ -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());
@@ -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);
}
@@ -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);
}
}
}
}
}
@@ -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]);
}
}
}
}
}
}
@@ -11,4 +11,6 @@ public enum NullabilityProblem {
nullableReturn,
passingNullableToNotNullParameter,
passingNullableArgumentToNonAnnotatedParameter,
passingNullToOptional,
passingNotNullToOptional
}
@@ -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));
}
@@ -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);
@@ -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),
@@ -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 ||
@@ -0,0 +1,6 @@
// "Replace with '.of()'" "true"
class A{
void test(){
com.google.common.base.Optional.of(1<caret>1);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.absent()'" "true"
class A{
void test(){
com.google.common.base.Optional.absent(<caret>);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.of()'" "true"
class A{
void test(){
java.util.Optional.of(1<caret>1);
}
}
@@ -0,0 +1,8 @@
// "Replace with '.of()'" "true"
class A{
void test(String s){
assert s != null;
java.util.Optional.of(<caret>s);
}
}
@@ -0,0 +1,7 @@
// "Replace with '.empty()'" "true"
class A {
void test() {
String s = null;
java.util.Optional.empty(<caret>);
}
}
@@ -0,0 +1,7 @@
// "Replace with '.empty()'" "true"
class A {
void test() {
String s = null;
java.util.Optional.empty(<caret>);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.of()'" "true"
class A{
void test(){
com.google.common.base.Optional.fromNullable(1<caret>1);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.absent()'" "true"
class A{
void test(){
com.google.common.base.Optional.fromNullable(n<caret>ull);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.of()'" "true"
class A{
void test(){
java.util.Optional.ofNullable(1<caret>1);
}
}
@@ -0,0 +1,8 @@
// "Replace with '.of()'" "true"
class A{
void test(String s){
assert s != null;
java.util.Optional.ofNullable(<caret>s);
}
}
@@ -0,0 +1,7 @@
// "Replace with '.empty()'" "true"
class A {
void test() {
String s = null;
java.util.Optional.ofNullable(n<caret>ull);
}
}
@@ -0,0 +1,7 @@
// "Replace with '.empty()'" "true"
class A {
void test() {
String s = null;
java.util.Optional.ofNullable(<caret>s);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.of()'" "false"
class A{
void test(String s){
java.util.Optional.ofNullable(<caret>s);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.fromNullable()'" "true"
class A{
void test(){
com.google.common.base.Optional.fromNullable(n<caret>ull);
}
}
@@ -0,0 +1,6 @@
// "Replace with '.fromNullable()'" "true"
class A{
void test(){
com.google.common.base.Optional.of(n<caret>ull);
}
}
@@ -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();
}
}
@@ -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());
@@ -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) {
@@ -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);
}
@@ -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);
}
}
@@ -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;
}
}
}
@@ -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.";
@@ -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;
@@ -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);
@@ -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 {
@@ -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>
@@ -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();
@@ -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);
}
}
@@ -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;
@@ -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
@@ -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;
}
@@ -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"
@@ -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
@@ -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
@@ -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>
@@ -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);
}
}
@@ -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