From d713d972769719b844247087fa82de30a2603e46 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 15 Mar 2012 15:55:43 +0400 Subject: [PATCH 01/18] IDEA-48825 Groovy: \u000a and \u000d sequences in String literal are green --- .../jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java | 2 ++ plugins/groovy/testdata/highlighting/IncorrectEscaping.groovy | 2 ++ 2 files changed, 4 insertions(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java index edb3b8798b1f..b7a948d5f302 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java @@ -741,6 +741,8 @@ public class GrStringUtil { if (index + 4 <= chars.length()) { try { int code = Integer.parseInt(chars.substring(index, index + 4), 16); + //line separators are invalid here + if (code == 0x000a || code == 0x000d) return false; c = chars.charAt(index); if (c == '+' || c == '-') return false; outChars.append((char)code); diff --git a/plugins/groovy/testdata/highlighting/IncorrectEscaping.groovy b/plugins/groovy/testdata/highlighting/IncorrectEscaping.groovy index f578bc6b9af4..bab3ad3a8d12 100644 --- a/plugins/groovy/testdata/highlighting/IncorrectEscaping.groovy +++ b/plugins/groovy/testdata/highlighting/IncorrectEscaping.groovy @@ -1,4 +1,6 @@ print '\n' +print '\u000a' +print "\u000d" print '\y' ptint "\n\a\t" print "\n\a${x}\t" From ca4a6e39d1b2b35cce2366a467329485fb192bfd Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 15 Mar 2012 16:23:37 +0400 Subject: [PATCH 02/18] IDEA-80213 Enable fragment editor for multiline strings --- .../lang/editor/GroovyLiteralCopyPasteProcessor.java | 6 ++---- .../plugins/groovy/lang/psi/util/GrStringUtil.java | 12 ++++++------ .../lang/resolve/GroovyStringLiteralManipulator.java | 7 ++++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java index 89c710f3ebbf..659c100a0058 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java @@ -157,13 +157,11 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce } if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) { - boolean escapeDoubleQuotes = !token.getText().contains("\"\"\""); - return GrStringUtil.escapeSymbolsForGString(s, escapeDoubleQuotes, false); + return GrStringUtil.escapeSymbolsForGString(s, !token.getText().contains("\"\"\""), false); } if (tokenType == mSTRING_LITERAL) { - boolean escapeQuotes = !token.getText().contains("'''"); - return GrStringUtil.escapeSymbolsForString(s, escapeQuotes, false); + return GrStringUtil.escapeSymbolsForString(s, !token.getText().contains("'''"), false); } return super.escapeCharCharacters(s, token); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java index b7a948d5f302..9658515a2ac7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java @@ -242,20 +242,20 @@ public class GrStringUtil { buffer.append(hexCode); } - public static String escapeSymbolsForGString(String s, boolean escapeDoubleQuotes, boolean forInjection) { + public static String escapeSymbolsForGString(String s, boolean isSingleLine, boolean forInjection) { StringBuilder b = new StringBuilder(); - escapeStringCharacters(s.length(), s, escapeDoubleQuotes ? "$\"" : "$", forInjection, true, b); + escapeStringCharacters(s.length(), s, isSingleLine ? "$\"" : "$", isSingleLine, true, b); if (!forInjection) { - unescapeCharacters(b, escapeDoubleQuotes ? "'" : "'\"", true); + unescapeCharacters(b, isSingleLine ? "'" : "'\"", true); } return b.toString(); } - public static String escapeSymbolsForString(String s, boolean escapeQuotes, boolean forInjection) { + public static String escapeSymbolsForString(String s, boolean isSingleLine, boolean forInjection) { final StringBuilder builder = new StringBuilder(); - escapeStringCharacters(s.length(), s, escapeQuotes ? "'" : "", forInjection, true, builder); + escapeStringCharacters(s.length(), s, isSingleLine ? "'" : "", isSingleLine, true, builder); if (!forInjection) { - unescapeCharacters(builder, escapeQuotes ? "$\"" : "$'\"", true); + unescapeCharacters(builder, isSingleLine ? "$\"" : "$'\"", true); } return builder.toString(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyStringLiteralManipulator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyStringLiteralManipulator.java index 0737a3e1aa64..67d975795cdc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyStringLiteralManipulator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyStringLiteralManipulator.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.resolve; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.AbstractElementManipulator; import com.intellij.util.IncorrectOperationException; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; @@ -36,10 +37,10 @@ public class GroovyStringLiteralManipulator extends AbstractElementManipulator Date: Thu, 15 Mar 2012 16:49:08 +0400 Subject: [PATCH 03/18] IDEA-82299 Groovy: Introduce Closure Parameter: selecting 'def' type for parameter of Closure type doesn't take effect --- .../extract/closure/ExtractClosureFromMethodProcessor.java | 3 ++- .../extract/closure/ExtractClosureHelperImpl.java | 6 +++++- .../parameter/GrIntroduceExpressionSettingsImpl.java | 2 +- .../introduce/parameter/GrIntroduceParameterDialog.java | 5 +++-- .../introduceParameter/ExtractClosureTest.groovy | 3 ++- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java index 16188752ecc5..3627c3b52566 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java @@ -274,7 +274,8 @@ public class ExtractClosureFromMethodProcessor extends ExtractClosureProcessorBa @NotNull @Override public PsiType getForcedType() { - return myHelper.getSelectedType(); + PsiType type = myHelper.getSelectedType(); + return type != null ? type : PsiType.getJavaLangObject(PsiManager.getInstance(myProject), GlobalSearchScope.allScope(myProject)); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java index b904ef7b5b5b..baa5dbd6d71d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java @@ -44,6 +44,7 @@ public class ExtractClosureHelperImpl extends ExtractInfoHelperBase implements G private final boolean myForceReturn; private PsiType myType = null; + private boolean myForceDef; public ExtractClosureHelperImpl(IntroduceParameterInfo info, String name, @@ -51,9 +52,10 @@ public class ExtractClosureHelperImpl extends ExtractInfoHelperBase implements G TIntArrayList toRemove, boolean generateDelegate, int replaceFieldsWithGetters, - boolean forceReturn) { + boolean forceReturn, boolean forceDef) { super(info); myForceReturn = forceReturn; + myForceDef = forceDef; myOwner = info.getToReplaceIn(); myToSearchFor = info.getToSearchFor(); myName = name; @@ -102,6 +104,8 @@ public class ExtractClosureHelperImpl extends ExtractInfoHelperBase implements G @Override public PsiType getSelectedType() { + if (myForceDef) return null; + if (myType == null) { final GrClosableBlock closure = ExtractClosureProcessorBase.generateClosure(this); PsiType type = closure.getType(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java index a93a26b3b02c..7fc90aa1101e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java @@ -39,7 +39,7 @@ public class GrIntroduceExpressionSettingsImpl extends ExtractClosureHelperImpl GrVariable var, PsiType selectedType, boolean forceReturn) { - super(info, name, declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, forceReturn); + super(info, name, declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, forceReturn, false); myExpr = expr; myVar = var; mySelectedType = selectedType; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java index 3d7fc2293e69..ad2c75a0f6c7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java @@ -325,7 +325,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntro @Nullable private PsiType inferClosureReturnType() { final ExtractClosureHelperImpl mockHelper = - new ExtractClosureHelperImpl(myInfo, "__test___n_", false, new TIntArrayList(), false, 0, false); + new ExtractClosureHelperImpl(myInfo, "__test___n_", false, new TIntArrayList(), false, 0, false, false); final PsiType returnType; final AccessToken token = WriteAction.start(); try { @@ -469,7 +469,8 @@ public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntro getParametersToRemove(), myDelegateViaOverloadingMethodCheckBox.isSelected(), getReplaceFieldsWithGetter(), - myForceReturnCheckBox.isSelected()); + myForceReturnCheckBox.isSelected(), + myTypeComboBox.getSelectedType() == null); if (toReplaceIn instanceof GrMethod) { invokeRefactoring(new ExtractClosureFromMethodProcessor(settings)); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy index 374dde1b4b45..911977c3a0e9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy @@ -46,7 +46,8 @@ public abstract class ExtractClosureTest extends LightGroovyTestCase { GrIntroduceParameterSettings helper = new ExtractClosureHelperImpl(info, "closure", false, new TIntArrayList(toRemove as int[]), false, - IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, forceReturn) + IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, + forceReturn, false) for (p in notToUseAsParams) { helper.parameterInfos[p].passAsParameter = false } From 95825980c78508b06ed165bad32402b4804ede1f Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 15 Mar 2012 16:56:07 +0400 Subject: [PATCH 04/18] IDEA-82814 Gradle: do not configure groovy library on a project import if it is already in the project dependencies 1. Refresh the internal structures after the intellij project structure changes implied by the import; 2. Don't perform 'startup refresh on project opening' after the import; --- .../importing/GradleModulesImporter.java | 33 ++++++++++--------- .../importing/GradleProjectImportBuilder.java | 5 +-- .../sync/GradleInitialProjectRefresher.java | 6 +++- .../plugins/gradle/util/GradleConstants.java | 2 ++ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java index 41c0725e5078..18d7dfe121b8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.config.GradleGroovyEnabler; import org.jetbrains.plugins.gradle.config.GradleSettings; import org.jetbrains.plugins.gradle.model.gradle.*; +import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel; import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask; import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleLog; @@ -318,6 +319,21 @@ public class GradleModulesImporter { finally { writeLock.finish(); } + final GradleSettings settings = GradleSettings.getInstance(intellijProject); + final String gradleHome = settings.getGradleHome(); + if (gradleHome != null) { + final GradleGroovyEnabler groovyEnabler = intellijProject.getComponent(GradleGroovyEnabler.class); + libraryToPreserve.set(groovyEnabler.setupGroovySdkIfNecessary(gradleHome)); + } + + // Force refresh the infrastructure in order to apply newly introduce intellij project structure changes + final GradleProjectStructureChangesModel changesModel = intellijProject.getComponent(GradleProjectStructureChangesModel.class); + if (changesModel != null) { + final GradleProject project = changesModel.getGradleProject(); + if (project != null) { + changesModel.update(project); + } + } } }; @@ -337,21 +353,8 @@ public class GradleModulesImporter { }); } }; - - Runnable setupGroovyTask = new Runnable() { - @Override - public void run() { - final GradleSettings settings = GradleSettings.getInstance(intellijProject); - final String gradleHome = settings.getGradleHome(); - if (gradleHome != null) { - final GradleGroovyEnabler groovyEnabler = intellijProject.getComponent(GradleGroovyEnabler.class); - libraryToPreserve.set(groovyEnabler.setupGroovySdkIfNecessary(gradleHome)); - } - resolveDependenciesTask.run(); - } - }; - - UIUtil.invokeLaterIfNeeded(setupGroovyTask); + + UIUtil.invokeLaterIfNeeded(resolveDependenciesTask); } private static void doSetupLibraries(@NotNull Map moduleMappings, diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java index fa12623f17ca..3c65acce4d9f 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java @@ -23,6 +23,7 @@ import org.jetbrains.plugins.gradle.model.gradle.GradleModule; import org.jetbrains.plugins.gradle.model.gradle.GradleProject; import org.jetbrains.plugins.gradle.ui.GradleIcons; import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; import javax.swing.*; @@ -78,8 +79,8 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder commit(final Project project, ModifiableModuleModel model, ModulesProvider modulesProvider, - ModifiableArtifactModel artifactModel) - { + ModifiableArtifactModel artifactModel) { + System.setProperty(GradleConstants.NEWLY_IMPORTED_PROJECT, Boolean.TRUE.toString()); final Runnable task = new Runnable() { @Override public void run() { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java index 7f0680d7b1f9..d1fd5d25b6b3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.sync; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; /** @@ -14,8 +15,11 @@ import org.jetbrains.plugins.gradle.util.GradleUtil; * @since 3/13/12 12:01 PM */ public class GradleInitialProjectRefresher implements StartupActivity { + @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") @Override public void runActivity(@NotNull Project project) { - GradleUtil.refreshProject(project); + if (!Boolean.getBoolean(GradleConstants.NEWLY_IMPORTED_PROJECT)) { + GradleUtil.refreshProject(project); + } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java index 4e7f2d577923..6f976c121c77 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java @@ -12,6 +12,8 @@ import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor; */ public class GradleConstants { + @NonNls public static final String NEWLY_IMPORTED_PROJECT = "gradle.newly.imported"; + @NonNls public static final String EXTENSION = "gradle"; @NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle"; From c0dcdcd22cc022bd489297567fe08dad104fd063 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 15 Mar 2012 16:58:30 +0400 Subject: [PATCH 05/18] "Can be null" doesn't imply "is null" --- .../codeInspection/dataFlow/StandardInstructionVisitor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 5ce2fbd6c1f5..ee177909adad 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -123,7 +123,11 @@ public class StandardInstructionVisitor extends InstructionVisitor { final DfaValue qualifier = memState.pop(); if (instruction.getExpression().isPhysical() && !memState.applyNotNull(qualifier)) { onInstructionProducesNPE(instruction, runner); - return DfaInstructionState.EMPTY_ARRAY; + + if (qualifier instanceof DfaVariableValue) { + final DfaNotNullValue.Factory factory = runner.getFactory().getNotNullFactory(); + memState.setVarValue((DfaVariableValue)qualifier, factory.create(((DfaVariableValue)qualifier).getPsiVariable().getType())); + } } return nextInstruction(instruction, runner, memState); From d165428546b6f9508e35e160336e39f7f9a7f532 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 15 Mar 2012 17:14:23 +0400 Subject: [PATCH 06/18] another fix for too eager casting in completion --- .../completion/JavaCompletionUtil.java | 27 ++++++++++--------- .../normal/InterfaceImplementationNoCast.java | 18 +++++++++++++ .../InterfaceImplementationNoCast_after.java | 18 +++++++++++++ .../completion/NormalCompletionTest.groovy | 1 + 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 800db37461d2..fb8437096563 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -504,28 +504,29 @@ public class JavaCompletionUtil { } if (plainQualifier != null) { Object o = item.getObject(); - if (containsMember(plainQualifier, o)) { - if (!(o instanceof PsiMethod)) { - return item; - } + if (o instanceof PsiMethod) { PsiType castType = castTypeItem.getPsiType(); if (plainQualifier instanceof PsiClassType && castType instanceof PsiClassType) { PsiMethod method = (PsiMethod)o; PsiClassType.ClassResolveResult plainResult = ((PsiClassType)plainQualifier).resolveGenerics(); PsiClass plainClass = plainResult.getElement(); - PsiClass castClass = ((PsiClassType)castType).resolveGenerics().getElement(); + if (plainClass != null && plainClass.findMethodBySignature(method, true) != null) { + PsiClass castClass = ((PsiClassType)castType).resolveGenerics().getElement(); - if (castClass == null || plainClass == null || !castClass.isInheritor(plainClass, true)) { - return item; - } + if (castClass == null || !castClass.isInheritor(plainClass, true)) { + return item; + } - PsiSubstitutor plainSub = plainResult.getSubstitutor(); - PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType); - if (method.getSignature(plainSub).equals(method.getSignature(castSub)) && - plainSub.substitute(method.getReturnType()).equals(castSub.substitute(method.getReturnType()))) { - return item; + PsiSubstitutor plainSub = plainResult.getSubstitutor(); + PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType); + if (method.getSignature(plainSub).equals(method.getSignature(castSub)) && + plainSub.substitute(method.getReturnType()).equals(castSub.substitute(method.getReturnType()))) { + return item; + } } } + } else if (containsMember(plainQualifier, o)) { + return item; } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java new file mode 100644 index 000000000000..5f342695a4fe --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java @@ -0,0 +1,18 @@ +public class Util2 { + void foo(XmlAttribute o ) { + if (o instanceof XmlAttributeImpl) { + o.getpar + } + } +} + +interface PsiElement { + PsiElement getParent(); +} +interface XmlAttribute extends PsiElement {} +class XmlAttributeImpl implements XmlAttribute { + @Override + public PsiElement getParent() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java new file mode 100644 index 000000000000..94718eeb8f2e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java @@ -0,0 +1,18 @@ +public class Util2 { + void foo(XmlAttribute o ) { + if (o instanceof XmlAttributeImpl) { + o.getParent() + } + } +} + +interface PsiElement { + PsiElement getParent(); +} +interface XmlAttribute extends PsiElement {} +class XmlAttributeImpl implements XmlAttribute { + @Override + public PsiElement getParent() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 49f4a214442c..772881af6d50 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1325,5 +1325,6 @@ public class ListUtils { } public void testListArrayListCast() { doTest('\n') } + public void testInterfaceImplementationNoCast() { doTest() } } From b76301df0f1d68a8e04e3042f0bd2e589b7628ab Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 15 Mar 2012 14:22:53 +0100 Subject: [PATCH 07/18] replace constructor with builder: escalate visibility (IDEA-82768) --- ...eplaceConstructorWithBuilderProcessor.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java index 32f5489fa54a..e5bd42743749 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java @@ -45,6 +45,7 @@ import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -156,6 +157,14 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto builderClass.add(method); } + //fix visibilities + final PsiMethod constructor = getWorkingConstructor(); + VisibilityUtil.escalateVisibility(constructor, builderClass); + PsiClass containingClass = constructor.getContainingClass(); + while (containingClass != null) { + VisibilityUtil.escalateVisibility(containingClass, builderClass); + containingClass = containingClass.getContainingClass(); + } } private void createSetter(PsiClass builderClass, ParameterData parameterData, PsiField field) { @@ -221,13 +230,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto private PsiMethod createMethodSignature(String createMethodName) { JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(myProject); final StringBuffer buf = new StringBuffer(); - PsiMethod constructor = getMostCommonConstructor(); - if (constructor == null){ - constructor = myConstructors[0]; - if (constructor.getParameterList().getParametersCount() == 0) { - constructor = myConstructors[1]; - } - } + final PsiMethod constructor = getWorkingConstructor(); for (PsiParameter parameter : constructor.getParameterList().getParameters()) { final String pureParamName = styleManager.variableNameToPropertyName(parameter.getName(), VariableKind.PARAMETER); if (buf.length() > 0) buf.append(", "); @@ -245,6 +248,17 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto ";\n}", constructor); } + private PsiMethod getWorkingConstructor() { + PsiMethod constructor = getMostCommonConstructor(); + if (constructor == null){ + constructor = myConstructors[0]; + if (constructor.getParameterList().getParametersCount() == 0) { + constructor = myConstructors[1]; + } + } + return constructor; + } + @Nullable private PsiMethod getMostCommonConstructor() { if (myConstructors.length == 1) return myConstructors[0]; From 6664f25f6cca7c388bf6cb57dbdd1b395a956a29 Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Thu, 15 Mar 2012 18:01:55 +0400 Subject: [PATCH 08/18] IDEA-81337 breakpoint viewer condition field combo dropdown does not close --- .../platform-api/src/com/intellij/openapi/ui/ComboBox.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java index b84c801e1b21..d1e0120f5423 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java @@ -76,7 +76,7 @@ public class ComboBox extends ComboBoxWithWidePopup implements AWTEventListener arrowButton.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { - if (!mySwingPopup) { + if (!isSwingPopup()) { e.consume(); setPopupVisible(true); } @@ -115,6 +115,9 @@ public class ComboBox extends ComboBoxWithWidePopup implements AWTEventListener } }); } + else if (!visible) { + super.setPopupVisible(visible); + } return; } From b0ec6b4c4a9bc66fb826fb4e21402bb9718b96b7 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 15 Mar 2012 18:29:48 +0400 Subject: [PATCH 09/18] pg docsamples test --- .../testFramework/ParsingTestCase.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java index 81275c29dd81..72249ee72680 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java @@ -61,6 +61,8 @@ import java.io.IOException; import java.util.Set; public abstract class ParsingTestCase extends PlatformLiteFixture { + protected static boolean OVERWRITE_TESTDATA = false; + protected String myFilePrefix = ""; protected String myFileExt; @NonNls protected final String myFullDataPath; @@ -270,21 +272,29 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { } private static void doCheckResult(String myFullDataPath, String targetDataName, String text) throws IOException { + text = text.trim(); + String expectedFileName = myFullDataPath + File.separatorChar + targetDataName; + if (OVERWRITE_TESTDATA) { + writeFile(expectedFileName, text); + System.out.println("File " + expectedFileName + " created."); + } try { - text = text.trim(); String expectedText = doLoadFile(myFullDataPath, targetDataName); assertEquals(targetDataName, expectedText, text); } catch(FileNotFoundException e){ - String fullName = myFullDataPath + File.separatorChar + targetDataName; - FileWriter writer = new FileWriter(fullName); - try { - writer.write(text); - } - finally { - writer.close(); - } - fail("No output text found. File " + fullName + " created."); + writeFile(expectedFileName, text); + fail("No output text found. File " + expectedFileName + " created."); + } + } + + private static void writeFile(String fullName, String text) throws IOException { + FileWriter writer = new FileWriter(fullName); + try { + writer.write(text); + } + finally { + writer.close(); } } From f4e9d475a3df5bf4f8e97cecbb6e6e32389567f8 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 15 Mar 2012 19:12:11 +0400 Subject: [PATCH 10/18] IDEA-77484 + tests --- .../dataFlow/ControlFlowAnalyzer.java | 10 +++++++++- .../fixture/CanBeNullDoesntImplyIsNull.java | 14 ++++++++++++++ .../inspection/dataFlow/fixture/NullableField.java | 9 +++++++++ .../DataFlowInspectionFixtureTest.java | 3 ++- 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/CanBeNullDoesntImplyIsNull.java create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/NullableField.java diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 3e0381d52e60..e99d06cbf2ad 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -16,6 +16,7 @@ package com.intellij.codeInspection.dataFlow; import com.intellij.codeInsight.ExceptionUtil; +import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.dataFlow.value.DfaUnknownValue; import com.intellij.codeInspection.dataFlow.value.DfaValue; @@ -1431,6 +1432,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { startElement(expression); DfaValue dfaValue = myFactory.create(expression); + PsiElement resolved = expression.resolve(); if (dfaValue instanceof DfaVariableValue) { DfaVariableValue dfaVariable = (DfaVariableValue)dfaValue; PsiVariable psiVariable = dfaVariable.getPsiVariable(); @@ -1442,7 +1444,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { final PsiExpression qualifierExpression = expression.getQualifierExpression(); if (qualifierExpression != null) { qualifierExpression.accept(this); - if (expression.resolve() instanceof PsiField) { + if (resolved instanceof PsiField) { addInstruction(new FieldReferenceInstruction(expression, null)); } else { @@ -1450,6 +1452,12 @@ class ControlFlowAnalyzer extends JavaElementVisitor { } } + if (dfaValue == null && resolved instanceof PsiField) { + // Accessing a field from another instance + dfaValue = myFactory.getTypeFactory().create(((PsiField)resolved).getType(), + NullableNotNullManager.isNullable((PsiModifierListOwner)resolved)); + } + addInstruction(new PushInstruction(dfaValue, expression)); finishElement(expression); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CanBeNullDoesntImplyIsNull.java b/java/java-tests/testData/inspection/dataFlow/fixture/CanBeNullDoesntImplyIsNull.java new file mode 100644 index 000000000000..56f577112808 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/CanBeNullDoesntImplyIsNull.java @@ -0,0 +1,14 @@ +import org.jetbrains.annotations.Nullable; + +public class DDD { + int test(boolean t) { + if (t && fff().length == 1) { + return 0; + } + return 1; + } + + public @Nullable DDD[] fff() { + return new DDD[8]; + } +} diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NullableField.java b/java/java-tests/testData/inspection/dataFlow/fixture/NullableField.java new file mode 100644 index 000000000000..0a341d37e4e9 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NullableField.java @@ -0,0 +1,9 @@ +import org.jetbrains.annotations.Nullable; + +public class DDD { + @Nullable + String field; + int test() { + return new DDD().field.hashCode(); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java index af8d11f9b962..9b6bd4cf2ce7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java @@ -33,5 +33,6 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas public void testNullableAnonymousVolatileNotNull() throws Throwable { doTest(); } public void testFieldInAnonymous() throws Throwable { doTest(); } - + public void testNullableField() throws Throwable { doTest(); } + public void testCanBeNullDoesntImplyIsNull() throws Throwable { doTest(); } } From 54865eb72cd199680d21d1619a4c3889720f9932 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 15 Mar 2012 19:18:16 +0400 Subject: [PATCH 11/18] IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes Added support for the project changes (name, language level) --- plugins/gradle/src/META-INF/plugin.xml | 1 + .../GradleConflictControlFactory.java | 8 +- .../GradleProjectConflictControlFactory.java | 77 +++++++++++++++++++ .../gradle/ui/MatrixControlBuilder.java | 34 ++++++-- 4 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleProjectConflictControlFactory.java diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index b6a5ec5aa1e0..177380050a79 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -61,6 +61,7 @@ + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleConflictControlFactory.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleConflictControlFactory.java index 746d19479961..9399f0eeca0c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleConflictControlFactory.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleConflictControlFactory.java @@ -30,12 +30,15 @@ import java.util.Collection; * @since 3/2/12 3:03 PM */ public class GradleConflictControlFactory { - + + @NotNull private final GradleProjectConflictControlFactory myProjectFactory; @NotNull private final GradleLibraryDependencyConflictControlFactory myLibraryDependencyFactory; @NotNull private final GradleCommonDependencyConflictControlFactory myCommonDependencyFactory; - public GradleConflictControlFactory(@NotNull GradleLibraryDependencyConflictControlFactory libraryFactory, + public GradleConflictControlFactory(@NotNull GradleProjectConflictControlFactory factory, + @NotNull GradleLibraryDependencyConflictControlFactory libraryFactory, @NotNull GradleCommonDependencyConflictControlFactory commonDependencyFactory) { + myProjectFactory = factory; myLibraryDependencyFactory = libraryFactory; myCommonDependencyFactory = commonDependencyFactory; } @@ -54,6 +57,7 @@ public class GradleConflictControlFactory { GradleUtil.dispatch(entity, new IntellijEntityVisitor() { @Override public void visit(@NotNull Project project) { + result.set(myProjectFactory.getControl(changes)); } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleProjectConflictControlFactory.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleProjectConflictControlFactory.java new file mode 100644 index 000000000000..822b27fcec3f --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/conflict/GradleProjectConflictControlFactory.java @@ -0,0 +1,77 @@ +package org.jetbrains.plugins.gradle.sync.conflict; + +import com.intellij.openapi.util.Ref; +import com.intellij.pom.java.LanguageLevel; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange; +import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitor; +import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitorAdapter; +import org.jetbrains.plugins.gradle.diff.project.GradleLanguageLevelChange; +import org.jetbrains.plugins.gradle.diff.project.GradleProjectRenameChange; +import org.jetbrains.plugins.gradle.ui.MatrixControlBuilder; +import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleUtil; + +import javax.swing.*; +import java.util.Collection; + +/** + * Thread-safe. + * + * @author Denis Zhdanov + * @since 3/15/12 4:26 PM + */ +public class GradleProjectConflictControlFactory { + + @SuppressWarnings("MethodMayBeStatic") + @Nullable + public JComponent getControl(Collection changes) { + final Ref renameChangeRef = new Ref(); + final Ref languageLevelChangeRef = new Ref(); + + GradleProjectStructureChangeVisitor visitor = new GradleProjectStructureChangeVisitorAdapter() { + @Override + public void visit(@NotNull GradleProjectRenameChange change) { + renameChangeRef.set(change); + } + + @Override + public void visit(@NotNull GradleLanguageLevelChange change) { + languageLevelChangeRef.set(change); + } + }; + + for (GradleProjectStructureChange change : changes) { + if (renameChangeRef.get() != null && languageLevelChangeRef.get() != null) { + break; + } + change.invite(visitor); + } + + final GradleProjectRenameChange renameChange = renameChangeRef.get(); + final GradleLanguageLevelChange languageLevelChange = languageLevelChangeRef.get(); + if (renameChange == null && languageLevelChange == null) { + return null; + } + + MatrixControlBuilder builder = GradleUtil.getConflictChangeBuilder(); + if (renameChange != null) { + builder.addRow(GradleBundle.message("gradle.import.structure.settings.label.name"), + renameChange.getGradleValue(), renameChange.getIntellijValue()); + } + + if (languageLevelChange != null) { + builder.addRow(GradleBundle.message("gradle.import.structure.settings.label.language.level"), + getTextToShow(languageLevelChange.getGradleValue()), getTextToShow(languageLevelChange.getIntellijValue())); + } + + return builder.build(); + } + + @NotNull + private static String getTextToShow(@NotNull LanguageLevel level) { + final String s = level.toString(); + return s.substring(s.indexOf('1')).replace('_', '.'); + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/MatrixControlBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/MatrixControlBuilder.java index abc73cc47962..b8581a6efa54 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/MatrixControlBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/MatrixControlBuilder.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumnModel; import java.awt.*; import java.util.Arrays; @@ -34,27 +35,36 @@ import java.util.Arrays; public class MatrixControlBuilder { private final DefaultTableModel myModel = new DefaultTableModel(); - private final JComponent result; + + private final JBTable myTable; + private final JComponent myResult; + private final int[] myColumnWidths; + private final FontMetrics myFontMetrics; public MatrixControlBuilder(@NotNull String ... columns) { myModel.addColumn(""); // Row name for (String column : columns) { myModel.addColumn(column); } - final JBTable table = new JBTable(myModel) { + myTable = new JBTable(myModel) { @Override public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } }; - table.setStriped(true); + myTable.setStriped(true); DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); renderer.setHorizontalAlignment(SwingConstants.CENTER); - for (int i = 1/* don't align row name */, max = table.getColumnCount(); i < max; i++) { - table.getColumnModel().getColumn(i).setCellRenderer(renderer); + for (int i = 1/* don't align row name */, max = myTable.getColumnCount(); i < max; i++) { + myTable.getColumnModel().getColumn(i).setCellRenderer(renderer); + } + myResult = ScrollPaneFactory.createScrollPane(myTable); + + myColumnWidths = new int[columns.length + 1/*'name' column*/]; + myFontMetrics = myTable.getFontMetrics(myTable.getFont()); + for (int i = 0; i < columns.length; i++) { + myColumnWidths[i + 1] = myFontMetrics.stringWidth(columns[i]); } - //table.setDefaultRenderer(String.class, renderer); - result = ScrollPaneFactory.createScrollPane(table); } /** @@ -82,10 +92,18 @@ public class MatrixControlBuilder { rowData[0] = name; System.arraycopy(values, 0, rowData, 1, values.length); myModel.addRow(rowData); + + for (int i = 0; i < rowData.length; i++) { + myColumnWidths[i] = Math.max(myFontMetrics.stringWidth(rowData[i].toString()), myColumnWidths[i]); + } } @NotNull public JComponent build() { - return result; + final TableColumnModel columnModel = myTable.getColumnModel(); + for (int i = 0; i < myColumnWidths.length; i++) { + columnModel.getColumn(i).setMinWidth(myColumnWidths[i] + 4); + } + return myResult; } } From e48d61295f0ec941c799539bcffebacfdaa03f61 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 15 Mar 2012 19:19:15 +0400 Subject: [PATCH 12/18] IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes Don't hide node toolbar on mouse move if the cursor is still under the toolbar --- .../GradleProjectStructureChangesPanel.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java index fbb2edcd5409..f42a25f92389 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java @@ -73,6 +73,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { private Object myNodeUnderMouse; private Object myNodeWithActiveToolbar; private Balloon myToolbar; + private JComponent myToolbarComponent; private boolean mySuppressToolbar; private boolean mySuppressCollapseTracking; @@ -226,7 +227,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { final Point mouseLocation = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(mouseLocation, myTree); final TreePath path = myTree.getPathForLocation(mouseLocation.x, mouseLocation.y); - if (path == null) { + if (path == null && !isUnderMouse(myToolbarComponent)) { hideToolbar(); return; } @@ -252,6 +253,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { .createBalloon(); Disposer.register(getProject(), balloon); Point hintPosition = GradleUtil.getHintPosition(node, myTree); + myToolbarComponent = toolbarComponent; myToolbar = balloon; myNodeWithActiveToolbar = node; balloon.show(new RelativePoint(myTree, hintPosition), Balloon.Position.below); @@ -269,9 +271,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { if (myToolbar == null) { return; } - final Point location = MouseInfo.getPointerInfo().getLocation(); - SwingUtilities.convertPointFromScreen(location, GradleProjectStructureChangesPanel.this); - if (GradleProjectStructureChangesPanel.this.contains(location)) { + if (isUnderMouse(GradleProjectStructureChangesPanel.this) || isUnderMouse(myToolbarComponent)) { myToolbarTrackingAlarm.addRequest(this, delayMillis); } else { @@ -280,6 +280,15 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { } }, delayMillis); } + + private static boolean isUnderMouse(@Nullable JComponent component) { + if (component == null) { + return false; + } + final Point location = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(location, component); + return component.contains(location); + } private void hideToolbar() { final Balloon toolbar = myToolbar; @@ -287,6 +296,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { if (toolbar != null && !toolbar.isDisposed()) { toolbar.hide(); myToolbar = null; + myToolbarComponent = null; myToolbarAppearanceAlarm.cancelAllRequests(); myToolbarTrackingAlarm.cancelAllRequests(); } From d4c3f081604bcc4de3f6ba38479f84f3eb44cb15 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 15 Mar 2012 19:19:43 +0400 Subject: [PATCH 13/18] EA-33846 - assert: GradleApiFacadeManager$.createJavaParameters --- .../config/GradleLibraryPresentationProvider.java | 10 +++++----- .../plugins/gradle/util/GradleLibraryManager.java | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLibraryPresentationProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLibraryPresentationProvider.java index 5cd1ebef6282..4c5496bf566c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLibraryPresentationProvider.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLibraryPresentationProvider.java @@ -32,6 +32,7 @@ import org.jetbrains.plugins.groovy.config.GroovyLibraryProperties; import javax.swing.*; import java.io.File; +import java.util.regex.Matcher; /** * @author nik @@ -114,11 +115,10 @@ public class GradleLibraryPresentationProvider extends GroovyLibraryPresentation @Nullable private static String getGradleJarVersion(VirtualFile file) { - // TODO den implement - //final Matcher matcher = GRADLE_JAR_FILE_PATTERN.matcher(file.getName()); - //if (matcher.matches()) { - // return matcher.group(2); - //} + final Matcher matcher = GradleLibraryManager.GRADLE_JAR_FILE_PATTERN.matcher(file.getName()); + if (matcher.matches()) { + return matcher.group(2); + } return null; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java index b878565f40ca..a504b9627115 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java @@ -27,8 +27,9 @@ import java.util.regex.Pattern; @SuppressWarnings("MethodMayBeStatic") public class GradleLibraryManager { - private static final Pattern GRADLE_JAR_FILE_PATTERN; - private static final Pattern ANY_GRADLE_JAR_FILE_PATTERN; + public static final Pattern GRADLE_JAR_FILE_PATTERN; + public static final Pattern ANY_GRADLE_JAR_FILE_PATTERN; + private static final String[] GRADLE_START_FILE_NAMES; @NonNls private static final String GRADLE_ENV_PROPERTY_NAME; static { From a7f9258a661a140255c18bfd40129caca0c3b78b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 15 Mar 2012 16:23:21 +0100 Subject: [PATCH 14/18] annoying horizontal scrolling --- .../src/com/intellij/ui/treeStructure/Tree.java | 9 +++++++++ .../src/com/intellij/util/ui/tree/TreeUtil.java | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index e4cc48f5e191..9b40cc59082a 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -57,6 +57,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith private Dimension myHoldSize; private final MySelectionModel mySelectionModel = new MySelectionModel(); + private boolean myHorizontalAutoScrolling = false; public Tree() { initTree_(); @@ -683,4 +684,12 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith return size; } + + public boolean isHorizontalAutoScrollingEnabled() { + return myHorizontalAutoScrolling; + } + + public void setHorizontalAutoScrollingEnabled(boolean enabled) { + myHorizontalAutoScrolling = enabled; + } } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index 8cc2d97de28b..3990fe048820 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -26,6 +26,7 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Range; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -565,6 +566,10 @@ public final class TreeUtil { bounds.width = visible.width; } + if (tree instanceof Tree && !((Tree)tree).isHorizontalAutoScrollingEnabled()) { + bounds.x = 0; + } + final Rectangle b1 = bounds; final Runnable runnable = new Runnable() { public void run() { From d75a9923f1777211ecc162dd4f0b573d959f8bae Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 15 Mar 2012 16:23:53 +0100 Subject: [PATCH 15/18] file structure popup performance --- .../intellij/ide/util/FileStructurePopup.java | 85 ++++++++++++++++--- .../ide/util/treeView/AbstractTreeUi.java | 7 +- .../ui/treeStructure/AlwaysExpandedTree.java | 23 +++++ .../src/misc/registry.properties | 3 +- 4 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/ui/treeStructure/AlwaysExpandedTree.java diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 5a9529260e5b..46b0b86a675c 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -39,6 +39,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.PsiDocumentManager; @@ -49,6 +50,7 @@ import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.ui.speedSearch.ElementFilter; import com.intellij.ui.speedSearch.SpeedSearchUtil; +import com.intellij.ui.treeStructure.AlwaysExpandedTree; import com.intellij.ui.treeStructure.Tree; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; @@ -76,6 +78,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.lang.reflect.Field; import java.util.*; import java.util.List; @@ -101,7 +104,7 @@ public class FileStructurePopup implements Disposable { @NonNls private static final String narrowDownPropertyKey = "FileStructurePopup.narrowDown"; private boolean myShouldNarrowDown = true; - private Tree myTree; + private FileStructureTree myTree; private FilteringTreeBuilder myAbstractTreeBuilder; private String myTitle; private TreeSpeedSearch mySpeedSearch; @@ -154,13 +157,9 @@ public class FileStructurePopup implements Disposable { return "structure view tree structure(model=" + myTreeModel + ")"; } }; - myTree = new JBTreeWithHintProvider(new DefaultMutableTreeNode(myTreeStructure.getRootElement())) { - @Override - protected PsiElement getPsiElementForHint(Object selectedValue) { - //noinspection ConstantConditions - return getPsi((FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)selectedValue).getUserObject()); - } - }; + + myTree = new FileStructureTree(myTreeStructure.getRootElement(), Registry.is("fast.tree.expand.in.structure.view")); + myTree.setCellRenderer(new NodeRenderer() { @Override protected void doAppend(@NotNull @Nls String fragment, @@ -180,8 +179,6 @@ public class FileStructurePopup implements Disposable { SpeedSearchUtil.appendFragmentsForSpeedSearch(myTree, fragment, SimpleTextAttributes.REGULAR_ATTRIBUTES, selected, this); } }); - myTree.setRootVisible(false); - myTree.setShowsRootHandles(true); mySpeedSearch = new MyTreeSpeedSearch(); mySpeedSearch.setComparator(new SpeedSearchComparator(false, true)); @@ -271,7 +268,7 @@ public class FileStructurePopup implements Disposable { } //final long cur = System.currentTimeMillis(); - myAbstractTreeBuilder.expandAll(new Runnable() { + final Runnable expandIsDone = new Runnable() { @Override public void run() { //System.out.println(System.currentTimeMillis() - cur); @@ -286,7 +283,14 @@ public class FileStructurePopup implements Disposable { } }); } - }); + }; + + //if (myTree.isAlwaysExpanded() || true) { + expandIsDone.run(); + //} else { + // myAbstractTreeBuilder.expandAll(expandIsDone); + //} + if (!ApplicationManager.getApplication().isUnitTestMode()) { final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myPopup); alarm.addRequest(new Runnable() { @@ -903,4 +907,59 @@ public class FileStructurePopup implements Disposable { } } + + class FileStructureTree extends JBTreeWithHintProvider implements AlwaysExpandedTree { + private final boolean fast; + + public FileStructureTree(Object rootElement, boolean fastExpand) { + super(new DefaultMutableTreeNode(rootElement)); + if (fastExpand) { + boolean newValueIsSet; + try { + final Field field = JTree.class.getDeclaredField("expandedState"); + field.setAccessible(true); + field.set(this, new Hashtable() { + @Override + public synchronized Object get(Object key) { + return Boolean.TRUE; + } + }); + newValueIsSet = true; + } + catch (Exception e) { + newValueIsSet = false; + } + fast = newValueIsSet; + } else { + fast = false; + } + + //TODO[kb]: hack expanded states in getUI().treeState + + setRootVisible(false); + setShowsRootHandles(true); + setHorizontalAutoScrollingEnabled(false); + } + + @Override + public boolean isAlwaysExpanded() { + return fast; + } + + @Override + public boolean isExpanded(TreePath path) { + return fast || super.isExpanded(path); + } + + @Override + public boolean isExpanded(int row) { + return fast || super.isExpanded(row); + } + + @Override + protected PsiElement getPsiElementForHint(Object selectedValue) { + //noinspection ConstantConditions + return getPsi((FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)selectedValue).getUserObject()); + } + } } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 36eb0ce043ca..55269e50ea8b 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -27,6 +27,7 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.registry.RegistryValue; import com.intellij.ui.LoadingNode; +import com.intellij.ui.treeStructure.AlwaysExpandedTree; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; @@ -751,7 +752,7 @@ public class AbstractTreeUi { } private boolean isAutoExpand(NodeDescriptor descriptor, boolean validate) { - if (descriptor == null) return false; + if (descriptor == null || isAlwaysExpandedTree()) return false; boolean autoExpand = getBuilder().isAutoExpandNode(descriptor); @@ -821,6 +822,10 @@ public class AbstractTreeUi { return isAutoExpand(getDescriptorFrom(node)); } + private boolean isAlwaysExpandedTree() { + return myTree instanceof AlwaysExpandedTree && ((AlwaysExpandedTree)myTree).isAlwaysExpanded(); + } + private AsyncResult update(final NodeDescriptor nodeDescriptor, boolean now) { final AsyncResult result = new AsyncResult(); diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/AlwaysExpandedTree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/AlwaysExpandedTree.java new file mode 100644 index 000000000000..870cb8e999a7 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/AlwaysExpandedTree.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2012 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.ui.treeStructure; + +/** + * @author Konstantin Bulenkov + */ +public interface AlwaysExpandedTree { + boolean isAlwaysExpanded(); +} diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 659a40f86395..0720f81f856a 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -199,4 +199,5 @@ core.pooled.threads=20 editor.dumb.mode.available=true enable.animation.on.dialogs=false vcs.remote.management.ready=false -type.ahead.logging.enabled=false \ No newline at end of file +type.ahead.logging.enabled=false +fast.tree.expand.in.structure.view=false \ No newline at end of file From 860142f10626db604b4a6aa32b34297911a5599f Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 15 Mar 2012 19:31:43 +0400 Subject: [PATCH 16/18] don't invoke VcsVfsListeners for files not under the VCS in question (don't track last unchanged content for files not under perforce) --- .../intellij/openapi/vcs/VcsVFSListener.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java index 028ed64d1b18..eee08caf705e 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java @@ -93,14 +93,19 @@ public abstract class VcsVFSListener implements Disposable { protected boolean isEventIgnored(final VirtualFileEvent event, boolean putInDirty) { if (event.isFromRefresh()) return true; - boolean vcsIgnored = myVcsManager.getVcsFor(event.getFile()) != myVcs || - (!myVcsManager.isFileInContent(event.getFile())) || myChangeListManager.isIgnoredFile(event.getFile()); + boolean vcsIgnored = !isUnderMyVcs(event.getFile()); if (vcsIgnored) { myDirtyFiles.add(event.getFile()); } return vcsIgnored; } + private boolean isUnderMyVcs(VirtualFile file) { + return myVcsManager.getVcsFor(file) == myVcs && + (myVcsManager.isFileInContent(file)) && + !myChangeListManager.isIgnoredFile(file); + } + protected void executeAdd() { final List addedFiles = acquireAddedFiles(); for (Iterator iterator = addedFiles.iterator(); iterator.hasNext(); ) { @@ -308,7 +313,10 @@ public abstract class VcsVFSListener implements Disposable { private class MyVirtualFileAdapter extends VirtualFileAdapter { public void fileCreated(final VirtualFileEvent event) { - VcsVFSListener.this.fileAdded(event, event.getFile()); + VirtualFile file = event.getFile(); + if (isUnderMyVcs(file)) { + VcsVFSListener.this.fileAdded(event, file); + } } public void fileCopied(final VirtualFileCopyEvent event) { @@ -385,8 +393,11 @@ public abstract class VcsVFSListener implements Disposable { @Override public void beforeContentsChange(VirtualFileEvent event) { - assert !event.getFile().isDirectory(); - VcsVFSListener.this.beforeContentsChange(event, event.getFile()); + VirtualFile file = event.getFile(); + assert !file.isDirectory(); + if (isUnderMyVcs(file)) { + VcsVFSListener.this.beforeContentsChange(event, file); + } } } From bb72890fe54b1aa1058b7f692ad4f2b47c52be05 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 15 Mar 2012 19:51:57 +0400 Subject: [PATCH 17/18] IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes Gradle project level is applied to the intellij project now --- .../gradle/importing/GradleProjectImportBuilder.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java index 3c65acce4d9f..7b27347971c7 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java @@ -10,10 +10,12 @@ import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Ref; import com.intellij.packaging.artifacts.ModifiableArtifactModel; +import com.intellij.pom.java.LanguageLevel; import com.intellij.projectImport.ProjectImportBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -81,6 +83,14 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder Date: Thu, 15 Mar 2012 19:54:20 +0400 Subject: [PATCH 18/18] IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes Don't state for the gradle-unaware projects --- .../openapi/components/PersistentStateComponent.java | 7 +++++-- .../jetbrains/plugins/gradle/config/GradleSettings.java | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java b/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java index 8e2656131128..43d411c6ba1e 100644 --- a/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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,6 +17,7 @@ package com.intellij.openapi.components; import com.intellij.util.xmlb.XmlSerializer; +import org.jetbrains.annotations.Nullable; /** * Every component which would like to persist its state across IDEA restarts @@ -28,9 +29,11 @@ import com.intellij.util.xmlb.XmlSerializer; public interface PersistentStateComponent { /** * @return a component state. All properties and public fields are serialized. Only values, which differ - * from default (i.e. the value of newly instantiated class) are serialized. + * from default (i.e. the value of newly instantiated class) are serialized. null value indicates + * that no state should be stored * @see XmlSerializer */ + @Nullable T getState(); /** diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettings.java index 2efdb62e35b8..68f23649e804 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettings.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.gradle.config; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.xmlb.XmlSerializerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,6 +58,10 @@ public class GradleSettings implements PersistentStateComponent, @Override public GradleSettings getState() { + if (StringUtil.isEmpty(getLinkedProjectPath())) { + // Don't save state for the gradle-unaware projects. + return null; + } myExpandStates.get().clear(); if (PRESERVE_EXPAND_STATE) { myExpandStates.get().putAll(myWorkingExpandStates.get());