From ba799ce032cd0b56b674449c9bec2a30758b87c5 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 14 Apr 2017 12:07:21 +0300 Subject: [PATCH 01/26] properties: fix update of structure view & resource bundle editor (IDEA-170695) --- .../PropertiesPsiTreeChangePreprocessor.java | 82 +++++++++++++++++ plugins/properties/src/META-INF/plugin.xml | 2 + .../PropertiesModificationTest.java | 90 +++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java create mode 100644 plugins/properties/testSrc/com/intellij/lang/properties/PropertiesModificationTest.java diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java new file mode 100644 index 000000000000..8f886f9ac715 --- /dev/null +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2017 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.lang.properties.psi.impl; + +import com.intellij.lang.properties.parsing.PropertiesTokenTypes; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiManager; +import com.intellij.psi.impl.PsiTreeChangeEventImpl; +import com.intellij.psi.impl.PsiTreeChangePreprocessorBase; +import com.intellij.psi.tree.TokenSet; +import com.intellij.psi.util.PsiUtilCore; +import org.jetbrains.annotations.NotNull; + +public class PropertiesPsiTreeChangePreprocessor extends PsiTreeChangePreprocessorBase { + private static final TokenSet CODE_BLOCK_ELEMENTS = TokenSet.create(PropertiesTokenTypes.VALUE_CHARACTERS, + PropertiesTokenTypes.END_OF_LINE_COMMENT, + PropertiesTokenTypes.WHITE_SPACE, + PropertiesTokenTypes.KEY_VALUE_SEPARATOR); + + public PropertiesPsiTreeChangePreprocessor(@NotNull PsiManager psiManager) { + super(psiManager); + } + + @Override + protected void onTreeChanged(@NotNull PsiTreeChangeEventImpl event) { + if (event.isGenericChange()) return; + switch (event.getCode()) { + case BEFORE_PROPERTY_CHANGE: + case BEFORE_CHILD_REMOVAL: + case BEFORE_CHILD_ADDITION: + case BEFORE_CHILD_MOVEMENT: + case BEFORE_CHILDREN_CHANGE: + case BEFORE_CHILD_REPLACEMENT: + return; + case CHILD_ADDED: + if (isCodeBlock(event.getChild())) return; + break; + case CHILD_REMOVED: + if (isCodeBlock(event.getChild())) return; + break; + case CHILD_REPLACED: + if (isCodeBlock(event.getOldChild()) || isCodeBlock(event.getNewChild())) return; + break; + case CHILD_MOVED: + if (isCodeBlock(event.getChild())) return; + break; + case CHILDREN_CHANGED: + if (isCodeBlock(event.getChild())) return; + case PROPERTY_CHANGED: + break; + } + doIncOutOfCodeBlockCounter(); + } + + @Override + protected boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event) { + return event.getFile() instanceof PropertiesFile; + } + + @Override + protected boolean isOutOfCodeBlock(@NotNull PsiElement element) { + throw new IllegalStateException(); + } + + private static boolean isCodeBlock(@NotNull PsiElement element) { + return CODE_BLOCK_ELEMENTS.contains(PsiUtilCore.getElementType(element)); + } +} diff --git a/plugins/properties/src/META-INF/plugin.xml b/plugins/properties/src/META-INF/plugin.xml index fc22b76a0c68..6bc313ede341 100644 --- a/plugins/properties/src/META-INF/plugin.xml +++ b/plugins/properties/src/META-INF/plugin.xml @@ -123,6 +123,8 @@ + + diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesModificationTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesModificationTest.java new file mode 100644 index 000000000000..8e4198e9b73d --- /dev/null +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesModificationTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2017 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.lang.properties; + +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.util.PsiModificationTracker; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; + +public class PropertiesModificationTest extends LightCodeInsightFixtureTestCase { + + public void testValueEditing() { + doTestEditing(" # comment", false); + } + + public void testKeyEditing() { + doTestEditing("key = value", true); + } + + public void testCommentEditing() { + doTestEditing("key = value", false); + } + + public void testKeyReplacement() { + doTestReplacement("key = value", true); + } + + public void testValueReplacement() { + doTestReplacement("key = value", false); + } + + public void testCommentReplacement() { + doTestReplacement("key = value \n# comment \n key2 = value2", false); + } + + public void testKeyDeletion() { + doTestDeletion("key = value", true); + } + + public void testPropertiesDeletion() { + doTestDeletion("key1 = value1 \n" + + "key2 = value2 \n" + + "key3 = value3 \n" + + "key4 = value4 \n" + + "key5 = value5 \n", true); + } + + private void doTestEditing(@NotNull String text, boolean isOutOfBlockModificationExpected) { + doTest(text, () -> myFixture.type("xxx"), isOutOfBlockModificationExpected); + } + + private void doTestReplacement(@NotNull String text, boolean isOutOfBlockModificationExpected) { + doTest(text, () -> WriteCommandAction.runWriteCommandAction(getProject(), () -> { + SelectionModel sel = getEditor().getSelectionModel(); + getEditor().getDocument().replaceString(sel.getSelectionStart(), sel.getSelectionEnd(), "xxx"); + }), isOutOfBlockModificationExpected); + } + + private void doTestDeletion(@NotNull String text, boolean isOutOfBlockModificationExpected) { + doTest(text, () -> WriteCommandAction.runWriteCommandAction(getProject(), () -> { + SelectionModel sel = getEditor().getSelectionModel(); + getEditor().getDocument().deleteString(sel.getSelectionStart(), sel.getSelectionEnd()); + }), isOutOfBlockModificationExpected); + } + + private void doTest(@NotNull String text, Runnable modificationAction, boolean isOutOfBlockModificationExpected) { + myFixture.configureByText("test.properties", text); + PsiModificationTracker tracker = myFixture.getPsiManager().getModificationTracker(); + long oldMod = tracker.getOutOfCodeBlockModificationCount(); + modificationAction.run(); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + long newMod = tracker.getOutOfCodeBlockModificationCount(); + assertTrue(isOutOfBlockModificationExpected ^ oldMod == newMod); + } +} From 0931e87ebd33294a0d0de20a3bf85eaf3eafd4b0 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 14 Apr 2017 12:56:44 +0300 Subject: [PATCH 02/26] PreferMostUsedWeigher should not affect completion sorting if generated element is suggested --- .../completion/PreferMostUsedWeigher.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferMostUsedWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferMostUsedWeigher.java index eb70ab28f935..afd2dd2abfb0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferMostUsedWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferMostUsedWeigher.java @@ -56,16 +56,17 @@ class PreferMostUsedWeigher extends LookupElementWeigher { if (!(psi instanceof PsiMember)) { return null; } - else { - if (OBJECT_METHOD_PATTERN.accepts(psi)) { - return null; - } - if (looksLikeHelperMethodOrConst(psi)) { - return null; - } - final Integer occurrenceCount = myCompilerReferenceService.getCompileTimeOccurrenceCount(psi, myConstructorSuggestion); - return occurrenceCount == null ? null : - occurrenceCount; + if (element.getUserData(JavaGenerateMemberCompletionContributor.GENERATE_ELEMENT) != null) { + return null; } + if (OBJECT_METHOD_PATTERN.accepts(psi)) { + return null; + } + if (looksLikeHelperMethodOrConst(psi)) { + return null; + } + final Integer occurrenceCount = myCompilerReferenceService.getCompileTimeOccurrenceCount(psi, myConstructorSuggestion); + return occurrenceCount == null ? null : -occurrenceCount; } //Objects.requireNonNull is an example From fc98b768310135a0f84a8af14917a7637e620ce3 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Thu, 13 Apr 2017 21:24:11 +0300 Subject: [PATCH 03/26] Java: Mark service implementations as used if the service declaration is used - support implicit and vararg constructors (IDEA-169204) --- .../reference/RefJavaModuleImpl.java | 29 ++++++++------ .../unusedExternalImplementation/expected.xml | 20 +++++++++- .../unusedImplementation/expected.xml | 20 +++++++++- .../MyServiceImpl.java | 8 ++++ .../unusedVarargConstructor/expected.xml | 38 +++++++++++++++++++ .../varargConstructor/MyServiceImpl.java | 8 ++++ .../varargConstructor/expected.xml | 3 ++ .../Java9UnusedServiceImplementationsTest.kt | 4 ++ 8 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/MyServiceImpl.java create mode 100644 java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/expected.xml create mode 100644 java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/MyServiceImpl.java create mode 100644 java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/expected.xml diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java index e3273c4b553d..e91851e45941 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java @@ -127,14 +127,28 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule { for (PsiJavaCodeReferenceElement implementationReference : implementationList.getReferenceElements()) { final PsiElement implementationClass = implementationReference.resolve(); if (implementationClass instanceof PsiClass) { + RefElement refTargetElement = null; PsiElement targetElement = getProviderMethod((PsiClass)implementationClass); + if (targetElement == null) { - targetElement = getDefaultConstructor((PsiClass)implementationClass); - if (targetElement == null) { - targetElement = implementationClass; + final RefElement refClass = getRefManager().getReference(implementationClass); + if (refClass instanceof RefClassImpl) { + final RefMethod refConstructor = ((RefClassImpl)refClass).getDefaultConstructor(); + if (refConstructor != null) { + final PsiModifierListOwner constructorElement = refConstructor.getElement(); + if (constructorElement != null && constructorElement.hasModifierProperty(PsiModifier.PUBLIC)) { + refTargetElement = refConstructor; + targetElement = constructorElement; + } + } } } - final RefElement refTargetElement = getRefManager().getReference(targetElement); + if (targetElement == null) { + targetElement = implementationClass; + } + if (refTargetElement == null) { + refTargetElement = getRefManager().getReference(targetElement); + } if (refTargetElement != null) { ((RefJavaElementImpl)refInterface) .addReference(refTargetElement, targetElement, providerInterface, false, true, null); @@ -187,11 +201,4 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule { m.hasModifierProperty(PsiModifier.STATIC) && m.getParameterList().getParametersCount() == 0); } - - @Nullable - private static PsiMethod getDefaultConstructor(@NotNull PsiClass psiClass) { - final PsiMethod[] constructors = psiClass.getConstructors(); - return ContainerUtil.find(constructors, m -> m.hasModifierProperty(PsiModifier.PUBLIC) && - m.getParameterList().getParametersCount() == 0); - } } diff --git a/java/java-tests/testData/inspection/unusedServiceImplementations/unusedExternalImplementation/expected.xml b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedExternalImplementation/expected.xml index 4057c0b897a1..07e39458ded6 100644 --- a/java/java-tests/testData/inspection/unusedServiceImplementations/unusedExternalImplementation/expected.xml +++ b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedExternalImplementation/expected.xml @@ -6,7 +6,16 @@ my.ext unused declaration - Class is not instantiated. + Class has one instantiation but it is not reachable from entry points. + + + + MyServiceExt.java + 4 + my.ext + + unused declaration + Class has one instantiation but it is not reachable from entry points. @@ -17,4 +26,13 @@ unused declaration <ul><li>Method owner class is never instantiated OR</li><li>An instantiation is not reachable from entry points.</li></ul> + + + MyService.java + 1 + my.api + + unused declaration + &nbsp;Interface has an implementation but <ul><li>it is never instantiated OR</li><li>no instantiations are reachable from entry points.</li></ul> + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/unusedServiceImplementations/unusedImplementation/expected.xml b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedImplementation/expected.xml index 0d81e05ee29e..c01808e2552f 100644 --- a/java/java-tests/testData/inspection/unusedServiceImplementations/unusedImplementation/expected.xml +++ b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedImplementation/expected.xml @@ -6,7 +6,25 @@ my.impl unused declaration - Class is not instantiated. + Class has one instantiation but it is not reachable from entry points. + + + + MyServiceImpl.java + 4 + my.impl + + unused declaration + Class has one instantiation but it is not reachable from entry points. + + + + MyService.java + 1 + my.api + + unused declaration + &nbsp;Interface has an implementation but <ul><li>it is never instantiated OR</li><li>no instantiations are reachable from entry points.</li></ul> diff --git a/java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/MyServiceImpl.java b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/MyServiceImpl.java new file mode 100644 index 000000000000..a4f9594fd2fe --- /dev/null +++ b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/MyServiceImpl.java @@ -0,0 +1,8 @@ +package my.impl; +import my.api.MyService; + +public class MyServiceImpl implements MyService { + public MyServiceImpl(Object... objects) {System.out.println(objects);} + @Override + public void foo() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/expected.xml b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/expected.xml new file mode 100644 index 000000000000..10fe147b5bbe --- /dev/null +++ b/java/java-tests/testData/inspection/unusedServiceImplementations/unusedVarargConstructor/expected.xml @@ -0,0 +1,38 @@ + + + + MyServiceImpl.java + 5 + my.impl + + unused declaration + Constructor has usage(s) but they all belong to calls chain that has no members reachable from entry points. + + + + MyServiceImpl.java + 4 + my.impl + + unused declaration + Class has one instantiation but it is not reachable from entry points. + + + + MyService.java + 1 + my.api + + unused declaration + <ul><li>Method owner class is never instantiated OR</li><li>An instantiation is not reachable from entry points.</li></ul> + + + + MyService.java + 1 + my.api + + unused declaration + &nbsp;Interface has an implementation but <ul><li>it is never instantiated OR</li><li>no instantiations are reachable from entry points.</li></ul> + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/MyServiceImpl.java b/java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/MyServiceImpl.java new file mode 100644 index 000000000000..a4f9594fd2fe --- /dev/null +++ b/java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/MyServiceImpl.java @@ -0,0 +1,8 @@ +package my.impl; +import my.api.MyService; + +public class MyServiceImpl implements MyService { + public MyServiceImpl(Object... objects) {System.out.println(objects);} + @Override + public void foo() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/expected.xml b/java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/expected.xml new file mode 100644 index 000000000000..5e933496b9cf --- /dev/null +++ b/java/java-tests/testData/inspection/unusedServiceImplementations/varargConstructor/expected.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/Java9UnusedServiceImplementationsTest.kt b/java/java-tests/testSrc/com/intellij/codeInspection/Java9UnusedServiceImplementationsTest.kt index 8a8be31ff7ef..00279bd4ab61 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/Java9UnusedServiceImplementationsTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInspection/Java9UnusedServiceImplementationsTest.kt @@ -48,12 +48,16 @@ class Java9UnusedServiceImplementationsTest : LightJava9ModulesCodeInsightFixtur fun testProvider() = doTest() + fun testVarargConstructor() = doTest() + fun testUnusedImplementation() = doTest(false) fun testUnusedConstructor() = doTest(false) fun testUnusedProvider() = doTest(false) + fun testUnusedVarargConstructor() = doTest(false) + fun testExternalImplementation() = doTest(sameModule = false) fun testExternalConstructor() = doTest(sameModule = false) From 31e8018b6c05cc82703b46a704a4dcc07cb9c7fb Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 14 Apr 2017 13:20:02 +0300 Subject: [PATCH 04/26] OC-15345 variable declarations don't hide type declarations in Swift 3 --- .../intellij/util/containers/ContainerUtil.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index c72f9193ebef..14a256e68ce5 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -1560,6 +1560,20 @@ public class ContainerUtil extends ContainerUtilRt { return result.isEmpty() ? ContainerUtil.emptyList() : result; } + @NotNull + @Contract(pure=true) + public static > EnumSet intersection(@NotNull EnumSet collection1, @NotNull EnumSet collection2) { + if (collection1.isEmpty()) return collection1; + if (collection2.isEmpty()) return collection2; + + EnumSet smallerCollection = collection1.size() < collection2.size() ? collection1 : collection2; + EnumSet biggerCollection = collection1.size() < collection2.size() ? collection2 : collection1; + + EnumSet result = EnumSet.copyOf(smallerCollection); + result.removeAll(EnumSet.complementOf(biggerCollection)); + return result; + } + @Nullable @Contract(pure=true) public static T getFirstItem(@Nullable Collection items) { From f70fc63eb68d009039d3b30bbb8025268d9323fe Mon Sep 17 00:00:00 2001 From: "alexey.afanasiev" Date: Fri, 14 Apr 2017 13:23:26 +0300 Subject: [PATCH 05/26] IDEA-170505 Strange formatting of Groovy enum with @Deprecated value --- .../auxiliary/annotations/Annotation.java | 16 ---------- .../auxiliary/modifiers/Modifiers.java | 7 ++++- .../typeDefinitions/members/EnumConstant.java | 4 +-- .../processors/GroovyIndentProcessor.java | 6 ++++ .../processors/GroovySpacingProcessor.java | 6 +++- .../lang/formatter/FormatterTest.groovy | 30 +++++++++++++++++++ .../statements/typedef/enums/enum10.test | 2 ++ .../statements/typedef/enums/enum11.test | 6 ++++ .../statements/typedef/enums/enum12.test | 2 ++ .../statements/typedef/enums/enum13.test | 2 ++ .../statements/typedef/enums/enum5.test | 2 ++ .../statements/typedef/enums/enum6.test | 2 ++ .../statements/typedef/enums/enum8.test | 4 +++ .../statements/typedef/enums/enum9.test | 2 ++ .../parsing/groovy/types/innerEnum.test | 14 +++++++++ 15 files changed, 85 insertions(+), 20 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java index 3ddb9a7c32df..d9a65c89f522 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java @@ -61,20 +61,4 @@ public class Annotation { annMarker.done(GroovyElementTypes.ANNOTATION); return true; } - - public static void parseAnnotationOptional(PsiBuilder builder, GroovyParser parser) { - PsiBuilder.Marker annOptMarker = builder.mark(); - - boolean hasAnnotations = false; - while (parse(builder, parser)) { - ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); - hasAnnotations = true; - } - - if (hasAnnotations) { - annOptMarker.done(GroovyElementTypes.MODIFIERS); - } else { - annOptMarker.rollbackTo(); - } - } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java index e540b5ac0990..0479294c8d01 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java @@ -35,7 +35,12 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils; */ public class Modifiers { + public static boolean parse(PsiBuilder builder, GroovyParser parser) { + return parse(builder, parser, false); + } + + public static boolean parse(PsiBuilder builder, GroovyParser parser, boolean annotationsOnly) { PsiBuilder.Marker modifiersMarker = builder.mark(); boolean hasModifiers = false; @@ -44,7 +49,7 @@ public class Modifiers { final PsiBuilder.Marker modifierListItem = builder.mark(); if (hasModifiers) ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); - final boolean parsed = Annotation.parse(builder, parser) || parseModifier(builder); + final boolean parsed = Annotation.parse(builder, parser) || (!annotationsOnly && parseModifier(builder)); if (parsed) { if (PathExpression.isQualificationDot(builder)) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java index 5e19ee82f6a8..62ab051695ba 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java @@ -21,7 +21,7 @@ import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyParser; -import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.annotations.Annotation; +import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.modifiers.Modifiers; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arguments.ArgumentList; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.TypeDefinition; import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils; @@ -35,7 +35,7 @@ public class EnumConstant { PsiBuilder.Marker ecMarker = builder.mark(); ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); - Annotation.parseAnnotationOptional(builder, parser); + Modifiers.parse(builder, parser, true); if (!ParserUtils.getToken(builder, GroovyTokenTypes.mIDENT)) { ecMarker.rollbackTo(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java index 67a30cf99952..b855ff506d6d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java @@ -55,6 +55,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrImplements import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAnnotationMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList; @@ -228,6 +229,11 @@ public class GroovyIndentProcessor extends GroovyElementVisitor { myResult = Indent.getContinuationWithoutFirstIndent(); } + @Override + public void visitEnumConstant(@NotNull GrEnumConstant enumConstant) { + Indent.getNoneIndent(); + } + @Override public void visitDocComment(@NotNull GrDocComment comment) { if (myChildType != GroovyDocTokenTypes.mGDOC_COMMENT_START) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java index bd37decc15ca..c494530a1335 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java @@ -317,7 +317,11 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitEnumConstant(@NotNull GrEnumConstant enumConstant) { - manageSpaceBeforeCallLParenth(); + if (myType1 == GroovyElementTypes.MODIFIERS) { + createSpaceInCode(true); + } else { + manageSpaceBeforeCallLParenth(); + } } @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy index f545f5a1c0c8..83cc58c9fe10 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy @@ -688,6 +688,36 @@ def foooo( ''') } + void testEnumAnnotations() { + checkFormatting('''\ +enum GroovyEnum { + FOO, + @Deprecated + BAR(""), + DAR +} +''', '''\ +enum GroovyEnum { + FOO, + @Deprecated + BAR(""), + DAR +} +''') + } + + void testEnumAnnotationsSingleLine() { + checkFormatting('''\ +enum GroovyEnum { + @Deprecated BAR("") +} +''', '''\ +enum GroovyEnum { + @Deprecated BAR("") +} +''') + } + void testAlignFor() { groovySettings.ALIGN_MULTILINE_FOR = true checkFormatting('''\ diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum10.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum10.test index 789573d711d6..4e7caf757c65 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum10.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum10.test @@ -18,6 +18,8 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('CONST') PsiElement(new line)('\n ') Variable definitions diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum11.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum11.test index 86c5d1fc69e1..9d9c84d94e5c 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum11.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum11.test @@ -20,15 +20,21 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('Const1') PsiElement(new line)('\n ') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('Const2') PsiElement(,)(',') Enumeration constant PsiElement(new line)('\n ') + Modifiers + PsiElement(identifier)('Const3') PsiElement(new line)('\n ') Variable definitions diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum12.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum12.test index 3b815e198e89..127d34959284 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum12.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum12.test @@ -17,6 +17,8 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('Const') PsiElement(;)(';') PsiWhiteSpace(' ') diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum13.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum13.test index 1b12f0881842..9a8fb345b57e 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum13.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum13.test @@ -14,5 +14,7 @@ Groovy script PsiElement({)('{') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('CONST') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test index 1f2d2e8a4f97..17cc6c705649 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test @@ -19,6 +19,8 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('foo') PsiWhiteSpace(' ') Arguments diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test index 2ed2a2184094..d0a43174f19f 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test @@ -17,6 +17,8 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('foo') PsiElement(new line)('\n') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum8.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum8.test index ab9a1c2be4be..6826a41ce427 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum8.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum8.test @@ -18,11 +18,15 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('CONST1') PsiElement(new line)('\n ') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('CONST2') PsiElement(new line)('\n') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum9.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum9.test index 16838b5dda14..b433081d23cd 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum9.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum9.test @@ -17,6 +17,8 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('CONST1') PsiErrorElement:';', '}' or new line expected diff --git a/plugins/groovy/testdata/parsing/groovy/types/innerEnum.test b/plugins/groovy/testdata/parsing/groovy/types/innerEnum.test index bfa2b85653e5..76659bcf5fc3 100644 --- a/plugins/groovy/testdata/parsing/groovy/types/innerEnum.test +++ b/plugins/groovy/testdata/parsing/groovy/types/innerEnum.test @@ -37,30 +37,44 @@ Groovy script PsiWhiteSpace('\n ') Enumeration constants Enumeration constant + Modifiers + PsiElement(identifier)('SUNDAY') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('MONDAY') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('TUESDAY') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('WEDNESDAY') PsiElement(,)(',') Enumeration constant PsiElement(new line)('\n ') + Modifiers + PsiElement(identifier)('THURSDAY') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('FRIDAY') PsiElement(,)(',') PsiWhiteSpace(' ') Enumeration constant + Modifiers + PsiElement(identifier)('SATURDAY') PsiElement(new line)('\n ') PsiElement(})('}') From 6439e456896b0fd22dcbcdc7f12a5b311c4c5267 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 14 Apr 2017 13:32:00 +0300 Subject: [PATCH 06/26] IDEA-171426 Disabling "Hide navigation popups on focus loss" prevents resizing of Find class by name dialog --- .../ide/util/gotoByName/ChooseByNamePopup.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java index 6577b11ae924..bf35a3e6f853 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java @@ -152,6 +152,13 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP preferredScrollPaneSize.width = Math.max(myTextFieldPanel.getWidth(), preferredScrollPaneSize.width); + // in 'focus follows mouse' mode, to avoid focus escaping to editor, don't reduce popup size when list size is reduced + if (myDropdownPopup != null && !isCloseByFocusLost()) { + Dimension currentSize = myDropdownPopup.getSize(); + if (preferredScrollPaneSize.width < currentSize.width) preferredScrollPaneSize.width = currentSize.width; + if (preferredScrollPaneSize.height < currentSize.height) preferredScrollPaneSize.height = currentSize.height; + } + Rectangle preferredBounds = new Rectangle(bounds.x, bounds.y, preferredScrollPaneSize.width, preferredScrollPaneSize.height); Rectangle original = new Rectangle(preferredBounds); @@ -190,13 +197,7 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP } else { myDropdownPopup.setLocation(preferredBounds.getLocation()); - - // in 'focus follows mouse' mode, to avoid focus escaping to editor, don't reduce popup size when list size is reduced - final Dimension currentSize = myDropdownPopup.getSize(); - if (UISettings.getInstance().getHideNavigationOnFocusLoss() || - preferredBounds.width > currentSize.width || preferredBounds.height > currentSize.height) { - myDropdownPopup.setSize(preferredBounds.getSize()); - } + myDropdownPopup.setSize(preferredBounds.getSize()); } } From c31f7ca36f4af8070e847a305fb038d6a5c123ad Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 14 Apr 2017 13:33:07 +0300 Subject: [PATCH 07/26] AbstractPopup: getSize and setSize must be consistent --- .../com/intellij/ui/popup/AbstractPopup.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 3932fd6638b9..cbf19409b6ea 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1314,7 +1314,7 @@ public class AbstractPopup implements JBPopup { } } - size = computeWindowSize(size); + size.height += getAdComponentHeight(); final Window window = getContentWindow(myContent); if (window != null) { @@ -1590,27 +1590,27 @@ public class AbstractPopup implements JBPopup { } else { if (adjustByContent) { - toSet = computeWindowSize(toSet); + toSet.height += getAdComponentHeight(); } updateMaskAndAlpha(setSize(myContent, toSet)); } } - private Dimension computeWindowSize(Dimension size) { - if (myAdComponent != null && myAdComponent.isShowing()) { - size.height += myAdComponent.getPreferredSize().height + 1; - } - return size; + private int getAdComponentHeight() { + return myAdComponent != null && myAdComponent.isShowing() ? myAdComponent.getPreferredSize().height + 1 : 0; } @Override public Dimension getSize() { if (myPopup != null) { final Window popupWindow = getContentWindow(myContent); - return (popupWindow == null) ? myForcedSize : popupWindow.getSize(); - } else { - return myForcedSize; + if (popupWindow != null) { + Dimension size = popupWindow.getSize(); + size.height -= getAdComponentHeight(); + return size; + } } + return myForcedSize; } @Override From fe9ea5b112ea89a64400f400ff8d2766c5ea8d9b Mon Sep 17 00:00:00 2001 From: Eldar Abusalimov Date: Fri, 14 Apr 2017 13:38:00 +0300 Subject: [PATCH 08/26] execution: (test) Trim trailing spaces in PtyCommandLineTest For some reason WinPty loses trailing spaces in the argument. --- .../com/intellij/execution/GeneralCommandLineTest.java | 4 ++-- .../testSrc/com/intellij/execution/PtyCommandLineTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java b/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java index 8d6f264a1b78..f87c889a88ce 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java @@ -291,7 +291,7 @@ public class GeneralCommandLineTest { if (argument.trim().isEmpty()) continue; // would report "ECHO is on" GeneralCommandLine commandLine = createCommandLine(ExecUtil.getWindowsShellName(), "/D", "/C", "echo", argument); String output = execAndGetOutput(commandLine); - assertEquals(commandLine.getPreparedCommandLine(), argument + "\n", output); + assertEquals(commandLine.getPreparedCommandLine(), filterExpectedOutput(argument) + "\n", output); } } @@ -305,7 +305,7 @@ public class GeneralCommandLineTest { for (String argument : ARGUMENTS) { GeneralCommandLine commandLine = createCommandLine(cygwinPrintf.getPath(), "[%s]\\\\n", argument); String output = execAndGetOutput(commandLine); - assertEquals(commandLine.getPreparedCommandLine(), filterExpectedOutput("[" + argument + "]\n"), output); + assertEquals(commandLine.getPreparedCommandLine(), filterExpectedOutput("[" + argument + "]") + "\n", output); } } diff --git a/platform/platform-tests/testSrc/com/intellij/execution/PtyCommandLineTest.java b/platform/platform-tests/testSrc/com/intellij/execution/PtyCommandLineTest.java index 2b270deb21b7..f728e9715857 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/PtyCommandLineTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/PtyCommandLineTest.java @@ -32,7 +32,7 @@ public class PtyCommandLineTest extends GeneralCommandLineTest { @NotNull @Override protected String filterExpectedOutput(@NotNull String output) { - if (SystemInfo.isWindows) output = expandTabs(output, 8); + if (SystemInfo.isWindows) output = StringUtil.trimTrailing(expandTabs(output, 8)); return output; } From c27f0832864ce31aed8cb89bd5d0c5fc7bb439b2 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 14 Apr 2017 13:50:33 +0300 Subject: [PATCH 09/26] IDEA-153597 Settings > Appearance > "Override default fonts" should display current font when unchecked --- .../src/com/intellij/ide/ui/UISettings.kt | 11 ++++++++--- .../com/intellij/ide/ui/AppearanceConfigurable.java | 11 +++++++++++ platform/util/src/com/intellij/util/ui/JBUI.java | 4 +++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt index 13595ec315c0..08ed57c673c0 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt @@ -19,6 +19,7 @@ import com.intellij.ide.WelcomeWizardUtil import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.* +import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.IconLoader import com.intellij.openapi.util.Pair import com.intellij.openapi.util.SystemInfo @@ -264,6 +265,8 @@ class UISettings : BaseState(), PersistentStateComponent { } companion object { + private val LOG = Logger.getInstance(UISettings::class.java) + const val ANIMATION_DURATION = 300 // Milliseconds /** Not tabbed pane. */ @@ -369,14 +372,16 @@ class UISettings : BaseState(), PersistentStateComponent { @JvmStatic fun restoreFontSize(readSize: Int, readScale: Float?): Int { + var size = readSize if (readScale == null || readScale <= 0) { // Reset font to default on switch from IDE-managed HiDPI to JRE-managed HiDPI. Doesn't affect OSX. - if (UIUtil.isJreHiDPIEnabled() && !SystemInfo.isMac) return UIUtil.DEF_SYSTEM_FONT_SIZE.toInt() + if (UIUtil.isJreHiDPIEnabled() && !SystemInfo.isMac) size = UIUtil.DEF_SYSTEM_FONT_SIZE.toInt() } else { - return ((readSize.toFloat() / readScale) * normalizingScale).toInt() + size = ((readSize.toFloat() / readScale) * normalizingScale).toInt() } - return readSize + LOG.info("Loaded: fontSize=$readSize, fontScale=$readScale; restored: fontSize=$size, fontScale=$normalizingScale") + return size } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index e8184f6beb2e..fdef6fcde7cd 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -35,6 +35,7 @@ import com.intellij.ui.FontComboBox; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -198,9 +199,11 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab settings.setAllowMergeButtons(myComponent.myAllowMergeButtons.isSelected()); update |= settings.getCycleScrolling() != myComponent.myCycleScrollingCheckBox.isSelected(); settings.setCycleScrolling(myComponent.myCycleScrollingCheckBox.isSelected()); + boolean shouldResetLafFonts = false; if (settings.getOverrideLafFonts() != myComponent.myOverrideLAFFonts.isSelected()) { shouldUpdateUI = true; update = true; + shouldResetLafFonts = !myComponent.myOverrideLAFFonts.isSelected(); } settings.setOverrideLafFonts(myComponent.myOverrideLAFFonts.isSelected()); settings.setMoveMouseOnDefaultButton(myComponent.myMoveMouseOnDefaultButtonCheckBox.isSelected()); @@ -253,6 +256,14 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab if (shouldUpdateUI) { lafManager.updateUI(); + if (shouldResetLafFonts) { + int defSize = JBUI.Fonts.label().getSize(); + settings.setFontSize(defSize); + myComponent.myFontSizeCombo.getModel().setSelectedItem(String.valueOf(defSize)); + String defName = JBUI.Fonts.label().getFontName(); + settings.setFontFace(defName); + myComponent.myFontCombo.setFontName(defName); + } } if (WindowManagerEx.getInstanceEx().isAlphaModeSupported()) { diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 686cb3a36f8b..43b3b18fd530 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -152,6 +152,8 @@ public class JBUI { static { setUserScaleFactor(UIUtil.isJreHiDPIEnabled() ? 1f : SYSTEM_SCALE_FACTOR); + LOG.info("System scale factor: " + SYSTEM_SCALE_FACTOR + " (" + + (UIUtil.isJreHiDPIEnabled() ? "JRE-managed" : "IDE-managed") + " HiDPI)"); } /** @@ -315,7 +317,7 @@ public class JBUI { private static void setUserScaleFactorProperty(float scale) { PCS.firePropertyChange(USER_SCALE_FACTOR_PROPERTY, userScaleFactor, userScaleFactor = scale); - LOG.info("UI scale factor: " + userScaleFactor); + LOG.info("User scale factor: " + userScaleFactor); } /** From fd1bf63dbb7ea1de5e277e1956db3a1c8ad7431a Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 14 Apr 2017 14:13:34 +0300 Subject: [PATCH 10/26] properties: use PsiBasedFormattingModel (IDEA-163408) --- .../PropertiesFormattingModelBuilder.java | 42 ++----------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/plugins/properties/src/com/intellij/lang/properties/formatting/PropertiesFormattingModelBuilder.java b/plugins/properties/src/com/intellij/lang/properties/formatting/PropertiesFormattingModelBuilder.java index 699616b5bcbb..d6fa4e658007 100644 --- a/plugins/properties/src/com/intellij/lang/properties/formatting/PropertiesFormattingModelBuilder.java +++ b/plugins/properties/src/com/intellij/lang/properties/formatting/PropertiesFormattingModelBuilder.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormattingDocumentModelImpl; +import com.intellij.psi.formatter.PsiBasedFormattingModel; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.impl.source.tree.TreeUtil; @@ -34,10 +35,10 @@ import org.jetbrains.annotations.Nullable; public class PropertiesFormattingModelBuilder implements FormattingModelBuilder { @NotNull @Override - public PropertiesFormattingModel createModel(PsiElement element, CodeStyleSettings settings) { + public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { final ASTNode root = TreeUtil.getFileElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(element)); final FormattingDocumentModelImpl documentModel = FormattingDocumentModelImpl.createOn(element.getContainingFile()); - return new PropertiesFormattingModel(root, documentModel, settings); + return new PsiBasedFormattingModel(element.getContainingFile(), new PropertiesRootBlock(root, settings), documentModel); } @Nullable @@ -45,41 +46,4 @@ public class PropertiesFormattingModelBuilder implements FormattingModelBuilder public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { return null; } - - private static class PropertiesFormattingModel implements FormattingModel { - private final FormattingDocumentModelImpl myDocumentModel; - private PropertiesRootBlock myRoot; - - public PropertiesFormattingModel(ASTNode root, FormattingDocumentModelImpl documentModel, CodeStyleSettings settings) { - myRoot = new PropertiesRootBlock(root, settings); - myDocumentModel = documentModel; - } - - @NotNull - @Override - public Block getRootBlock() { - return myRoot; - } - - @NotNull - @Override - public FormattingDocumentModel getDocumentModel() { - return myDocumentModel; - } - - @Override - public TextRange replaceWhiteSpace(TextRange textRange, String whiteSpace) { - return textRange; - } - - @Override - public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) { - return null; - } - - @Override - public void commitChanges() { - - } - } } From d7c135b7b93332f27a1d3a3a54372cf7652802af Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 11 Apr 2017 22:11:04 +0300 Subject: [PATCH 11/26] [vcs-log] introduce VcsLogDiffHandler interface and an implementation for git This class will handle diff from log-based file history. We could use DiffFromHistoryHandler for this, but the problem is that standart handler can not handle diff for directories (IDEA-170456, IDEA-171150) and vcs-specific handlers work with vcs-specific instances of VcsFileRevision. There is no api to create such revisions from log, and it is unclear whether we really want to have it, since VcsFileRevision is such a flawed concept (this is why we have things like VcsFileRevisionEx). So new, VcsFileRevision-free, handler is introduced to help with the problem. --- .../intellij/vcs/log/VcsLogDiffHandler.java | 33 ++++ .../com/intellij/vcs/log/VcsLogProvider.java | 3 + .../vcs/log/impl/TestVcsLogProvider.java | 6 + .../src/git4idea/log/GitLogDiffHandler.java | 168 ++++++++++++++++++ .../src/git4idea/log/GitLogProvider.java | 6 + .../org/zmlx/hg4idea/log/HgLogProvider.java | 6 + 6 files changed, 222 insertions(+) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java create mode 100644 plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java new file mode 100644 index 000000000000..826fe76e0252 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2017 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.vcs.log; + +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface VcsLogDiffHandler { + void showDiff(@NotNull VirtualFile root, + @Nullable FilePath leftPath, @NotNull Hash leftHash, + @Nullable FilePath rightPath, @NotNull Hash rightHash) throws VcsException; + + void showDiffWithLocal(@NotNull VirtualFile root, + @Nullable FilePath revisionPath, + @NotNull Hash hash, @NotNull FilePath localPath) + throws VcsException; +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java index 0eb26b4a5002..6e001856eb36 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java @@ -147,6 +147,9 @@ public interface VcsLogProvider { @Nullable String getCurrentBranch(@NotNull VirtualFile root); + @Nullable + VcsLogDiffHandler getDiffHandler(); + interface Requirements { /** diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java index 7f9b4e69fb6a..e266d4cb777e 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java @@ -234,6 +234,12 @@ public class TestVcsLogProvider implements VcsLogProvider { return null; } + @Nullable + @Override + public VcsLogDiffHandler getDiffHandler() { + return null; + } + private static class MockRefManager implements VcsLogRefManager { public static final Comparator FAKE_COMPARATOR = (o1, o2) -> 0; diff --git a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java new file mode 100644 index 000000000000..06a3918bf092 --- /dev/null +++ b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java @@ -0,0 +1,168 @@ +/* + * Copyright 2000-2017 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 git4idea.log; + +import com.intellij.diff.DiffContentFactoryEx; +import com.intellij.diff.DiffManager; +import com.intellij.diff.DiffRequestFactoryImpl; +import com.intellij.diff.contents.DiffContent; +import com.intellij.diff.contents.EmptyContent; +import com.intellij.diff.requests.DiffRequest; +import com.intellij.diff.requests.SimpleDiffRequest; +import com.intellij.diff.util.DiffUserDataKeysEx; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.history.VcsDiffUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.WaitForProgressToShow; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsLogDiffHandler; +import com.intellij.vcsUtil.VcsFileUtil; +import git4idea.GitRevisionNumber; +import git4idea.changes.GitChangeUtils; +import git4idea.util.GitFileUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; + +import static com.intellij.util.ObjectUtils.chooseNotNull; +import static com.intellij.util.ObjectUtils.notNull; + +public class GitLogDiffHandler implements VcsLogDiffHandler { + private static final Logger LOG = Logger.getInstance(GitLogDiffHandler.class); + @NotNull private final Project myProject; + @NotNull private final DiffContentFactoryEx myDiffContentFactory; + + public GitLogDiffHandler(@NotNull Project project) { + myProject = project; + myDiffContentFactory = DiffContentFactoryEx.getInstanceEx(); + } + + @Override + public void showDiff(@NotNull VirtualFile root, + @Nullable FilePath leftPath, + @NotNull Hash leftHash, + @Nullable FilePath rightPath, + @NotNull Hash rightHash) throws VcsException { + if (leftPath == null && rightPath == null) return; + + if (chooseNotNull(leftPath, rightPath).isDirectory()) { + showDiffForDirectory(root, chooseNotNull(leftPath, rightPath), leftHash, rightHash); + } + else { + try { + DiffContent leftDiffContent = createDiffContent(root, leftPath, leftHash); + DiffContent rightDiffContent = createDiffContent(root, rightPath, rightHash); + + DiffRequest request = new SimpleDiffRequest(getTitle(leftPath, rightPath), + leftDiffContent, rightDiffContent, + leftHash.asString(), rightHash.asString()); + + WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> DiffManager.getInstance().showDiff(myProject, request), null, myProject); + } + catch (IOException e) { + LOG.error(e); + } + } + } + + @Override + public void showDiffWithLocal(@NotNull VirtualFile root, @Nullable FilePath revisionPath, @NotNull Hash revisionHash, + @NotNull FilePath localPath) + throws VcsException { + if (localPath.isDirectory()) { + showDiffForDirectory(root, localPath, revisionHash, null); + } + else { + try { + DiffContent leftDiffContent = createDiffContent(root, revisionPath, revisionHash); + + VirtualFile file = localPath.getVirtualFile(); + LOG.assertTrue(file != null); + DiffContent rightDiffContent = myDiffContentFactory.create(myProject, file); + + DiffRequest request = new SimpleDiffRequest(getTitle(revisionPath, localPath), + leftDiffContent, rightDiffContent, + revisionHash.asString(), "(Local)"); + + WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> DiffManager.getInstance().showDiff(myProject, request), null, myProject); + } + catch (IOException e) { + LOG.error(e); + } + } + } + + private void showDiffForDirectory(@NotNull VirtualFile root, + @NotNull FilePath directoryPath, + @NotNull Hash leftRevision, @Nullable Hash rightRevision) throws VcsException { + Collection diff = GitChangeUtils.getDiff(myProject, root, + leftRevision.asString(), rightRevision == null ? null : rightRevision.asString(), + Collections.singleton(directoryPath)); + WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> { + String dialogTitle = "Changes between " + + leftRevision.asString() + + " and " + + (rightRevision == null ? "current revision" : rightRevision.asString()) + + " in " + + getTitle(directoryPath, directoryPath); + VcsDiffUtil.showChangesDialog(myProject, dialogTitle, + ContainerUtil.newArrayList(diff)); + }, + null, + myProject); + } + + @NotNull + private DiffContent createDiffContent(@NotNull VirtualFile root, + @Nullable FilePath path, + @NotNull Hash hash) throws IOException, VcsException { + DiffContent diffContent; + if (path == null) { + diffContent = new EmptyContent(); + } + else { + byte[] content = GitFileUtils.getFileContent(myProject, root, hash.asString(), VcsFileUtil.relativePath(root, path)); + diffContent = myDiffContentFactory.createFromBytes(myProject, content, path); + } + + diffContent.putUserData(DiffUserDataKeysEx.REVISION_INFO, new Pair<>(path, new GitRevisionNumber(hash.asString()))); + + return diffContent; + } + + @NotNull + private static String getTitle(@Nullable FilePath leftPath, @Nullable FilePath rightPath) { + LOG.assertTrue(leftPath != null || rightPath != null); + + if (Objects.equals(rightPath, leftPath)) { + return DiffRequestFactoryImpl.getContentTitle(notNull(leftPath)); + } + if (leftPath == null || rightPath == null) { + return DiffRequestFactoryImpl.getContentTitle(chooseNotNull(leftPath, rightPath)); + } + return DiffRequestFactoryImpl.getTitle(leftPath, rightPath, " -> "); + } +} diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index 87cb84b1027d..fa975deb9411 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -529,6 +529,12 @@ public class GitLogProvider implements VcsLogProvider { return currentBranchName; } + @Nullable + @Override + public VcsLogDiffHandler getDiffHandler() { + return new GitLogDiffHandler(myProject); + } + @SuppressWarnings("unchecked") @Nullable @Override diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java index 6932b860dd81..557ebd2afd22 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java @@ -335,6 +335,12 @@ public class HgLogProvider implements VcsLogProvider { return repository.getCurrentBranchName(); } + @Nullable + @Override + public VcsLogDiffHandler getDiffHandler() { + return null; + } + @Nullable @Override public T getPropertyValue(VcsLogProperties.VcsLogProperty property) { From 099e618d73a0e7bd674f1ca58bbcd3277fbf681b Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 00:03:08 +0300 Subject: [PATCH 12/26] [file-history] use VcsLogDiffHandler when comparing revisions in file history Since VcsLogDiffHandler can handle directory diff, this fixes IDEA-170456. --- .../vcs/log/history/FileHistoryUi.java | 15 ++++ .../CompareRevisionsFromHistoryAction.java | 79 +++++++++++-------- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUi.java index b198b97a8057..9c4c503ef56b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUi.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUi.java @@ -130,6 +130,21 @@ public class FileHistoryUi extends AbstractVcsLogUi { return null; } + @Nullable + public FilePath getPath(@NotNull VcsFullCommitDetails details) { + if (myPath.isDirectory()) return myPath; + + List changes = collectRelevantChanges(details); + for (Change change : changes) { + ContentRevision revision = change.getAfterRevision(); + if (revision != null) { + return revision.getFile(); + } + } + + return null;// file was deleted + } + @NotNull public List collectRelevantChanges(@NotNull VcsFullCommitDetails details) { Set fileNames = getFileNames(details); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java index feafd3dfeca0..b98c57ebce43 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java @@ -18,22 +18,25 @@ package com.intellij.vcs.log.ui.actions.history; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsDataKeys; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.actions.diff.ShowDiffAction; import com.intellij.openapi.vcs.changes.actions.diff.ShowDiffContext; -import com.intellij.openapi.vcs.history.DiffFromHistoryHandler; -import com.intellij.openapi.vcs.history.StandardDiffFromHistoryHandler; import com.intellij.openapi.vcs.history.VcsDiffUtil; -import com.intellij.openapi.vcs.history.VcsFileRevision; -import com.intellij.util.ObjectUtils; +import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.CommitId; import com.intellij.vcs.log.VcsFullCommitDetails; -import com.intellij.vcs.log.data.LoadingDetails; +import com.intellij.vcs.log.VcsLogDiffHandler; import com.intellij.vcs.log.history.FileHistoryUi; import com.intellij.vcs.log.impl.VcsLogUtil; import com.intellij.vcs.log.ui.VcsLogInternalDataKeys; @@ -43,12 +46,13 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.List; +import static com.intellij.util.ObjectUtils.notNull; + public class CompareRevisionsFromHistoryAction extends AnAction implements DumbAware { private static final String COMPARE_TEXT = "Compare"; private static final String COMPARE_DESCRIPTION = "Compare selected versions"; private static final String DIFF_TEXT = "Show Diff"; private static final String DIFF_DESCRIPTION = "Show diff with previous version"; - @NotNull private final DiffFromHistoryHandler myDiffHandler = new StandardDiffFromHistoryHandler(); public void update(@NotNull AnActionEvent e) { Project project = e.getProject(); @@ -61,31 +65,21 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA e.getPresentation().setVisible(true); - List details = ui.getVcsLog().getSelectedDetails(); - + List commits = ui.getVcsLog().getSelectedCommits(); if (e.getInputEvent() instanceof KeyEvent) { e.getPresentation().setEnabled(true); } else { - if (details.size() == 2) { - VcsFullCommitDetails detail0 = details.get(0); - VcsFullCommitDetails detail1 = details.get(1); - if (detail0 != null && !(detail0 instanceof LoadingDetails) && - detail1 != null && !(detail1 instanceof LoadingDetails)) { - VcsFileRevision newestRevision = ui.createRevision(detail0); - VcsFileRevision olderRevision = ui.createRevision(detail1); - e.getPresentation().setEnabled(newestRevision != null && olderRevision != null && !filePath.isDirectory()); - } - else { - e.getPresentation().setEnabled(!filePath.isDirectory()); - } + if (commits.size() == 2) { + VcsLogDiffHandler handler = ui.getLogData().getLogProvider(commits.get(0).getRoot()).getDiffHandler(); + e.getPresentation().setEnabled(handler != null); } else { - e.getPresentation().setEnabled(details.size() == 1); + e.getPresentation().setEnabled(commits.size() == 1); } } - if (details.size() == 2) { + if (commits.size() == 2) { e.getPresentation().setText(COMPARE_TEXT); e.getPresentation().setDescription(COMPARE_DESCRIPTION); } @@ -109,24 +103,41 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA VcsLogUtil.triggerUsage(e); List commits = ui.getVcsLog().getSelectedCommits(); - if (filePath.isDirectory()) { - if (commits.size() != 1) return; - } - else { - if (commits.size() != 1 && commits.size() != 2) return; - } + if (commits.size() != 1 && commits.size() != 2) return; + + VirtualFile root = commits.get(0).getRoot(); + VcsLogDiffHandler handler = ui.getLogData().getLogProvider(root).getDiffHandler(); + if (commits.size() == 2 && handler == null) return; List commitIds = ContainerUtil.map(commits, c -> ui.getLogData().getCommitIndex(c.getHash(), c.getRoot())); ui.getLogData().getCommitDetailsGetter().loadCommitsData(commitIds, details -> { if (details.size() == 2) { - VcsFileRevision newestRevision = ui.createRevision(details.get(0)); - VcsFileRevision olderRevision = ui.createRevision(details.get(1)); - if (olderRevision != null && newestRevision != null) { - myDiffHandler.showDiffForTwo(project, filePath, olderRevision, newestRevision); - } + // we only need details here to get file names for each revision + // in order to fix this FileNamesData should be refactored + // so that it could return a single file path for each revision + VcsFullCommitDetails newestDetail = details.get(0); + VcsFullCommitDetails olderDetail = details.get(1); + ProgressIndicator indicator = ui.getLogData().getProgress().createProgressIndicator(true); + ProgressManager.getInstance() + .runProcessWithProgressAsynchronously(new Task.Backgroundable(project, "Comparing Revisions...", false) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + notNull(handler).showDiff(root, ui.getPath(olderDetail), olderDetail.getId(), ui.getPath(newestDetail), newestDetail.getId()); + } + catch (VcsException e1) { + VcsBalloonProblemNotifier.showOverVersionControlView(project, "Could not compare revisions " + + olderDetail.getId().asString() + + " and " + + newestDetail.getId().asString() + + "\n" + + e1.getMessage(), MessageType.ERROR); + } + } + }, indicator); } else if (details.size() == 1) { - VcsFullCommitDetails detail = ObjectUtils.notNull(ContainerUtil.getFirstItem(details)); + VcsFullCommitDetails detail = notNull(ContainerUtil.getFirstItem(details)); List changes = ui.collectRelevantChanges(detail); if (filePath.isDirectory()) { VcsDiffUtil.showChangesDialog(project, "Changes in " + detail.getId().toShortString() + " for " + filePath.getName(), From 15b98239ea1044f7ed128c59d584fec9efa7831a Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 19:23:41 +0300 Subject: [PATCH 13/26] [file-history] move code for loading diff in background to GitLogDiffHandler Reuse the code in all diff kinds. This way actions would not need to manage background execution themselves. --- .../intellij/vcs/log/VcsLogDiffHandler.java | 6 +- .../CompareRevisionsFromHistoryAction.java | 19 +-- .../src/git4idea/log/GitLogDiffHandler.java | 152 ++++++++++++------ 3 files changed, 104 insertions(+), 73 deletions(-) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java index 826fe76e0252..f334465a062f 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java @@ -16,7 +16,6 @@ package com.intellij.vcs.log; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,10 +23,9 @@ import org.jetbrains.annotations.Nullable; public interface VcsLogDiffHandler { void showDiff(@NotNull VirtualFile root, @Nullable FilePath leftPath, @NotNull Hash leftHash, - @Nullable FilePath rightPath, @NotNull Hash rightHash) throws VcsException; + @Nullable FilePath rightPath, @NotNull Hash rightHash); void showDiffWithLocal(@NotNull VirtualFile root, @Nullable FilePath revisionPath, - @NotNull Hash hash, @NotNull FilePath localPath) - throws VcsException; + @NotNull Hash hash, @NotNull FilePath localPath); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java index b98c57ebce43..dea68d90358e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java @@ -117,24 +117,7 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA // so that it could return a single file path for each revision VcsFullCommitDetails newestDetail = details.get(0); VcsFullCommitDetails olderDetail = details.get(1); - ProgressIndicator indicator = ui.getLogData().getProgress().createProgressIndicator(true); - ProgressManager.getInstance() - .runProcessWithProgressAsynchronously(new Task.Backgroundable(project, "Comparing Revisions...", false) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - try { - notNull(handler).showDiff(root, ui.getPath(olderDetail), olderDetail.getId(), ui.getPath(newestDetail), newestDetail.getId()); - } - catch (VcsException e1) { - VcsBalloonProblemNotifier.showOverVersionControlView(project, "Could not compare revisions " + - olderDetail.getId().asString() + - " and " + - newestDetail.getId().asString() + - "\n" + - e1.getMessage(), MessageType.ERROR); - } - } - }, indicator); + notNull(handler).showDiff(root, ui.getPath(olderDetail), olderDetail.getId(), ui.getPath(newestDetail), newestDetail.getId()); } else if (details.size() == 1) { VcsFullCommitDetails detail = notNull(ContainerUtil.getFirstItem(details)); diff --git a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java index 06a3918bf092..42c1cb59ec89 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java +++ b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java @@ -23,15 +23,21 @@ import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.requests.DiffRequest; import com.intellij.diff.requests.SimpleDiffRequest; import com.intellij.diff.util.DiffUserDataKeysEx; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.history.VcsDiffUtil; +import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.WaitForProgressToShow; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLogDiffHandler; @@ -39,11 +45,11 @@ import com.intellij.vcsUtil.VcsFileUtil; import git4idea.GitRevisionNumber; import git4idea.changes.GitChangeUtils; import git4idea.util.GitFileUtils; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Collection; import java.util.Collections; import java.util.Objects; @@ -65,87 +71,131 @@ public class GitLogDiffHandler implements VcsLogDiffHandler { @Nullable FilePath leftPath, @NotNull Hash leftHash, @Nullable FilePath rightPath, - @NotNull Hash rightHash) throws VcsException { + @NotNull Hash rightHash) { if (leftPath == null && rightPath == null) return; if (chooseNotNull(leftPath, rightPath).isDirectory()) { showDiffForDirectory(root, chooseNotNull(leftPath, rightPath), leftHash, rightHash); } else { - try { - DiffContent leftDiffContent = createDiffContent(root, leftPath, leftHash); - DiffContent rightDiffContent = createDiffContent(root, rightPath, rightHash); + loadDiffAndShow(new ThrowableComputable() { + @Override + public DiffRequest compute() throws VcsException { + DiffContent leftDiffContent = createDiffContent(root, leftPath, leftHash); + DiffContent rightDiffContent = createDiffContent(root, rightPath, rightHash); - DiffRequest request = new SimpleDiffRequest(getTitle(leftPath, rightPath), - leftDiffContent, rightDiffContent, - leftHash.asString(), rightHash.asString()); - - WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> DiffManager.getInstance().showDiff(myProject, request), null, myProject); - } - catch (IOException e) { - LOG.error(e); - } + return new SimpleDiffRequest(getTitle(leftPath, rightPath), + leftDiffContent, rightDiffContent, + leftHash.asString(), rightHash.asString()); + } + }, + request -> DiffManager.getInstance().showDiff(myProject, request), + "Calculating Diff for " + chooseNotNull(rightPath, leftPath).getName()); } } @Override public void showDiffWithLocal(@NotNull VirtualFile root, @Nullable FilePath revisionPath, @NotNull Hash revisionHash, - @NotNull FilePath localPath) - throws VcsException { + @NotNull FilePath localPath) { if (localPath.isDirectory()) { showDiffForDirectory(root, localPath, revisionHash, null); } else { - try { - DiffContent leftDiffContent = createDiffContent(root, revisionPath, revisionHash); + loadDiffAndShow(new ThrowableComputable() { + @Override + public DiffRequest compute() throws VcsException { + DiffContent leftDiffContent = createDiffContent(root, revisionPath, revisionHash); - VirtualFile file = localPath.getVirtualFile(); - LOG.assertTrue(file != null); - DiffContent rightDiffContent = myDiffContentFactory.create(myProject, file); + VirtualFile file = localPath.getVirtualFile(); + LOG.assertTrue(file != null); + DiffContent rightDiffContent = myDiffContentFactory.create(myProject, file); - DiffRequest request = new SimpleDiffRequest(getTitle(revisionPath, localPath), - leftDiffContent, rightDiffContent, - revisionHash.asString(), "(Local)"); - - WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> DiffManager.getInstance().showDiff(myProject, request), null, myProject); - } - catch (IOException e) { - LOG.error(e); - } + return new SimpleDiffRequest(getTitle(revisionPath, localPath), + leftDiffContent, rightDiffContent, + revisionHash.asString(), "(Local)"); + } + }, + request -> DiffManager.getInstance().showDiff(myProject, request), "Calculating Diff for " + localPath.getName()); } } private void showDiffForDirectory(@NotNull VirtualFile root, @NotNull FilePath directoryPath, - @NotNull Hash leftRevision, @Nullable Hash rightRevision) throws VcsException { - Collection diff = GitChangeUtils.getDiff(myProject, root, - leftRevision.asString(), rightRevision == null ? null : rightRevision.asString(), - Collections.singleton(directoryPath)); - WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> { - String dialogTitle = "Changes between " + - leftRevision.asString() + - " and " + - (rightRevision == null ? "current revision" : rightRevision.asString()) + - " in " + - getTitle(directoryPath, directoryPath); - VcsDiffUtil.showChangesDialog(myProject, dialogTitle, - ContainerUtil.newArrayList(diff)); - }, - null, - myProject); + @NotNull Hash leftRevision, @Nullable Hash rightRevision) { + loadDiffAndShow(() -> GitChangeUtils.getDiff(myProject, root, + leftRevision.asString(), rightRevision == null ? null : rightRevision.asString(), + Collections.singleton(directoryPath)), + (diff) -> { + String dialogTitle = "Changes between " + + leftRevision.asString() + + " and " + + (rightRevision == null ? "current revision" : rightRevision.asString()) + + " in " + + getTitle(directoryPath, directoryPath); + VcsDiffUtil.showChangesDialog(myProject, dialogTitle, ContainerUtil.newArrayList(diff)); + }, "Calculating Diff for " + directoryPath.getName()); + } + + private void loadDiffAndShow(@NotNull ThrowableComputable load, + @NotNull Consumer show, + @NotNull @Nls(capitalization = Nls.Capitalization.Title) String title) { + if (ApplicationManager.getApplication().isDispatchThread()) { + ProgressManager.getInstance().run(new Task.Backgroundable(myProject, title + "...", false) { + @Nullable private T myResult; + + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + myResult = load.compute(); + } + catch (VcsException e) { + throw new RuntimeException(e); + } + } + + @Override + public void onSuccess() { + if (myResult != null) { + show.consume(myResult); + } + } + + @Override + public void onThrowable(@NotNull Throwable error) { + VcsBalloonProblemNotifier.showOverVersionControlView(myProject, title + " failed\n" + + error.getMessage(), MessageType.ERROR); + } + }); + } + else { + try { + T result = load.compute(); + ApplicationManager.getApplication().invokeLater(() -> show.consume(result)); + } + catch (VcsException e) { + VcsBalloonProblemNotifier.showOverVersionControlView(myProject, title + " failed\n" + + e.getMessage(), MessageType.ERROR); + } + } } @NotNull private DiffContent createDiffContent(@NotNull VirtualFile root, @Nullable FilePath path, - @NotNull Hash hash) throws IOException, VcsException { + @NotNull Hash hash) throws VcsException { + DiffContent diffContent; if (path == null) { diffContent = new EmptyContent(); } else { - byte[] content = GitFileUtils.getFileContent(myProject, root, hash.asString(), VcsFileUtil.relativePath(root, path)); - diffContent = myDiffContentFactory.createFromBytes(myProject, content, path); + try { + byte[] content = GitFileUtils.getFileContent(myProject, root, hash.asString(), VcsFileUtil.relativePath(root, path)); + diffContent = myDiffContentFactory.createFromBytes(myProject, content, path); + } + catch (IOException e) { + throw new VcsException(e); + } } diffContent.putUserData(DiffUserDataKeysEx.REVISION_INFO, new Pair<>(path, new GitRevisionNumber(hash.asString()))); From 1e2e154c7bbcccf0fdf89df7db807e38870b8928 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 21:58:08 +0300 Subject: [PATCH 14/26] [file-history] use VcsLogDiffHandler for diff with local in file history This fixes directory diff IDEA-171150. --- .../ShowDiffWithLocalFromHistoryAction.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java index 9705212778a9..3fa1861d1131 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java @@ -20,30 +20,29 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vcs.history.CurrentRevision; -import com.intellij.openapi.vcs.history.StandardDiffFromHistoryHandler; -import com.intellij.openapi.vcs.history.VcsFileRevision; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcs.log.CommitId; import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsLogDiffHandler; import com.intellij.vcs.log.history.FileHistoryUi; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.intellij.util.ObjectUtils.notNull; +import java.util.List; public class ShowDiffWithLocalFromHistoryAction extends FileHistorySingleCommitAction { @Override protected boolean isEnabled(@NotNull FileHistoryUi ui, @Nullable VcsFullCommitDetails detail, @NotNull AnActionEvent e) { FilePath filePath = e.getData(VcsDataKeys.FILE_PATH); - if (filePath == null || filePath.isDirectory() || filePath.getVirtualFile() == null) { - // currently not working for directories, to be fixed later + if (filePath == null || filePath.getVirtualFile() == null) { return false; } - if (detail != null) { - VcsFileRevision fileRevision = ui.createRevision(detail); - if (fileRevision == null) return false; + List commits = ui.getVcsLog().getSelectedCommits(); + if (filePath.isDirectory()) { + VcsLogDiffHandler handler = ui.getLogData().getLogProvider(commits.get(0).getRoot()).getDiffHandler(); + if (handler == null) return false; } return true; @@ -57,11 +56,11 @@ public class ShowDiffWithLocalFromHistoryAction extends FileHistorySingleCommitA if (ChangeListManager.getInstance(project).isFreezedWithNotification(null)) return; FilePath path = e.getRequiredData(VcsDataKeys.FILE_PATH); - VcsFileRevision revision = ui.createRevision(detail); - if (revision != null) { - StandardDiffFromHistoryHandler handler = new StandardDiffFromHistoryHandler(); - handler.showDiffForTwo(project, path, revision, new CurrentRevision(notNull(path.getVirtualFile()), VcsRevisionNumber.NULL)); + VirtualFile root = detail.getRoot(); + VcsLogDiffHandler handler = ui.getLogData().getLogProvider(root).getDiffHandler(); + if (handler != null) { + handler.showDiffWithLocal(root, ui.getPath(detail), detail.getId(), path); } } } From 50284989b6343c588325a9ddf782073e2809a74d Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 22:13:37 +0300 Subject: [PATCH 15/26] [file-history] introduce data key for VcsLogDiffHandler --- .../vcs/log/history/FileHistoryPanel.java | 7 ++++++ .../vcs/log/ui/VcsLogInternalDataKeys.java | 2 ++ .../CompareRevisionsFromHistoryAction.java | 10 ++++---- .../ShowDiffWithLocalFromHistoryAction.java | 24 ++++--------------- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryPanel.java index 8df92e243f1b..141084025036 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryPanel.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.history.VcsFileRevision; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.*; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; @@ -35,6 +36,7 @@ import com.intellij.vcs.log.ui.frame.DetailsPanel; import com.intellij.vcs.log.ui.table.VcsLogGraphTable; import com.intellij.vcs.log.util.VcsLogUiUtil; import com.intellij.vcs.log.visible.VisiblePack; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,6 +53,7 @@ public class FileHistoryPanel extends JPanel implements DataProvider, Disposable @NotNull private final JBSplitter myDetailsSplitter; @NotNull private final FilePath myFilePath; @NotNull private final FileHistoryUi myUi; + @NotNull private final VirtualFile myRoot; public FileHistoryPanel(@NotNull FileHistoryUi ui, @NotNull VcsLogData logData, @@ -58,6 +61,7 @@ public class FileHistoryPanel extends JPanel implements DataProvider, Disposable @NotNull FilePath filePath) { myUi = ui; myFilePath = filePath; + myRoot = notNull(VcsUtil.getVcsRootFor(logData.getProject(), myFilePath)); myGraphTable = new VcsLogGraphTable(myUi, logData, visiblePack) { @Override protected boolean isSpeedSearchEnabled() { @@ -150,6 +154,9 @@ public class FileHistoryPanel extends JPanel implements DataProvider, Disposable else if (VcsDataKeys.VCS_NON_LOCAL_HISTORY_SESSION.is(dataId)) { return false; } + else if (VcsLogInternalDataKeys.LOG_DIFF_HANDLER.is(dataId)) { + return myUi.getLogData().getLogProvider(myRoot).getDiffHandler(); + } return null; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogInternalDataKeys.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogInternalDataKeys.java index a085525ffc03..6fb238ebe720 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogInternalDataKeys.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogInternalDataKeys.java @@ -16,6 +16,7 @@ package com.intellij.vcs.log.ui; import com.intellij.openapi.actionSystem.DataKey; +import com.intellij.vcs.log.VcsLogDiffHandler; import com.intellij.vcs.log.history.FileHistoryUi; import com.intellij.vcs.log.impl.VcsLogManager; import com.intellij.vcs.log.impl.VcsLogUiProperties; @@ -24,4 +25,5 @@ public class VcsLogInternalDataKeys { public static final DataKey LOG_MANAGER = DataKey.create("Vcs.Log.Manager"); public static final DataKey LOG_UI_PROPERTIES = DataKey.create("Vcs.Log.Ui.Properties"); public static final DataKey FILE_HISTORY_UI = DataKey.create("Vcs.FileHistory.Ui"); + public static final DataKey LOG_DIFF_HANDLER = DataKey.create("Vcs.Log.Diff.Handler"); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java index dea68d90358e..6f048af48a35 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java @@ -71,8 +71,7 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA } else { if (commits.size() == 2) { - VcsLogDiffHandler handler = ui.getLogData().getLogProvider(commits.get(0).getRoot()).getDiffHandler(); - e.getPresentation().setEnabled(handler != null); + e.getPresentation().setEnabled(e.getData(VcsLogInternalDataKeys.LOG_DIFF_HANDLER) != null); } else { e.getPresentation().setEnabled(commits.size() == 1); @@ -105,8 +104,8 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA List commits = ui.getVcsLog().getSelectedCommits(); if (commits.size() != 1 && commits.size() != 2) return; - VirtualFile root = commits.get(0).getRoot(); - VcsLogDiffHandler handler = ui.getLogData().getLogProvider(root).getDiffHandler(); + VcsLogDiffHandler handler = e.getData(VcsLogInternalDataKeys.LOG_DIFF_HANDLER); + // this check is needed here since we may come on key event without performing proper checks if (commits.size() == 2 && handler == null) return; List commitIds = ContainerUtil.map(commits, c -> ui.getLogData().getCommitIndex(c.getHash(), c.getRoot())); @@ -117,7 +116,8 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA // so that it could return a single file path for each revision VcsFullCommitDetails newestDetail = details.get(0); VcsFullCommitDetails olderDetail = details.get(1); - notNull(handler).showDiff(root, ui.getPath(olderDetail), olderDetail.getId(), ui.getPath(newestDetail), newestDetail.getId()); + notNull(handler).showDiff(olderDetail.getRoot(), ui.getPath(olderDetail), olderDetail.getId(), + ui.getPath(newestDetail), newestDetail.getId()); } else if (details.size() == 1) { VcsFullCommitDetails detail = notNull(ContainerUtil.getFirstItem(details)); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java index 3fa1861d1131..fdf6f4e7efb0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/ShowDiffWithLocalFromHistoryAction.java @@ -20,32 +20,21 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcs.log.CommitId; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLogDiffHandler; import com.intellij.vcs.log.history.FileHistoryUi; +import com.intellij.vcs.log.ui.VcsLogInternalDataKeys; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public class ShowDiffWithLocalFromHistoryAction extends FileHistorySingleCommitAction { @Override protected boolean isEnabled(@NotNull FileHistoryUi ui, @Nullable VcsFullCommitDetails detail, @NotNull AnActionEvent e) { FilePath filePath = e.getData(VcsDataKeys.FILE_PATH); - if (filePath == null || filePath.getVirtualFile() == null) { - return false; - } + VcsLogDiffHandler handler = e.getData(VcsLogInternalDataKeys.LOG_DIFF_HANDLER); - List commits = ui.getVcsLog().getSelectedCommits(); - if (filePath.isDirectory()) { - VcsLogDiffHandler handler = ui.getLogData().getLogProvider(commits.get(0).getRoot()).getDiffHandler(); - if (handler == null) return false; - } - - return true; + return filePath != null && filePath.getVirtualFile() != null && handler != null; } @Override @@ -56,11 +45,8 @@ public class ShowDiffWithLocalFromHistoryAction extends FileHistorySingleCommitA if (ChangeListManager.getInstance(project).isFreezedWithNotification(null)) return; FilePath path = e.getRequiredData(VcsDataKeys.FILE_PATH); + VcsLogDiffHandler handler = e.getRequiredData(VcsLogInternalDataKeys.LOG_DIFF_HANDLER); - VirtualFile root = detail.getRoot(); - VcsLogDiffHandler handler = ui.getLogData().getLogProvider(root).getDiffHandler(); - if (handler != null) { - handler.showDiffWithLocal(root, ui.getPath(detail), detail.getId(), path); - } + handler.showDiffWithLocal(detail.getRoot(), ui.getPath(detail), detail.getId(), path); } } From 5de57ee32d9e150da0748fd7c967e5d11f8d02a8 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 23:06:28 +0300 Subject: [PATCH 16/26] [diff] DiffRequestFactory.getTitle accepts nulls --- .../intellij/diff/DiffRequestFactoryImpl.java | 10 +++++++- .../src/git4idea/log/GitLogDiffHandler.java | 23 ++++--------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java index 98dc253fb707..dcb5c7284d0c 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java @@ -45,6 +45,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import static com.intellij.util.ObjectUtils.chooseNotNull; + public class DiffRequestFactoryImpl extends DiffRequestFactory { private final DiffContentFactoryEx myContentFactory = DiffContentFactoryEx.getInstanceEx(); @@ -127,7 +129,13 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { } @NotNull - public static String getTitle(@NotNull FilePath path1, @NotNull FilePath path2, @NotNull String separator) { + public static String getTitle(@Nullable FilePath path1, @Nullable FilePath path2, @NotNull String separator) { + assert path1 != null || path2 != null; + + if (path1 == null || path2 == null) { + return getContentTitle(chooseNotNull(path1, path2)); + } + if ((path1.isDirectory() || path2.isDirectory()) && path1.getPath().equals(path2.getPath())) { return path1.getPresentableUrl(); } diff --git a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java index 42c1cb59ec89..bcb8854a1f8d 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java +++ b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java @@ -17,7 +17,6 @@ package git4idea.log; import com.intellij.diff.DiffContentFactoryEx; import com.intellij.diff.DiffManager; -import com.intellij.diff.DiffRequestFactoryImpl; import com.intellij.diff.contents.DiffContent; import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.requests.DiffRequest; @@ -51,10 +50,9 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Collections; -import java.util.Objects; +import static com.intellij.diff.DiffRequestFactoryImpl.getTitle; import static com.intellij.util.ObjectUtils.chooseNotNull; -import static com.intellij.util.ObjectUtils.notNull; public class GitLogDiffHandler implements VcsLogDiffHandler { private static final Logger LOG = Logger.getInstance(GitLogDiffHandler.class); @@ -84,7 +82,7 @@ public class GitLogDiffHandler implements VcsLogDiffHandler { DiffContent leftDiffContent = createDiffContent(root, leftPath, leftHash); DiffContent rightDiffContent = createDiffContent(root, rightPath, rightHash); - return new SimpleDiffRequest(getTitle(leftPath, rightPath), + return new SimpleDiffRequest(getTitle(leftPath, rightPath, " -> "), leftDiffContent, rightDiffContent, leftHash.asString(), rightHash.asString()); } @@ -110,7 +108,7 @@ public class GitLogDiffHandler implements VcsLogDiffHandler { LOG.assertTrue(file != null); DiffContent rightDiffContent = myDiffContentFactory.create(myProject, file); - return new SimpleDiffRequest(getTitle(revisionPath, localPath), + return new SimpleDiffRequest(getTitle(revisionPath, localPath, " -> "), leftDiffContent, rightDiffContent, revisionHash.asString(), "(Local)"); } @@ -131,7 +129,7 @@ public class GitLogDiffHandler implements VcsLogDiffHandler { " and " + (rightRevision == null ? "current revision" : rightRevision.asString()) + " in " + - getTitle(directoryPath, directoryPath); + getTitle(directoryPath, directoryPath, " -> "); VcsDiffUtil.showChangesDialog(myProject, dialogTitle, ContainerUtil.newArrayList(diff)); }, "Calculating Diff for " + directoryPath.getName()); } @@ -202,17 +200,4 @@ public class GitLogDiffHandler implements VcsLogDiffHandler { return diffContent; } - - @NotNull - private static String getTitle(@Nullable FilePath leftPath, @Nullable FilePath rightPath) { - LOG.assertTrue(leftPath != null || rightPath != null); - - if (Objects.equals(rightPath, leftPath)) { - return DiffRequestFactoryImpl.getContentTitle(notNull(leftPath)); - } - if (leftPath == null || rightPath == null) { - return DiffRequestFactoryImpl.getContentTitle(chooseNotNull(leftPath, rightPath)); - } - return DiffRequestFactoryImpl.getTitle(leftPath, rightPath, " -> "); - } } From 32e715073c12e82c2a7d83790b19c16f4ae3b5ec Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 23:44:15 +0300 Subject: [PATCH 17/26] [vcs-log] add javadoc --- .../intellij/vcs/log/VcsLogDiffHandler.java | 23 +++++++++++++++++++ .../com/intellij/vcs/log/VcsLogProvider.java | 5 ++++ 2 files changed, 28 insertions(+) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java index f334465a062f..24dd4441878a 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java @@ -20,11 +20,34 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * Enables showing diff between revisions and comparing file or directory state between a revision and a local version in log-based file history. + * Methods of this class could be called from EDT, so it should deal with it appropriately by starting a background task for long operations, + * eg for loading revisions content. + */ public interface VcsLogDiffHandler { + + /** + * Show diff between (the after-state of) two revisions in the specified files or directories. + * + * @param root repository root. + * @param leftPath path to the file on the left, null means file is missing in this revision. + * @param leftHash hash of the revision on the left. + * @param rightPath path to the file on the right, null means file is missing in this revision. + * @param rightHash hash of the revision on the right. + */ void showDiff(@NotNull VirtualFile root, @Nullable FilePath leftPath, @NotNull Hash leftHash, @Nullable FilePath rightPath, @NotNull Hash rightHash); + /** + * Show diff between (the after-state of) specified revision and local version for the specified file or directory. + * + * @param root repository root. + * @param revisionPath path to the file in the specified revision, null means file is not present in the revision. + * @param hash hash of the revision. + * @param localPath local path to the file. + */ void showDiffWithLocal(@NotNull VirtualFile root, @Nullable FilePath revisionPath, @NotNull Hash hash, @NotNull FilePath localPath); diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java index 6e001856eb36..f17de3d09285 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java @@ -147,6 +147,11 @@ public interface VcsLogProvider { @Nullable String getCurrentBranch(@NotNull VirtualFile root); + /** + * Returns {@link VcsLogDiffHandler} for this provider in order to support comparing commits and with local version from log-based file history. + * + * @return diff handler or null if unsupported. + */ @Nullable VcsLogDiffHandler getDiffHandler(); From d88601cd57e74caaf9aef84ab8c267ad6b69f537 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 14 Apr 2017 14:32:31 +0300 Subject: [PATCH 18/26] allow renderer to provide elements one by one --- .../intellij/debugger/engine/JavaValue.java | 53 ++++++++++++------- .../ui/impl/DebuggerTreeRenderer.java | 3 +- .../ui/tree/render/ArrayRenderer.java | 17 +++--- .../ui/tree/render/ChildrenBuilder.java | 17 +++++- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index 349cf19bb605..b5470faefe28 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -36,11 +36,11 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiElement; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ThreeState; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; @@ -347,10 +347,8 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV @Override public void contextAction(@NotNull SuspendContextImpl suspendContext) throws Exception { - final XValueChildrenList children = new XValueChildrenList(); - final NodeRenderer renderer = myValueDescriptor.getRenderer(myEvaluationContext.getDebugProcess()); - final Ref remainingNum = new Ref<>(0); - renderer.buildChildren(myValueDescriptor.getValue(), new ChildrenBuilder() { + myValueDescriptor.getRenderer(myEvaluationContext.getDebugProcess()) + .buildChildren(myValueDescriptor.getValue(), new ChildrenBuilder() { @Override public NodeDescriptorFactory getDescriptorManager() { return myNodeManager; @@ -368,7 +366,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV @Override public void setRemaining(int remaining) { - remainingNum.set(remaining); + node.tooManyChildren(remaining); } @Override @@ -379,23 +377,38 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV } @Override - public void setChildren(List nodes) { - for (DebuggerTreeNode node : nodes) { - final NodeDescriptor descriptor = node.getDescriptor(); - if (descriptor instanceof ValueDescriptorImpl) { - // Value is calculated already in NodeManagerImpl - children.add(create(JavaValue.this, (ValueDescriptorImpl)descriptor, myEvaluationContext, myNodeManager, false)); - } - else if (descriptor instanceof MessageDescriptor) { - children.add(new JavaStackFrame.DummyMessageValueNode(descriptor.getLabel(), null)); - } + public void addChildren(List nodes, boolean last) { + if (nodes.isEmpty()) { + node.addChildren(XValueChildrenList.EMPTY, last); + } + else { + nodes.stream().map(DebuggerTreeNode::getDescriptor).forEach(descriptor -> { + if (descriptor instanceof ValueDescriptorImpl) { + // Value is calculated already in NodeManagerImpl + node.addChildren(XValueChildrenList.singleton( + create(JavaValue.this, (ValueDescriptorImpl)descriptor, myEvaluationContext, myNodeManager, false)), last); + } + else if (descriptor instanceof MessageDescriptor) { + node.addChildren(XValueChildrenList.singleton( + new JavaStackFrame.DummyMessageValueNode(descriptor.getLabel(), DebuggerTreeRenderer.getDescriptorIcon(descriptor))), last); + } + }); } } + + @Override + public void setChildren(List nodes) { + addChildren(nodes, true); + } + + @Override + public void setMessage(@NotNull String message, + @Nullable Icon icon, + @NotNull SimpleTextAttributes attributes, + @Nullable XDebuggerTreeNodeHyperlink link) { + node.setMessage(message, icon, attributes, link); + } }, myEvaluationContext); - node.addChildren(children, true); - if (remainingNum.get() > 0) { - node.tooManyChildren(remainingNum.get()); - } } }); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java index fb8a715d3a88..944e32e0c436 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java @@ -19,6 +19,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.ui.impl.watch.*; +import com.intellij.debugger.ui.tree.NodeDescriptor; import com.intellij.debugger.ui.tree.ValueDescriptor; import com.intellij.debugger.ui.tree.render.EnumerationChildrenRenderer; import com.intellij.icons.AllIcons; @@ -62,7 +63,7 @@ public class DebuggerTreeRenderer extends ColoredTreeCellRenderer { } @Nullable - public static Icon getDescriptorIcon(NodeDescriptorImpl descriptor) { + public static Icon getDescriptorIcon(NodeDescriptor descriptor) { Icon nodeIcon = null; if (descriptor instanceof ThreadGroupDescriptorImpl) { nodeIcon = (((ThreadGroupDescriptorImpl)descriptor).isCurrent() ? AllIcons.Debugger.ThreadGroupCurrent : AllIcons.Debugger.ThreadGroup); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java index 599eabc1d9c6..47770d233a8e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java @@ -37,6 +37,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiExpression; +import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.IncorrectOperationException; import com.sun.jdi.ArrayReference; import com.sun.jdi.ArrayType; @@ -45,8 +46,7 @@ import com.sun.jdi.Value; import org.jdom.Element; import org.jetbrains.annotations.NonNls; -import java.util.ArrayList; -import java.util.List; +import java.util.Collections; /** * User: lex @@ -99,7 +99,6 @@ public class ArrayRenderer extends NodeRendererImpl{ public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) { DebuggerManagerThreadImpl.assertIsManagerThread(); - List children = new ArrayList<>(); NodeManagerImpl nodeManager = (NodeManagerImpl)builder.getNodeManager(); NodeDescriptorFactory descriptorFactory = builder.getDescriptorManager(); @@ -133,7 +132,7 @@ public class ArrayRenderer extends NodeRendererImpl{ continue; } - children.add(arrayItemNode); + builder.addChildren(Collections.singletonList(arrayItemNode), false); added++; if (added > ENTRIES_LIMIT) { break; @@ -141,24 +140,26 @@ public class ArrayRenderer extends NodeRendererImpl{ } } + builder.addChildren(Collections.emptyList(), true); + if (added == 0) { if (START_INDEX == 0 && array.length() - 1 <= END_INDEX) { - children.add(nodeManager.createMessageNode(ALL_ELEMENTS_IN_RANGE_ARE_NULL)); + builder.setMessage(DebuggerBundle.message("message.node.all.elements.null"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, null); } else { - children.add(nodeManager.createMessageNode(DebuggerBundle.message("message.node.all.array.elements.null", START_INDEX, END_INDEX))); + builder.setMessage(DebuggerBundle.message("message.node.all.array.elements.null", START_INDEX, END_INDEX), null, + SimpleTextAttributes.REGULAR_ATTRIBUTES, null); } } else { if (hiddenNulls) { - children.add(0, nodeManager.createMessageNode(HIDDEN_NULL_ELEMENTS)); + builder.setMessage(DebuggerBundle.message("message.node.elements.null.hidden"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, null); } if (!myForced && END_INDEX < array.length() - 1) { builder.setRemaining(array.length() - 1 - END_INDEX); } } } - builder.setChildren(children); } private static boolean elementIsNull(ArrayReference arrayReference, int index) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ChildrenBuilder.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ChildrenBuilder.java index e98867a81496..416089ed0de7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ChildrenBuilder.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ChildrenBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -16,7 +16,12 @@ package com.intellij.debugger.ui.tree.render; import com.intellij.debugger.ui.tree.*; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.List; public interface ChildrenBuilder { @@ -28,6 +33,16 @@ public interface ChildrenBuilder { void setChildren(List children); + default void addChildren(List children, boolean last) { + setChildren(children); + } + + default void setMessage(@NotNull String message, + @Nullable Icon icon, + @NotNull SimpleTextAttributes attributes, + @Nullable XDebuggerTreeNodeHyperlink link) { + } + void setRemaining(int remaining); void initChildrenArrayRenderer(ArrayRenderer renderer); From 7d2b7c2f8bf4bacc6fedba23edc8d29feab41284 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Thu, 13 Apr 2017 15:04:56 +0300 Subject: [PATCH 19/26] cleanup --- .../settings/ExternalProjectSettings.java | 3 +-- .../execution/TaskCompletionProvider.java | 1 - .../service/ui/ExternalToolWindowManager.java | 26 +++++++------------ .../test/AbstractExternalSystemTest.groovy | 5 ++-- .../plugins/gradle/GradleManager.java | 1 - 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java index ba97513e8a31..866848c1adab 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java @@ -16,7 +16,6 @@ package com.intellij.openapi.externalSystem.settings; import com.intellij.openapi.util.Comparing; -import com.intellij.util.xmlb.annotations.AbstractCollection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +36,7 @@ public abstract class ExternalProjectSettings implements Comparable getModules() { - return myModules == null ? Collections.emptySet() : myModules; + return myModules == null ? Collections.emptySet() : myModules; } public void setModules(@Nullable Set modules) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java index bb178343685a..fabdfe8e2fa8 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java @@ -32,7 +32,6 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.TextAccessor; -import com.intellij.util.BooleanFunction; import com.intellij.util.containers.ContainerUtil; import groovyjarjarcommonscli.Options; import icons.ExternalSystemIcons; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java index aac83b3abc68..5058c4bd6c7f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java @@ -37,28 +37,22 @@ public class ExternalToolWindowManager { settings.subscribe(new ExternalSystemSettingsListenerAdapter() { @Override public void onProjectsLinked(@NotNull Collection linked) { - if (settings.getLinkedProjectsSettings().size() != 1) { - return; - } ToolWindow toolWindow = getToolWindow(project, manager.getSystemId()); if (toolWindow != null) { toolWindow.setAvailable(true, null); } else { - StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() { - @Override - public void run() { - if (project.isDisposed()) return; + StartupManager.getInstance(project).runWhenProjectIsInitialized((DumbAwareRunnable)() -> { + if (project.isDisposed()) return; - ExternalSystemUtil.ensureToolWindowInitialized(project, manager.getSystemId()); - ToolWindowManager.getInstance(project).invokeLater(() -> { - if (project.isDisposed()) return; - ToolWindow toolWindow1 = getToolWindow(project, manager.getSystemId()); - if (toolWindow1 != null) { - toolWindow1.setAvailable(true, null); - } - }); - } + ExternalSystemUtil.ensureToolWindowInitialized(project, manager.getSystemId()); + ToolWindowManager.getInstance(project).invokeLater(() -> { + if (project.isDisposed()) return; + ToolWindow toolWindow1 = getToolWindow(project, manager.getSystemId()); + if (toolWindow1 != null) { + toolWindow1.setAvailable(true, null); + } + }); }); } } diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy index cbb967d50584..97e51ae185a7 100644 --- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy +++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy @@ -14,6 +14,7 @@ * limitations under the License. */ package com.intellij.openapi.externalSystem.test + import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.extensions.ExtensionPoint import com.intellij.openapi.extensions.Extensions @@ -21,12 +22,9 @@ import com.intellij.openapi.externalSystem.ExternalSystemManager import com.intellij.openapi.externalSystem.model.DataNode import com.intellij.openapi.externalSystem.model.project.ProjectData import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager -import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.ex.ProjectRootManagerEx import com.intellij.openapi.util.io.FileUtil -import com.intellij.testFramework.PlatformTestCase import com.intellij.testFramework.SkipInHeadlessEnvironment import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.fixtures.IdeaProjectTestFixture @@ -37,6 +35,7 @@ import org.jetbrains.annotations.Nullable import java.lang.reflect.Field import java.lang.reflect.Modifier + /** * @author Denis Zhdanov * @since 8/7/13 2:04 PM diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java index 42a2b87ea91a..fc892bb85a67 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java @@ -53,7 +53,6 @@ import com.intellij.util.Function; import com.intellij.util.PathUtil; import com.intellij.util.PathsList; import com.intellij.util.containers.ContainerUtilRt; -import com.intellij.util.execution.ParametersListUtil; import com.intellij.util.messages.MessageBusConnection; import icons.GradleIcons; import org.jetbrains.annotations.NotNull; From 408602b96dfa0b97fa8b82eeb29820a6ade2c4cd Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 14 Apr 2017 12:17:56 +0300 Subject: [PATCH 20/26] Gradle: do not fail project compilation if gradle config was not imported yet --- .../config/GradleResourceCompilerConfigurationGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java index 5d41af3777cb..e79e923fd9b6 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java @@ -193,7 +193,7 @@ public class GradleResourceCompilerConfigurationGenerator { final ExternalProject externalRootProject = lazyExternalProjectMap.get(gradleProjectPath); if (externalRootProject == null) { - context.addMessage(CompilerMessageCategory.ERROR, + context.addMessage(CompilerMessageCategory.WARNING, String.format("Unable to make the module: %s, related gradle configuration was not found. " + "Please, re-import the Gradle project and try again.", module.getName()), VfsUtilCore.pathToUrl(gradleProjectPath), -1, -1); From 86360b368d2d0e2d9ee341a41824bc8ec72387bd Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 14 Apr 2017 12:20:01 +0300 Subject: [PATCH 21/26] ES: move ImportSpec to API module --- .../com/intellij/openapi/externalSystem/importing/ImportSpec.java | 0 .../openapi/externalSystem/importing/ImportSpecBuilder.java | 0 .../intellij/openapi/externalSystem/importing/ImportSpecImpl.java | 0 .../externalSystem/service/execution/ProgressExecutionMode.java | 0 .../service/project/ExternalProjectRefreshCallback.java | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename platform/{external-system-impl => external-system-api}/src/com/intellij/openapi/externalSystem/importing/ImportSpec.java (100%) rename platform/{external-system-impl => external-system-api}/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java (100%) rename platform/{external-system-impl => external-system-api}/src/com/intellij/openapi/externalSystem/importing/ImportSpecImpl.java (100%) rename platform/{external-system-impl => external-system-api}/src/com/intellij/openapi/externalSystem/service/execution/ProgressExecutionMode.java (100%) rename platform/{external-system-impl => external-system-api}/src/com/intellij/openapi/externalSystem/service/project/ExternalProjectRefreshCallback.java (100%) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/importing/ImportSpec.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpec.java similarity index 100% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/importing/ImportSpec.java rename to platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpec.java diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java similarity index 100% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java rename to platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/importing/ImportSpecImpl.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecImpl.java similarity index 100% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/importing/ImportSpecImpl.java rename to platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecImpl.java diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ProgressExecutionMode.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/execution/ProgressExecutionMode.java similarity index 100% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ProgressExecutionMode.java rename to platform/external-system-api/src/com/intellij/openapi/externalSystem/service/execution/ProgressExecutionMode.java diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ExternalProjectRefreshCallback.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ExternalProjectRefreshCallback.java similarity index 100% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ExternalProjectRefreshCallback.java rename to platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ExternalProjectRefreshCallback.java From 31dd179c8015beaedf65d08f7c00607d754d0ec8 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 14 Apr 2017 13:18:26 +0300 Subject: [PATCH 22/26] ES: extract ProjectDataManager interface to API module --- .../service/project/ProjectDataManager.java | 67 +++ .../project/manage/ProjectDataManager.java | 380 ++-------------- .../manage/ProjectDataManagerImpl.java | 416 ++++++++++++++++++ .../ui/ExternalProjectDataSelectorDialog.java | 5 +- .../test/ExternalSystemImportingTestCase.java | 33 +- 5 files changed, 537 insertions(+), 364 deletions(-) create mode 100644 platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ProjectDataManager.java create mode 100644 platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ProjectDataManager.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ProjectDataManager.java new file mode 100644 index 000000000000..52582de8366b --- /dev/null +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ProjectDataManager.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2017 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.openapi.externalSystem.service.project; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * Aggregates all {@link ProjectDataService#EP_NAME registered data services} + * and provides entry points for project data management. + * + * @author Vladislav Soroka + * @since 4/16/13 11:38 AM + */ +public interface ProjectDataManager { + static ProjectDataManager getInstance() { + return ServiceManager.getService(ProjectDataManager.class); + } + + @SuppressWarnings("unchecked") + void importData(@NotNull Collection> nodes, + @NotNull Project project, + @NotNull IdeModifiableModelsProvider modelsProvider, + boolean synchronous); + + void importData(@NotNull Collection> nodes, @NotNull Project project, boolean synchronous); + + void importData(@NotNull DataNode node, + @NotNull Project project, + @NotNull IdeModifiableModelsProvider modelsProvider, + boolean synchronous); + + void importData(@NotNull DataNode node, + @NotNull Project project, + boolean synchronous); + + void ensureTheDataIsReadyToUse(@Nullable DataNode dataNode); + + @Nullable + ExternalProjectInfo getExternalProjectData(@NotNull Project project, + @NotNull ProjectSystemId projectSystemId, + @NotNull String externalProjectPath); + + @NotNull + Collection getExternalProjectsData(@NotNull Project project, @NotNull ProjectSystemId projectSystemId); +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java index bdb4445ef521..37fc4f8f27aa 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -15,394 +15,102 @@ */ package com.intellij.openapi.externalSystem.service.project.manage; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.externalSystem.model.*; -import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; +import com.intellij.openapi.externalSystem.model.Key; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; -import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl; -import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; -import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; -import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.impl.ProjectImpl; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.NotNullLazyValue; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.Consumer; -import com.intellij.util.ExceptionUtil; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.ContainerUtilRt; -import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; - -import static com.intellij.util.containers.ContainerUtil.map2Array; +import java.util.Collection; /** - * Aggregates all {@link ProjectDataService#EP_NAME registered data services} and provides entry points for project data management. - * - * @author Denis Zhdanov - * @since 4/16/13 11:38 AM + * @deprecated use {@link com.intellij.openapi.externalSystem.service.project.ProjectDataManager} instead */ -public class ProjectDataManager { - - private static final Logger LOG = Logger.getInstance("#" + ProjectDataManager.class.getName()); - private static final com.intellij.openapi.util.Key DATA_READY = - com.intellij.openapi.util.Key.create("externalSystem.data.ready"); - - @NotNull private final NotNullLazyValue, List>>> myServices; +public class ProjectDataManager extends ProjectDataManagerImpl { public static ProjectDataManager getInstance() { - return ServiceManager.getService(ProjectDataManager.class); + return new ProjectDataManager(ProjectDataManagerImpl.getInstance()); } - public ProjectDataManager() { - myServices = new NotNullLazyValue, List>>>() { - @NotNull - @Override - protected Map, List>> compute() { - Map, List>> result = ContainerUtilRt.newHashMap(); - for (ProjectDataService service : ProjectDataService.EP_NAME.getExtensions()) { - List> services = result.get(service.getTargetDataKey()); - if (services == null) { - result.put(service.getTargetDataKey(), services = ContainerUtilRt.newArrayList()); - } - services.add(service); - } + private final ProjectDataManagerImpl delegate; - for (List> services : result.values()) { - ExternalSystemApiUtil.orderAwareSort(services); - } - return result; - } - }; - } + public ProjectDataManager(ProjectDataManagerImpl delegate) {this.delegate = delegate;} - @SuppressWarnings("unchecked") + @Override public void importData(@NotNull Collection> nodes, @NotNull Project project, @NotNull IdeModifiableModelsProvider modelsProvider, boolean synchronous) { - if (project.isDisposed()) return; - - MultiMap, DataNode> grouped = ExternalSystemApiUtil.recursiveGroup(nodes); - for (Key key : myServices.getValue().keySet()) { - if (!grouped.containsKey(key)) { - grouped.put(key, Collections.>emptyList()); - } - } - - final Collection> projects = grouped.get(ProjectKeys.PROJECT); - // only one project(can be multi-module project) expected for per single import - assert projects.size() == 1 || projects.isEmpty(); - - final DataNode projectNode = (DataNode)ContainerUtil.getFirstItem(projects); - final ProjectData projectData; - ProjectSystemId projectSystemId; - if (projectNode != null) { - projectData = projectNode.getData(); - projectSystemId = projectNode.getData().getOwner(); - ExternalProjectsDataStorage.getInstance(project).saveInclusionSettings(projectNode); - } - else { - projectData = null; - DataNode aModuleNode = (DataNode)ContainerUtil.getFirstItem(grouped.get(ProjectKeys.MODULE)); - projectSystemId = aModuleNode != null ? aModuleNode.getData().getOwner() : null; - } - - if (projectSystemId != null) { - ExternalSystemUtil.scheduleExternalViewStructureUpdate(project, projectSystemId); - } - - List onSuccessImportTasks = ContainerUtil.newSmartList(); - try { - final Set, Collection>>> entries = grouped.entrySet(); - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - indicator.setIndeterminate(false); - } - final int size = entries.size(); - int count = 0; - List postImportTasks = ContainerUtil.newSmartList(); - for (Map.Entry, Collection>> entry : entries) { - if (indicator != null) { - String message = ExternalSystemBundle.message( - "progress.update.text", projectSystemId != null ? projectSystemId.getReadableName() : "", - "Refresh " + getReadableText(entry.getKey())); - indicator.setText(message); - indicator.setFraction((double)count++ / size); - } - doImportData(entry.getKey(), entry.getValue(), projectData, project, modelsProvider, postImportTasks, onSuccessImportTasks); - } - - for (Runnable postImportTask : postImportTasks) { - postImportTask.run(); - } - - commit(modelsProvider, project, synchronous, "Imported data"); - if (indicator != null) { - indicator.setIndeterminate(true); - } - } - catch (Throwable t) { - dispose(modelsProvider, project, synchronous); - ExceptionUtil.rethrowAllAsUnchecked(t); - } - - for (Runnable onSuccessImportTask : ContainerUtil.reverse(onSuccessImportTasks)) { - onSuccessImportTask.run(); - } + delegate.importData(nodes, project, modelsProvider, synchronous); } - @NotNull - private static String getReadableText(@NotNull Key key) { - StringBuilder buffer = new StringBuilder(); - String s = key.toString(); - for (int i = 0; i < s.length(); i++) { - char currChar = s.charAt(i); - if (Character.isUpperCase(currChar)) { - if (i != 0) { - buffer.append(' '); - } - buffer.append(StringUtil.toLowerCase(currChar)); - } - else { - buffer.append(currChar); - } - } - return buffer.toString(); - } - - public void importData(@NotNull Collection> nodes, @NotNull Project project, boolean synchronous) { - Collection> dummy = ContainerUtil.newSmartList(); - for (DataNode node : nodes) { - dummy.add(node); - } - importData(dummy, project, new IdeModifiableModelsProviderImpl(project), synchronous); + @Override + public void importData(@NotNull Collection> nodes, + @NotNull Project project, boolean synchronous) { + delegate.importData(nodes, project, synchronous); } + @Override public void importData(@NotNull DataNode node, @NotNull Project project, @NotNull IdeModifiableModelsProvider modelsProvider, boolean synchronous) { - Collection> dummy = ContainerUtil.newSmartList(); - dummy.add(node); - importData(dummy, project, modelsProvider, synchronous); + delegate.importData(node, project, modelsProvider, synchronous); } + @Override public void importData(@NotNull DataNode node, - @NotNull Project project, - boolean synchronous) { - importData(node, project, new IdeModifiableModelsProviderImpl(project), synchronous); - } - - @SuppressWarnings("unchecked") - private void doImportData(@NotNull Key key, - @NotNull Collection> nodes, - @Nullable final ProjectData projectData, - @NotNull final Project project, - @NotNull final IdeModifiableModelsProvider modelsProvider, - @NotNull final List postImportTasks, - @NotNull final List onSuccessImportTasks) { - if (project.isDisposed()) return; - if (project instanceof ProjectImpl) { - assert ((ProjectImpl)project).isComponentsCreated(); - } - - final List> toImport = ContainerUtil.newSmartList(); - final List> toIgnore = ContainerUtil.newSmartList(); - - for (DataNode node : nodes) { - if (!key.equals(node.getKey())) continue; - - if (node.isIgnored()) { - toIgnore.add(node); - } - else { - toImport.add(node); - } - } - - ensureTheDataIsReadyToUse((Collection)toImport); - - final List> services = myServices.getValue().get(key); - if (services == null) { - LOG.warn(String.format( - "Can't import data nodes '%s'. Reason: no service is registered for key %s. Available services for %s", - toImport, key, myServices.getValue().keySet() - )); - } - else { - for (ProjectDataService service : services) { - final long importStartTime = System.currentTimeMillis(); - ((ProjectDataService)service).importData(toImport, projectData, project, modelsProvider); - if(LOG.isDebugEnabled()) { - final long importTimeInMs = (System.currentTimeMillis() - importStartTime); - LOG.debug(String.format("Service %s imported data in %d ms", service.getClass().getSimpleName(), importTimeInMs)); - } - - if(projectData != null) { - ensureTheDataIsReadyToUse((Collection)toIgnore); - final long removeStartTime = System.currentTimeMillis(); - final Computable> orphanIdeDataComputable = - ((ProjectDataService)service).computeOrphanData(toImport, projectData, project, modelsProvider); - ((ProjectDataService)service).removeData(orphanIdeDataComputable, toIgnore, projectData, project, modelsProvider); - if(LOG.isDebugEnabled()) { - final long removeTimeInMs = (System.currentTimeMillis() - removeStartTime); - LOG.debug(String.format("Service %s computed and removed data in %d ms", service.getClass().getSimpleName(), removeTimeInMs)); - } - } - } - } - - if (services != null && projectData != null) { - postImportTasks.add(() -> { - for (ProjectDataService service : services) { - if (service instanceof AbstractProjectDataService) { - final long taskStartTime = System.currentTimeMillis(); - ((AbstractProjectDataService)service).postProcess(toImport, projectData, project, modelsProvider); - if(LOG.isDebugEnabled()) { - final long taskTimeInMs = (System.currentTimeMillis() - taskStartTime); - LOG.debug(String.format("Service %s run post import task in %d ms", service.getClass().getSimpleName(), taskTimeInMs)); - } - } - } - }); - onSuccessImportTasks.add(() -> { - for (ProjectDataService service : services) { - if (service instanceof AbstractProjectDataService) { - final long taskStartTime = System.currentTimeMillis(); - ((AbstractProjectDataService)service).onSuccessImport(project); - if(LOG.isDebugEnabled()) { - final long taskTimeInMs = (System.currentTimeMillis() - taskStartTime); - LOG.debug(String.format("Service %s run post import task in %d ms", service.getClass().getSimpleName(), taskTimeInMs)); - } - } - } - }); - } + @NotNull Project project, boolean synchronous) { + delegate.importData(node, project, synchronous); } + @Override public void ensureTheDataIsReadyToUse(@Nullable DataNode dataNode) { - if (dataNode == null) return; - if (Boolean.TRUE.equals(dataNode.getUserData(DATA_READY))) return; - - ExternalSystemApiUtil.visit(dataNode, dataNode1 -> { - prepareDataToUse(dataNode1); - dataNode1.putUserData(DATA_READY, Boolean.TRUE); - }); + delegate.ensureTheDataIsReadyToUse(dataNode); } - @SuppressWarnings("unchecked") + @Override public void removeData(@NotNull Key key, @NotNull Collection toRemove, - @NotNull final Collection> toIgnore, - @NotNull final ProjectData projectData, + @NotNull Collection> toIgnore, + @NotNull ProjectData projectData, @NotNull Project project, - @NotNull final IdeModifiableModelsProvider modelsProvider, + @NotNull IdeModifiableModelsProvider modelsProvider, boolean synchronous) { - try { - List> services = myServices.getValue().get(key); - for (ProjectDataService service : services) { - final long removeStartTime = System.currentTimeMillis(); - service.removeData(new Computable.PredefinedValueComputable(toRemove), toIgnore, projectData, project, modelsProvider); - if(LOG.isDebugEnabled()) { - final long removeTimeInMs = System.currentTimeMillis() - removeStartTime; - LOG.debug(String.format("Service %s removed data in %d ms", service.getClass().getSimpleName(), removeTimeInMs)); - } - } - - commit(modelsProvider, project, synchronous, "Removed data"); - } - catch (Throwable t) { - dispose(modelsProvider, project, synchronous); - ExceptionUtil.rethrowAllAsUnchecked(t); - } + delegate.removeData(key, toRemove, toIgnore, projectData, project, modelsProvider, synchronous); } + @Override public void removeData(@NotNull Key key, @NotNull Collection toRemove, - @NotNull final Collection> toIgnore, - @NotNull final ProjectData projectData, - @NotNull Project project, - boolean synchronous) { - removeData(key, toRemove, toIgnore, projectData, project, new IdeModifiableModelsProviderImpl(project), synchronous); + @NotNull Collection> toIgnore, + @NotNull ProjectData projectData, + @NotNull Project project, boolean synchronous) { + delegate.removeData(key, toRemove, toIgnore, projectData, project, synchronous); } - public void updateExternalProjectData(@NotNull Project project, @NotNull ExternalProjectInfo externalProjectInfo) { - if (!project.isDisposed()) { - ExternalProjectsManager.getInstance(project).updateExternalProjectData(externalProjectInfo); - } + @Override + public void updateExternalProjectData(@NotNull Project project, + @NotNull ExternalProjectInfo externalProjectInfo) { + delegate.updateExternalProjectData(project, externalProjectInfo); } @Nullable + @Override public ExternalProjectInfo getExternalProjectData(@NotNull Project project, @NotNull ProjectSystemId projectSystemId, @NotNull String externalProjectPath) { - return !project.isDisposed() ? ExternalProjectsDataStorage.getInstance(project).get(projectSystemId, externalProjectPath) : null; + return delegate.getExternalProjectData(project, projectSystemId, externalProjectPath); } @NotNull - public Collection getExternalProjectsData(@NotNull Project project, @NotNull ProjectSystemId projectSystemId) { - if (!project.isDisposed()) { - return ExternalProjectsDataStorage.getInstance(project).list(projectSystemId); - } - else { - return ContainerUtil.emptyList(); - } - } - - private void ensureTheDataIsReadyToUse(@NotNull Collection> nodes) { - for (DataNode node : nodes) { - ensureTheDataIsReadyToUse(node); - } - } - - private void prepareDataToUse(@NotNull DataNode dataNode) { - final Map, List>> servicesByKey = myServices.getValue(); - List> services = servicesByKey.get(dataNode.getKey()); - if (services != null) { - try { - dataNode.prepareData(map2Array(services, ClassLoader.class, service -> service.getClass().getClassLoader())); - } - catch (Exception e) { - LOG.debug(e); - dataNode.clear(true); - } - } - } - - private static void commit(@NotNull final IdeModifiableModelsProvider modelsProvider, - @NotNull Project project, - boolean synchronous, - @NotNull final String commitDesc) { - ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { - @Override - public void execute() { - final long startTime = System.currentTimeMillis(); - modelsProvider.commit(); - final long timeInMs = System.currentTimeMillis() - startTime; - LOG.debug(String.format("%s committed in %d ms", commitDesc, timeInMs)); - } - }); - } - - private static void dispose(@NotNull final IdeModifiableModelsProvider modelsProvider, - @NotNull Project project, - boolean synchronous) { - ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { - @Override - public void execute() { - modelsProvider.dispose(); - } - }); + @Override + public Collection getExternalProjectsData(@NotNull Project project, + @NotNull ProjectSystemId projectSystemId) { + return delegate.getExternalProjectsData(project, projectSystemId); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java new file mode 100644 index 000000000000..dcdaad0854b1 --- /dev/null +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java @@ -0,0 +1,416 @@ +/* + * Copyright 2000-2013 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.openapi.externalSystem.service.project.manage; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.externalSystem.model.*; +import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.model.project.ProjectData; +import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; +import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; +import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; +import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.impl.ProjectImpl; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ExceptionUtil; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.ContainerUtilRt; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import static com.intellij.util.containers.ContainerUtil.map2Array; + +/** + * Aggregates all {@link ProjectDataService#EP_NAME registered data services} and provides entry points for project data management. + * + * @author Denis Zhdanov + * @since 4/16/13 11:38 AM + */ +public class ProjectDataManagerImpl implements ProjectDataManager { + + private static final Logger LOG = Logger.getInstance("#" + ProjectDataManagerImpl.class.getName()); + private static final com.intellij.openapi.util.Key DATA_READY = + com.intellij.openapi.util.Key.create("externalSystem.data.ready"); + + @NotNull private final NotNullLazyValue, List>>> myServices; + + public static ProjectDataManagerImpl getInstance() { + ProjectDataManager service = ServiceManager.getService(ProjectDataManager.class); + return (ProjectDataManagerImpl)service; + } + + public ProjectDataManagerImpl() { + myServices = new NotNullLazyValue, List>>>() { + @NotNull + @Override + protected Map, List>> compute() { + Map, List>> result = ContainerUtilRt.newHashMap(); + for (ProjectDataService service : ProjectDataService.EP_NAME.getExtensions()) { + List> services = result.get(service.getTargetDataKey()); + if (services == null) { + result.put(service.getTargetDataKey(), services = ContainerUtilRt.newArrayList()); + } + services.add(service); + } + + for (List> services : result.values()) { + ExternalSystemApiUtil.orderAwareSort(services); + } + return result; + } + }; + } + + @SuppressWarnings("unchecked") + @Override + public void importData(@NotNull Collection> nodes, + @NotNull Project project, + @NotNull IdeModifiableModelsProvider modelsProvider, + boolean synchronous) { + if (project.isDisposed()) return; + + MultiMap, DataNode> grouped = ExternalSystemApiUtil.recursiveGroup(nodes); + for (Key key : myServices.getValue().keySet()) { + if (!grouped.containsKey(key)) { + grouped.put(key, Collections.emptyList()); + } + } + + final Collection> projects = grouped.get(ProjectKeys.PROJECT); + // only one project(can be multi-module project) expected for per single import + assert projects.size() == 1 || projects.isEmpty(); + + final DataNode projectNode = (DataNode)ContainerUtil.getFirstItem(projects); + final ProjectData projectData; + ProjectSystemId projectSystemId; + if (projectNode != null) { + projectData = projectNode.getData(); + projectSystemId = projectNode.getData().getOwner(); + ExternalProjectsDataStorage.getInstance(project).saveInclusionSettings(projectNode); + } + else { + projectData = null; + DataNode aModuleNode = (DataNode)ContainerUtil.getFirstItem(grouped.get(ProjectKeys.MODULE)); + projectSystemId = aModuleNode != null ? aModuleNode.getData().getOwner() : null; + } + + if (projectSystemId != null) { + ExternalSystemUtil.scheduleExternalViewStructureUpdate(project, projectSystemId); + } + + List onSuccessImportTasks = ContainerUtil.newSmartList(); + try { + final Set, Collection>>> entries = grouped.entrySet(); + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.setIndeterminate(false); + } + final int size = entries.size(); + int count = 0; + List postImportTasks = ContainerUtil.newSmartList(); + for (Map.Entry, Collection>> entry : entries) { + if (indicator != null) { + String message = ExternalSystemBundle.message( + "progress.update.text", projectSystemId != null ? projectSystemId.getReadableName() : "", + "Refresh " + getReadableText(entry.getKey())); + indicator.setText(message); + indicator.setFraction((double)count++ / size); + } + doImportData(entry.getKey(), entry.getValue(), projectData, project, modelsProvider, postImportTasks, onSuccessImportTasks); + } + + for (Runnable postImportTask : postImportTasks) { + postImportTask.run(); + } + + commit(modelsProvider, project, synchronous, "Imported data"); + if (indicator != null) { + indicator.setIndeterminate(true); + } + + project.getMessageBus().syncPublisher(ProjectDataImportListener.TOPIC) + .onImportFinished(projectData != null ? projectData.getLinkedExternalProjectPath() : null); + } + catch (Throwable t) { + dispose(modelsProvider, project, synchronous); + ExceptionUtil.rethrowAllAsUnchecked(t); + } + + for (Runnable onSuccessImportTask : ContainerUtil.reverse(onSuccessImportTasks)) { + onSuccessImportTask.run(); + } + } + + @NotNull + private static String getReadableText(@NotNull Key key) { + StringBuilder buffer = new StringBuilder(); + String s = key.toString(); + for (int i = 0; i < s.length(); i++) { + char currChar = s.charAt(i); + if (Character.isUpperCase(currChar)) { + if (i != 0) { + buffer.append(' '); + } + buffer.append(StringUtil.toLowerCase(currChar)); + } + else { + buffer.append(currChar); + } + } + return buffer.toString(); + } + + @Override + public void importData(@NotNull Collection> nodes, @NotNull Project project, boolean synchronous) { + Collection> dummy = ContainerUtil.newSmartList(); + dummy.addAll(nodes); + importData(dummy, project, new IdeModifiableModelsProviderImpl(project), synchronous); + } + + @Override + public void importData(@NotNull DataNode node, + @NotNull Project project, + @NotNull IdeModifiableModelsProvider modelsProvider, + boolean synchronous) { + Collection> dummy = ContainerUtil.newSmartList(); + dummy.add(node); + importData(dummy, project, modelsProvider, synchronous); + } + + @Override + public void importData(@NotNull DataNode node, + @NotNull Project project, + boolean synchronous) { + importData(node, project, new IdeModifiableModelsProviderImpl(project), synchronous); + } + + @SuppressWarnings("unchecked") + private void doImportData(@NotNull Key key, + @NotNull Collection> nodes, + @Nullable final ProjectData projectData, + @NotNull final Project project, + @NotNull final IdeModifiableModelsProvider modelsProvider, + @NotNull final List postImportTasks, + @NotNull final List onSuccessImportTasks) { + if (project.isDisposed()) return; + if (project instanceof ProjectImpl) { + assert ((ProjectImpl)project).isComponentsCreated(); + } + + final List> toImport = ContainerUtil.newSmartList(); + final List> toIgnore = ContainerUtil.newSmartList(); + + for (DataNode node : nodes) { + if (!key.equals(node.getKey())) continue; + + if (node.isIgnored()) { + toIgnore.add(node); + } + else { + toImport.add(node); + } + } + + ensureTheDataIsReadyToUse((Collection)toImport); + + final List> services = myServices.getValue().get(key); + if (services == null) { + LOG.warn(String.format( + "Can't import data nodes '%s'. Reason: no service is registered for key %s. Available services for %s", + toImport, key, myServices.getValue().keySet() + )); + } + else { + for (ProjectDataService service : services) { + final long importStartTime = System.currentTimeMillis(); + ((ProjectDataService)service).importData(toImport, projectData, project, modelsProvider); + if (LOG.isDebugEnabled()) { + final long importTimeInMs = (System.currentTimeMillis() - importStartTime); + LOG.debug(String.format("Service %s imported data in %d ms", service.getClass().getSimpleName(), importTimeInMs)); + } + + if (projectData != null) { + ensureTheDataIsReadyToUse((Collection)toIgnore); + final long removeStartTime = System.currentTimeMillis(); + final Computable> orphanIdeDataComputable = + ((ProjectDataService)service).computeOrphanData(toImport, projectData, project, modelsProvider); + ((ProjectDataService)service).removeData(orphanIdeDataComputable, toIgnore, projectData, project, modelsProvider); + if (LOG.isDebugEnabled()) { + final long removeTimeInMs = (System.currentTimeMillis() - removeStartTime); + LOG.debug(String.format("Service %s computed and removed data in %d ms", service.getClass().getSimpleName(), removeTimeInMs)); + } + } + } + } + + if (services != null && projectData != null) { + postImportTasks.add(() -> { + for (ProjectDataService service : services) { + if (service instanceof AbstractProjectDataService) { + final long taskStartTime = System.currentTimeMillis(); + ((AbstractProjectDataService)service).postProcess(toImport, projectData, project, modelsProvider); + if (LOG.isDebugEnabled()) { + final long taskTimeInMs = (System.currentTimeMillis() - taskStartTime); + LOG.debug(String.format("Service %s run post import task in %d ms", service.getClass().getSimpleName(), taskTimeInMs)); + } + } + } + }); + onSuccessImportTasks.add(() -> { + for (ProjectDataService service : services) { + if (service instanceof AbstractProjectDataService) { + final long taskStartTime = System.currentTimeMillis(); + ((AbstractProjectDataService)service).onSuccessImport(project); + if (LOG.isDebugEnabled()) { + final long taskTimeInMs = (System.currentTimeMillis() - taskStartTime); + LOG.debug(String.format("Service %s run post import task in %d ms", service.getClass().getSimpleName(), taskTimeInMs)); + } + } + } + }); + } + } + + @Override + public void ensureTheDataIsReadyToUse(@Nullable DataNode dataNode) { + if (dataNode == null) return; + if (Boolean.TRUE.equals(dataNode.getUserData(DATA_READY))) return; + + ExternalSystemApiUtil.visit(dataNode, dataNode1 -> { + prepareDataToUse(dataNode1); + dataNode1.putUserData(DATA_READY, Boolean.TRUE); + }); + } + + @SuppressWarnings("unchecked") + public void removeData(@NotNull Key key, + @NotNull Collection toRemove, + @NotNull final Collection> toIgnore, + @NotNull final ProjectData projectData, + @NotNull Project project, + @NotNull final IdeModifiableModelsProvider modelsProvider, + boolean synchronous) { + try { + List> services = myServices.getValue().get(key); + for (ProjectDataService service : services) { + final long removeStartTime = System.currentTimeMillis(); + service.removeData(new Computable.PredefinedValueComputable(toRemove), toIgnore, projectData, project, modelsProvider); + if (LOG.isDebugEnabled()) { + final long removeTimeInMs = System.currentTimeMillis() - removeStartTime; + LOG.debug(String.format("Service %s removed data in %d ms", service.getClass().getSimpleName(), removeTimeInMs)); + } + } + + commit(modelsProvider, project, synchronous, "Removed data"); + } + catch (Throwable t) { + dispose(modelsProvider, project, synchronous); + ExceptionUtil.rethrowAllAsUnchecked(t); + } + } + + public void removeData(@NotNull Key key, + @NotNull Collection toRemove, + @NotNull final Collection> toIgnore, + @NotNull final ProjectData projectData, + @NotNull Project project, + boolean synchronous) { + removeData(key, toRemove, toIgnore, projectData, project, new IdeModifiableModelsProviderImpl(project), synchronous); + } + + public void updateExternalProjectData(@NotNull Project project, @NotNull ExternalProjectInfo externalProjectInfo) { + if (!project.isDisposed()) { + ExternalProjectsManagerImpl.getInstance(project).updateExternalProjectData(externalProjectInfo); + } + } + + @Nullable + @Override + public ExternalProjectInfo getExternalProjectData(@NotNull Project project, + @NotNull ProjectSystemId projectSystemId, + @NotNull String externalProjectPath) { + return !project.isDisposed() ? ExternalProjectsDataStorage.getInstance(project).get(projectSystemId, externalProjectPath) : null; + } + + @NotNull + @Override + public Collection getExternalProjectsData(@NotNull Project project, @NotNull ProjectSystemId projectSystemId) { + if (!project.isDisposed()) { + return ExternalProjectsDataStorage.getInstance(project).list(projectSystemId); + } + else { + return ContainerUtil.emptyList(); + } + } + + private void ensureTheDataIsReadyToUse(@NotNull Collection> nodes) { + for (DataNode node : nodes) { + ensureTheDataIsReadyToUse(node); + } + } + + private void prepareDataToUse(@NotNull DataNode dataNode) { + final Map, List>> servicesByKey = myServices.getValue(); + List> services = servicesByKey.get(dataNode.getKey()); + if (services != null) { + try { + dataNode.prepareData(map2Array(services, ClassLoader.class, service -> service.getClass().getClassLoader())); + } + catch (Exception e) { + LOG.debug(e); + dataNode.clear(true); + } + } + } + + private static void commit(@NotNull final IdeModifiableModelsProvider modelsProvider, + @NotNull Project project, + boolean synchronous, + @NotNull final String commitDesc) { + ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { + @Override + public void execute() { + final long startTime = System.currentTimeMillis(); + modelsProvider.commit(); + final long timeInMs = System.currentTimeMillis() - startTime; + LOG.debug(String.format("%s committed in %d ms", commitDesc, timeInMs)); + } + }); + } + + private static void dispose(@NotNull final IdeModifiableModelsProvider modelsProvider, + @NotNull Project project, + boolean synchronous) { + ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { + @Override + public void execute() { + modelsProvider.dispose(); + } + }); + } +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java index 96461c020e32..cd7f5336ce84 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java @@ -31,7 +31,8 @@ import com.intellij.openapi.externalSystem.model.project.Identifiable; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManagerImpl; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; @@ -123,7 +124,7 @@ public class ExternalProjectDataSelectorDialog extends DialogWrapper { } private void init(@NotNull ExternalProjectInfo projectInfo) { - ProjectDataManager.getInstance().ensureTheDataIsReadyToUse(projectInfo.getExternalProjectStructure()); + ProjectDataManagerImpl.getInstance().ensureTheDataIsReadyToUse(projectInfo.getExternalProjectStructure()); myProjectInfo = projectInfo; myExternalSystemUiAware = ExternalSystemUiUtil.getUiAware(myProjectInfo.getProjectSystemId()); myTree = createTree(); diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java index 465ea6900ea6..0aab905163b5 100644 --- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java +++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java @@ -15,8 +15,6 @@ */ package com.intellij.openapi.externalSystem.test; -import com.intellij.openapi.application.AccessToken; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.ex.CompilerPathsEx; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; @@ -26,7 +24,8 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManagerImpl; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; @@ -45,14 +44,12 @@ import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.artifacts.ArtifactManager; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.util.BooleanFunction; -import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; @@ -162,7 +159,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest List actual = new ArrayList<>(); for (ContentEntry contentRoot : contentRoots) { for (SourceFolder f : contentRoot.getSourceFolders(rootType)) { - rootUrl = rootUrl == null ? VirtualFileManager.extractPath(contentRoot.getUrl()) : VirtualFileManager.extractPath(rootUrl); + rootUrl = VirtualFileManager.extractPath(rootUrl == null ? contentRoot.getUrl() : rootUrl); String folderUrl = VirtualFileManager.extractPath(f.getUrl()); if (folderUrl.startsWith(rootUrl)) { int length = rootUrl.length() + 1; @@ -215,7 +212,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest } private static String getAbsolutePath(String path) { - path = VfsUtil.urlToPath(path); + path = VfsUtilCore.urlToPath(path); path = PathUtil.getCanonicalPath(path); return FileUtil.toSystemIndependentName(path); } @@ -364,28 +361,12 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest protected void assertArtifacts(String... expectedNames) { final List actualNames = ContainerUtil.map( - ArtifactManager.getInstance(myProject).getAllArtifactsIncludingInvalid(), new Function() { - @Override - public String fun(Artifact artifact) { - return artifact.getName(); - } - }); + ArtifactManager.getInstance(myProject).getAllArtifactsIncludingInvalid(), + (Function)artifact -> artifact.getName()); assertUnorderedElementsAreEqual(actualNames, expectedNames); } - protected Module getModule(final String name) { - AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock(); - try { - Module m = ModuleManager.getInstance(myProject).findModuleByName(name); - assertNotNull("Module " + name + " not found", m); - return m; - } - finally { - accessToken.finish(); - } - } - private ContentEntry getContentRoot(String moduleName) { ContentEntry[] ee = getContentRoots(moduleName); List roots = new ArrayList<>(); @@ -415,7 +396,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest } protected void ignoreData(BooleanFunction> booleanFunction, final boolean ignored) { - final ExternalProjectInfo externalProjectInfo = ProjectDataManager.getInstance().getExternalProjectData( + final ExternalProjectInfo externalProjectInfo = ProjectDataManagerImpl.getInstance().getExternalProjectData( myProject, getExternalSystemId(), getCurrentExternalProjectSettings().getExternalProjectPath()); assertNotNull(externalProjectInfo); From 43593dc12cc64061be6eda11e13752ed37e5af54 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 14 Apr 2017 13:34:33 +0300 Subject: [PATCH 23/26] ES: extract ExternalProjectsManager interface to API module --- .../importing/ImportSpecBuilder.java | 2 +- .../manage/ExternalProjectsManager.java | 45 +++++++++++++++++++ .../action/DetachExternalProjectAction.java | 13 +++--- ...SystemSelectProjectDataToImportAction.java | 2 +- .../action/IgnoreExternalProjectAction.java | 2 +- .../action/task/AssignShortcutAction.java | 4 +- .../task/ToggleTaskActivationAction.java | 4 +- .../ExternalSystemStartupActivity.java | 4 +- .../execution/TaskCompletionProvider.java | 2 +- .../ExternalSystemResolveProjectTask.java | 5 +-- .../ExternalSystemNotificationManager.java | 4 +- .../ExternalSystemProjectsWatcher.java | 26 +++++------ .../ExternalModuleStructureExtension.java | 2 +- .../manage/ExternalProjectsDataStorage.java | 12 +++-- ....java => ExternalProjectsManagerImpl.java} | 32 ++++++++----- .../manage/ExternalSystemKeymapExtension.java | 8 ++-- .../ExternalSystemRunManagerListener.java | 9 ++-- .../manage/ExternalSystemTaskActivator.java | 19 ++++---- .../AbstractExternalProjectImportBuilder.java | 15 ++++--- ...stractExternalSystemToolWindowFactory.java | 4 +- .../ui/ConfigureTasksActivationDialog.java | 6 +-- .../ui/SelectExternalSystemNodeDialog.java | 7 ++- .../util/ExternalSystemUtil.java | 11 ++--- .../view/ExternalProjectsViewImpl.java | 10 ++--- .../test/AbstractExternalSystemTest.groovy | 2 +- .../plugins/gradle/GradleManager.java | 2 +- .../build/CachedModuleDataFinder.java | 2 +- .../project/GradleStartupActivity.java | 2 +- .../wizard/GradleParentProjectForm.java | 2 +- .../wizard/GradleProjectImportBuilder.java | 9 +++- .../settings/GradleExtensionsSettings.java | 2 +- 31 files changed, 167 insertions(+), 102 deletions(-) create mode 100644 platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java rename platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/{ExternalProjectsManager.java => ExternalProjectsManagerImpl.java} (92%) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java index 6b9ad4fd2c69..d548cdc0924e 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/importing/ImportSpecBuilder.java @@ -21,7 +21,7 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java new file mode 100644 index 000000000000..86a068b12e9b --- /dev/null +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2016 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.openapi.externalSystem.service.project.manage; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.externalSystem.importing.ImportSpec; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +/** + * @author Vladislav.Soroka + * @since 10/23/2014 + */ +public interface ExternalProjectsManager { + + static ExternalProjectsManager getInstance(@NotNull Project project) { + return ServiceManager.getService(project, ExternalProjectsManager.class); + } + + @NotNull + Project getProject(); + + void refreshProject(@NotNull String externalProjectPath, @NotNull ImportSpec importSpec); + + void runWhenInitialized(Runnable runnable); + + boolean isIgnored(@NotNull ProjectSystemId systemId, @NotNull String projectPath); + + void setIgnored(@NotNull DataNode dataNode, boolean isIgnored); +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java index e84d1b09ca54..56ef19992f37 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java @@ -18,20 +18,17 @@ package com.intellij.openapi.externalSystem.action; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; -import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManagerImpl; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.view.ProjectNode; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.util.containers.ContainerUtilRt; @@ -87,7 +84,7 @@ public class DetachExternalProjectAction extends ExternalSystemNodeAction orphanModules = ContainerUtilRt.newArrayList(); @@ -102,8 +99,8 @@ public class DetachExternalProjectAction extends ExternalSystemNodeAction>emptyList(), projectData, project, false); + ProjectDataManagerImpl.getInstance().removeData( + ProjectKeys.MODULE, orphanModules, Collections.emptyList(), projectData, project, false); } } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java index 0528ca44fe40..85e0fd2dfcc1 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java @@ -20,7 +20,7 @@ import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelectorDialog; import com.intellij.openapi.externalSystem.view.ExternalSystemNode; import com.intellij.openapi.externalSystem.view.ProjectNode; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/IgnoreExternalProjectAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/IgnoreExternalProjectAction.java index 5b057a8bad08..2581635886ed 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/IgnoreExternalProjectAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/IgnoreExternalProjectAction.java @@ -24,7 +24,7 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ExternalConfigPathAware; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.externalSystem.view.ExternalSystemNode; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/AssignShortcutAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/AssignShortcutAction.java index 0008a6016657..4a22db75eeb3 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/AssignShortcutAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/AssignShortcutAction.java @@ -24,7 +24,7 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.model.task.TaskData; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemKeymapExtension; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager; import com.intellij.openapi.externalSystem.view.ExternalSystemNode; @@ -55,7 +55,7 @@ public class AssignShortcutAction extends ExternalSystemNodeAction { @NotNull ProjectSystemId projectSystemId, @NotNull TaskData taskData, @NotNull AnActionEvent e) { - final ExternalSystemShortcutsManager shortcutsManager = ExternalProjectsManager.getInstance(project).getShortcutsManager(); + final ExternalSystemShortcutsManager shortcutsManager = ExternalProjectsManagerImpl.getInstance(project).getShortcutsManager(); final String actionId = shortcutsManager.getActionId(taskData.getLinkedExternalProjectPath(), taskData.getName()); if (actionId != null) { AnAction action = ActionManager.getInstance().getAction(actionId); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleTaskActivationAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleTaskActivationAction.java index 07b4bf54144e..eb575a58b73c 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleTaskActivationAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleTaskActivationAction.java @@ -22,7 +22,7 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; import com.intellij.openapi.externalSystem.view.ExternalSystemNode; import com.intellij.openapi.externalSystem.view.RunConfigurationNode; @@ -108,6 +108,6 @@ public abstract class ToggleTaskActivationAction extends ExternalSystemToggleAct private ExternalSystemTaskActivator getTaskActivator(AnActionEvent e) { - return ExternalProjectsManager.getInstance(getProject(e)).getTaskActivator(); + return ExternalProjectsManagerImpl.getInstance(getProject(e)).getTaskActivator(); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemStartupActivity.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemStartupActivity.java index 6024f5d75af1..674e40369841 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemStartupActivity.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemStartupActivity.java @@ -20,7 +20,7 @@ import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.service.project.ProjectRenameAware; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.service.ui.ExternalToolWindowManager; import com.intellij.openapi.externalSystem.service.vcs.ExternalSystemVcsRegistrar; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; @@ -62,7 +62,7 @@ public class ExternalSystemStartupActivity implements StartupActivity { ProjectRenameAware.beAware(project); }; - ExternalProjectsManager.getInstance(project).init(); + ExternalProjectsManagerImpl.getInstance(project).init(); DumbService.getInstance(project).runWhenSmart(DisposeAwareRunnable.create(task, project)); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java index fabdfe8e2fa8..1bcd738b7d87 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/TaskCompletionProvider.java @@ -26,7 +26,7 @@ import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.service.execution.cmd.CommandLineCompletionProvider; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.project.Project; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java index 817d01c69b3c..d6447c1e4619 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java @@ -1,6 +1,5 @@ package com.intellij.openapi.externalSystem.service.internal; -import com.intellij.execution.configurations.ParametersList; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.model.DataNode; @@ -15,7 +14,7 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskState; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType; import com.intellij.openapi.externalSystem.service.ExternalSystemFacadeManager; import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManagerImpl; import com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl; import com.intellij.openapi.externalSystem.service.remote.RemoteExternalSystemProjectResolver; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; @@ -139,7 +138,7 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask final long currentTimeMillis = System.currentTimeMillis(); projectInfo.setLastImportTimestamp(currentTimeMillis); projectInfo.setLastSuccessfulImportTimestamp(state == ExternalSystemTaskState.FAILED ? -1 : currentTimeMillis); - ProjectDataManager.getInstance().updateExternalProjectData(getIdeProject(), projectInfo); + ProjectDataManagerImpl.getInstance().updateExternalProjectData(getIdeProject(), projectInfo); } } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java index 0a18419b8b9e..1c3346bbb589 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java @@ -28,7 +28,7 @@ import com.intellij.openapi.externalSystem.ExternalSystemConfigurableAware; import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.model.LocationAwareExternalSystemException; import com.intellij.openapi.externalSystem.model.ProjectSystemId; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; @@ -156,7 +156,7 @@ public class ExternalSystemNotificationManager implements Disposable { NotificationGroup group; if (notificationData.getBalloonGroup() == null) { ExternalProjectsView externalProjectsView = - ExternalProjectsManager.getInstance(myProject).getExternalProjectsView(externalSystemId); + ExternalProjectsManagerImpl.getInstance(myProject).getExternalProjectsView(externalSystemId); group = externalProjectsView instanceof ExternalProjectsViewImpl ? ((ExternalProjectsViewImpl)externalProjectsView).getNotificationGroup() : null; } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/autoimport/ExternalSystemProjectsWatcher.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/autoimport/ExternalSystemProjectsWatcher.java index bb8b2db75726..ce2429871012 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/autoimport/ExternalSystemProjectsWatcher.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/autoimport/ExternalSystemProjectsWatcher.java @@ -33,7 +33,7 @@ import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMo import com.intellij.openapi.externalSystem.service.internal.ExternalSystemProcessingManager; import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager; import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; @@ -609,22 +609,20 @@ public class ExternalSystemProjectsWatcher extends ExternalSystemTaskNotificatio PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file); if (psiFile != null) { final CRC32 crc32 = new CRC32(); - ApplicationManager.getApplication().runReadAction(() -> { - psiFile.acceptChildren(new PsiRecursiveElementVisitor() { - @Override - public void visitElement(PsiElement element) { - if (element instanceof LeafElement && !(element instanceof PsiWhiteSpace) && !(element instanceof PsiComment)) { - String text = element.getText(); - if (!text.trim().isEmpty()) { - for (int i = 0, end = text.length(); i < end; i++) { - crc32.update(text.charAt(i)); - } + ApplicationManager.getApplication().runReadAction(() -> psiFile.acceptChildren(new PsiRecursiveElementVisitor() { + @Override + public void visitElement(PsiElement element) { + if (element instanceof LeafElement && !(element instanceof PsiWhiteSpace) && !(element instanceof PsiComment)) { + String text = element.getText(); + if (!text.trim().isEmpty()) { + for (int i = 0, end = text.length(); i < end; i++) { + crc32.update(text.charAt(i)); } } - super.visitElement(element); } - }); - }); + super.visitElement(element); + } + })); newCrc = crc32.getValue(); } else { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalModuleStructureExtension.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalModuleStructureExtension.java index 2d76753ee28b..c624421e1c8e 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalModuleStructureExtension.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalModuleStructureExtension.java @@ -176,6 +176,6 @@ public class ExternalModuleStructureExtension extends ModuleStructureExtension { private static void unlinkProject(@NotNull Project project, ProjectSystemId systemId, String rootProjectPath) { ExternalSystemApiUtil.getLocalSettings(project, systemId).forgetExternalProjects(Collections.singleton(rootProjectPath)); ExternalSystemApiUtil.getSettings(project, systemId).unlinkExternalProject(rootProjectPath); - ExternalProjectsManager.getInstance(project).forgetExternalProjectData(systemId, rootProjectPath); + ExternalProjectsManagerImpl.getInstance(project).forgetExternalProjectData(systemId, rootProjectPath); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java index de4e72d3f9e6..cc7d901fdaa8 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java @@ -19,7 +19,10 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.ExternalSystemManager; -import com.intellij.openapi.externalSystem.model.*; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; +import com.intellij.openapi.externalSystem.model.Key; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo; import com.intellij.openapi.externalSystem.model.project.ExternalConfigPathAware; @@ -35,7 +38,8 @@ import com.intellij.openapi.module.ModuleTypeId; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.*; +import com.intellij.util.Alarm; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.xmlb.annotations.AbstractCollection; @@ -105,7 +109,7 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per final DataNode projectStructure = externalProjectInfo.getExternalProjectStructure(); if (projectStructure == null) return false; - ProjectDataManager.getInstance().ensureTheDataIsReadyToUse(projectStructure); + ProjectDataManagerImpl.getInstance().ensureTheDataIsReadyToUse(projectStructure); return externalProjectInfo.getExternalProjectPath().equals(projectStructure.getData().getLinkedExternalProjectPath()); } catch (Exception e) { @@ -262,7 +266,7 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per if (linkedProjectSettings != null && ContainerUtil.isEmpty(linkedProjectSettings.getModules())) { final Set modulePaths = ContainerUtil.map2Set( - ExternalSystemApiUtil.findAllRecursively(externalProjectInfo.getExternalProjectStructure(), ProjectKeys.MODULE), + ExternalSystemApiUtil.findAllRecursively(externalProjectInfo.getExternalProjectStructure(), MODULE), node -> node.getData().getLinkedExternalProjectPath()); linkedProjectSettings.setModules(modulePaths); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java similarity index 92% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java rename to platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java index aea2cfc34737..e7dbc98ef102 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.ExternalSystemManager; +import com.intellij.openapi.externalSystem.importing.ImportSpec; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ProjectSystemId; @@ -54,7 +55,7 @@ import static com.intellij.openapi.externalSystem.model.ProjectKeys.TASK; * @since 10/23/2014 */ @State(name = "ExternalProjectsManager", storages = {@Storage(StoragePathMacros.WORKSPACE_FILE)}) -public class ExternalProjectsManager implements PersistentStateComponent, Disposable { +public class ExternalProjectsManagerImpl implements ExternalProjectsManager, PersistentStateComponent, Disposable { private static final Logger LOG = Logger.getInstance(ExternalProjectsManager.class); private final AtomicBoolean isInitializationFinished = new AtomicBoolean(); @@ -71,12 +72,7 @@ public class ExternalProjectsManager implements PersistentStateComponent myProjectsViews = new SmartList<>(); private ExternalSystemProjectsWatcher myWatcher; - - public static ExternalProjectsManager getInstance(@NotNull Project project) { - return ServiceManager.getService(project, ExternalProjectsManager.class); - } - - public ExternalProjectsManager(@NotNull Project project) { + public ExternalProjectsManagerImpl(@NotNull Project project) { myProject = project; myShortcutsManager = new ExternalSystemShortcutsManager(project); Disposer.register(this, myShortcutsManager); @@ -84,7 +80,13 @@ public class ExternalProjectsManager implements PersistentStateComponent o.getSystemId().getId(), o -> o.getSystemId())); for (Map.Entry systemState : myState.getExternalSystemsState().entrySet()) { ProjectSystemId systemId = systemIds.get(systemState.getKey()); - if(systemId == null) continue; + if (systemId == null) continue; for (Map.Entry activationStateEntry : systemState.getValue().getExternalSystemsTaskActivation() .entrySet()) { @@ -243,6 +251,7 @@ public class ExternalProjectsManager implements PersistentStateComponent dataNode, boolean isIgnored) { ExternalProjectsDataStorage.getInstance(myProject).setIgnored(dataNode, isIgnored); ExternalSystemKeymapExtension.updateActions(myProject, ExternalSystemApiUtil.findAllRecursively(dataNode, TASK)); @@ -264,7 +274,7 @@ public class ExternalProjectsManager implements PersistentStateComponent projectToActionsMapping = MultiMap.create(); for (ExternalSystemManager manager : ExternalSystemApiUtil.getAllManagers()) { - projectToActionsMapping.putValues(manager.getSystemId(), ContainerUtil.emptyList()); + projectToActionsMapping.putValues(manager.getSystemId(), ContainerUtil.emptyList()); } ActionManager actionManager = ActionManager.getInstance(); @@ -194,7 +194,7 @@ public class ExternalSystemKeymapExtension implements KeymapExtension { private static void createActions(Project project, Collection> taskNodes) { ActionManager actionManager = ActionManager.getInstance(); - final ExternalSystemShortcutsManager shortcutsManager = ExternalProjectsManager.getInstance(project).getShortcutsManager(); + final ExternalSystemShortcutsManager shortcutsManager = ExternalProjectsManagerImpl.getInstance(project).getShortcutsManager(); if (actionManager != null) { for (DataNode each : taskNodes) { final DataNode moduleData = ExternalSystemApiUtil.findParent(each, ProjectKeys.MODULE); @@ -233,7 +233,7 @@ public class ExternalSystemKeymapExtension implements KeymapExtension { } public static String getActionPrefix(@NotNull Project project, @Nullable String path) { - return ExternalProjectsManager.getInstance(project).getShortcutsManager().getActionId(path, null); + return ExternalProjectsManagerImpl.getInstance(project).getShortcutsManager().getActionId(path, null); } public static void updateRunConfigurationActions(Project project, ProjectSystemId systemId) { @@ -251,7 +251,7 @@ public class ExternalSystemKeymapExtension implements KeymapExtension { Set settings = new THashSet<>( RunManager.getInstance(project).getConfigurationSettingsList(configurationType)); - final ExternalSystemShortcutsManager shortcutsManager = ExternalProjectsManager.getInstance(project).getShortcutsManager(); + final ExternalSystemShortcutsManager shortcutsManager = ExternalProjectsManagerImpl.getInstance(project).getShortcutsManager(); for (RunnerAndConfigurationSettings configurationSettings : settings) { ExternalSystemRunConfigurationAction runConfigurationAction = new ExternalSystemRunConfigurationAction(project, configurationSettings); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemRunManagerListener.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemRunManagerListener.java index 0426ef1f3a11..9df90b449f0f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemRunManagerListener.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemRunManagerListener.java @@ -23,6 +23,7 @@ import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; import com.intellij.openapi.externalSystem.service.execution.AbstractExternalSystemTaskConfigurationType; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl.ExternalProjectsStateProvider; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.util.Pair; @@ -42,11 +43,11 @@ import static com.intellij.openapi.externalSystem.service.project.manage.Externa */ class ExternalSystemRunManagerListener implements RunManagerListener { - private ExternalProjectsManager myManager; + private ExternalProjectsManagerImpl myManager; private final Map> myMap; public ExternalSystemRunManagerListener(ExternalProjectsManager manager) { - myManager = manager; + myManager = (ExternalProjectsManagerImpl)manager; myMap = ContainerUtil.newConcurrentMap(); } @@ -61,7 +62,7 @@ class ExternalSystemRunManagerListener implements RunManagerListener { final Pair pair = myMap.remove(System.identityHashCode(settings)); if (pair == null) return; - final ExternalProjectsManager.ExternalProjectsStateProvider stateProvider = myManager.getStateProvider(); + final ExternalProjectsStateProvider stateProvider = myManager.getStateProvider(); final ExternalSystemTaskExecutionSettings taskExecutionSettings = ((ExternalSystemRunConfiguration)settings.getConfiguration()).getSettings(); @@ -87,7 +88,7 @@ class ExternalSystemRunManagerListener implements RunManagerListener { if (settings.getConfiguration() instanceof ExternalSystemRunConfiguration) { final Pair pair = myMap.get(System.identityHashCode(settings)); if (pair != null) { - final ExternalProjectsManager.ExternalProjectsStateProvider stateProvider = myManager.getStateProvider(); + final ExternalProjectsStateProvider stateProvider = myManager.getStateProvider(); final ExternalSystemTaskExecutionSettings taskExecutionSettings = ((ExternalSystemRunConfiguration)settings.getConfiguration()).getSettings(); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemTaskActivator.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemTaskActivator.java index 90cb58ce357d..44a507be9742 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemTaskActivator.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemTaskActivator.java @@ -29,20 +29,18 @@ import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.service.execution.AbstractExternalSystemTaskConfigurationType; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager.ExternalProjectsStateProvider; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl.ExternalProjectsStateProvider; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.task.TaskCallback; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; -import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FactoryMap; @@ -96,7 +94,7 @@ public class ExternalSystemTaskActivator { public String getDescription(ProjectSystemId systemId, String projectPath, String taskName) { List result = new ArrayList<>(); final ExternalProjectsStateProvider stateProvider = - ExternalProjectsManager.getInstance(myProject).getStateProvider(); + ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); final TaskActivationState taskActivationState = stateProvider.getTasksActivation(systemId, projectPath); if (taskActivationState == null) return null; @@ -133,7 +131,8 @@ public class ExternalSystemTaskActivator { } public boolean runTasks(@NotNull Collection modules, @NotNull Phase... phases) { - final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider(); + final ExternalProjectsStateProvider stateProvider = + ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); final Queue> tasksQueue = new LinkedList<>(); @@ -245,7 +244,7 @@ public class ExternalSystemTaskActivator { } public boolean isTaskOfPhase(@NotNull TaskData taskData, @NotNull Phase phase) { - final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider(); + final ExternalProjectsStateProvider stateProvider = ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); final TaskActivationState taskActivationState = stateProvider.getTasksActivation(taskData.getOwner(), taskData.getLinkedExternalProjectPath()); if (taskActivationState == null) return false; @@ -263,7 +262,7 @@ public class ExternalSystemTaskActivator { public void addTasks(@NotNull Collection entries) { if (entries.isEmpty()) return; - final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider(); + final ExternalProjectsStateProvider stateProvider = ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); for (TaskActivationEntry entry : entries) { final TaskActivationState taskActivationState = stateProvider.getTasksActivation(entry.systemId, entry.projectPath); taskActivationState.getTasks(entry.phase).add(entry.taskName); @@ -279,7 +278,7 @@ public class ExternalSystemTaskActivator { public void removeTasks(@NotNull Collection entries) { if (entries.isEmpty()) return; - final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider(); + final ExternalProjectsStateProvider stateProvider = ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); for (TaskActivationEntry activationEntry : entries) { final TaskActivationState taskActivationState = stateProvider.getTasksActivation(activationEntry.systemId, activationEntry.projectPath); @@ -300,7 +299,7 @@ public class ExternalSystemTaskActivator { public void moveTasks(@NotNull Collection entries, int increment) { LOG.assertTrue(increment == -1 || increment == 1); - final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider(); + final ExternalProjectsStateProvider stateProvider = ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); for (TaskActivationEntry activationEntry : entries) { final TaskActivationState taskActivationState = stateProvider.getTasksActivation(activationEntry.systemId, activationEntry.projectPath); @@ -319,7 +318,7 @@ public class ExternalSystemTaskActivator { int increment) { LOG.assertTrue(increment == -1 || increment == 1); - final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider(); + final ExternalProjectsStateProvider stateProvider = ExternalProjectsManagerImpl.getInstance(myProject).getStateProvider(); final Map activationMap = stateProvider.getProjectsTasksActivationMap(systemId); final List currentPaths = ContainerUtil.newArrayList(activationMap.keySet()); if (pathsGroup != null) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java index 7ce64b7be2d5..2e8020570867 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java @@ -13,11 +13,7 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; -import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; -import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl; -import com.intellij.openapi.externalSystem.service.project.IdeUIModifiableModelsProvider; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.*; import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl; import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelectorDialog; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; @@ -71,6 +67,15 @@ public abstract class AbstractExternalProjectImportBuilder myExternalProjectNode; + /** + * @deprecated use {@link AbstractExternalProjectImportBuilder#AbstractExternalProjectImportBuilder(ProjectDataManager, AbstractImportFromExternalSystemControl, ProjectSystemId)} + */ + public AbstractExternalProjectImportBuilder(@NotNull com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager projectDataManager, + @NotNull C control, + @NotNull ProjectSystemId externalSystemId) { + this((ProjectDataManager)projectDataManager, control, externalSystemId); + } + public AbstractExternalProjectImportBuilder(@NotNull ProjectDataManager projectDataManager, @NotNull C control, @NotNull ProjectSystemId externalSystemId) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java index 49f5d05c0609..41fe11678801 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java @@ -16,7 +16,7 @@ package com.intellij.openapi.externalSystem.service.task.ui; import com.intellij.openapi.externalSystem.model.ProjectSystemId; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import com.intellij.openapi.project.DumbAware; @@ -45,7 +45,7 @@ public abstract class AbstractExternalSystemToolWindowFactory implements ToolWin toolWindow.setTitle(myExternalSystemId.getReadableName()); ContentManager contentManager = toolWindow.getContentManager(); final ExternalProjectsViewImpl projectsView = new ExternalProjectsViewImpl(project, (ToolWindowEx)toolWindow, myExternalSystemId); - ExternalProjectsManager.getInstance(project).registerView(projectsView); + ExternalProjectsManagerImpl.getInstance(project).registerView(projectsView); ContentImpl tasksContent = new ContentImpl(projectsView, ExternalSystemBundle.message("tool.window.title.projects"), true); contentManager.addContent(tasksContent); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ConfigureTasksActivationDialog.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ConfigureTasksActivationDialog.java index ff8cb1d5c682..573caa240402 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ConfigureTasksActivationDialog.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ConfigureTasksActivationDialog.java @@ -27,9 +27,10 @@ import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl.ExternalProjectsStateProvider; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator.Phase; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.externalSystem.service.project.manage.TaskActivationState; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; @@ -67,8 +68,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; -import static com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager.ExternalProjectsStateProvider; -import static com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager.getInstance; +import static com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl.getInstance; import static com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator.TaskActivationEntry; /** diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/SelectExternalSystemNodeDialog.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/SelectExternalSystemNodeDialog.java index dd9d38027270..c891721243ef 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/SelectExternalSystemNodeDialog.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/SelectExternalSystemNodeDialog.java @@ -19,8 +19,8 @@ import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.view.ExternalProjectsStructure; import com.intellij.openapi.externalSystem.view.ExternalProjectsView; import com.intellij.openapi.externalSystem.view.ExternalProjectsViewAdapter; @@ -32,7 +32,6 @@ import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.treeStructure.SimpleNode; import com.intellij.ui.treeStructure.SimpleNodeVisitor; import com.intellij.ui.treeStructure.SimpleTree; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.tree.TreeUtil; @@ -81,7 +80,7 @@ public class SelectExternalSystemNodeDialog extends DialogWrapper { myTree = new SimpleTree(); myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - final ExternalProjectsView projectsView = ExternalProjectsManager.getInstance(project).getExternalProjectsView(systemId); + final ExternalProjectsView projectsView = ExternalProjectsManagerImpl.getInstance(project).getExternalProjectsView(systemId); if(projectsView != null) { final ExternalProjectsStructure treeStructure = new ExternalProjectsStructure(project, myTree) { @SuppressWarnings("unchecked") diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index fd6d6f7cadb4..79b65ff87e9a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -52,10 +52,11 @@ import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolv import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager; import com.intellij.openapi.externalSystem.service.notification.NotificationSource; import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDataService; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManagerImpl; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.task.TaskCallback; @@ -405,7 +406,7 @@ public class ExternalSystemUtil { .clearNotifications(null, NotificationSource.PROJECT_SYNC, externalSystemId); } - final ExternalSystemTaskActivator externalSystemTaskActivator = ExternalProjectsManager.getInstance(project).getTaskActivator(); + final ExternalSystemTaskActivator externalSystemTaskActivator = ExternalProjectsManagerImpl.getInstance(project).getTaskActivator(); if (!isPreviewMode && !externalSystemTaskActivator.runTasks(externalProjectPath, ExternalSystemTaskActivator.Phase.BEFORE_SYNC)) { return; } @@ -785,7 +786,7 @@ public class ExternalSystemUtil { } public static void scheduleExternalViewStructureUpdate(@NotNull final Project project, @NotNull final ProjectSystemId systemId) { - ExternalProjectsView externalProjectsView = ExternalProjectsManager.getInstance(project).getExternalProjectsView(systemId); + ExternalProjectsView externalProjectsView = ExternalProjectsManagerImpl.getInstance(project).getExternalProjectsView(systemId); if (externalProjectsView instanceof ExternalProjectsViewImpl) { ((ExternalProjectsViewImpl)externalProjectsView).scheduleStructureUpdate(); } @@ -799,7 +800,7 @@ public class ExternalSystemUtil { ExternalSystemApiUtil.getSettings(project, projectSystemId).getLinkedProjectSettings(externalProjectPath); if (linkedProjectSettings == null) return null; - return ProjectDataManager.getInstance().getExternalProjectData( + return ProjectDataManagerImpl.getInstance().getExternalProjectData( project, projectSystemId, linkedProjectSettings.getExternalProjectPath()); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java index 163c20b982c2..bf9431ba98ac 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java @@ -31,10 +31,10 @@ import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecution import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemTaskLocation; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; @@ -77,7 +77,7 @@ public class ExternalProjectsViewImpl extends SimpleToolWindowPanel implements D @NotNull private final Project myProject; @NotNull - private final ExternalProjectsManager myProjectsManager; + private final ExternalProjectsManagerImpl myProjectsManager; @NotNull private final ToolWindowEx myToolWindow; @NotNull @@ -101,7 +101,7 @@ public class ExternalProjectsViewImpl extends SimpleToolWindowPanel implements D myToolWindow = toolWindow; myExternalSystemId = externalSystemId; myUiAware = ExternalSystemUiUtil.getUiAware(externalSystemId); - myProjectsManager = ExternalProjectsManager.getInstance(myProject); + myProjectsManager = ExternalProjectsManagerImpl.getInstance(myProject); String toolWindowId = toolWindow instanceof ToolWindowImpl ? ((ToolWindowImpl)toolWindow).getId() : myExternalSystemId.getReadableName(); @@ -527,7 +527,7 @@ public class ExternalProjectsViewImpl extends SimpleToolWindowPanel implements D } private List getSelectedNodes(Class aClass) { - return myStructure != null ? myStructure.getSelectedNodes(myTree, aClass) : ContainerUtil.emptyList(); + return myStructure != null ? myStructure.getSelectedNodes(myTree, aClass) : ContainerUtil.emptyList(); } private List getSelectedProjectNodes() { diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy index 97e51ae185a7..2b774bb8bdc6 100644 --- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy +++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy @@ -21,7 +21,7 @@ import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.externalSystem.ExternalSystemManager import com.intellij.openapi.externalSystem.model.DataNode import com.intellij.openapi.externalSystem.model.project.ProjectData -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java index fc892bb85a67..032308c97264 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java @@ -32,8 +32,8 @@ import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.service.project.ExternalSystemProjectResolver; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.service.project.autoimport.CachingExternalSystemAutoImportAware; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.externalSystem.service.ui.DefaultExternalSystemUiAware; import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/CachedModuleDataFinder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/CachedModuleDataFinder.java index faa008c06adb..e2cceebf80c9 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/CachedModuleDataFinder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/CachedModuleDataFinder.java @@ -20,7 +20,7 @@ import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.text.StringUtil; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java index 3569832846c2..977a6f0932c1 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java @@ -28,8 +28,8 @@ import com.intellij.openapi.compiler.CompileTask; import com.intellij.openapi.compiler.CompilerManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; import com.intellij.openapi.vfs.VfsUtilCore; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleParentProjectForm.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleParentProjectForm.java index a63c8e2f0dfd..1ce104ae44d7 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleParentProjectForm.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleParentProjectForm.java @@ -25,7 +25,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.service.ui.ExternalProjectPathField; import com.intellij.openapi.externalSystem.service.ui.SelectExternalProjectDialog; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java index edf1e7313ea5..4d891072282e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java @@ -24,7 +24,7 @@ import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjec import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil; import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalProjectImportBuilder; import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelectorDialog; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; @@ -54,6 +54,13 @@ import java.util.List; */ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBuilder { + /** + * @deprecated use {@link GradleProjectImportBuilder#GradleProjectImportBuilder(ProjectDataManager)} + */ + public GradleProjectImportBuilder(@NotNull com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager dataManager) { + this((ProjectDataManager)dataManager); + } + public GradleProjectImportBuilder(@NotNull ProjectDataManager dataManager) { super(dataManager, new ImportFromGradleControl(), GradleConstants.SYSTEM_ID); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java index e09c0997b274..171b4db663b0 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java @@ -22,7 +22,7 @@ import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; From a6a32f53fe05eef0c843cb775e0930a7614fc15c Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 14 Apr 2017 13:36:33 +0300 Subject: [PATCH 24/26] ES: extract ExternalProjectsManager interface to API module --- .../src/META-INF/ExternalSystemExtensions.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml b/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml index 374d8c40b91e..a450d8d4ec48 100644 --- a/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml +++ b/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml @@ -19,8 +19,11 @@ - - + + From 5d456ac6cbed2f80d0633f5bfcb4b41b15f9c4da Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 14 Apr 2017 13:41:24 +0300 Subject: [PATCH 25/26] ES: apply changes if ExternalSystemSettings configuration file has been changed by external process (like git checkout) --- .../manage/ProjectDataImportListener.java | 28 +++++++ .../AbstractExternalSystemSettings.java | 45 ++++++++-- .../test/ExternalSystemTestCase.java | 6 +- .../GradleProjectOpenProcessorTest.java | 82 +++++++++++++++++++ 4 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataImportListener.java diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataImportListener.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataImportListener.java new file mode 100644 index 000000000000..0c08fbe5687d --- /dev/null +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataImportListener.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2017 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.openapi.externalSystem.service.project.manage; + +import com.intellij.util.messages.Topic; + +/** + * @author Vladislav Soroka + * @since 4/13/17 11:38 AM + */ +public interface ProjectDataImportListener { + Topic TOPIC = new Topic<>("project data import listener", ProjectDataImportListener.class); + + void onImportFinished(String projectPath); +} diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java index 280da73e6538..71255e518dfb 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java @@ -16,6 +16,11 @@ package com.intellij.openapi.externalSystem.settings; import com.intellij.openapi.Disposable; +import com.intellij.openapi.externalSystem.ExternalSystemManager; +import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; +import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; import com.intellij.openapi.project.Project; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.messages.Topic; @@ -138,13 +143,17 @@ public abstract class AbstractExternalSystemSettings< } public void setLinkedProjectsSettings(@NotNull Collection settings) { + setLinkedProjectsSettings(settings, null); + } + + private void setLinkedProjectsSettings(@NotNull Collection settings, @Nullable ExternalSystemSettingsListener listener) { List added = ContainerUtilRt.newArrayList(); Map removed = ContainerUtilRt.newHashMap(myLinkedProjectsSettings); myLinkedProjectsSettings.clear(); for (PS current : settings) { myLinkedProjectsSettings.put(current.getExternalProjectPath(), current); } - + for (PS current : settings) { PS old = removed.remove(current.getExternalProjectPath()); if (old == null) { @@ -152,15 +161,24 @@ public abstract class AbstractExternalSystemSettings< } else { if (current.isUseAutoImport() != old.isUseAutoImport()) { + if (listener != null) { + listener.onUseAutoImportChange(current.isUseAutoImport(), current.getExternalProjectPath()); + } getPublisher().onUseAutoImportChange(current.isUseAutoImport(), current.getExternalProjectPath()); } checkSettings(old, current); } } if (!added.isEmpty()) { + if (listener != null) { + listener.onProjectsLinked(added); + } getPublisher().onProjectsLinked(added); } if (!removed.isEmpty()) { + if (listener != null) { + listener.onProjectsUnlinked(removed.keySet()); + } getPublisher().onProjectsUnlinked(removed.keySet()); } } @@ -192,10 +210,27 @@ public abstract class AbstractExternalSystemSettings< protected void loadState(@NotNull State state) { Set settings = state.getLinkedExternalProjectsSettings(); if (settings != null) { - myLinkedProjectsSettings.clear(); - for (PS projectSettings : settings) { - myLinkedProjectsSettings.put(projectSettings.getExternalProjectPath(), projectSettings); - } + setLinkedProjectsSettings(settings, new ExternalSystemSettingsListenerAdapter() { + @Override + public void onProjectsLinked(@NotNull Collection linked) { + for (Object o : linked) { + final ExternalProjectSettings settings = (ExternalProjectSettings)o; + for (ExternalSystemManager manager : ExternalSystemManager.EP_NAME.getExtensions()) { + AbstractExternalSystemSettings se = (AbstractExternalSystemSettings)manager.getSettingsProvider().fun(myProject); + ProjectSystemId externalSystemId = manager.getSystemId(); + if (settings == se.getLinkedProjectSettings(settings.getExternalProjectPath())) { + ExternalProjectsManager.getInstance(myProject).refreshProject( + settings.getExternalProjectPath(), + new ImportSpecBuilder(myProject, externalSystemId) + .useDefaultCallback() + .use(ProgressExecutionMode.IN_BACKGROUND_ASYNC) + .build() + ); + } + } + } + } + }); } } diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java index 68f0a00e0f91..8a08eeadeecc 100644 --- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java +++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java @@ -462,9 +462,13 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase { } protected Module getModule(final String name) { + return getModule(myProject, name); + } + + protected Module getModule(Project project, String name) { AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock(); try { - Module m = ModuleManager.getInstance(myProject).findModuleByName(name); + Module m = ModuleManager.getInstance(project).findModuleByName(name); assertNotNull("Module " + name + " not found", m); return m; } diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleProjectOpenProcessorTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleProjectOpenProcessorTest.java index de3d199a4ea3..af8eb7228752 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleProjectOpenProcessorTest.java +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleProjectOpenProcessorTest.java @@ -22,6 +22,8 @@ import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.ProjectJdkTable; @@ -31,12 +33,17 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.ProjectInspectionProfileManager; +import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.SmartList; +import com.intellij.util.concurrency.Semaphore; +import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.util.GradleConstants; import org.junit.Test; import org.junit.runners.Parameterized; +import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -94,6 +101,81 @@ public class GradleProjectOpenProcessorTest extends GradleImportingTestCase { } } + @Test + public void testGradleSettingsFileModification() throws IOException { + VirtualFile foo = createProjectSubDir("foo"); + createProjectSubFile("foo/build.gradle", "apply plugin: 'java'"); + createProjectSubFile("foo/.idea/modules.xml", + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""); + createProjectSubFile("foo/foo.iml", + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""); + createProjectSubFile("foo/bar.iml", + "\n" + + "\n" + + " \n" + + " \n" + + ""); + + Project fooProject = executeOnEdt(() -> ProjectUtil.openProject(foo.getPath(), null, true)); + + try { + assertTrue(fooProject.isOpen()); + edt(() -> UIUtil.dispatchAllInvocationEvents()); + assertModules(fooProject, "foo", "bar"); + + Semaphore semaphore = new Semaphore(1); + final MessageBusConnection myBusConnection = fooProject.getMessageBus().connect(); + myBusConnection.subscribe(ProjectDataImportListener.TOPIC, path -> semaphore.up()); + createProjectSubFile("foo/.idea/gradle.xml", + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + ""); + edt(() -> UIUtil.dispatchAllInvocationEvents()); + edt(() -> PlatformTestUtil.saveProject(fooProject)); + assert semaphore.waitFor(100000); + assertTrue("The module has not been linked", + ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, getModule(fooProject, "foo"))); + } + finally { + edt(() -> closeProject(fooProject)); + } + assertFalse(fooProject.isOpen()); + assertTrue(fooProject.isDisposed()); + + //edt(() -> PlatformTestUtil.saveProject(myProject)); + //importProject("apply plugin: 'java'"); + //assertModules("project", "project_main", "project_test"); + } + @Test public void testOpenAndImportProjectInHeadlessMode() throws Exception { VirtualFile foo = createProjectSubDir("foo"); From 27a140d91b1b47ca5b4bff4869e30d48707c3729 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 14 Apr 2017 15:00:31 +0300 Subject: [PATCH 26/26] properties: fix NPE --- .../psi/impl/PropertiesPsiTreeChangePreprocessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java index 8f886f9ac715..739f4e0cc389 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesPsiTreeChangePreprocessor.java @@ -59,7 +59,7 @@ public class PropertiesPsiTreeChangePreprocessor extends PsiTreeChangePreprocess if (isCodeBlock(event.getChild())) return; break; case CHILDREN_CHANGED: - if (isCodeBlock(event.getChild())) return; + if (isCodeBlock(event.getParent())) return; case PROPERTY_CHANGED: break; }