diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi index ba2d6c266fd6..663c28d15e59 100644 --- a/build/conf/nsis/idea.nsi +++ b/build/conf/nsis/idea.nsi @@ -1881,8 +1881,11 @@ skip_delete_settings: !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 7" "State" StrCmp $R3 1 "" skip_delete_tools SetShellVarContext current - IfFileExists "$LOCALAPPDATA\${MANUFACTURER}\BuildTools\*.*" 0 continue_uninstall + IfFileExists "$LOCALAPPDATA\${MANUFACTURER}\BuildTools\*.*" 0 delete_downloaded_jdk8 RmDir /r "$LOCALAPPDATA\${MANUFACTURER}\BuildTools" +delete_downloaded_jdk8: + IfFileExists "$LOCALAPPDATA\${MANUFACTURER}\jdk8\*.*" 0 continue_uninstall + RmDir /r "$LOCALAPPDATA\${MANUFACTURER}\jdk8" continue_uninstall: StrCmp $baseRegKey "HKLM" 0 skip_delete_tools diff --git a/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java b/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java index dde58f0d1e66..b0293d4c918a 100644 --- a/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java +++ b/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java @@ -68,7 +68,6 @@ import java.util.List; import java.util.*; final class ThumbnailViewUI extends JPanel implements DataProvider, Disposable { - private final VirtualFileListener vfsListener = new VFSListener(); private final OptionsChangeListener optionsListener = new OptionsChangeListener(); private static final Navigatable[] EMPTY_NAVIGATABLE_ARRAY = new Navigatable[]{}; @@ -107,7 +106,7 @@ final class ThumbnailViewUI extends JPanel implements DataProvider, Disposable { cellRenderer = new ThumbnailListCellRenderer(); ImageComponent imageComponent = cellRenderer.getImageComponent(); - VirtualFileManager.getInstance().addVirtualFileListener(vfsListener); + VirtualFileManager.getInstance().addVirtualFileListener(new VFSListener(), this); Options options = OptionsManager.getInstance().getOptions(); EditorOptions editorOptions = options.getEditorOptions(); @@ -624,8 +623,6 @@ final class ThumbnailViewUI extends JPanel implements DataProvider, Disposable { Options options = OptionsManager.getInstance().getOptions(); options.removePropertyChangeListener(optionsListener); - VirtualFileManager.getInstance().removeVirtualFileListener(vfsListener); - list = null; cellRenderer = null; tagsPanel = null; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java index 6065d07a76a3..75ccbe8f3168 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.dataFlow; import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet; @@ -163,7 +149,7 @@ class CustomMethodHandlers { if (TypeUtils.isJavaLangObject(type)) { return Object.class; } - if (TypeUtils.typeEquals("java.lang.CharSequence", type)) { + if (TypeUtils.typeEquals(JAVA_LANG_CHARSEQUENCE, type)) { return CharSequence.class; } if (PsiType.INT.equals(type)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java index dfbd37f7650d..904bcf8f80b5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java @@ -119,7 +119,7 @@ public class AllClassesGetter { final Project project = context.getProject(); final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(project); - processJavaClasses(prefixMatcher, project, scope, new LimitedAccessibleClassPreprocessor(parameters, filterByScope, consumer)); + processJavaClasses(prefixMatcher, project, scope, new LimitedAccessibleClassPreprocessor(parameters, filterByScope, c->{consumer.consume(c); return true;})); } public static void processJavaClasses(@NotNull final PrefixMatcher prefixMatcher, @@ -131,6 +131,7 @@ public class AllClassesGetter { if (prefixMatcher.prefixMatches(s)) { names.add(s); } + return true; }); LinkedHashSet sorted = CompletionUtil.sortMatching(prefixMatcher, names); AllClassesSearchExecutor.processClassesByNames(project, scope, sorted, processor); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index 1166a3b4c504..b26f2f559eeb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -106,6 +106,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { JavaPsiClassReferenceElement item = AllClassesGetter.createLookupItem(anno, JAVA_CLASS_INSERT_HANDLER); item.addLookupStrings(getClassNameWithContainers(anno)); consumer.consume(item); + return true; }); for (String name : CompletionUtil.sortMatching(matcher, annoMap.keySet())) { if (!ContainerUtil.process(annoMap.get(name), processor)) break; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 7440dc967e4a..72b4420df83b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -7,6 +7,7 @@ import com.intellij.codeInsight.completion.scope.CompletionElement; import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; import com.intellij.codeInsight.daemon.impl.analysis.LambdaHighlightingUtil; +import com.intellij.codeInsight.editorActions.TabOutScopesTracker; import com.intellij.codeInsight.guess.GuessManager; import com.intellij.codeInsight.lookup.*; import com.intellij.codeInspection.java15api.Java15APIUsageInspection; @@ -98,7 +99,7 @@ public class JavaCompletionUtil { JavaMemberNameCompletionContributor.completeVariableNameForRefactoring(project, set, camelHumpMatcher, varType, varKind, true, false); } - public static void putAllMethods(LookupElement item, List methods) { + public static void putAllMethods(LookupElement item, List methods) { item.putUserData(ALL_METHODS_ATTRIBUTE, ContainerUtil.map(methods, method -> SmartPointerManager.getInstance(method.getProject()).createSmartPsiElementPointer(method))); } @@ -827,7 +828,15 @@ public class JavaCompletionUtil { } } - toInsert.processTail(context.getEditor(), context.getTailOffset()); + Editor editor = context.getEditor(); + int tailOffset = context.getTailOffset(); + int afterTailOffset = toInsert.processTail(editor, tailOffset); + int caretOffset = editor.getCaretModel().getOffset(); + if (afterTailOffset > tailOffset && + tailOffset > caretOffset && + TabOutScopesTracker.getInstance().removeScopeEndingAt(editor, caretOffset) > 0) { + TabOutScopesTracker.getInstance().registerEmptyScope(editor, caretOffset, afterTailOffset - caretOffset); + } return true; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index bc1f47f82d08..10da8ed151c2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -223,7 +223,8 @@ public class JavaDocCompletionContributor extends CompletionContributor { for (LookupElement element : completeJavadocReference(ref.getElement(), ref)) { result.addElement(LookupElementDecorator.withInsertHandler(element, wrapIntoLinkTag((context, item) -> element.handleInsert(context)))); } - } else if (matcher.getPrefix().length() > 0) { + } + else if (matcher.getPrefix().length() > 0) { InsertHandler handler = wrapIntoLinkTag(JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER); AllClassesGetter.processJavaClasses(parameters, matcher, parameters.getInvocationCount() == 1, psiClass -> result.addElement(AllClassesGetter.createLookupItem(psiClass, handler))); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java index 37120f20cac2..ccc4f235f057 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java @@ -69,7 +69,7 @@ public class JavaStaticMemberProcessor extends StaticMemberProcessor { } @Override - protected LookupElement createLookupElement(@NotNull List overloads, + protected LookupElement createLookupElement(@NotNull List overloads, @NotNull PsiClass containingClass, boolean shouldImport) { shouldImport |= myOriginalPosition != null && PsiTreeUtil.isAncestor(containingClass, myOriginalPosition, false); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java index 98f18602e73a..b95c63e4384b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java @@ -20,7 +20,6 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl; -import com.intellij.util.Consumer; import com.intellij.util.Processor; import gnu.trove.THashSet; @@ -34,18 +33,18 @@ class LimitedAccessibleClassPreprocessor implements Processor { private final PsiElement myContext; private final CompletionParameters myParameters; private final boolean myFilterByScope; - private final Consumer myConsumer; + private final Processor myProcessor; private final int myLimit = Registry.intValue("ide.completion.variant.limit"); private int myCount; private final Set myQNames = new THashSet<>(); private final boolean myPkgContext; private final String myPackagePrefix; - LimitedAccessibleClassPreprocessor(CompletionParameters parameters, boolean filterByScope, Consumer consumer) { + LimitedAccessibleClassPreprocessor(CompletionParameters parameters, boolean filterByScope, Processor processor) { myContext = parameters.getPosition(); myParameters = parameters; myFilterByScope = filterByScope; - myConsumer = consumer; + myProcessor = processor; myPkgContext = JavaCompletionUtil.inSomePackage(myContext); myPackagePrefix = getPackagePrefix(myContext, myParameters.getOffset()); } @@ -70,7 +69,7 @@ class LimitedAccessibleClassPreprocessor implements Processor { return true; } String name = psiClass.getName(); - if (name != null && name.length() > 0 && Character.isLowerCase(name.charAt(0)) && + if (name != null && !name.isEmpty() && Character.isLowerCase(name.charAt(0)) && !Registry.is("ide.completion.show.lower.case.classes")) { return true; } @@ -83,7 +82,7 @@ class LimitedAccessibleClassPreprocessor implements Processor { LOG.debug("Processing class " + qName); } if (qName != null && qName.startsWith(myPackagePrefix) && myQNames.add(qName)) { - myConsumer.consume(psiClass); + if (!myProcessor.process(psiClass)) return false; if (++myCount > myLimit) { LOG.debug("Limit reached"); return false; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java index 69da72b66e4f..c6427736dfa3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java @@ -147,5 +147,5 @@ public abstract class StaticMemberProcessor { @Nullable protected abstract LookupElement createLookupElement(@NotNull PsiMember member, @NotNull PsiClass containingClass, boolean shouldImport); - protected abstract LookupElement createLookupElement(@NotNull List overloads, @NotNull PsiClass containingClass, boolean shouldImport); + protected abstract LookupElement createLookupElement(@NotNull List overloads, @NotNull PsiClass containingClass, boolean shouldImport); } diff --git a/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java b/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java index b92ef68a9be0..19e27c6dcdbb 100644 --- a/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection; import com.intellij.codeInsight.ExpressionUtil; @@ -1773,7 +1773,7 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal static final CallMatcher COLLECTOR_JOINING = staticCall(JAVA_UTIL_STREAM_COLLECTORS, "joining") .parameterCount(0); static final CallMatcher COLLECTOR_JOINING_DELIMITER = staticCall(JAVA_UTIL_STREAM_COLLECTORS, "joining") - .parameterTypes("java.lang.CharSequence"); + .parameterTypes(JAVA_LANG_CHARSEQUENCE); @Override public String getName() { @@ -1826,7 +1826,7 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal if (ARRAYS_STREAM.matches(qualifier) || (COLLECTION_STREAM.matches(qualifier) && ExpressionUtils.getEffectiveQualifier(qualifier.getMethodExpression()) != null)) { PsiType elementType = StreamApiUtil.getStreamElementType(qualifier.getType()); - if (InheritanceUtil.isInheritor(elementType, "java.lang.CharSequence")) { + if (InheritanceUtil.isInheritor(elementType, JAVA_LANG_CHARSEQUENCE)) { return new JoiningStringsFix(); } } @@ -1911,11 +1911,11 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal if (PsiUtil.skipParenthesizedExprDown(argumentExpressions[1]) != call) return null; PsiExpression delimiter = argumentExpressions[0]; if (delimiter == null) return null; - if(!InheritanceUtil.isInheritor(delimiter.getType(), "java.lang.CharSequence")) return null; + if(!InheritanceUtil.isInheritor(delimiter.getType(), JAVA_LANG_CHARSEQUENCE)) return null; PsiMethodCallExpression stream = getQualifierMethodCall(call); if (stream == null) return null; PsiType elementType = StreamApiUtil.getStreamElementType(stream.getType()); - if (!InheritanceUtil.isInheritor(elementType, "java.lang.CharSequence")) return null; + if (!InheritanceUtil.isInheritor(elementType, JAVA_LANG_CHARSEQUENCE)) return null; return new Context(maybeJoinCall, delimiter, argument); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java b/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java index b608a3c0a07a..0a2f408f6c50 100644 --- a/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.streamMigration; import com.intellij.codeInspection.*; @@ -26,6 +26,7 @@ import java.util.List; import java.util.Objects; import static com.intellij.codeInsight.intention.impl.StreamRefactoringUtil.getMapOperationName; +import static com.intellij.psi.CommonClassNames.JAVA_LANG_CHARSEQUENCE; import static com.intellij.util.ObjectUtils.tryCast; public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalInspectionTool { @@ -137,7 +138,7 @@ public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalIns PsiExpression[] operands = polyadicExpression.getOperands(); String mapToString; PsiType operandType = operands[0].getType(); - if (!InheritanceUtil.isInheritor(operandType, "java.lang.CharSequence")) { + if (!InheritanceUtil.isInheritor(operandType, JAVA_LANG_CHARSEQUENCE)) { if (!StreamApiUtil.isSupportedStreamElement(operandType)) return null; mapToString = "."+getMapOperationName(operandType, type)+"(String::valueOf)"; } else { @@ -150,7 +151,7 @@ public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalIns .pairMap(EquivalenceChecker.getCanonicalPsiEquivalence()::expressionsAreEquivalent) .allMatch(Boolean.TRUE::equals)) { delimiter = operands[1]; - if (!InheritanceUtil.isInheritor(delimiter.getType(), "java.lang.CharSequence") && + if (!InheritanceUtil.isInheritor(delimiter.getType(), JAVA_LANG_CHARSEQUENCE) && !(delimiter instanceof PsiLiteralExpression && PsiType.CHAR.equals(delimiter.getType()))) { return null; } diff --git a/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java b/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java index 22e755dea893..71f788d4f6fa 100644 --- a/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java +++ b/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.streamMigration; @@ -41,6 +27,7 @@ import java.util.function.Predicate; import static com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil.isEffectivelyFinal; import static com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.isCallOf; +import static com.intellij.psi.CommonClassNames.JAVA_LANG_CHARSEQUENCE; import static com.intellij.util.ObjectUtils.tryCast; import static com.siyeh.ig.psiutils.ControlFlowUtils.getInitializerUsageStatus; import static com.siyeh.ig.psiutils.ExpressionUtils.resolveLocalVariable; @@ -330,7 +317,7 @@ public class JoiningMigration extends BaseStreamApiMigration { } } } - if (!InheritanceUtil.isInheritor(type, "java.lang.CharSequence")) { + if (!InheritanceUtil.isInheritor(type, JAVA_LANG_CHARSEQUENCE)) { if (!neighborIsString || (type instanceof PsiArrayType && ((PsiArrayType)type).getComponentType().equals(PsiType.CHAR))) { PsiLiteralExpression literalExpression = tryCast(expression, PsiLiteralExpression.class); if (literalExpression != null) { diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java b/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java index 808aeb4720b7..c3d7b24ac553 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java @@ -84,11 +84,13 @@ public class JavaCallReferenceProcessor implements CallReferenceProcessor { final PsiElement element = reference.getElement(); final PsiMember key = CallHierarchyNodeDescriptor.getEnclosingElement(element); + CallHierarchyNodeDescriptor parentDescriptor = (CallHierarchyNodeDescriptor) data.getNodeDescriptor(); + if (isRecursiveNode(method, parentDescriptor)) return false; synchronized (methodToDescriptorMap) { CallHierarchyNodeDescriptor d = (CallHierarchyNodeDescriptor)methodToDescriptorMap.get(key); if (d == null) { - d = new CallHierarchyNodeDescriptor(myProject, (CallHierarchyNodeDescriptor)data.getNodeDescriptor(), element, false, true); + d = new CallHierarchyNodeDescriptor(myProject, parentDescriptor, element, false, true); methodToDescriptorMap.put(key, d); } else if (!d.hasReference(reference)) { @@ -98,4 +100,25 @@ public class JavaCallReferenceProcessor implements CallReferenceProcessor { } return false; } + + private static boolean isRecursiveNode(@NotNull PsiMethod method, @NotNull CallHierarchyNodeDescriptor parentDescriptor) { + // detect recursion + // the current call-site calls *method* + // Thus, we already have a node that represents *method* + // Check whether we have any other node along the parent-chain that represents that same method + + NodeDescriptor ancestorDescriptor = parentDescriptor; + // Start check on grandparent + while ((ancestorDescriptor = ancestorDescriptor.getParentDescriptor()) != null) { + if (ancestorDescriptor instanceof CallHierarchyNodeDescriptor) { + PsiMember ancestorCallSite = ((CallHierarchyNodeDescriptor)ancestorDescriptor).getEnclosingElement(); + if (ancestorCallSite == method) { + // We have at least two occurrences in the parent chain of method already + // Don't search any deeper + return true; + } + } + } + return false; + } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java index ebd764b92cb4..b852305487a4 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java @@ -17,7 +17,6 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.AllClassesSearch; -import com.intellij.util.Consumer; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; import com.intellij.util.indexing.IdFilter; @@ -50,6 +49,7 @@ public class AllClassesSearchExecutor implements QueryExecutor sorted = new ArrayList<>(names); @@ -75,18 +75,15 @@ public class AllClassesSearchExecutor implements QueryExecutor consumer) { - DumbService.getInstance(project).runReadActionInSmartMode((Computable)() -> { + public static boolean processClassNames(final Project project, final GlobalSearchScope scope, final Processor processor) { + boolean success = DumbService.getInstance(project).runReadActionInSmartMode((Computable)() -> PsiShortNamesCache.getInstance(project).processAllClassNames(s -> { ProgressManager.checkCanceled(); - consumer.consume(s); - return true; - }, scope, IdFilter.getProjectIdFilter(project, true)); - return null; - }); + return processor.process(s); + }, scope, IdFilter.getProjectIdFilter(project, true))); ProgressManager.checkCanceled(); - return project; + return success; } private static boolean processScopeRootForAllClasses(@NotNull final PsiElement scopeRoot, @NotNull final Processor processor) { diff --git a/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java new file mode 100644 index 000000000000..b2f5460a32fc --- /dev/null +++ b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java @@ -0,0 +1,9 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +class A { + public static void main(String[] args) { + recursive(); + } + public static void recursive() { + recursive(); + } +} diff --git a/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml new file mode 100644 index 000000000000..d8101f0674d8 --- /dev/null +++ b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java new file mode 100644 index 000000000000..255c46fe530a --- /dev/null +++ b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java @@ -0,0 +1,13 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +class A { + public static void main(String[] args) { + recursive1(); + } + public static void recursive1() { + recursive2(); + } + + public static void recursive2() { + recursive1(); + } +} diff --git a/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml new file mode 100644 index 000000000000..cc117a25fd0e --- /dev/null +++ b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java index 99656ecd19c1..4d29cb4673e5 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java @@ -90,6 +90,15 @@ public class EditorTabOutTest extends AbstractParameterInfoTestCase { "}"); } + public void testSemicolon() { + configureJava("class C { void m() { System.exi } }"); + complete("exit"); + checkResult("class C { void m() { System.exit(); } }"); + type('1'); + tabOut(); + checkResult("class C { void m() { System.exit(1); } }"); + } + private void tabOut() { myFixture.performEditorAction(IdeActions.ACTION_BRACE_OR_QUOTE_OUT); } diff --git a/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java b/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java index 47bc9e6edf88..9ef56c77ff69 100644 --- a/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java +++ b/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java @@ -58,6 +58,14 @@ public class JavaCallHierarchyTest extends HierarchyViewTestBase { doJavaCallTypeHierarchyTest("B", "xyzzy", "B.java", "D.java", "A.java"); } + public void testDirectRecursion() throws Exception { + doJavaCallTypeHierarchyTest("A", "recursive", "A.java"); + } + + public void testIndirectRecursion() throws Exception { + doJavaCallTypeHierarchyTest("A", "recursive2", "A.java"); + } + public void testIdeaDev41005_Inheritance() throws Exception { doJavaCallTypeHierarchyTest("D", "xyzzy", "B.java", "D.java", "A.java", "C.java"); } diff --git a/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java b/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java index 262a0f117277..cb70612a8136 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java @@ -5,12 +5,9 @@ import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import gnu.trove.TIntHashSet; -import gnu.trove.TIntIterator; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.*; -import java.util.function.IntFunction; /** * Set of VirtualFiles optimized for compact storage of very large number of files @@ -146,31 +143,8 @@ public class CompactVirtualFileSet extends AbstractSet { Iterator idsIterator = ids == null ? Collections.emptyIterator() : ContainerUtil.mapIterator(ids.stream().iterator(), id -> virtualFileManager.findFileById(id)); Iterator idSetIterator = idSet == null ? Collections.emptyIterator() : - mapIterator(idSet.iterator(), id -> virtualFileManager.findFileById(id)); + ContainerUtil.mapIterator(idSet.iterator(), id -> virtualFileManager.findFileById(id)); Iterator weirdFileIterator = weirdFiles.iterator(); return ContainerUtil.filterIterator(ContainerUtil.concatIterators(idsIterator, idSetIterator, weirdFileIterator), Objects::nonNull); } - - // todo move to ContainerUtil when ported util to java level 8 - @NotNull - @Contract(pure=true) - public static Iterator mapIterator(@NotNull final TIntIterator iterator, @NotNull final IntFunction mapper) { - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public U next() { - return mapper.apply(iterator.next()); - } - - @Override - public void remove() { - iterator.remove(); - } - }; - } - } diff --git a/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java b/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java index 10d0971224ae..a530a539bbb6 100644 --- a/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java +++ b/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java @@ -21,7 +21,8 @@ public final class SimpleTextAttributes { @MagicConstant(flags = { STYLE_PLAIN, STYLE_BOLD, STYLE_ITALIC, STYLE_STRIKEOUT, STYLE_WAVED, STYLE_UNDERLINE, - STYLE_BOLD_DOTTED_LINE, STYLE_SEARCH_MATCH, STYLE_SMALLER, STYLE_OPAQUE, STYLE_CLICKABLE}) + STYLE_BOLD_DOTTED_LINE, STYLE_SEARCH_MATCH, STYLE_SMALLER, STYLE_OPAQUE, + STYLE_CLICKABLE, STYLE_HOVERED}) public @interface StyleAttributeConstant { } public static final int STYLE_PLAIN = Font.PLAIN; @@ -36,6 +37,7 @@ public final class SimpleTextAttributes { public static final int STYLE_SMALLER = STYLE_SEARCH_MATCH << 1; public static final int STYLE_OPAQUE = STYLE_SMALLER << 1; public static final int STYLE_CLICKABLE = STYLE_OPAQUE << 1; + public static final int STYLE_HOVERED = STYLE_CLICKABLE << 1; public static final SimpleTextAttributes REGULAR_ATTRIBUTES = new SimpleTextAttributes(STYLE_PLAIN, null); public static final SimpleTextAttributes REGULAR_BOLD_ATTRIBUTES = new SimpleTextAttributes(STYLE_BOLD, null); @@ -83,7 +85,7 @@ public final class SimpleTextAttributes { this(null, fgColor, waveColor, style); } - public SimpleTextAttributes(@Nullable final Color bgColor, final Color fgColor, @Nullable final Color waveColor, @StyleAttributeConstant int style) { + public SimpleTextAttributes(@Nullable Color bgColor, Color fgColor, @Nullable Color waveColor, @StyleAttributeConstant int style) { if ((~(STYLE_PLAIN | STYLE_BOLD | STYLE_ITALIC | @@ -94,7 +96,8 @@ public final class SimpleTextAttributes { STYLE_SEARCH_MATCH | STYLE_SMALLER | STYLE_OPAQUE | - STYLE_CLICKABLE) & style) != 0) { + STYLE_CLICKABLE | + STYLE_HOVERED) & style) != 0) { throw new IllegalArgumentException("Wrong style: " + style); } @@ -172,6 +175,10 @@ public final class SimpleTextAttributes { return BitUtil.isSet(myStyle, STYLE_CLICKABLE); } + public boolean isHovered() { + return BitUtil.isSet(myStyle, STYLE_HOVERED); + } + @NotNull public static SimpleTextAttributes fromTextAttributes(TextAttributes attributes) { if (attributes == null) return REGULAR_ATTRIBUTES; diff --git a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java index b148eb75d822..2be73d1adb45 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java @@ -152,6 +152,7 @@ public class PluginClassLoader extends UrlClassLoader { private static final Set KOTLIN_STDLIB_CLASSES_USED_IN_SIGNATURES = ContainerUtil.set( "kotlin.sequences.Sequence", + "kotlin.Lazy", "kotlin.Unit", "kotlin.Pair", "kotlin.Triple", diff --git a/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java b/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java index c921ff64f97c..8e3946902d81 100644 --- a/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java +++ b/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java @@ -16,6 +16,7 @@ package com.intellij.diff; import com.intellij.openapi.ui.WindowWrapper; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,19 +33,21 @@ public class DiffDialogHints { // @Nullable private final WindowWrapper.Mode myMode; - @Nullable private Component myParent; + @Nullable private final Component myParent; + @Nullable private final Consumer myWindowConsumer; public DiffDialogHints(@Nullable WindowWrapper.Mode mode) { this(mode, null); } public DiffDialogHints(@Nullable WindowWrapper.Mode mode, @Nullable Component parent) { - myMode = mode; - myParent = parent; + this(mode, parent, null); } - public void setParent(@Nullable Component value) { - myParent = value; + public DiffDialogHints(@Nullable WindowWrapper.Mode mode, @Nullable Component parent, @Nullable Consumer windowConsumer) { + myMode = mode; + myParent = parent; + myWindowConsumer = windowConsumer; } // @@ -60,4 +63,12 @@ public class DiffDialogHints { public Component getParent() { return myParent; } + + /** + * NB: Consumer might not be called at all (ex: for external diff/merge tools, that do not spawn WindowWrapper) + */ + @Nullable + public Consumer getWindowConsumer() { + return myWindowConsumer; + } } diff --git a/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java b/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java index cef525a236aa..5852f78c1bee 100644 --- a/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java +++ b/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java @@ -17,6 +17,7 @@ package com.intellij.diff; import com.intellij.diff.chains.DiffRequestChain; import com.intellij.diff.merge.MergeRequest; +import com.intellij.diff.merge.MergeRequestProducer; import com.intellij.diff.merge.MergeTool; import com.intellij.diff.requests.DiffRequest; import com.intellij.openapi.components.ServiceManager; @@ -50,6 +51,9 @@ public abstract class DiffManagerEx extends DiffManager { @CalledInAwt public abstract void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequest request); + @CalledInAwt + public abstract void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequestProducer request, @NotNull DiffDialogHints hints); + @NotNull public abstract List getDiffTools(); diff --git a/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java b/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java index e6040a65403a..ac4fb0f677b8 100644 --- a/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java +++ b/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java @@ -91,6 +91,13 @@ public abstract class DiffRequestFactory { @NotNull List contentTitles, @Nullable Consumer applyCallback) throws InvalidDiffRequestException; + @NotNull + public abstract MergeRequest createMergeRequest(@Nullable Project project, + @NotNull VirtualFile output, + @NotNull List byteContents, + @Nullable String title, + @NotNull List contentTitles) throws InvalidDiffRequestException; + @NotNull public abstract TextMergeRequest createTextMergeRequest(@Nullable Project project, @NotNull VirtualFile output, diff --git a/platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java b/platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java new file mode 100644 index 000000000000..5496e78237f6 --- /dev/null +++ b/platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java @@ -0,0 +1,60 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.diff.merge; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Key; +import com.intellij.util.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EventListener; + +import static com.intellij.openapi.diagnostic.Logger.getInstance; + +public class MergeCallback { + private static final Logger LOG = getInstance(MergeCallback.class); + + private static final Key KEY = Key.create("com.intellij.diff.merge.MergeCallback"); + private static final MergeCallback EMPTY = new MergeCallback(); + + public void applyResult(@NotNull MergeResult result) { + } + + public boolean checkIsValid() { + return true; + } + + public void addListener(@NotNull Listener listener, @NotNull Disposable disposable) { + } + + + @NotNull + public static T register(@NotNull T request, @Nullable MergeCallback callback) { + LOG.assertTrue(request.getUserData(KEY) == null); + if (callback != null) request.putUserData(KEY, callback); + return request; + } + + @NotNull + public static T register(@NotNull T request, @Nullable Consumer callback) { + return register(request, new MergeCallback() { + @Override + public void applyResult(@NotNull MergeResult result) { + if (callback != null) callback.consume(result); + } + }); + } + + @NotNull + public static MergeCallback getCallback(@NotNull MergeRequest request) { + MergeCallback callback = request.getUserData(KEY); + return callback != null ? callback : EMPTY; + } + + + public interface Listener extends EventListener { + default void fireConflictInvalid() { + } + } +} diff --git a/platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java b/platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java new file mode 100644 index 000000000000..bc37feb8fdc9 --- /dev/null +++ b/platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java @@ -0,0 +1,19 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.diff.merge; + +import com.intellij.diff.chains.DiffRequestProducerException; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.UserDataHolder; +import org.jetbrains.annotations.CalledInBackground; +import org.jetbrains.annotations.NotNull; + +public interface MergeRequestProducer { + @NotNull + String getName(); + + @CalledInBackground + @NotNull + MergeRequest process(@NotNull UserDataHolder context, @NotNull ProgressIndicator indicator) + throws DiffRequestProducerException, ProcessCanceledException; +} diff --git a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java index 44d08d78e6bc..728d376f58be 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java @@ -133,6 +133,12 @@ public class DiffManagerImpl extends DiffManagerEx { @Override @CalledInAwt public void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequest request) { - new MergeWindow(project, request).show(); + new MergeWindow.ForRequest(project, request, DiffDialogHints.MODAL).show(); + } + + @Override + @CalledInAwt + public void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequestProducer requestProducer, @NotNull DiffDialogHints hints) { + new MergeWindow.ForProducer(project, requestProducer, hints).show(); } } diff --git a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java index d0f70ee940fe..6820af6d9159 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java @@ -18,6 +18,7 @@ package com.intellij.diff; import com.intellij.diff.contents.DiffContent; import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.contents.FileContent; +import com.intellij.diff.merge.MergeCallback; import com.intellij.diff.merge.MergeRequest; import com.intellij.diff.merge.MergeResult; import com.intellij.diff.merge.TextMergeRequest; @@ -232,7 +233,8 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { contents.add(myContentFactory.create(project, text, fileType)); } - return new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, titles, applyCallback); + TextMergeRequestImpl request = new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, titles); + return MergeCallback.register(request, applyCallback); } @NotNull @@ -243,14 +245,22 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { @Nullable String title, @NotNull List contentTitles, @Nullable Consumer applyCallback) throws InvalidDiffRequestException { - if (byteContents.size() != 3) throw new IllegalArgumentException(); - if (contentTitles.size() != 3) throw new IllegalArgumentException(); + MergeRequest request = createMergeRequest(project, output, byteContents, title, contentTitles); + return MergeCallback.register(request, applyCallback); + } + @NotNull + @Override + public MergeRequest createMergeRequest(@Nullable Project project, + @NotNull VirtualFile output, + @NotNull List byteContents, + @Nullable String title, + @NotNull List contentTitles) throws InvalidDiffRequestException { try { - return createTextMergeRequest(project, output, byteContents, title, contentTitles, applyCallback); + return createTextMergeRequest(project, output, byteContents, title, contentTitles); } catch (InvalidDiffRequestException e) { - return createBinaryMergeRequest(project, output, byteContents, title, contentTitles, applyCallback); + return createBinaryMergeRequest(project, output, byteContents, title, contentTitles); } } @@ -262,6 +272,16 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { @Nullable String title, @NotNull List contentTitles, @Nullable Consumer applyCallback) throws InvalidDiffRequestException { + TextMergeRequest request = createTextMergeRequest(project, output, byteContents, title, contentTitles); + return MergeCallback.register(request, applyCallback); + } + + @NotNull + private TextMergeRequest createTextMergeRequest(@Nullable Project project, + @NotNull VirtualFile output, + @NotNull List byteContents, + @Nullable String title, + @NotNull List contentTitles) throws InvalidDiffRequestException { if (byteContents.size() != 3) throw new IllegalArgumentException(); if (contentTitles.size() != 3) throw new IllegalArgumentException(); @@ -277,7 +297,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { contents.add(myContentFactory.createDocumentFromBytes(project, bytes, output)); } - return new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, contentTitles, applyCallback); + return new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, contentTitles); } @NotNull @@ -288,6 +308,16 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { @Nullable String title, @NotNull List contentTitles, @Nullable Consumer applyCallback) throws InvalidDiffRequestException { + MergeRequest request = createBinaryMergeRequest(project, output, byteContents, title, contentTitles); + return MergeCallback.register(request, applyCallback); + } + + @NotNull + private MergeRequest createBinaryMergeRequest(@Nullable Project project, + @NotNull VirtualFile output, + @NotNull List byteContents, + @Nullable String title, + @NotNull List contentTitles) throws InvalidDiffRequestException { if (byteContents.size() != 3) throw new IllegalArgumentException(); if (contentTitles.size() != 3) throw new IllegalArgumentException(); @@ -301,7 +331,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { contents.add(myContentFactory.createFromBytes(project, bytes, output)); } - return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback); + return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles); } catch (IOException e) { throw new InvalidDiffRequestException("Can't read from file", e); @@ -384,7 +414,9 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { byteContents.add(file.contentsToByteArray()); // TODO: we can read contents from file when needed } - return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback); + BinaryMergeRequestImpl request = new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, + title, contentTitles); + return MergeCallback.register(request, applyCallback); } catch (IOException e) { throw new InvalidDiffRequestException("Can't read from file", e); diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java index e4d0053e27bd..c223edd68f1a 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.WindowWrapper; import com.intellij.openapi.ui.WindowWrapperBuilder; import com.intellij.openapi.util.Disposer; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,6 +58,9 @@ public abstract class DiffWindowBase { .build(); myWrapper.setImages(DiffUtil.DIFF_FRAME_ICONS); Disposer.register(myWrapper, myProcessor); + + Consumer wrapperHandler = myHints.getWindowConsumer(); + if (wrapperHandler != null) wrapperHandler.consume(myWrapper); } public void show() { diff --git a/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java b/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java index 70055802dc21..26c6e8dada33 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java @@ -48,12 +48,7 @@ public class ErrorMergeTool implements MergeTool { myMergeRequest = request; myPanel = new JPanel(new BorderLayout()); - myPanel.add(createComponent(), BorderLayout.CENTER); - } - - @NotNull - private JComponent createComponent() { - return DiffUtil.createMessagePanel("Can't show diff"); + myPanel.add(DiffUtil.createMessagePanel("Can't show merge"), BorderLayout.CENTER); } @NotNull diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java index 1fc51b5b6790..c66b6340f157 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java @@ -16,14 +16,25 @@ import com.intellij.notification.NotificationType; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.util.BackgroundTaskUtil; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.BooleanGetter; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; +import com.intellij.ui.EditorNotificationPanel; +import com.intellij.ui.LightColors; +import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.components.panels.Wrapper; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.JBEmptyBorder; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.CalledInAwt; @@ -53,17 +64,17 @@ public abstract class MergeRequestProcessor implements Disposable { @NotNull private final Wrapper myContentPanel; @NotNull private final Wrapper myToolbarPanel; @NotNull private final Wrapper myToolbarStatusPanel; + @NotNull private final Wrapper myNotificationPanel; + @NotNull private final Wrapper myButtonsPanel; - @NotNull private final MergeRequest myRequest; + @Nullable private MergeRequest myRequest; @NotNull private MergeTool.MergeViewer myViewer; @Nullable private BooleanGetter myCloseHandler; - @Nullable private BottomActions myBottomActions; private boolean myConflictResolved = false; - public MergeRequestProcessor(@Nullable Project project, @NotNull MergeRequest request) { + public MergeRequestProcessor(@Nullable Project project) { myProject = project; - myRequest = request; myContext = new MyDiffContext(); myContext.putUserData(DiffUserDataKeys.PLACE, DiffPlaces.MERGE); @@ -75,28 +86,23 @@ public abstract class MergeRequestProcessor implements Disposable { myToolbarPanel = new Wrapper(); myToolbarPanel.setFocusable(true); myToolbarStatusPanel = new Wrapper(); + myNotificationPanel = new Wrapper(); + myButtonsPanel = new Wrapper(); myPanel = JBUI.Panels.simplePanel(myMainPanel); - JPanel topPanel = JBUI.Panels.simplePanel(myToolbarPanel).addToRight(myToolbarStatusPanel); + JPanel topPanel = JBUI.Panels.simplePanel(myToolbarPanel) + .addToRight(myToolbarStatusPanel) + .addToBottom(myNotificationPanel); myMainPanel.add(topPanel, BorderLayout.NORTH); myMainPanel.add(myContentPanel, BorderLayout.CENTER); + myMainPanel.add(myButtonsPanel, BorderLayout.SOUTH); myMainPanel.setFocusTraversalPolicyProvider(true); myMainPanel.setFocusTraversalPolicy(new MyFocusTraversalPolicy()); - MergeTool.MergeViewer viewer; - try { - viewer = getFittedTool().createComponent(myContext, myRequest); - } - catch (Throwable e) { - LOG.error(e); - viewer = ErrorMergeTool.INSTANCE.createComponent(myContext, myRequest); - } - - myViewer = viewer; - updateBottomActions(); + myViewer = new MessageMergeViewer(myContext, "Loading..."); } // @@ -104,9 +110,50 @@ public abstract class MergeRequestProcessor implements Disposable { // @CalledInAwt - public void init() { - setTitle(myRequest.getTitle()); + public void init(@NotNull MergeRequest request) { + setTitle(request.getTitle()); + + myRequest = request; + myViewer = createViewerFor(request); initViewer(); + installCallbackListener(myRequest); + } + + @CalledInAwt + public void init(@NotNull MergeRequestProducer request) { + setTitle(request.getName()); + initViewer(); + + ModalityState modality = ModalityState.stateForComponent(myPanel); + BackgroundTaskUtil.executeOnPooledThread(this, () -> { + try { + MergeRequest mergeRequest = request.process(myContext, ProgressManager.getInstance().getProgressIndicator()); + ApplicationManager.getApplication().invokeLater( + () -> { + myRequest = mergeRequest; + swapViewer(createViewerFor(mergeRequest)); + installCallbackListener(myRequest); + }, + modality); + } + catch (Throwable e) { + LOG.warn(e); + ApplicationManager.getApplication().invokeLater( + () -> swapViewer(new MessageMergeViewer(myContext, "Can't show merge: " + e.getMessage())), + modality); + } + }); + } + + @NotNull + private MergeTool.MergeViewer createViewerFor(@NotNull MergeRequest request) { + try { + return getFittedTool(request).createComponent(myContext, request); + } + catch (Throwable e) { + LOG.error(e); + return ErrorMergeTool.INSTANCE.createComponent(myContext, request); + } } @CalledInAwt @@ -118,6 +165,8 @@ public abstract class MergeRequestProcessor implements Disposable { buildToolbar(toolbarComponents.toolbarActions); myToolbarStatusPanel.setContent(toolbarComponents.statusPanel); myCloseHandler = toolbarComponents.closeHandler; + + updateBottomActions(); } @CalledInAwt @@ -129,16 +178,49 @@ public abstract class MergeRequestProcessor implements Disposable { myContentPanel.setContent(null); myToolbarPanel.setContent(null); myToolbarStatusPanel.setContent(null); + myButtonsPanel.setContent(null); myCloseHandler = null; - myBottomActions = null; } private void updateBottomActions() { - myBottomActions = new BottomActions(); - myBottomActions.applyLeft = myViewer.getResolveAction(MergeResult.LEFT); - myBottomActions.applyRight = myViewer.getResolveAction(MergeResult.RIGHT); - myBottomActions.resolveAction = myViewer.getResolveAction(MergeResult.RESOLVED); - myBottomActions.cancelAction = myViewer.getResolveAction(MergeResult.CANCEL); + Action applyLeft = myViewer.getResolveAction(MergeResult.LEFT); + Action applyRight = myViewer.getResolveAction(MergeResult.RIGHT); + Action resolveAction = myViewer.getResolveAction(MergeResult.RESOLVED); + Action cancelAction = myViewer.getResolveAction(MergeResult.CANCEL); + + if (resolveAction != null) { + resolveAction.putValue(DialogWrapper.DEFAULT_ACTION, true); + + new DumbAwareAction() { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + resolveAction.actionPerformed(null); + } + }.registerCustomShortcutSet(CommonShortcuts.CTRL_ENTER, getRootPane(), this); + } + + List leftActions = ContainerUtil.packNullables(applyLeft, applyRight); + List rightActions = SystemInfo.isMac ? ContainerUtil.packNullables(cancelAction, resolveAction) + : ContainerUtil.packNullables(resolveAction, cancelAction); + + JRootPane rootPane = getRootPane(); + JPanel buttonsPanel = new NonOpaquePanel(new BorderLayout()); + buttonsPanel.setBorder(new JBEmptyBorder(UIUtil.PANEL_REGULAR_INSETS)); + + if (leftActions.size() > 0) { + buttonsPanel.add(createButtonsPanel(leftActions, rootPane), BorderLayout.WEST); + } + if (rightActions.size() > 0) { + buttonsPanel.add(createButtonsPanel(rightActions, rootPane), BorderLayout.EAST); + } + + myButtonsPanel.setContent(buttonsPanel); + } + + @NotNull + private static JPanel createButtonsPanel(@NotNull List actions, @Nullable JRootPane rootPane) { + List buttons = ContainerUtil.map(actions, action -> DialogWrapper.createJButtonForAction(action, rootPane)); + return DialogWrapper.layoutButtonsPanel(buttons); } @NotNull @@ -151,12 +233,14 @@ public abstract class MergeRequestProcessor implements Disposable { DiffUtil.addActionBlock(group, viewerActions); - List requestContextActions = myRequest.getUserData(DiffUserDataKeys.CONTEXT_ACTIONS); + List requestContextActions = myRequest != null ? myRequest.getUserData(DiffUserDataKeys.CONTEXT_ACTIONS) : null; DiffUtil.addActionBlock(group, requestContextActions); List contextActions = myContext.getUserData(DiffUserDataKeys.CONTEXT_ACTIONS); DiffUtil.addActionBlock(group, contextActions); + DiffUtil.addActionBlock(group, ActionManager.getInstance().getAction(IdeActions.ACTION_CONTEXT_HELP)); + return group; } @@ -173,10 +257,10 @@ public abstract class MergeRequestProcessor implements Disposable { } @NotNull - private MergeTool getFittedTool() { + private MergeTool getFittedTool(@NotNull MergeRequest request) { for (MergeTool tool : myAvailableTools) { try { - if (tool.canShow(myContext, myRequest)) return tool; + if (tool.canShow(myContext, request)) return tool; } catch (Throwable e) { LOG.error(e); @@ -191,6 +275,34 @@ public abstract class MergeRequestProcessor implements Disposable { setWindowTitle(title); } + private void installCallbackListener(@NotNull MergeRequest request) { + MergeCallback callback = MergeCallback.getCallback(request); + callback.addListener(new MergeCallback.Listener() { + @Override + public void fireConflictInvalid() { + showInvalidRequestNotification(); + } + }, this); + + if (!callback.checkIsValid()) { + showInvalidRequestNotification(); + } + } + + private void showInvalidRequestNotification() { + if (!myNotificationPanel.isNull()) return; + + EditorNotificationPanel notification = new EditorNotificationPanel(LightColors.RED); + notification.setText("Conflict is not valid and no longer can be resolved."); + notification.createActionLabel("Abort Resolve", () -> { + applyRequestResult(MergeResult.CANCEL); + closeDialog(); + }); + myNotificationPanel.setContent(notification); + myMainPanel.validate(); + myMainPanel.repaint(); + } + @Override public void dispose() { if (myDisposed) return; @@ -207,7 +319,7 @@ public abstract class MergeRequestProcessor implements Disposable { @CalledInAwt private void applyRequestResult(@NotNull MergeResult result) { - if (myConflictResolved) return; + if (myConflictResolved || myRequest == null) return; myConflictResolved = true; try { myRequest.applyResult(result); @@ -220,6 +332,7 @@ public abstract class MergeRequestProcessor implements Disposable { @CalledInAwt private void reopenWithTool(@NotNull MergeTool tool) { + if (myRequest == null) return; if (myConflictResolved) { LOG.warn("Can't reopen with " + tool + " - conflict already resolved"); return; @@ -239,11 +352,13 @@ public abstract class MergeRequestProcessor implements Disposable { return; } + swapViewer(newViewer); + } + + private void swapViewer(@NotNull MergeTool.MergeViewer newViewer) { DiffUtil.runPreservingFocus(myContext, () -> { destroyViewer(); myViewer = newViewer; - updateBottomActions(); - rebuildSouthPanel(); initViewer(); }); } @@ -259,10 +374,11 @@ public abstract class MergeRequestProcessor implements Disposable { protected void setWindowTitle(@NotNull String title) { } - protected abstract void rebuildSouthPanel(); - public abstract void closeDialog(); + @Nullable + protected abstract JRootPane getRootPane(); + @Nullable public T getContextUserData(@NotNull Key key) { return myContext.getUserData(key); @@ -302,16 +418,6 @@ public abstract class MergeRequestProcessor implements Disposable { return myConflictResolved || myCloseHandler == null || myCloseHandler.get(); } - @NotNull - public BottomActions getBottomActions() { - return myBottomActions != null ? myBottomActions : new BottomActions(); - } - - @Nullable - public String getHelpId() { - return PlatformDataKeys.HELP_ID.getData(myMainPanel); - } - // // Misc // @@ -404,7 +510,7 @@ public abstract class MergeRequestProcessor implements Disposable { return myProject; } else if (PlatformDataKeys.HELP_ID.is(dataId)) { - if (myRequest.getUserData(DiffUserDataKeys.HELP_ID) != null) { + if (myRequest != null && myRequest.getUserData(DiffUserDataKeys.HELP_ID) != null) { return myRequest.getUserData(DiffUserDataKeys.HELP_ID); } else { @@ -415,7 +521,7 @@ public abstract class MergeRequestProcessor implements Disposable { return myViewer; } - DataProvider requestProvider = myRequest.getUserData(DiffUserDataKeys.DATA_PROVIDER); + DataProvider requestProvider = myRequest != null ? myRequest.getUserData(DiffUserDataKeys.DATA_PROVIDER) : null; if (requestProvider != null) { data = requestProvider.getData(dataId); if (data != null) return data; @@ -468,11 +574,4 @@ public abstract class MergeRequestProcessor implements Disposable { MergeRequestProcessor.this.reopenWithTool(tool); } } - - public static class BottomActions { - @Nullable public Action applyLeft; - @Nullable public Action applyRight; - @Nullable public Action resolveAction; - @Nullable public Action cancelAction; - } } diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java index d943c09d8c6d..db0e29252087 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.diff.merge; +import com.intellij.configurationStore.StoreReloadManager; import com.intellij.diff.DiffContext; import com.intellij.diff.contents.DiffContent; import com.intellij.diff.merge.MergeTool.MergeViewer; @@ -34,6 +35,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.merge.MergeData; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.projectImport.ProjectOpenProcessor; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -43,6 +46,8 @@ import javax.swing.*; import java.awt.event.ActionEvent; import java.util.List; +import static com.intellij.openapi.project.ProjectUtil.isProjectOrWorkspaceFile; + public class MergeUtil { @NotNull public static Action createSimpleResolveAction(@NotNull MergeResult result, @@ -63,7 +68,7 @@ public class MergeUtil { } @NotNull - public static String getResolveActionTitle(@NotNull MergeResult result, @NotNull MergeRequest request, @NotNull MergeContext context) { + public static String getResolveActionTitle(@NotNull MergeResult result, @Nullable MergeRequest request, @Nullable MergeContext context) { Function getter = DiffUtil.getUserData(request, context, DiffUserDataKeysEx.MERGE_ACTION_CAPTIONS); String message = getter != null ? getter.fun(result) : null; if (message != null) return message; @@ -156,6 +161,14 @@ public class MergeUtil { return Messages.showYesNoDialog(component.getRootPane(), message, title, Messages.getQuestionIcon()) == Messages.YES; } + public static boolean shouldRestoreOriginalContentOnCancel(@NotNull MergeRequest request) { + MergeCallback callback = MergeCallback.getCallback(request); + if (callback.checkIsValid()) return true; + return Messages.showYesNoDialog("Merge conflict is outdated. Restore file content prior to conflict resolve start?", + DiffBundle.message("cancel.visual.merge.dialog.title"), "Restore", "Do nothing", + Messages.getQuestionIcon()) == Messages.YES; + } + public static void putRevisionInfos(@NotNull MergeRequest request, @NotNull MergeData data) { if (request instanceof ThreesideMergeRequest) { List contents = ((ThreesideMergeRequest)request).getContents(); @@ -182,4 +195,18 @@ public class MergeUtil { } } } + + public static void reportProjectFileChangeIfNeeded(@Nullable Project project, @Nullable VirtualFile file) { + if (project != null && file != null && isProjectFile(file)) { + StoreReloadManager.getInstance().saveChangedProjectFile(file, project); + } + } + + private static boolean isProjectFile(@NotNull VirtualFile file) { + if (file.isDirectory()) return false; + if (isProjectOrWorkspaceFile(file)) return true; + + ProjectOpenProcessor importProvider = ProjectOpenProcessor.getImportProvider(file); + return importProvider != null && importProvider.lookForProjectsInDirectory(); + } } diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java index ff9ac360ce54..646e9a4f8675 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java @@ -15,57 +15,58 @@ */ package com.intellij.diff.merge; +import com.intellij.diff.DiffDialogHints; import com.intellij.diff.util.DiffUserDataKeys; import com.intellij.diff.util.DiffUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.WindowWrapper; +import com.intellij.openapi.ui.WindowWrapperBuilder; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.components.panels.Wrapper; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.Consumer; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.List; -public class MergeWindow { +public abstract class MergeWindow { private static final Logger LOG = Logger.getInstance(MergeWindow.class); @Nullable private final Project myProject; - @NotNull private final MergeRequest myMergeRequest; + @NotNull private final DiffDialogHints myHints; - private MyDialog myWrapper; + private MergeRequestProcessor myProcessor; + private WindowWrapper myWrapper; - public MergeWindow(@Nullable Project project, @NotNull MergeRequest mergeRequest) { + public MergeWindow(@Nullable Project project, @NotNull DiffDialogHints hints) { myProject = project; - myMergeRequest = mergeRequest; + myHints = hints; } protected void init() { - MergeRequestProcessor processor = new MergeRequestProcessor(myProject, myMergeRequest) { - @Override - public void closeDialog() { - myWrapper.doCancelAction(); - } + if (myWrapper != null) return; - @Override - protected void setWindowTitle(@NotNull String title) { - myWrapper.setTitle(title); - } + myProcessor = createProcessor(); - @Override - protected void rebuildSouthPanel() { - myWrapper.rebuildSouthPanel(); - } - }; + String dialogGroupKey = myProcessor.getContextUserData(DiffUserDataKeys.DIALOG_GROUP_KEY); + if (dialogGroupKey == null) dialogGroupKey = "MergeDialog"; - myWrapper = new MyDialog(processor); - myWrapper.init(); + myWrapper = new WindowWrapperBuilder(DiffUtil.getWindowMode(myHints), new MyPanel(myProcessor.getComponent())) + .setProject(myProject) + .setParent(myHints.getParent()) + .setDimensionServiceKey(dialogGroupKey) + .setPreferredFocusedComponent(() -> myProcessor.getPreferredFocusedComponent()) + .setOnShowCallback(() -> initProcessor(myProcessor)) + .setOnCloseHandler(() -> myProcessor.checkCloseAction()) + .build(); + myWrapper.setImages(DiffUtil.DIFF_FRAME_ICONS); + Disposer.register(myWrapper, myProcessor); + + Consumer wrapperHandler = myHints.getWindowConsumer(); + if (wrapperHandler != null) wrapperHandler.consume(myWrapper); } public void show() { @@ -77,100 +78,30 @@ public class MergeWindow { myWrapper.show(); } - // TODO: use WindowWrapper - private static class MyDialog extends DialogWrapper { - @NotNull private final MergeRequestProcessor myProcessor; - @NotNull private final Wrapper mySouthPanel = new Wrapper(); - - MyDialog(@NotNull MergeRequestProcessor processor) { - super(processor.getProject(), true); - myProcessor = processor; - } - - @Override - public void init() { - super.init(); - Disposer.register(getDisposable(), myProcessor); - UIUtil.runWhenWindowOpened(getWindow(), () -> myProcessor.init()); - } - - @Nullable - @Override - protected JComponent createCenterPanel() { - return new MyPanel(myProcessor.getComponent()); - } - - @Nullable - @Override - protected JComponent createSouthPanel() { - rebuildSouthPanel(); - return mySouthPanel; - } - - @Nullable - @Override - public JComponent getPreferredFocusedComponent() { - return myProcessor.getPreferredFocusedComponent(); - } - - @Nullable - @Override - protected String getDimensionServiceKey() { - return StringUtil.notNullize(myProcessor.getContextUserData(DiffUserDataKeys.DIALOG_GROUP_KEY), "MergeDialog"); - } - - @NotNull - @Override - protected Action[] createActions() { - MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions(); - List actions = ContainerUtil.skipNulls(ContainerUtil.list(bottomActions.resolveAction, bottomActions.cancelAction)); - if (bottomActions.resolveAction != null) { - bottomActions.resolveAction.putValue(DialogWrapper.DEFAULT_ACTION, true); + @NotNull + private MergeRequestProcessor createProcessor() { + return new MergeRequestProcessor(myProject) { + @Override + public void closeDialog() { + myWrapper.close(); } - return actions.toArray(new Action[0]); - } - @NotNull - @Override - protected Action[] createLeftSideActions() { - MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions(); - List actions = ContainerUtil.skipNulls(ContainerUtil.list(bottomActions.applyLeft, bottomActions.applyRight)); - return actions.toArray(new Action[0]); - } + @Override + protected void setWindowTitle(@NotNull String title) { + myWrapper.setTitle(title); + } - @NotNull - @Override - protected Action getOKAction() { - MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions(); - if (bottomActions.resolveAction != null) return bottomActions.resolveAction; - return super.getOKAction(); - } - - @NotNull - @Override - protected Action getCancelAction() { - MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions(); - if (bottomActions.cancelAction != null) return bottomActions.cancelAction; - return super.getCancelAction(); - } - - @Nullable - @Override - protected String getHelpId() { - return myProcessor.getHelpId(); - } - - @Override - public void doCancelAction() { - if (!myProcessor.checkCloseAction()) return; - super.doCancelAction(); - } - - public void rebuildSouthPanel() { - mySouthPanel.setContent(super.createSouthPanel()); - } + @Nullable + @Override + protected JRootPane getRootPane() { + RootPaneContainer container = ObjectUtils.tryCast(myWrapper.getWindow(), RootPaneContainer.class); + return container != null ? container.getRootPane() : null; + } + }; } + protected abstract void initProcessor(@NotNull MergeRequestProcessor processor); + private static class MyPanel extends JPanel { MyPanel(@NotNull JComponent content) { super(new BorderLayout()); @@ -184,4 +115,34 @@ public class MergeWindow { return new Dimension(Math.max(windowSize.width, size.width), Math.max(windowSize.height, size.height)); } } + + public static class ForRequest extends MergeWindow { + @NotNull private final MergeRequest myMergeRequest; + + public ForRequest(@Nullable Project project, @NotNull MergeRequest mergeRequest, @NotNull DiffDialogHints hints) { + super(project, hints); + myMergeRequest = mergeRequest; + } + + + @Override + protected void initProcessor(@NotNull MergeRequestProcessor processor) { + processor.init(myMergeRequest); + } + } + + public static class ForProducer extends MergeWindow { + @NotNull private final MergeRequestProducer myMergeRequestProducer; + + public ForProducer(@Nullable Project project, @NotNull MergeRequestProducer mergeRequestProducer, @NotNull DiffDialogHints hints) { + super(project, hints); + myMergeRequestProducer = mergeRequestProducer; + } + + + @Override + protected void initProcessor(@NotNull MergeRequestProcessor processor) { + processor.init(myMergeRequestProducer); + } + } } diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java b/platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java new file mode 100644 index 000000000000..7a563b3f088c --- /dev/null +++ b/platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java @@ -0,0 +1,59 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.diff.merge; + +import com.intellij.diff.util.DiffUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; + +class MessageMergeViewer implements MergeTool.MergeViewer { + @NotNull private final MergeContext myMergeContext; + + @NotNull private final JPanel myPanel; + + MessageMergeViewer(@NotNull MergeContext context, @NotNull String message) { + myMergeContext = context; + + myPanel = new JPanel(new BorderLayout()); + myPanel.add(DiffUtil.createMessagePanel(message), BorderLayout.CENTER); + } + + @NotNull + @Override + public JComponent getComponent() { + return myPanel; + } + + @Nullable + @Override + public JComponent getPreferredFocusedComponent() { + return null; + } + + @NotNull + @Override + public MergeTool.ToolbarComponents init() { + return new MergeTool.ToolbarComponents(); + } + + @Nullable + @Override + public Action getResolveAction(@NotNull final MergeResult result) { + if (result != MergeResult.CANCEL) return null; + + String caption = MergeUtil.getResolveActionTitle(result, null, myMergeContext); + return new AbstractAction(caption) { + @Override + public void actionPerformed(ActionEvent e) { + myMergeContext.finishMerge(result); + } + }; + } + + @Override + public void dispose() { + } +} diff --git a/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java b/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java index 2d019cf521c1..4a3566cece21 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java @@ -30,6 +30,7 @@ import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.command.UndoConfirmationPolicy; import com.intellij.openapi.diff.DiffBundle; @@ -43,7 +44,6 @@ import com.intellij.openapi.editor.markup.MarkupEditorFilter; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.progress.util.BackgroundTaskUtil; import com.intellij.openapi.progress.util.ProgressWindow; import com.intellij.openapi.project.DumbAware; @@ -80,6 +80,11 @@ public class TextMergeViewer implements MergeTool.MergeViewer { @NotNull private final MyThreesideViewer myViewer; + private final Action myCancelResolveAction; + private final Action myLeftResolveAction; + private final Action myRightResolveAction; + private final Action myAcceptResolveAction; + public TextMergeViewer(@NotNull MergeContext context, @NotNull TextMergeRequest request) { myMergeContext = context; myMergeRequest = request; @@ -91,6 +96,11 @@ public class TextMergeViewer implements MergeTool.MergeViewer { diffRequest.putUserData(DiffUserDataKeys.FORCE_READ_ONLY_CONTENTS, new boolean[]{true, false, true}); myViewer = new MyThreesideViewer(diffContext, diffRequest); + + myCancelResolveAction = myViewer.getResolveAction(MergeResult.CANCEL); + myLeftResolveAction = myViewer.getResolveAction(MergeResult.LEFT); + myRightResolveAction = myViewer.getResolveAction(MergeResult.RIGHT); + myAcceptResolveAction = myViewer.getResolveAction(MergeResult.RESOLVED); } @NotNull @@ -145,7 +155,18 @@ public class TextMergeViewer implements MergeTool.MergeViewer { @Nullable @Override public Action getResolveAction(@NotNull MergeResult result) { - return myViewer.getResolveAction(result); + switch (result) { + case CANCEL: + return myCancelResolveAction; + case LEFT: + return myLeftResolveAction; + case RIGHT: + return myRightResolveAction; + case RESOLVED: + return myAcceptResolveAction; + default: + return null; + } } @Override @@ -383,34 +404,25 @@ public class TextMergeViewer implements MergeTool.MergeViewer { // This is made to reduce unwanted modifications before rediff is finished. // It could happen between this init() EDT chunk and invokeLater(). getEditor().setViewer(true); + myLoadingPanel.startLoading(); + myAcceptResolveAction.setEnabled(false); - // we need invokeLater() here because viewer is partially-initialized (ex: there are no toolbar or status panel) - // user can see this state while we're showing progress indicator, so we want let init() to finish. - ApplicationManager.getApplication().invokeLater(() -> ProgressManager.getInstance().run(new Task.Modal(getProject(), "Computing Differences...", true) { - private Runnable myCallback; + BackgroundTaskUtil.executeOnPooledThread(this, () -> { + ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - @Override - public void run(@NotNull ProgressIndicator indicator) { - myCallback = doPerformRediff(indicator); + Runnable callback; + try { + callback = doPerformRediff(indicator); } - - @Override - public void onCancel() { - myMergeContext.finishMerge(MergeResult.CANCEL); + catch (ProcessCanceledException e) { + callback = () -> myMergeContext.finishMerge(MergeResult.CANCEL); } - - @Override - public void onThrowable(@NotNull Throwable error) { - LOG.error(error); - myMergeContext.finishMerge(MergeResult.CANCEL); + catch (Throwable e) { + LOG.error(e); + callback = () -> myMergeContext.finishMerge(MergeResult.CANCEL); } - - @Override - public void onSuccess() { - if (isDisposed()) return; - myCallback.run(); - } - })); + ApplicationManager.getApplication().invokeLater(callback, ModalityState.stateForComponent(myPanel)); + }); } @NotNull @@ -453,6 +465,8 @@ public class TextMergeViewer implements MergeTool.MergeViewer { private void apply(@NotNull List fragments, @NotNull List conflictTypes, @NotNull IgnorePolicy ignorePolicy) { + if (isDisposed()) return; + clearDiffPresentation(); resetChangeCounters(); @@ -481,6 +495,8 @@ public class TextMergeViewer implements MergeTool.MergeViewer { myStatusPanel.update(); getEditor().setViewer(false); + myLoadingPanel.stopLoading(); + myAcceptResolveAction.setEnabled(true); myInnerDiffWorker.onEverythingChanged(); myInitialRediffFinished = true; @@ -676,7 +692,7 @@ public class TextMergeViewer implements MergeTool.MergeViewer { String message = DiffBundle.message("merge.all.changes.processed.message.text"); DiffUtil.showSuccessPopup(message, point, this, () -> { - if (isDisposed()) return; + if (isDisposed() || myLoadingPanel.isLoading()) return; destroyChangedBlocks(); myMergeContext.finishMerge(MergeResult.RESOLVED); }); diff --git a/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java b/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java index 6e09badee659..dd54bd422acb 100644 --- a/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java @@ -19,7 +19,9 @@ import com.intellij.CommonBundle; import com.intellij.diff.contents.DiffContent; import com.intellij.diff.contents.FileContent; import com.intellij.diff.merge.BinaryMergeRequest; +import com.intellij.diff.merge.MergeCallback; import com.intellij.diff.merge.MergeResult; +import com.intellij.diff.merge.MergeUtil; import com.intellij.diff.util.DiffUtil; import com.intellij.diff.util.ThreeSide; import com.intellij.openapi.command.WriteCommandAction; @@ -27,7 +29,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,16 +48,13 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { @Nullable private final String myTitle; @NotNull private final List myTitles; - @Nullable private final Consumer myApplyCallback; - public BinaryMergeRequestImpl(@Nullable Project project, @NotNull FileContent file, @NotNull byte[] originalContent, @NotNull List contents, @NotNull List byteContents, @Nullable String title, - @NotNull List contentTitles, - @Nullable Consumer applyCallback) { + @NotNull List contentTitles) { assert byteContents.size() == 3; assert contents.size() == 3; assert contentTitles.size() == 3; @@ -70,8 +68,6 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { myTitle = title; myTitles = contentTitles; - myApplyCallback = applyCallback; - onAssigned(true); } @@ -111,7 +107,7 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { final byte[] applyContent; switch (result) { case CANCEL: - applyContent = myOriginalContent; + applyContent = MergeUtil.shouldRestoreOriginalContentOnCancel(this) ? myOriginalContent : null; break; case LEFT: applyContent = ThreeSide.LEFT.select(myByteContents); @@ -140,7 +136,7 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { }); } - if (myApplyCallback != null) myApplyCallback.consume(result); + MergeCallback.getCallback(this).applyResult(result); } finally { onAssigned(false); diff --git a/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java b/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java index 104b1945ee16..e392c199ee5d 100644 --- a/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java @@ -16,13 +16,14 @@ package com.intellij.diff.requests; import com.intellij.diff.contents.DocumentContent; +import com.intellij.diff.merge.MergeCallback; import com.intellij.diff.merge.MergeResult; +import com.intellij.diff.merge.MergeUtil; import com.intellij.diff.merge.TextMergeRequest; import com.intellij.diff.util.DiffUtil; import com.intellij.diff.util.ThreeSide; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,15 +39,12 @@ public class TextMergeRequestImpl extends TextMergeRequest { @Nullable private final String myTitle; @NotNull private final List myTitles; - @Nullable private final Consumer myApplyCallback; - public TextMergeRequestImpl(@Nullable Project project, @NotNull DocumentContent output, @NotNull CharSequence originalContent, @NotNull List contents, @Nullable String title, - @NotNull List contentTitles, - @Nullable Consumer applyCallback) { + @NotNull List contentTitles) { assert contents.size() == 3; assert contentTitles.size() == 3; myProject = project; @@ -58,8 +56,6 @@ public class TextMergeRequestImpl extends TextMergeRequest { myTitles = contentTitles; myTitle = title; - myApplyCallback = applyCallback; - onAssigned(true); } @@ -93,7 +89,7 @@ public class TextMergeRequestImpl extends TextMergeRequest { final CharSequence applyContent; switch (result) { case CANCEL: - applyContent = myOriginalContent; + applyContent = MergeUtil.shouldRestoreOriginalContentOnCancel(this) ? myOriginalContent : null; break; case LEFT: CharSequence leftContent = ThreeSide.LEFT.select(getContents()).getDocument().getImmutableCharSequence(); @@ -114,7 +110,7 @@ public class TextMergeRequestImpl extends TextMergeRequest { DiffUtil.executeWriteCommand(myOutput.getDocument(), myProject, null, () -> myOutput.getDocument().setText(applyContent)); } - if (myApplyCallback != null) myApplyCallback.consume(result); + MergeCallback.getCallback(this).applyResult(result); } finally { onAssigned(false); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java index 58438b1278bf..b5325c669cea 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java @@ -28,14 +28,11 @@ import com.intellij.openapi.ListSelection; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; 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.Messages; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.ThrowableConvertor; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -88,7 +85,7 @@ public class ExternalDiffTool { private static List loadRequestsUnderProgress(@Nullable Project project, @NotNull DiffRequestChain chain) throws Throwable { if (chain instanceof AsyncDiffRequestChain) { - return loadInBackground(project, "Loading Requests", indicator -> { + return VcsUtil.computeWithModalProgress(project, "Loading Requests", true, indicator -> { ListSelection listSelection = ((AsyncDiffRequestChain)chain).loadRequestsInBackground(); return collectRequests(project, listSelection.getList(), listSelection.getSelectedIndex(), indicator); }); @@ -97,7 +94,9 @@ public class ExternalDiffTool { List allProducers = chain.getRequests(); int index = chain.getIndex(); - return loadInBackground(project, "Loading Requests", indicator -> collectRequests(project, allProducers, index, indicator)); + return VcsUtil.computeWithModalProgress(project, "Loading Requests", true, indicator -> { + return collectRequests(project, allProducers, index, indicator); + }); } } @@ -162,28 +161,4 @@ public class ExternalDiffTool { } return true; } - - - @Nullable - private static T loadInBackground(@Nullable Project project, - @NotNull String title, - @NotNull ThrowableConvertor computable) throws Throwable { - final Ref requestsRef = new Ref<>(); - final Ref exceptionRef = new Ref<>(); - - ProgressManager.getInstance().run(new Task.Modal(project, title, true) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - try { - requestsRef.set(computable.convert(indicator)); - } - catch (Throwable e) { - exceptionRef.set(e); - } - } - }); - - if (!exceptionRef.isNull()) throw exceptionRef.get(); - return requestsRef.get(); - } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java index 4693a8310f62..0d3190b73d00 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java @@ -37,18 +37,21 @@ import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.util.Disposer; import com.intellij.pom.Navigatable; +import com.intellij.ui.components.JBLoadingPanel; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.util.ArrayList; import java.util.List; public abstract class ThreesideDiffViewer extends ListenerDiffViewerBase { @NotNull protected final SimpleDiffPanel myPanel; @NotNull protected final ThreesideContentPanel myContentPanel; + @NotNull protected final JBLoadingPanel myLoadingPanel; @NotNull private final List myHolders; @@ -63,7 +66,10 @@ public abstract class ThreesideDiffViewer extends Listen myFocusTrackerSupport = new FocusTrackerSupport.Threeside(myHolders); myContentPanel = new ThreesideContentPanel(myHolders, titlePanel); - myPanel = new SimpleDiffPanel(myContentPanel, this, context); + myLoadingPanel = new JBLoadingPanel(new BorderLayout(), this, 300); + myLoadingPanel.add(myContentPanel, BorderLayout.CENTER); + + myPanel = new SimpleDiffPanel(myLoadingPanel, this, context); } @Override diff --git a/platform/dvcs-impl/src/META-INF/dvcs.xml b/platform/dvcs-impl/src/META-INF/dvcs.xml index c408414ef181..8d43989226f1 100644 --- a/platform/dvcs-impl/src/META-INF/dvcs.xml +++ b/platform/dvcs-impl/src/META-INF/dvcs.xml @@ -7,6 +7,7 @@ + diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java b/platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java new file mode 100644 index 000000000000..d282a615b990 --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java @@ -0,0 +1,63 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.dvcs.repo; + +import com.intellij.dvcs.DvcsRememberedInputs; +import com.intellij.ide.impl.ProjectUtil; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.util.PathUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.net.URLDecoder; + +/** + * Provides default paths for clone repository functionality. + * Default implementation suggests to clone a project to the `[project dir]/[last url component]`. + */ +public abstract class ClonePathProvider { + private static final ExtensionPointName EP_NAME = + ExtensionPointName.create("com.intellij.clonePathProvider"); + + @NotNull + public static String defaultParentDirectoryPath(@NotNull Project project, @NotNull DvcsRememberedInputs rememberedInputs) { + for (ClonePathProvider provider : EP_NAME.getExtensionList()) { + String directoryPath = provider.getParentDirectoryPath(project, rememberedInputs); + if (StringUtil.isNotEmpty(directoryPath)) { + return directoryPath; + } + } + + String parentDirectory = rememberedInputs.getCloneParentDir(); + return StringUtil.isEmptyOrSpaces(parentDirectory) ? ProjectUtil.getBaseDir() : parentDirectory; + } + + @NotNull + public static String relativeDirectoryPathForVcsUrl(@NotNull Project project, @NotNull String vcsUrl) { + for (ClonePathProvider provider : EP_NAME.getExtensionList()) { + String directoryPath = provider.getRelativeDirectoryPathForVcsUrl(project, vcsUrl); + if (StringUtil.isNotEmpty(directoryPath)) { + return directoryPath; + } + } + return safeUrlDecode(PathUtil.getFileName(vcsUrl)); + } + + @NotNull + private static String safeUrlDecode(@NotNull String encoded) { + try { + return URLDecoder.decode(encoded, CharsetToolkit.UTF8); + } + catch (Exception e) { + return encoded; + } + } + + @Nullable + public abstract String getParentDirectoryPath(@NotNull Project project, @NotNull DvcsRememberedInputs rememberedInputs); + + @Nullable + public abstract String getRelativeDirectoryPathForVcsUrl(@NotNull Project project, @NotNull String vcsUrl); +} diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java index b2b4cac6cb2f..d36e53bd8071 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java @@ -7,7 +7,7 @@ import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.hosting.RepositoryHostingService; import com.intellij.dvcs.hosting.RepositoryListLoader; import com.intellij.dvcs.hosting.RepositoryListLoadingException; -import com.intellij.ide.impl.ProjectUtil; +import com.intellij.dvcs.repo.ClonePathProvider; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.IdeActions; @@ -30,7 +30,6 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBOptionButton; @@ -51,11 +50,9 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; -import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -import java.net.URLDecoder; import java.nio.file.*; import java.util.List; import java.util.*; @@ -181,8 +178,6 @@ public abstract class CloneDvcsDialog extends DialogWrapper { } private void initComponents(@Nullable String defaultUrl) { - String parentDirectory = getRememberedInputs().getCloneParentDir(); - myRepositoryUrlComboboxModel = new CollectionComboBoxModel<>(); myRepositoryUrlField = TextFieldWithAutoCompletion.create(myProject, myRepositoryUrlComboboxModel.getItems(), @@ -204,7 +199,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { myRepositoryUrlField.addDocumentListener(new DocumentListener() { @Override public void documentChanged(@NotNull com.intellij.openapi.editor.event.DocumentEvent event) { - myDirectoryField.trySetChildPath(defaultDirectoryName(myRepositoryUrlField.getText().trim())); + myDirectoryField.trySetChildPath(defaultDirectoryPath(myRepositoryUrlField.getText().trim())); } }); myRepositoryUrlField.addDocumentListener(new DocumentListener() { @@ -220,9 +215,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor(); fcd.setShowFileSystemRoots(true); fcd.setHideIgnored(false); - myDirectoryField = new MyTextFieldWithBrowseButton(StringUtil.isEmptyOrSpaces(parentDirectory) - ? ProjectUtil.getBaseDir() - : parentDirectory); + myDirectoryField = new MyTextFieldWithBrowseButton(ClonePathProvider.defaultParentDirectoryPath(myProject, getRememberedInputs())); myDirectoryField.addBrowseFolderListener(DvcsBundle.getString("clone.destination.directory.browser.title"), DvcsBundle.getString("clone.destination.directory.browser.description"), myProject, @@ -517,16 +510,6 @@ public abstract class CloneDvcsDialog extends DialogWrapper { rememberedInputs.setCloneParentDir(getParentDirectory()); } - @NotNull - private static String safeUrlDecode(@NotNull String encoded) { - try { - return URLDecoder.decode(encoded, CharsetToolkit.UTF8); - } - catch (Exception e) { - return encoded; - } - } - /** * Get default name for checked out directory * @@ -534,30 +517,8 @@ public abstract class CloneDvcsDialog extends DialogWrapper { * @return a default repository name */ @NotNull - private String defaultDirectoryName(@NotNull final String url) { - return stripSuffix(safeUrlDecode(getLastPathFragment(url))); - } - - @NotNull - private String stripSuffix(@NotNull String directoryName) { - return directoryName.endsWith(myVcsDirectoryName) - ? directoryName.substring(0, directoryName.length() - myVcsDirectoryName.length()) - : directoryName; - } - - @NotNull - private static String getLastPathFragment(@NotNull final String url) { - // Suppose it's a URL - int i = url.lastIndexOf('/'); - - // No? Maybe win-style path? - if (i == -1 && File.separatorChar != '/') i = url.lastIndexOf(File.separatorChar); - - if (i < 0) return ""; - - if (i == url.length() - 1) return getLastPathFragment(url.substring(0, i)); - - return url.substring(i + 1); + private String defaultDirectoryPath(@NotNull final String url) { + return StringUtil.trimEnd(ClonePathProvider.relativeDirectoryPathForVcsUrl(myProject, url), myVcsDirectoryName); } @Nullable diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt index 2f56c1ada679..c32dcfef2255 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt @@ -16,7 +16,7 @@ import java.io.Closeable */ @ApiStatus.Experimental class ExternalSystemEventDispatcher(task: ExternalSystemTask, - private val progressListener: BuildProgressListener?) : Closeable, Appendable, BuildProgressListener { + progressListener: BuildProgressListener?) : Closeable, Appendable, BuildProgressListener { private var outputMessageDispatcher: ExternalSystemOutputMessageDispatcher? = null init { @@ -37,8 +37,8 @@ class ExternalSystemEventDispatcher(task: ExternalSystemTask, foundFactory = it } } - outputMessageDispatcher = foundFactory?.create(task.getId(), progressListener, buildOutputParsers) - ?: DefaultOutputMessageDispatcher(task.getId(), progressListener, buildOutputParsers) + outputMessageDispatcher = foundFactory?.create(task.id, progressListener, buildOutputParsers) + ?: DefaultOutputMessageDispatcher(task.id, progressListener, buildOutputParsers) } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt index be59d7a0ca99..087e0da49c12 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt @@ -26,7 +26,6 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage private var isDisposed = false private val mutex = Any() - private val postponedSourceFolderCreator = PostponedSourceFolderCreator() private val sourceFolders = PathPrefixTreeMapImpl() private val sourceFoldersByModule = THashMap() @@ -63,8 +62,6 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage override fun dispose() { assert(!isDisposed) { "Source folder manager already disposed" } isDisposed = true - val virtualFileManager = VirtualFileManager.getInstance() - virtualFileManager.removeVirtualFileListener(postponedSourceFolderCreator) } fun isDisposed() = isDisposed @@ -131,6 +128,6 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage init { val virtualFileManager = VirtualFileManager.getInstance() - virtualFileManager.addVirtualFileListener(postponedSourceFolderCreator, project) + virtualFileManager.addVirtualFileListener(PostponedSourceFolderCreator(), this) } } \ No newline at end of file diff --git a/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java b/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java index f2a9dcfeb97a..9e2fa4e09f72 100644 --- a/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java +++ b/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java @@ -16,6 +16,7 @@ package com.intellij.util.indexing; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ContentIterator; @@ -35,12 +36,13 @@ public abstract class IdFilter { private static final Key> INSIDE_PROJECT = Key.create("INSIDE_PROJECT"); private static final Key> OUTSIDE_PROJECT = Key.create("OUTSIDE_PROJECT"); - public static IdFilter getProjectIdFilter(final Project project, final boolean includeNonProjectItems) { + @NotNull + public static IdFilter getProjectIdFilter(@NotNull Project project, final boolean includeNonProjectItems) { Key> key = includeNonProjectItems ? OUTSIDE_PROJECT : INSIDE_PROJECT; + CachedValueProvider provider = () -> CachedValueProvider.Result.create(buildProjectIdFilter(project, includeNonProjectItems), + ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS); return CachedValuesManager.getManager(project).getCachedValue(project, key, - () -> CachedValueProvider.Result - .create(buildProjectIdFilter(project, includeNonProjectItems), - ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS), false); + provider, false); } @NotNull @@ -56,8 +58,9 @@ public abstract class IdFilter { if (!includeNonProjectItems) { ProjectRootManager.getInstance(project).getFileIndex().iterateContent(iterator); - } else { - FileBasedIndex.getInstance().iterateIndexableFiles(iterator, project, null); + } + else { + FileBasedIndex.getInstance().iterateIndexableFiles(iterator, project, ProgressIndicatorProvider.getGlobalProgressIndicator()); } if (LOG.isDebugEnabled()) { diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java index 0d223df3d8bd..bbec44cadbbf 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java @@ -193,23 +193,21 @@ public class LowLevelSearchUtil { FileViewProvider viewProvider, CharSequence buffer, TextRange range) { - StringBuilder msg = new StringBuilder() - .append("Range for element: '").append(scope).append("' = ").append(range) - .append(" is out of file '").append(file).append("' range: ").append(file.getTextRange()) - .append("; file contents length: ").append(buffer.length()) - .append("\n file provider: ").append(viewProvider); + String msg = "Range for element: '" + scope + "' = " + range + " is out of file '" + file + "' range: " + file.getTextRange(); + msg += "; file contents length: " + buffer.length(); + msg += "\n file provider: " + viewProvider; Document document = viewProvider.getDocument(); if (document != null) { - msg.append("\n committed=").append(PsiDocumentManager.getInstance(file.getProject()).isCommitted(document)); + msg += "\n committed=" + PsiDocumentManager.getInstance(file.getProject()).isCommitted(document); } for (Language language : viewProvider.getLanguages()) { final PsiFile root = viewProvider.getPsi(language); - msg.append("\n root ").append(language).append(" length=").append(root.getTextLength()); - if (root instanceof PsiFileImpl) { - msg.append("; contentsLoaded=").append(((PsiFileImpl)root).isContentsLoaded()); - } + //noinspection StringConcatenationInLoop + msg += "\n root " + language + " length=" + root.getTextLength() + (root instanceof PsiFileImpl + ? "; contentsLoaded=" + ((PsiFileImpl)root).isContentsLoaded() : ""); } - LOG.error(msg.toString()); + + LOG.error(msg); } // map (text to be scanned -> list of cached pairs of (searcher used to scan text, occurrences found)) diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java b/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java index a1a2a7a3fe13..66917f80b498 100644 --- a/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java +++ b/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java @@ -29,7 +29,7 @@ interface FileNameIndexService { @NotNull Collection getVirtualFilesByName(Project project, @NotNull String name, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter); - void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter); + void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter); @NotNull Collection getFilesWithFileType(@NotNull FileType type, @NotNull GlobalSearchScope scope); diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java index 0687c3eff0cc..7130c419e978 100644 --- a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java +++ b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java @@ -56,7 +56,7 @@ public class FilenameIndex { return ArrayUtil.toStringArray(names); } - public static void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) { + public static void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) { getService().processAllFileNames(processor, scope, filter); } diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java index c704bf96a70f..f795d40d0033 100644 --- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java @@ -2,54 +2,29 @@ package com.intellij.application.options.codeStyle.properties; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import com.intellij.util.containers.BidirectionalMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.List; -class BraceStyleAccessor extends ExternalStringAccessor implements CodeStyleChoiceList { - private final static BidirectionalMap BRACE_STYLE_MAP = new BidirectionalMap<>(); - - public static final String VALUE_END_OF_LINE = "end_of_line"; - public static final String VALUE_NEXT_LINE = "next_line"; - public static final String VALUE_NEXT_LINE_IF_WRAPPED = "next_line_if_wrapped"; - public static final String VALUE_WHITESMITHS = "whitesmiths"; - public static final String VALUE_GNU = "gnu"; - - private final static List ALL_VALUES = - Arrays.asList(VALUE_END_OF_LINE, VALUE_NEXT_LINE, VALUE_NEXT_LINE_IF_WRAPPED, VALUE_WHITESMITHS, VALUE_GNU); - - static { - BRACE_STYLE_MAP.put(CommonCodeStyleSettings.END_OF_LINE, VALUE_END_OF_LINE); - BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE, VALUE_NEXT_LINE); - BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED, VALUE_NEXT_LINE_IF_WRAPPED); - BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE_SHIFTED, VALUE_WHITESMITHS); - BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE_SHIFTED2, VALUE_GNU); - } +class BraceStyleAccessor extends MagicIntegerConstAccessor { BraceStyleAccessor(@NotNull Object object, @NotNull Field field) { - super(object, field); + super(object, + field, + new int[]{ + CommonCodeStyleSettings.END_OF_LINE, + CommonCodeStyleSettings.NEXT_LINE, + CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED, + CommonCodeStyleSettings.NEXT_LINE_SHIFTED, + CommonCodeStyleSettings.NEXT_LINE_SHIFTED2 + }, + new String[]{ + "end_of_line", + "next_line", + "next_line_if_wrapped", + "whitesmiths", + "gnu" + }); } - @Nullable - @Override - protected Integer fromExternal(@NotNull String str) { - List keys = BRACE_STYLE_MAP.getKeysByValue(str); - return keys != null && keys.size() > 0 ? keys.get(0) : null; - } - - @NotNull - @Override - protected String toExternal(@NotNull Integer value) { - return BRACE_STYLE_MAP.get(value); - } - - @NotNull - @Override - public List getChoices() { - return ALL_VALUES; - } } diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java index 6d0dd2601894..fd693d735f00 100644 --- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java @@ -1,6 +1,7 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.application.options.codeStyle.properties; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings.BraceStyleConstant; import com.intellij.psi.codeStyle.CommonCodeStyleSettings.WrapConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,7 +37,8 @@ class FieldAccessorFactory { if (wrapAnnotation != null) { return ValueType.WRAP; } - else if (fieldName.endsWith("BRACE_STYLE")) { + BraceStyleConstant braceAnnotation = myField.getAnnotation(BraceStyleConstant.class); + if (braceAnnotation != null) { return ValueType.BRACE_STYLE; } else if (fieldName.endsWith("_BRACE_FORCE")) { diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java index 73c07c7e4e24..f4ce69982cf2 100644 --- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java @@ -2,50 +2,24 @@ package com.intellij.application.options.codeStyle.properties; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import com.intellij.util.containers.BidirectionalMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.List; -class ForceBracesAccessor extends ExternalStringAccessor implements CodeStyleChoiceList { - - private final static BidirectionalMap FORCE_BRACES_MAP = new BidirectionalMap<>(); - - public static final String VALUE_NEVER = "never"; - public static final String VALUE_MULTILINE = "if_multiline"; - public static final String VALUE_ALWAYS = "always"; - - private final static List ALL_VALUES = Arrays.asList(VALUE_NEVER, VALUE_MULTILINE, VALUE_ALWAYS); - - static { - FORCE_BRACES_MAP.put(CommonCodeStyleSettings.DO_NOT_FORCE, VALUE_NEVER); - FORCE_BRACES_MAP.put(CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE, VALUE_MULTILINE); - FORCE_BRACES_MAP.put(CommonCodeStyleSettings.FORCE_BRACES_ALWAYS, VALUE_ALWAYS); - } +class ForceBracesAccessor extends MagicIntegerConstAccessor { ForceBracesAccessor(@NotNull Object object, @NotNull Field field) { - super(object, field); - } - - @Nullable - @Override - protected Integer fromExternal(@NotNull String str) { - List keys = FORCE_BRACES_MAP.getKeysByValue(str); - return keys != null && keys.size() > 0 ? keys.get(0) : null; - } - - @NotNull - @Override - protected String toExternal(@NotNull Integer value) { - return FORCE_BRACES_MAP.get(value); - } - - @NotNull - @Override - public List getChoices() { - return ALL_VALUES; + super(object, + field, + new int[]{ + CommonCodeStyleSettings.DO_NOT_FORCE, + CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE, + CommonCodeStyleSettings.FORCE_BRACES_ALWAYS + }, + new String[]{ + "never", + "if_multiline", + "always" + }); } } diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java new file mode 100644 index 000000000000..058e4de6ba28 --- /dev/null +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java @@ -0,0 +1,43 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.application.options.codeStyle.properties; + +import com.intellij.util.containers.BidirectionalMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +public class MagicIntegerConstAccessor extends ExternalStringAccessor implements CodeStyleChoiceList { + private final BidirectionalMap myValueMap = new BidirectionalMap<>(); + + public MagicIntegerConstAccessor(@NotNull Object object, + @NotNull Field field, + int[] intValues, + String[] strValues) { + super(object, field); + for (int i = 0; i < Math.min(intValues.length, strValues.length); i ++) { + myValueMap.put(intValues[i], strValues[i]); + } + } + + @Nullable + @Override + protected final Integer fromExternal(@NotNull String str) { + List keys = myValueMap.getKeysByValue(str); + return keys != null && keys.size() > 0 ? keys.get(0) : null; + } + + @NotNull + @Override + protected final String toExternal(@NotNull Integer value) { + return myValueMap.get(value); + } + + @NotNull + @Override + public final List getChoices() { + return new ArrayList<>(myValueMap.values()); + } +} diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java index 5b36127b0d7d..9dfd58cd9d0c 100644 --- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java @@ -2,53 +2,28 @@ package com.intellij.application.options.codeStyle.properties; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import com.intellij.util.containers.BidirectionalMap; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.util.List; -class WrappingAccessor extends ExternalStringAccessor implements CodeStyleChoiceList { - private final static BidirectionalMap WRAPPING_MAP = new BidirectionalMap<>(); - - public static final String VALUE_OFF = "off"; - public static final String VALUE_NORMAL = "normal"; - public static final String VALUE_ON_EVERY_ITEM = "on_every_item"; - public static final String VALUE_SPLIT_INTO_LINES = "split_into_lines"; - - public final static List ALL_VALUES = - ContainerUtil.immutableList(VALUE_OFF, VALUE_NORMAL, VALUE_ON_EVERY_ITEM, VALUE_SPLIT_INTO_LINES); - - static { - WRAPPING_MAP.put(CommonCodeStyleSettings.DO_NOT_WRAP, VALUE_OFF); - WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_AS_NEEDED, VALUE_NORMAL); - WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, VALUE_ON_EVERY_ITEM); - WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_AS_NEEDED | CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, VALUE_ON_EVERY_ITEM); - WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_ALWAYS, VALUE_SPLIT_INTO_LINES); - } +class WrappingAccessor extends MagicIntegerConstAccessor { WrappingAccessor(@NotNull Object object, @NotNull Field field) { - super(object, field); + super(object, field, + new int[]{ + CommonCodeStyleSettings.DO_NOT_WRAP, + CommonCodeStyleSettings.WRAP_AS_NEEDED, + CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, + CommonCodeStyleSettings.WRAP_AS_NEEDED | CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, + CommonCodeStyleSettings.WRAP_ALWAYS + }, + new String[]{ + "off", + "normal", + "on_every_item", + "on_every_item", + "split_into_lines", + }); } - @Nullable - @Override - protected Integer fromExternal(@NotNull String str) { - List keys = WRAPPING_MAP.getKeysByValue(str); - return keys != null && keys.size() > 0 ? keys.get(0) : null; - } - - @NotNull - @Override - protected String toExternal(@NotNull Integer value) { - return WRAPPING_MAP.get(value); - } - - @NotNull - @Override - public List getChoices() { - return ALL_VALUES; - } } diff --git a/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java b/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java index 3c23241f76f9..ecec01938f91 100644 --- a/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java +++ b/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java @@ -2,6 +2,7 @@ package com.intellij.build.output; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -9,7 +10,8 @@ import org.jetbrains.annotations.Nullable; */ @ApiStatus.Experimental public interface BuildOutputInstantReader { - Object getBuildId(); + @NotNull + Object getParentEventId(); @Nullable String readLine(); diff --git a/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java b/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java index e624bbc0019a..242d5ff57640 100644 --- a/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java +++ b/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java @@ -2,7 +2,6 @@ package com.intellij.build.output; import com.intellij.build.events.BuildEvent; -import com.intellij.build.events.MessageEvent; import org.jetbrains.annotations.ApiStatus; import java.util.function.Consumer; diff --git a/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java b/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java index 814a69a3936a..9f61545f6ed7 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java +++ b/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java @@ -3,7 +3,6 @@ package com.intellij.codeInsight.editorActions; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Editor; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -11,7 +10,6 @@ import org.jetbrains.annotations.NotNull; * quote/bracket) using Tab key. The scope is usually created (registered) when a pair of quotes/brackets is inserted into a document, and * lives until user 'tabs out' of this scope, or performs editing outside it. */ -@ApiStatus.Experimental public interface TabOutScopesTracker { static TabOutScopesTracker getInstance() { return ServiceManager.getService(TabOutScopesTracker.class); @@ -29,7 +27,16 @@ public interface TabOutScopesTracker { * Registers a new scope (empty at the time of call) at the given offset. Provided offset is supposed to point at the location between * just inserted pair of quotes/brackets. */ - void registerEmptyScope(@NotNull Editor editor, int offset); + default void registerEmptyScope(@NotNull Editor editor, int offset) { + registerEmptyScope(editor, offset, 1); + } + + /** + * Same as {@link #registerEmptyScope(Editor, int)} but allows to set custom caret shift on exiting the scope. This is for the cases when scope suffix contains more than one character (e.g. a closing parenthesis and a semicolon). + * + * @param caretShift a positive value, representing desired caret offset shift when Tab is used to exit the scope + */ + void registerEmptyScope(@NotNull Editor editor, int offset, int caretShift); /** * Checks whether given offset is at the end of tracked scope (so if caret is located at that offset, Tab key can be used to move out of @@ -40,9 +47,10 @@ public interface TabOutScopesTracker { /** * Removes a tracked scope (if any) ending at the given offset. * - * @return whether there was a scope ending at given offset + * @return a positive value indicating required caret shift, if there was a scope ending at given offset, and zero otherwise * * @see #hasScopeEndingAt(Editor, int) + * @see #registerEmptyScope(Editor, int, int) */ - boolean removeScopeEndingAt(@NotNull Editor editor, int offset); + int removeScopeEndingAt(@NotNull Editor editor, int offset); } diff --git a/platform/lang-api/src/com/intellij/formatting/Block.java b/platform/lang-api/src/com/intellij/formatting/Block.java index a8955603acc7..f4834d8658cc 100644 --- a/platform/lang-api/src/com/intellij/formatting/Block.java +++ b/platform/lang-api/src/com/intellij/formatting/Block.java @@ -39,6 +39,8 @@ public interface Block { * Returns the list of child blocks for the specified block. Important: The same list * of blocks must be returned when {@code getSubBlocks()} is repeatedly called on a particular * {@code Block} instance. + * Even more Important: + * If immutable list is returned (e.g. {@code Collections.singletonList(xxx)}, you must mark this {@link Block} class with {@link com.intellij.formatting.ReadOnlyBlockContainer} marker interface. * * @return the child block list. * @see #isLeaf() diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index 59baf1d091d3..01271fd9a585 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -331,6 +331,7 @@ public class CommonCodeStyleSettings { public static final int NEXT_LINE_IF_WRAPPED = 5; @MagicConstant(intValues = {END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_SHIFTED2, NEXT_LINE_IF_WRAPPED}) + @Retention(RetentionPolicy.RUNTIME) public @interface BraceStyleConstant {} @BraceStyleConstant public int BRACE_STYLE = END_OF_LINE; diff --git a/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt b/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt index 86f7f247aac5..b0319db33570 100644 --- a/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt +++ b/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt @@ -17,7 +17,7 @@ import java.util.concurrent.Future /** * @author Vladislav.Soroka */ -open class BuildOutputInstantReaderImpl(private val buildId: Any, +open class BuildOutputInstantReaderImpl(private val parentEventId: Any, buildProgressListener: BuildProgressListener, parsers: List) : BuildOutputInstantReader, Closeable, Appendable { private val readJob: Job @@ -29,14 +29,14 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any, private val appendedLineProcessor: LineProcessor init { - readJob = createReadJob(buildProgressListener, this, parsers) + readJob = createReadJob(buildProgressListener, parsers) val appendScope = CoroutineScope(Dispatchers.Default + appendParentJob) appendedLineProcessor = MyLineProcessor(readJob, appendScope, outputLinesChannel) } private fun createReadJob(buildProgressListener: BuildProgressListener, - reader: BuildOutputInstantReaderImpl, parsers: List): Job { + val thisReader: BuildOutputInstantReader = this return CoroutineScope(Dispatchers.Default).launch(start = CoroutineStart.LAZY) { var lastMessage: BuildEvent? = null val messageConsumer = { event: BuildEvent -> @@ -48,11 +48,11 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any, } while (true) { - val line = reader.readLine() ?: break + val line = thisReader.readLine() ?: break if (line.isBlank()) continue for (parser in parsers) { - val readerWrapper = BuildOutputInstantReaderWrapper(reader) + val readerWrapper = BuildOutputInstantReaderWrapper(thisReader) if (parser.parse(line, readerWrapper, messageConsumer)) break readerWrapper.pushBackReadLines() } @@ -60,8 +60,8 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any, } } - override fun getBuildId(): Any { - return buildId + override fun getParentEventId(): Any { + return parentEventId } override fun append(csq: CharSequence): BuildOutputInstantReaderImpl { @@ -146,10 +146,10 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any, } } - private class BuildOutputInstantReaderWrapper(private val reader: BuildOutputInstantReaderImpl) : BuildOutputInstantReader { + private class BuildOutputInstantReaderWrapper(private val reader: BuildOutputInstantReader) : BuildOutputInstantReader { private var linesRead = 0 - override fun getBuildId(): Any = reader.buildId + override fun getParentEventId(): Any = reader.parentEventId override fun readLine(): String? { val line = reader.readLine() diff --git a/java/compiler/impl/src/com/intellij/build/output/JavacOutputParser.java b/platform/lang-impl/src/com/intellij/build/output/JavacOutputParser.java similarity index 90% rename from java/compiler/impl/src/com/intellij/build/output/JavacOutputParser.java rename to platform/lang-impl/src/com/intellij/build/output/JavacOutputParser.java index 52052ef7dc62..94bd72e05856 100644 --- a/java/compiler/impl/src/com/intellij/build/output/JavacOutputParser.java +++ b/platform/lang-impl/src/com/intellij/build/output/JavacOutputParser.java @@ -39,17 +39,17 @@ public class JavacOutputParser implements BuildOutputParser { if (part1.equalsIgnoreCase("error") /* jikes */ || part1.equalsIgnoreCase("Caused by")) { // +1 so we don't include the colon String text = line.substring(colonIndex1 + 1).trim(); - messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, text, line)); + messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, text, line)); return true; } if (part1.equalsIgnoreCase("warning")) { // +1 so we don't include the colon String text = line.substring(colonIndex1 + 1).trim(); - messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.WARNING, COMPILER_MESSAGES_GROUP, text, line)); + messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.WARNING, COMPILER_MESSAGES_GROUP, text, line)); return true; } if (part1.equalsIgnoreCase("javac")) { - messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, line, line)); + messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, line, line)); return true; } if (part1.equalsIgnoreCase("Note")) { @@ -60,7 +60,7 @@ public class JavacOutputParser implements BuildOutputParser { if (file.isFile()) { message = message.substring(javaFileExtensionIndex + ".java".length() + 1); String detailedMessage = amendNextInfoLinesIfNeeded(file.getPath() + ":\n" + message, reader); - messageConsumer.accept(new FileMessageEventImpl(reader.getBuildId(), MessageEvent.Kind.INFO, COMPILER_MESSAGES_GROUP, + messageConsumer.accept(new FileMessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.INFO, COMPILER_MESSAGES_GROUP, message, detailedMessage, new FilePosition(file, 0, 0))); return true; @@ -124,7 +124,7 @@ public class JavacOutputParser implements BuildOutputParser { if (column >= 0) { messageList = convertMessages(messageList); String msgText = StringUtil.join(messageList, SystemProperties.getLineSeparator()); - messageConsumer.accept(new FileMessageEventImpl(reader.getBuildId(), kind, COMPILER_MESSAGES_GROUP, msgText, msgText, + messageConsumer.accept(new FileMessageEventImpl(reader.getParentEventId(), kind, COMPILER_MESSAGES_GROUP, msgText, msgText, new FilePosition(file, lineNumber - 1, column))); return true; } @@ -135,7 +135,7 @@ public class JavacOutputParser implements BuildOutputParser { } if (line.endsWith("java.lang.OutOfMemoryError")) { - messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, + messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, "Out of memory.", line)); return true; } diff --git a/java/compiler/impl/src/com/intellij/build/output/KotlincOutputParser.kt b/platform/lang-impl/src/com/intellij/build/output/KotlincOutputParser.kt similarity index 85% rename from java/compiler/impl/src/com/intellij/build/output/KotlincOutputParser.kt rename to platform/lang-impl/src/com/intellij/build/output/KotlincOutputParser.kt index 3c85188eba28..b694a1c072c5 100644 --- a/java/compiler/impl/src/com/intellij/build/output/KotlincOutputParser.kt +++ b/platform/lang-impl/src/com/intellij/build/output/KotlincOutputParser.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.build.output import com.intellij.build.FilePosition @@ -37,7 +37,7 @@ class KotlincOutputParser : BuildOutputParser { val fileExtension = file.extension.toLowerCase() if (!file.isFile || (fileExtension != "kt" && fileExtension != "java")) { - return addMessage(createMessage(reader.buildId, getMessageKind(severity), lineWoSeverity.amendNextLinesIfNeeded(reader), line), + return addMessage(createMessage(reader.parentEventId, getMessageKind(severity), lineWoSeverity.amendNextLinesIfNeeded(reader), line), consumer) } @@ -57,15 +57,15 @@ class KotlincOutputParser : BuildOutputParser { if (lineNumber != null) { val symbolNumberText = symbolNumber.toInt() return addMessage(createMessageWithLocation( - reader.buildId, getMessageKind(severity), message, path, lineNumber.toInt(), symbolNumberText, details), consumer) + reader.parentEventId, getMessageKind(severity), message, path, lineNumber.toInt(), symbolNumberText, details), consumer) } } - return addMessage(createMessage(reader.buildId, getMessageKind(severity), message, details), consumer) + return addMessage(createMessage(reader.parentEventId, getMessageKind(severity), message, details), consumer) } else { val text = lineWoSeverity.amendNextLinesIfNeeded(reader) - return addMessage(createMessage(reader.buildId, getMessageKind(severity), text, text), consumer) + return addMessage(createMessage(reader.parentEventId, getMessageKind(severity), text, text), consumer) } } @@ -139,12 +139,12 @@ class KotlincOutputParser : BuildOutputParser { return true } - private fun createMessage(buildId: Any, messageKind: MessageEvent.Kind, text: String, detail: String): MessageEvent { - return MessageEventImpl(buildId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail) + private fun createMessage(parentId: Any, messageKind: MessageEvent.Kind, text: String, detail: String): MessageEvent { + return MessageEventImpl(parentId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail) } private fun createMessageWithLocation( - buildId: Any, + parentId: Any, messageKind: MessageEvent.Kind, text: String, file: String, @@ -152,7 +152,7 @@ class KotlincOutputParser : BuildOutputParser { columnIndex: Int, detail: String ): FileMessageEventImpl { - return FileMessageEventImpl(buildId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail, + return FileMessageEventImpl(parentId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail, FilePosition(File(file), lineNumber - 1, columnIndex - 1)) } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index 0db7e4285de0..a77aec50a48e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -10,6 +10,7 @@ import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.ide.actions.BaseNavigateToSourceAction; import com.intellij.ide.actions.ExternalJavaDocAction; +import com.intellij.ide.actions.WindowAction; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.documentation.CompositeDocumentationProvider; import com.intellij.lang.documentation.DocumentationMarkup; @@ -17,11 +18,13 @@ import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.lang.documentation.ExternalDocumentationHandler; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.AnActionListener; import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl; import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -927,13 +930,21 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr AbstractPopup hint = myHint; if (hint == null || mySizeTrackerRegistered) return; mySizeTrackerRegistered = true; - hint.addResizeListener(() -> { - myManuallyResized = true; - if (myStoreSize) { - hint.setDimensionServiceKey(DocumentationManager.NEW_JAVADOC_LOCATION_AND_SIZE); - hint.storeDimensionSize(); + hint.addResizeListener(this::onManualResizing, this); + ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(AnActionListener.TOPIC, new AnActionListener() { + @Override + public void afterActionPerformed(@NotNull AnAction action, @NotNull DataContext dataContext, @NotNull AnActionEvent event) { + if (action instanceof WindowAction) onManualResizing(); } - }, this); + }); + } + + private void onManualResizing() { + myManuallyResized = true; + if (myStoreSize && myHint != null) { + myHint.setDimensionServiceKey(DocumentationManager.NEW_JAVADOC_LOCATION_AND_SIZE); + myHint.storeDimensionSize(); + } } private int definitionPreferredWidth() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index d5801d535783..40da18976ace 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -14,6 +14,7 @@ import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeEventQueue; import com.intellij.ide.actions.BaseNavigateToSourceAction; +import com.intellij.ide.actions.WindowAction; import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.ide.util.PropertiesComponent; import com.intellij.ide.util.gotoByName.ChooseByNameBase; @@ -104,7 +105,8 @@ public class DocumentationManager extends DockablePopupManager CARET_SHIFT = Key.create("tab.out.caret.shift"); + @Override - public void registerEmptyScope(@NotNull Editor editor, int offset) { + public void registerEmptyScope(@NotNull Editor editor, int offset, int caretShift) { ApplicationManager.getApplication().assertIsDispatchThread(); assert !editor.isDisposed() : "Disposed editor"; + assert caretShift > 0 : "Caret shift must be positive"; if (!CodeInsightSettings.getInstance().TAB_EXITS_BRACKETS_AND_QUOTES) return; @@ -37,35 +40,35 @@ public class TabOutScopesTrackerImpl implements TabOutScopesTracker { if (!(editor instanceof EditorImpl)) return; Tracker tracker = Tracker.forEditor((EditorImpl)editor, true); - tracker.registerScope(offset); + tracker.registerScope(offset, caretShift); } @Override public boolean hasScopeEndingAt(@NotNull Editor editor, int offset) { - return checkOrRemoveScopeEndingAt(editor, offset, false); + return checkOrRemoveScopeEndingAt(editor, offset, false) > 0; } @Override - public boolean removeScopeEndingAt(@NotNull Editor editor, int offset) { + public int removeScopeEndingAt(@NotNull Editor editor, int offset) { return checkOrRemoveScopeEndingAt(editor, offset, true); } - private static boolean checkOrRemoveScopeEndingAt(@NotNull Editor editor, int offset, boolean removeScope) { + private static int checkOrRemoveScopeEndingAt(@NotNull Editor editor, int offset, boolean removeScope) { ApplicationManager.getApplication().assertIsDispatchThread(); - if (!CodeInsightSettings.getInstance().TAB_EXITS_BRACKETS_AND_QUOTES) return false; + if (!CodeInsightSettings.getInstance().TAB_EXITS_BRACKETS_AND_QUOTES) return 0; if (editor instanceof EditorWindow) { DocumentWindow documentWindow = ((EditorWindow)editor).getDocument(); offset = documentWindow.injectedToHost(offset); editor = ((EditorWindow)editor).getDelegate(); } - if (!(editor instanceof EditorImpl)) return false; + if (!(editor instanceof EditorImpl)) return 0; Tracker tracker = Tracker.forEditor((EditorImpl)editor, false); - if (tracker == null) return false; + if (tracker == null) return 0; - return tracker.hasScopeEndingAt(offset, removeScope); + return tracker.getCaretShiftForScopeEndingAt(offset, removeScope); } private static class Tracker extends DocumentBulkUpdateListener.Adapter implements DocumentListener { @@ -98,24 +101,26 @@ public class TabOutScopesTrackerImpl implements TabOutScopesTracker { return result; } - private void registerScope(int offset) { + private void registerScope(int offset, int caretShift) { RangeMarker marker = myEditor.getDocument().createRangeMarker(offset, offset); marker.setGreedyToLeft(true); marker.setGreedyToRight(true); + if (caretShift > 1) marker.putUserData(CARET_SHIFT, caretShift); getCurrentScopes(true).add(marker); } - private boolean hasScopeEndingAt(int offset, boolean remove) { + private int getCaretShiftForScopeEndingAt(int offset, boolean remove) { List scopes = getCurrentScopes(false); - if (scopes == null) return false; + if (scopes == null) return 0; for (Iterator it = scopes.iterator(); it.hasNext(); ) { RangeMarker scope = it.next(); if (offset == scope.getEndOffset()) { if (remove) it.remove(); - return true; + Integer caretShift = scope.getUserData(CARET_SHIFT); + return caretShift == null ? 1 : caretShift; } } - return false; + return 0; } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java index 1969616f0c64..10cf42f351a0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java @@ -305,7 +305,7 @@ public class TemplateImpl extends Template implements SchemeElement { } mySegments = new SmartList<>(); - StringBuilder buffer = new StringBuilder(); + StringBuilder buffer = new StringBuilder(myString.length()); TemplateTextLexer lexer = new TemplateTextLexer(); lexer.start(myString); diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java deleted file mode 100644 index be4b4424a805..000000000000 --- a/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2000-2009 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.extapi.psi; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2019.2") -public abstract class MetadataPsiElementBase extends PsiElementBase { - - private final PsiElement mySourceElement; - - public MetadataPsiElementBase(PsiElement sourceElement) { - mySourceElement = sourceElement; - } - - @Override - public TextRange getTextRange() { - return mySourceElement != null? mySourceElement.getTextRange() : null; - } - - @Override - public int getStartOffsetInParent() { - final PsiElement parent = getParent(); - return (parent == null) ? 0 : getTextRange().getStartOffset() - parent.getTextRange().getStartOffset(); - } - - @Override - public int getTextLength() { - return mySourceElement.getTextLength(); - } - - @Override - public int getTextOffset() { - return mySourceElement.getTextOffset(); - } - - @Override - public String getText() { - return mySourceElement.getText(); - } - - @Override - @NotNull - public char[] textToCharArray() { - return mySourceElement.textToCharArray(); - } - - @Override - public boolean textContains(char c) { - return mySourceElement.textContains(c); - } - - public PsiElement getSourceElement() { - return mySourceElement; - } -} diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java deleted file mode 100644 index 5eb81451d5d6..000000000000 --- a/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2000-2014 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.extapi.psi; - -import com.intellij.ide.util.PsiNavigationSupport; -import com.intellij.navigation.ItemPresentation; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.pom.Navigatable; -import com.intellij.psi.*; -import com.intellij.psi.impl.ElementBase; -import com.intellij.psi.impl.ResolveScopeManager; -import com.intellij.psi.impl.SharedPsiElementImplUtil; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.SearchScope; -import com.intellij.util.ArrayUtil; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * @deprecated Please use {@link com.intellij.psi.impl.PsiElementBase} as a base class - * or one of its descendants, e.g. {@link ASTWrapperPsiElement}, as suggested in a - * tutorial - */ -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2019.2") -public abstract class PsiElementBase extends ElementBase implements NavigatablePsiElement { - private static final Logger LOG = Logger.getInstance("#com.intellij.extapi.psi.PsiElementBase"); - - @Override - public PsiElement copy() { - return (PsiElement)clone(); - } - - @Override - public PsiElement add(@NotNull PsiElement element) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public void checkAdd(@NotNull PsiElement element) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiElement addRangeBefore(@NotNull PsiElement first, @NotNull PsiElement last, PsiElement anchor) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public void delete() throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public void checkDelete() throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public void deleteChildRange(PsiElement first, PsiElement last) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException { - throw new UnsupportedOperationException(getClass().getName()); - } - - @Override - public PsiReference getReference() { - return null; - } - - @Override - public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { - return true; - } - - @Override - @NotNull - public Project getProject() { - final PsiManager manager = getManager(); - if (manager == null) { - throw new PsiInvalidElementAccessException(this); - } - - return manager.getProject(); - } - - @Override - public PsiManager getManager() { - final PsiElement parent = getParent(); - return parent != null ? parent.getManager() : null; - } - - @Override - public PsiFile getContainingFile() { - final PsiElement parent = getParent(); - if (parent == null) throw new PsiInvalidElementAccessException(this); - return parent.getContainingFile(); - } - - @Override - public PsiReference findReferenceAt(int offset) { - return SharedPsiElementImplUtil.findReferenceAt(this, offset); - } - - @Override - @NotNull - public PsiElement getNavigationElement() { - return this; - } - - @Override - public PsiElement getOriginalElement() { - return this; - } - - //Q: get rid of these methods? - @Override - public boolean textMatches(@NotNull CharSequence text) { - return Comparing.equal(getText(), text, true); - } - - @Override - public boolean textMatches(@NotNull PsiElement element) { - return getText().equals(element.getText()); - } - - @Override - public void accept(@NotNull PsiElementVisitor visitor) { - visitor.visitElement(this); - } - - @Override - public void acceptChildren(@NotNull PsiElementVisitor visitor) { - PsiElement child = getFirstChild(); - while (child != null) { - child.accept(visitor); - child = child.getNextSibling(); - } - } - - @Override - public boolean isValid() { - final PsiElement parent = getParent(); - return parent != null && parent.isValid(); - } - - @Override - public boolean isWritable() { - final PsiElement parent = getParent(); - return parent != null && parent.isWritable(); - } - - @Override - @NotNull - public PsiReference[] getReferences() { - return SharedPsiElementImplUtil.getReferences(this); - } - - @Override - public PsiElement getContext() { - return getParent(); - } - - @Override - public boolean isPhysical() { - final PsiElement parent = getParent(); - return parent != null && parent.isPhysical(); - } - - @Override - @NotNull - public GlobalSearchScope getResolveScope() { - return ResolveScopeManager.getElementResolveScope(this); - } - - @Override - @NotNull - public SearchScope getUseScope() { - return ResolveScopeManager.getElementUseScope(this); - } - - /** - * Returns the UI presentation data for the PSI element. - * - * @return null, unless overridden in a subclass. - */ - @Override - public ItemPresentation getPresentation() { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public void navigate(boolean requestFocus) { - final Navigatable descriptor = PsiNavigationSupport.getInstance().getDescriptor(this); - if (descriptor != null) descriptor.navigate(requestFocus); - } - - @Override - public boolean canNavigate() { - return true; - } - - @Override - public boolean canNavigateToSource() { - final Navigatable descriptor = PsiNavigationSupport.getInstance().getDescriptor(this); - return descriptor != null && descriptor.canNavigateToSource(); - } - - @NotNull - protected T[] findChildrenByClass(Class aClass) { - List result = new ArrayList<>(); - for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) { - if (aClass.isInstance(cur)) result.add((T)cur); - } - return result.toArray(ArrayUtil.newArray(aClass, result.size())); - } - - @Nullable - protected T findChildByClass(Class aClass) { - for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) { - if (aClass.isInstance(cur)) return (T)cur; - } - return null; - } - - @NotNull - protected T findNotNullChildByClass(Class aClass) { - return notNullChild(findChildByClass(aClass)); - } - - @NotNull - protected T notNullChild(T child) { - if (child == null) { - LOG.error(getText() + "\n parent=" + getParent().getText()); - } - return child; - } - - @Override - public boolean isEquivalentTo(final PsiElement another) { - return this == another; - } -} diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java index 5b7c95f66247..67a2d2e54f23 100644 --- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java @@ -17,6 +17,8 @@ package com.intellij.formatting; import com.intellij.formatting.engine.ExpandableIndent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.TextRange; import com.intellij.psi.codeStyle.CodeStyleSettings; @@ -38,6 +40,7 @@ import java.util.Set; * The main idea of block wrapping is to associate information about {@link WhiteSpace white space before block} with the block itself. */ public class InitialInfoBuilder { + private static final Logger LOG = Logger.getInstance(InitialInfoBuilder.class); private static final RangesAssert ASSERT = new RangesAssert(); private static final boolean INLINE_TABS_ENABLED = "true".equalsIgnoreCase(System.getProperty("inline.tabs.enabled")); @@ -46,7 +49,7 @@ public class InitialInfoBuilder { private final MultiMap myBlocksToAlign = new MultiMap<>(); private final Set myAlignmentsInsideRangeToModify = ContainerUtil.newHashSet(); - private boolean myCollectAlignmentsInsideFormattingRange = false; + private boolean myCollectAlignmentsInsideFormattingRange; private final FormattingDocumentModel myModel; private final FormatTextRanges myAffectedRanges; @@ -88,14 +91,14 @@ public class InitialInfoBuilder { myFormatterTagHandler = new FormatterTagHandler(settings); } - protected static InitialInfoBuilder prepareToBuildBlocksSequentially( - Block root, - FormattingDocumentModel model, - FormatProcessor.FormatOptions formatOptions, - CodeStyleSettings settings, - CommonCodeStyleSettings.IndentOptions options, - @NotNull FormattingProgressCallback progressCallback) - { + @NotNull + static InitialInfoBuilder prepareToBuildBlocksSequentially( + Block root, + FormattingDocumentModel model, + FormatProcessor.FormatOptions formatOptions, + CodeStyleSettings settings, + CommonCodeStyleSettings.IndentOptions options, + @NotNull FormattingProgressCallback progressCallback) { InitialInfoBuilder builder = new InitialInfoBuilder(root, model, formatOptions.myAffectedRanges, settings, options, formatOptions.myInterestingOffset, progressCallback); builder.setCollectAlignmentsInsideFormattingRange(formatOptions.myReformatContext); builder.buildFrom(root, 0, null, null, null); @@ -273,8 +276,24 @@ public class InitialInfoBuilder { if (!state.readOnly) { try { subBlocks.set(currentBlockIndex, null); // to prevent extra strong refs during model building - } catch (Throwable ex) { - // read-only blocks + } + catch (Throwable ex) { + // todo fix kotlin + if ("org.jetbrains.kotlin.idea.formatter.KotlinBlock".equals(currentRoot.getClass().getName())) { + // ignore + } + else { + // read-only blocks + String msg = "Unable to null elements of list I got from getSubBlocks(): " + subBlocks.getClass() + + ". If you really want to return immutable list, please mark " + currentRoot.getClass() + + " with 'ReadOnlyBlockContainer' interface"; + if (ApplicationManager.getApplication().isInternal() || ApplicationManager.getApplication().isUnitTestMode()) { + LOG.error(msg, ex); + } + else { + LOG.warn(msg, ex); + } + } } } diff --git a/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java b/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java index 855007f8d9e2..1a6a67ed54c9 100644 --- a/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java +++ b/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java @@ -34,6 +34,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsCodeFragmentFilter; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.IncorrectOperationException; @@ -177,6 +178,7 @@ public class ConfigureCodeStyleOnSelectedFragment implements IntentionAction, Lo private void applyFromUiToSettings() { try { myTabbedLanguagePanel.apply(mySettings); + CodeStyleSettingsManager.getInstance(myEditor.getProject()).notifyCodeStyleSettingsChanged(); } catch (ConfigurationException e) { LOG.debug("Can not apply code style settings from context menu to project code style settings"); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java index 8eb2deec3c6c..afff5bd296b0 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java @@ -114,7 +114,7 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider { * Invoke contributors directly, as multi-threading isn't of much value in Goto File, * and filling {@link ContributorsBasedGotoByModel#myContributorToItsSymbolsMap} is expensive for the default contributor. */ - private void processNames(Processor nameProcessor) { + private void processNames(Processor nameProcessor) { List contributors = DumbService.getDumbAwareExtensions(myProject, ChooseByNameContributor.FILE_EP_NAME); for (ChooseByNameContributor contributor : contributors) { if (contributor instanceof DefaultFileNavigationContributor) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java b/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java index e79d18e6354e..9897166996ce 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java @@ -10,13 +10,15 @@ import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Trinity; import com.intellij.ui.DocumentAdapter; -import com.intellij.ui.JBColor; import com.intellij.ui.ScrollingUtil; import com.intellij.ui.SimpleListCellRenderer; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBPanel; +import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBTextField; +import com.intellij.ui.components.fields.ExtendableTextComponent; +import com.intellij.ui.components.fields.ExtendableTextField; import com.intellij.util.BooleanFunction; import com.intellij.util.Consumer; import com.intellij.util.ui.JBUI; @@ -34,7 +36,7 @@ import static com.intellij.ide.ui.laf.darcula.DarculaUIUtil.Outline; public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposable { - private final JBTextField myNameField; + private final ExtendableTextField myNameField; private final JList> myTemplatesList; private JBPopup myErrorPopup; @@ -44,6 +46,7 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl public CreateWithTemplatesDialogPanel(@NotNull List> templates, @Nullable String selectedItem) { super(new BorderLayout()); + setBackground(JBUI.CurrentTheme.NewClassDialog.panelBackground()); myNameField = createNameField(); myTemplatesList = createTemplatesList(templates); @@ -54,7 +57,14 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl selectTemplate(selectedItem); add(myNameField, BorderLayout.NORTH); - add(myTemplatesList, BorderLayout.CENTER); + + JBScrollPane scrollPane = new JBScrollPane(myTemplatesList); + scrollPane.setBorder(JBUI.Borders.empty()); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + Box listHolder = new Box(BoxLayout.Y_AXIS); + listHolder.setBorder(JBUI.Borders.emptyTop(JBUI.CurrentTheme.NewClassDialog.fieldsSeparatorWidth())); + listHolder.add(scrollPane); + add(listHolder, BorderLayout.CENTER); } public JTextField getNameField() { @@ -100,8 +110,8 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl } @NotNull - private JBTextField createNameField() { - JBTextField res = new JBTextField(); + private ExtendableTextField createNameField() { + ExtendableTextField res = new ExtendableTextField(); Dimension minSize = res.getMinimumSize(); Dimension prefSize = res.getPreferredSize(); @@ -111,13 +121,10 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl res.setPreferredSize(prefSize); res.setColumns(30); - JBColor borderColor = JBColor.namedColor( - "TextField.borderColor", - JBColor.namedColor("Component.borderColor", new JBColor(0xbdbdbd, 0x646464)) - ); - Border border = JBUI.Borders.customLine(borderColor, 1, 0, 1, 0); + Border border = JBUI.Borders.customLine(JBUI.CurrentTheme.NewClassDialog.bordersColor(), 1, 0, 1, 0); Border errorBorder = new ErrorBorder(res.getBorder()); res.setBorder(JBUI.Borders.merge(border, errorBorder, false)); + res.setBackground(JBUI.CurrentTheme.NewClassDialog.searchFieldBackground()); res.putClientProperty("StatusVisibleFunction", (BooleanFunction) field -> field.getText().isEmpty()); res.getEmptyText().setText(IdeBundle.message("action.create.new.class.name.field")); @@ -144,38 +151,38 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl private JBList> createTemplatesList(@NotNull List> templates) { JBList> list = new JBList<>(templates); MouseAdapter mouseListener = new MouseAdapter() { - // to avoid selection item under mouse when dialog appears (IDEA-209879) - private boolean isFirstEvent = true; - - @Override - public void mouseMoved(MouseEvent e) { - if (isFirstEvent) { - isFirstEvent = false; - return; - } - selectItem(e.getPoint()); - } - @Override public void mouseClicked(MouseEvent e) { - selectItem(e.getPoint()); - if (myApplyAction != null) myApplyAction.consume(e); - } - - private void selectItem(Point point) { - int index = list.locationToIndex(point); - if (index >= 0) { - list.setSelectedIndex(index); - } + if (myApplyAction != null && e.getClickCount() > 1) myApplyAction.consume(e); } }; - list.addMouseMotionListener(mouseListener); + list.addMouseListener(mouseListener); list.setCellRenderer(LIST_RENDERER); list.setFocusable(false); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + list.addListSelectionListener(e -> { + Trinity selectedValue = list.getSelectedValue(); + if (selectedValue != null) { + setTextFieldIcon(selectedValue.second); + } + }); + + Border border = JBUI.Borders.merge( + JBUI.Borders.emptyLeft(JBUI.scale(5)), + JBUI.Borders.customLine(JBUI.CurrentTheme.NewClassDialog.bordersColor(), 1, 0, 0, 0), + true + ); + list.setBorder(border); return list; } + private void setTextFieldIcon(Icon icon) { + myNameField.setExtensions(new TemplateIconExtension(icon)); + myNameField.repaint(); + } + private void selectTemplate(@Nullable String selectedItem) { if (selectedItem == null) { myTemplatesList.setSelectedIndex(0); @@ -215,6 +222,22 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl } }; + private static class TemplateIconExtension implements ExtendableTextComponent.Extension { + private final Icon icon; + + private TemplateIconExtension(Icon icon) {this.icon = icon;} + + @Override + public Icon getIcon(boolean hovered) { + return icon; + } + + @Override + public boolean isIconBeforeText() { + return true; + } + } + private static class ErrorBorder implements Border { private final Border errorDelegateBorder; diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java index 991b90ad6482..2247f2bd88f7 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java @@ -76,15 +76,16 @@ public abstract class AbstractGotoSEContributor implements SearchEverywh @NotNull Processor consumer) { if (myProject == null) return; //nothing to search if (!isEmptyPatternSupported() && pattern.isEmpty()) return; - if (!isDumbModeSupported() && DumbService.getInstance(myProject).isDumb()) return; - - FilteringGotoByModel model = createModel(myProject); - if (filter != null) { - model.setFilterItems(filter.getSelectedElements()); - } ProgressIndicatorUtils.yieldToPendingWriteActions(); ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(() -> { + if (!isDumbModeSupported() && DumbService.getInstance(myProject).isDumb()) return; + + FilteringGotoByModel model = createModel(myProject); + if (filter != null) { + model.setFilterItems(filter.getSelectedElements()); + } + if (progressIndicator.isCanceled()) return; PsiElement context = psiContext != null && psiContext.isValid() ? psiContext : null; diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java index da5a4db7c248..513f68a37618 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java @@ -60,8 +60,6 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE } private final ConcurrentMap myContributorToItsSymbolsMap = ContainerUtil.newConcurrentMap(); - private volatile IdFilter myIdFilter; - private volatile boolean myIdFilterForLibraries; @Override public void processNames(final Processor nameProcessor, final boolean checkBoxState) { @@ -125,14 +123,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE } IdFilter getIdFilter(boolean withLibraries) { - IdFilter idFilter = myIdFilter; - - if (idFilter == null || myIdFilterForLibraries != withLibraries) { - idFilter = IdFilter.getProjectIdFilter(myProject, withLibraries); - myIdFilter = idFilter; - myIdFilterForLibraries = withLibraries; - } - return idFilter; + return IdFilter.getProjectIdFilter(myProject, withLibraries); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java b/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java index 7e97ea4f7ee1..239831f3b8d2 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java @@ -46,7 +46,7 @@ public class FileNameIndexServiceImpl implements FileNameIndexService { } @Override - public void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, IdFilter filter) { + public void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, IdFilter filter) { myIndex.processAllKeys(FilenameIndexImpl.NAME, processor, scope, filter); } diff --git a/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java b/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java index 213452e4d9c8..6ceccecb0f18 100644 --- a/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java +++ b/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java @@ -16,7 +16,6 @@ package com.intellij.psi.util.proximity; -import com.intellij.extapi.psi.MetadataPsiElementBase; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.util.Computable; @@ -86,8 +85,6 @@ public class PsiProximityComparator implements Comparator { @Nullable public static WeighingComparable getProximity(final PsiElement element, final PsiElement context) { if (element == null) return null; - //noinspection deprecation,ScheduledForRemoval - if (element instanceof MetadataPsiElementBase) return null; final Module contextModule = context != null ? ModuleUtilCore.findModuleForPsiElement(context) : null; return WeighingService.weigh(WEIGHER_KEY, element, new ProximityLocation(context, contextModule)); } @@ -95,10 +92,7 @@ public class PsiProximityComparator implements Comparator { @Nullable public static WeighingComparable getProximity(final Computable elementComputable, final PsiElement context, ProcessingContext processingContext) { PsiElement element = elementComputable.compute(); - if (element == null) return null; - //noinspection deprecation,ScheduledForRemoval - if (element instanceof MetadataPsiElementBase) return null; - if (context == null) return null; + if (element == null || context == null) return null; Module contextModule = processingContext.get(MODULE_BY_LOCATION); if (contextModule == null) { contextModule = ModuleUtilCore.findModuleForPsiElement(context); diff --git a/platform/lang-impl/testSources/com/intellij/build/output/BuildOutputInstantReaderImplTest.kt b/platform/lang-impl/testSources/com/intellij/build/output/BuildOutputInstantReaderImplTest.kt index 554c7ad6204e..13de477afd31 100644 --- a/platform/lang-impl/testSources/com/intellij/build/output/BuildOutputInstantReaderImplTest.kt +++ b/platform/lang-impl/testSources/com/intellij/build/output/BuildOutputInstantReaderImplTest.kt @@ -104,7 +104,7 @@ ${trashOut.prependIndent(" ")} buf.append(nextLine).append('\n') nextLine = reader.readLine() } - messageConsumer.accept(MessageEventImpl(reader.buildId, kind, null, buf.toString().dropLast(1), null)) + messageConsumer.accept(MessageEventImpl(reader.parentEventId, kind, null, buf.toString().dropLast(1), null)) return@BuildOutputParser true } return@BuildOutputParser false diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiCommands.java b/platform/platform-api/src/com/intellij/execution/process/AnsiCommands.java new file mode 100644 index 000000000000..d31b7c6b0de6 --- /dev/null +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiCommands.java @@ -0,0 +1,87 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.process; + +public final class AnsiCommands { + public static final int SGR_COMMAND_RESET = 0; + public static final int SGR_COMMAND_BOLD = 1; + public static final int SGR_COMMAND_FAINT = 2; + public static final int SGR_COMMAND_ITALIC = 3; + public static final int SGR_COMMAND_UNDERLINE = 4; + public static final int SGR_COMMAND_BLINK_SLOW = 5; + public static final int SGR_COMMAND_BLINK_RAPID = 6; + public static final int SGR_COMMAND_INVERSE = 7; + public static final int SGR_COMMAND_CONCEAL = 8; + public static final int SGR_COMMAND_CROSS_OUT = 9; + public static final int SGR_COMMAND_PRIMARY_FONT = 10; + public static final int SGR_COMMAND_FONT1 = 11; + public static final int SGR_COMMAND_FONT2 = 12; + public static final int SGR_COMMAND_FONT3 = 13; + public static final int SGR_COMMAND_FONT4 = 14; + public static final int SGR_COMMAND_FONT5 = 15; + public static final int SGR_COMMAND_FONT6 = 16; + public static final int SGR_COMMAND_FONT7 = 17; + public static final int SGR_COMMAND_FONT8 = 18; + public static final int SGR_COMMAND_FONT9 = 19; + public static final int SGR_COMMAND_FRAKTUR = 20; + public static final int SGR_COMMAND_DOUBLE_UNDERLINE = 21; + public static final int SGR_COMMAND_NO_BOLD_FAINT = 22; + public static final int SGR_COMMAND_NO_ITALIC_FRAKTUR = 23; + public static final int SGR_COMMAND_NO_UNDERLINE = 24; + public static final int SGR_COMMAND_NO_BLINK = 25; + public static final int SGR_COMMAND_NO_INVERSE = 27; + public static final int SGR_COMMAND_REVEAL = 28; + public static final int SGR_COMMAND_NO_CROSS_OUT = 29; + public static final int SGR_COMMAND_FG_COLOR0 = 30; + public static final int SGR_COMMAND_FG_COLOR1 = 31; + public static final int SGR_COMMAND_FG_COLOR2 = 32; + public static final int SGR_COMMAND_FG_COLOR3 = 33; + public static final int SGR_COMMAND_FG_COLOR4 = 34; + public static final int SGR_COMMAND_FG_COLOR5 = 35; + public static final int SGR_COMMAND_FG_COLOR6 = 36; + public static final int SGR_COMMAND_FG_COLOR7 = 37; + public static final int SGR_COMMAND_FG_COLOR_ENCODED = 38; + public static final int SGR_COMMAND_FG_COLOR_DEFAULT = 39; + public static final int SGR_COMMAND_BG_COLOR0 = 40; + public static final int SGR_COMMAND_BG_COLOR1 = 41; + public static final int SGR_COMMAND_BG_COLOR2 = 42; + public static final int SGR_COMMAND_BG_COLOR3 = 43; + public static final int SGR_COMMAND_BG_COLOR4 = 44; + public static final int SGR_COMMAND_BG_COLOR5 = 45; + public static final int SGR_COMMAND_BG_COLOR6 = 46; + public static final int SGR_COMMAND_BG_COLOR7 = 47; + public static final int SGR_COMMAND_BG_COLOR_ENCODED = 48; + public static final int SGR_COMMAND_BG_COLOR_DEFAULT = 49; + public static final int SGR_COMMAND_FRAMED = 51; + public static final int SGR_COMMAND_ENCIRCLED = 52; + public static final int SGR_COMMAND_OVERLINED = 53; + public static final int SGR_COMMAND_NO_FRAMED_ENCIRCLED = 54; + public static final int SGR_COMMAND_NO_OVERLINED = 55; + public static final int SGR_COMMAND_IDEOGRAM_UNDER_RIGHT = 60; + public static final int SGR_COMMAND_IDEOGRAM_UNDER_RIGHT_DOUBLE = 61; + public static final int SGR_COMMAND_IDEOGRAM_OVER_LEFT = 62; + public static final int SGR_COMMAND_IDEOGRAM_OVER_LEFT_DOUBLE = 63; + public static final int SGR_COMMAND_IDEOGRAM_STRESS = 64; + public static final int SGR_COMMAND_IDEOGRAM_OFF = 65; + public static final int SGR_COMMAND_FG_COLOR8 = 90; + public static final int SGR_COMMAND_FG_COLOR9 = 91; + public static final int SGR_COMMAND_FG_COLOR10 = 92; + public static final int SGR_COMMAND_FG_COLOR11 = 93; + public static final int SGR_COMMAND_FG_COLOR12 = 94; + public static final int SGR_COMMAND_FG_COLOR13 = 95; + public static final int SGR_COMMAND_FG_COLOR14 = 96; + public static final int SGR_COMMAND_FG_COLOR15 = 97; + public static final int SGR_COMMAND_BG_COLOR8 = 100; + public static final int SGR_COMMAND_BG_COLOR9 = 101; + public static final int SGR_COMMAND_BG_COLOR10 = 102; + public static final int SGR_COMMAND_BG_COLOR11 = 103; + public static final int SGR_COMMAND_BG_COLOR12 = 104; + public static final int SGR_COMMAND_BG_COLOR13 = 105; + public static final int SGR_COMMAND_BG_COLOR14 = 106; + public static final int SGR_COMMAND_BG_COLOR15 = 107; + // these are used with SGR_COMMAND_BG_COLOR_ENCODED/SGR_COMMAND_FG_COLOR_ENCODED + public static final int SGR_COLOR_ENCODING_INDEXED = 5; + public static final int SGR_COLOR_ENCODING_RGB = 2; + + private AnsiCommands() { + } +} diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java index adf5f955d5d2..58e058254ade 100644 --- a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java @@ -15,31 +15,28 @@ */ package com.intellij.execution.process; +import com.intellij.execution.process.AnsiStreamingLexer.AnsiElementType; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.intellij.execution.process.AnsiStreamingLexer.SGR; +import static com.intellij.execution.process.AnsiStreamingLexer.TEXT; + /** * See ANSI escape code. - * - * @author traff */ public class AnsiEscapeDecoder { - private static final char ESC_CHAR = '\u001B'; // Escape sequence start character - private static final String CSI = ESC_CHAR + "["; // "Control Sequence Initiator" - private static final String M_CSI = "m" + CSI; - private final ColoredOutputTypeRegistry myColoredOutputTypeRegistry = ColoredOutputTypeRegistry.getInstance(); - private String myUnhandledStdout; - private String myUnhandledStderr; - private ProcessOutputType myCurrentStdoutOutputType; - private ProcessOutputType myCurrentStderrOutputType; + + private final AnsiStreamingLexer myStdoutLexer = new AnsiStreamingLexer(); + private final AnsiStreamingLexer myStderrLexer = new AnsiStreamingLexer(); + private final AnsiTerminalEmulator myStdoutEmulator = new AnsiTerminalEmulator(); + private final AnsiTerminalEmulator myStderrEmulator = new AnsiTerminalEmulator(); /** * Parses ansi-color codes from text and sends text fragments with color attributes to textAcceptor @@ -50,185 +47,54 @@ public class AnsiEscapeDecoder { * It can implement ColoredChunksAcceptor to receive list of pairs (text, attribute). */ public void escapeText(@NotNull String text, @NotNull Key outputType, @NotNull ColoredTextAcceptor textAcceptor) { - text = prependUnhandledText(text, outputType); - int pos = 0; - int findEscSeqFromIndex = 0; + AnsiStreamingLexer effectiveLexer; + AnsiTerminalEmulator effectiveEmulator; + if (ProcessOutputType.isStdout(outputType)) { + effectiveLexer = myStdoutLexer; + effectiveEmulator = myStdoutEmulator; + } + else if (ProcessOutputType.isStderr(outputType)) { + effectiveLexer = myStderrLexer; + effectiveEmulator = myStderrEmulator; + } + else { + processTextWithoutAnsi(text, outputType, textAcceptor); + return; + } + + effectiveLexer.append(text); + effectiveLexer.advance(); + List> chunks = null; - int unhandledSuffixLength = 0; - while (true) { - int escSeqBeginInd = findEscSeqBeginIndex(text, findEscSeqFromIndex); - if (escSeqBeginInd < 0) { - if (escSeqBeginInd < -1) { - unhandledSuffixLength = decodeUnhandledSuffixLength(escSeqBeginInd); - } - break; + AnsiElementType elementType; + while ((elementType = effectiveLexer.getElementType()) != null) { + String elementText = effectiveLexer.getElementTextSmart(); + assert elementText != null; + if (elementType == SGR) { + effectiveEmulator.processSgr(elementText); } - int escSeqEndInd = findConsecutiveEscSequencesEndIndex(text, escSeqBeginInd); - if (escSeqEndInd < 0) { - if (escSeqEndInd == -1) { - // malformed escape sequence => add ESC[ - findEscSeqFromIndex = escSeqBeginInd + CSI.length(); - } - else { - unhandledSuffixLength = decodeUnhandledSuffixLength(escSeqEndInd); - break; - } + else if (elementType == TEXT) { + chunks = processTextChunk(chunks, elementText, outputType, textAcceptor); } else { - assert escSeqBeginInd <= escSeqEndInd; - if (pos < escSeqBeginInd) { - chunks = processTextChunk(chunks, text.substring(pos, escSeqBeginInd), outputType, textAcceptor); - } - pos = escSeqEndInd + 1; - findEscSeqFromIndex = pos; - if (text.charAt(escSeqEndInd) == 'm') { - String escSeq = text.substring(escSeqBeginInd, escSeqEndInd + 1); - // this is a simple fix for RUBY-8996: - // we replace several consecutive escape sequences with one which contains all these sequences - String colorAttribute = StringUtil.replace(escSeq, M_CSI, ";"); - ProcessOutputType resultType = myColoredOutputTypeRegistry.getOutputType(colorAttribute, outputType); - if (resultType.isStdout()) { - myCurrentStdoutOutputType = resultType; - } - else if (resultType.isStderr()) { - myCurrentStderrOutputType = resultType; - } - } + assert elementType == AnsiStreamingLexer.CONTROL; + // Commands other than SGR are unhandled currently. Extend here when it's needed. } + effectiveLexer.advance(); } - if (pos < text.length() - unhandledSuffixLength) { - chunks = processTextChunk(chunks, text.substring(pos, text.length() - unhandledSuffixLength), outputType, textAcceptor); - } - updateUnhandledSuffix(text, outputType, unhandledSuffixLength); if (chunks != null && textAcceptor instanceof ColoredChunksAcceptor) { ((ColoredChunksAcceptor)textAcceptor).coloredChunksAvailable(chunks); } } - private void updateUnhandledSuffix(@NotNull String text, @NotNull Key outputType, int unhandledSuffixLength) { - String unhandledSuffix = unhandledSuffixLength > 0 ? text.substring(text.length() - unhandledSuffixLength) : null; - if (ProcessOutputType.isStdout(outputType)) { - myUnhandledStdout = unhandledSuffix; - } - else if (ProcessOutputType.isStderr(outputType)) { - myUnhandledStderr = unhandledSuffix; - } - } - - @NotNull - private String prependUnhandledText(@NotNull String text, @NotNull Key outputType) { - String prevUnhandledText = null; - if (ProcessOutputType.isStdout(outputType)) { - prevUnhandledText = myUnhandledStdout; - myUnhandledStdout = null; - } - else if (ProcessOutputType.isStderr(outputType)) { - prevUnhandledText = myUnhandledStderr; - myUnhandledStderr = null; - } - return prevUnhandledText != null ? prevUnhandledText + text : text; - } - /** - * Returns the index of the first occurrence of CSI within the passed string that is greater than or equal to {@code fromIndex}, - * or negative number if CSI is not found: -1 - (length of text suffix to keep in case of an incomplete CSI). + * Fallback method for the {@link ProcessOutputTypes#SYSTEM system} output type. ANSI is not supported */ - private static int findEscSeqBeginIndex(@NotNull String text, int fromIndex) { - int ind = text.indexOf(CSI.charAt(0), fromIndex); - if (ind == -1) { - return -1; + private void processTextWithoutAnsi(@NotNull String text, @NotNull Key outputType, @NotNull ColoredTextAcceptor textAcceptor) { + List> chunks = processTextChunk(null, text, outputType, textAcceptor); + if (chunks != null && textAcceptor instanceof ColoredChunksAcceptor) { + ((ColoredChunksAcceptor)textAcceptor).coloredChunksAvailable(chunks); } - if (ind == text.length() - 1) { - return encodeUnhandledSuffixLength(text, ind); - } - return text.charAt(ind + 1) == CSI.charAt(1) ? ind : -1; - } - - /** - * Returns end index of all consecutive escape sequences started at {@code firstEscSeqBeginInd}, or - * a negative number if not found. Since an escape sequence could be split among several subsequent output chunks - * (e.g. because of automatic flushing of standard stream when its buffer is full), it should be parsed - * when all the needed output chunks are available. To achieve that, the return value encodes - * the length of the passed string suffix to keep in case of an incomplete last escape sequence: - * {@code -1 - (length of string suffix to keep in case of an incomplete last escape sequence)}.

- * If the return value is -1, no string suffix should be kept => a malformed escape sequence has been encountered. - * If the return value is less than -1, no actual handing of the incomplete escape sequence should be performed, - * the string suffix length should be decoded with {@code #decodeUnhandledSuffixLength(the return value)} and the suffix - * should be preserved until the next output chunk is available. - */ - private static int findConsecutiveEscSequencesEndIndex(@NotNull String text, int firstEscSeqBeginInd) { - int escSeqBeginInd = firstEscSeqBeginInd; - int lastMatchedColorEscSeqEndInd = -1; - int escSeqEndInd; - while ((escSeqEndInd = findEscSeqEndIndex(text, escSeqBeginInd)) >= 0) { - if (text.charAt(escSeqEndInd) != 'm') { - // Handle non-color escape sequences separately - // ColoredOutputTypeRegistry expects only color escape sequences and in a single consecutive text chunk - return lastMatchedColorEscSeqEndInd > 0 ? lastMatchedColorEscSeqEndInd : escSeqEndInd; - } - escSeqBeginInd = escSeqEndInd + 1; - lastMatchedColorEscSeqEndInd = escSeqEndInd; - if (escSeqEndInd + 1 >= text.length()) { - return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd); - } - if (text.charAt(escSeqEndInd + 1) != CSI.charAt(0)) { - break; - } - if (escSeqEndInd + 2 >= text.length()) { - return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd); - } - if (text.charAt(escSeqEndInd + 2) != CSI.charAt(1)) { - break; - } - } - if (escSeqEndInd < -1) { - return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd); - } - return lastMatchedColorEscSeqEndInd; - } - - /** - * @implSpec {@code The ESC [ is followed by any number (including none) of "parameter bytes" in the - * range 0x30-0x3F (ASCII 0-9:;<=>?), then by any number of "intermediate bytes" in the range 0x20-0x2F (ASCII space and - * !"#$%&'()*+,-./), then finally by a single "final byte" in the range 0x40-0x7E (ASCII @A-Z[\]^_`a-z{|}~).} - * @implNote Also, there are different sequences, aside CSI - */ - private static int findEscSeqEndIndex(@NotNull String text, int escSeqBeginInd) { - int parameterEndInd = escSeqBeginInd + CSI.length(); - while (parameterEndInd < text.length()) { - char ch = text.charAt(parameterEndInd); - if (0x30 <= ch && ch <= 0x3F) { - parameterEndInd++; - } - else { - break; - } - } - while (parameterEndInd < text.length()) { - char ch = text.charAt(parameterEndInd); - if (0x20 <= ch && ch <= 0x2F) { - parameterEndInd++; - } - else { - break; - } - } - if (parameterEndInd == text.length()) { - return encodeUnhandledSuffixLength(text, escSeqBeginInd); - } - char lastChar = text.charAt(parameterEndInd); - return 0x40 <= lastChar && lastChar <= 0x7E ? parameterEndInd : -1; - } - - private static int encodeUnhandledSuffixLength(@NotNull String text, int suffixStartInd) { - return -1 - (text.length() - suffixStartInd); - } - - private static int decodeUnhandledSuffixLength(int encodedUnhandledSuffixLength) { - if (encodedUnhandledSuffixLength >= -1) { - throw new AssertionError(); - } - return -encodedUnhandledSuffixLength - 1; } @Nullable @@ -252,10 +118,10 @@ public class AnsiEscapeDecoder { @NotNull protected Key getCurrentOutputAttributes(@NotNull Key outputType) { if (ProcessOutputType.isStdout(outputType)) { - return ObjectUtils.notNull(myCurrentStdoutOutputType, outputType); + return myStdoutEmulator.isInitialState() ? outputType : myColoredOutputTypeRegistry.getOutputType(myStdoutEmulator, outputType); } if (ProcessOutputType.isStderr(outputType)) { - return ObjectUtils.notNull(myCurrentStderrOutputType, outputType); + return myStderrEmulator.isInitialState() ? outputType : myColoredOutputTypeRegistry.getOutputType(myStderrEmulator, outputType); } return outputType; } diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java b/platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java new file mode 100644 index 000000000000..b78f435e6920 --- /dev/null +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java @@ -0,0 +1,162 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.process; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class AnsiStreamingLexer { + // element types + static final AnsiElementType TEXT = new AnsiElementType("TEXT"); + static final AnsiElementType SGR = new AnsiElementType("SGR"); + static final AnsiElementType CONTROL = new AnsiElementType("CONTROL"); + + static final char ESCAPE = '\u001b'; + static final String CSI = ESCAPE + "["; + static final char SGR_SUFFIX = 'm'; + + // current text buffer + private String myBuffer = ""; + + // current token start offset + private int myStartOffset = 0; + + // current token end offset + private int myEndOffset = 0; + + private AnsiElementType myElementType = null; + + /** + * Appending a {@code text} to the stream + */ + void append(@NotNull String text) { + myBuffer = myEndOffset < myBuffer.length() ? myBuffer.substring(myEndOffset) + text : text; + myStartOffset = 0; + myEndOffset = 0; + } + + /** + * @return element type of current token. null means we are not started or at the end of stream + */ + @Nullable + AnsiElementType getElementType() { + return myElementType; + } + + /** + * @return text of current token of null if we've not started or at the end of stream + */ + @Nullable + String getElementText() { + return myElementType == null ? null : myBuffer.substring(myStartOffset, myEndOffset); + } + + /** + * @return for {@link #SGR} elements return only content part of the text, between {@code CSI} and {@code m}. For the rest works + * the same way as {@link #getElementText()} + */ + @Nullable + String getElementTextSmart() { + if (myElementType == SGR) { + return myBuffer.substring(myStartOffset + CSI.length(), myEndOffset - 1); + } + return getElementText(); + } + + /** + * advances lexer to the next token if possible + */ + void advance() { + if (myEndOffset == myBuffer.length()) { + // EOF + myElementType = null; + return; + } + myStartOffset = myEndOffset; + if (myBuffer.charAt(myEndOffset) != ESCAPE) { + // just a text + advanceToEscape(); + return; + } + if (myEndOffset + 1 == myBuffer.length()) { + incompleteSequence(); + return; + } + + myEndOffset++; + if (myBuffer.charAt(myEndOffset) == '[') { + myEndOffset++; + processCSISequence(); + return; + } + // There can by anything from 0x40–0x5F https://en.wikipedia.org/wiki/ANSI_escape_code#Escape_sequences + // but we are ignoring this for now + advanceToEscape(); + } + + /** + * Advancing after CSI sequence, see https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences + * + * @implSpec {@code The ESC [ is followed by any number (including none) of "parameter bytes" in the + * range 0x30–0x3F (ASCII 0–9:;<=>?), then by any number of "intermediate bytes" in the range 0x20–0x2F (ASCII space and + * !"#$%&'()*+,-./), then finally by a single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).} + */ + private void processCSISequence() { + while (myEndOffset < myBuffer.length() && isInRange(myBuffer.charAt(myEndOffset), (char)0x30, (char)0x3F)) { + myEndOffset++; + } + while (myEndOffset < myBuffer.length() && isInRange(myBuffer.charAt(myEndOffset), (char)0x20, (char)0x2F)) { + myEndOffset++; + } + if (myEndOffset == myBuffer.length()) { + incompleteSequence(); + return; + } + + char lastChar = myBuffer.charAt(myEndOffset); + myEndOffset++; + if (lastChar == SGR_SUFFIX) { + myElementType = SGR; + } + else if (0x40 <= lastChar && lastChar <= 0x7E) { + myElementType = CONTROL; + } + else { + // broken seqeuence, considering as a text + advanceToEscape(); + } + } + + private void advanceToEscape() { + int escapeIndex = myBuffer.indexOf(ESCAPE, myEndOffset); + myEndOffset = escapeIndex != -1 ? escapeIndex : myBuffer.length(); + myElementType = TEXT; + } + + private void incompleteSequence() { + myElementType = null; + myEndOffset = myStartOffset; + } + + /** + * @return true iff {@code character} is inside chars range inclusive + */ + private static boolean isInRange(char character, char startRange, char endRange) { + return startRange <= character && character <= endRange; + } + + /** + * representing element type for ANSI stream. Not using ElementType to avoid wasting tokens + */ + static final class AnsiElementType { + private final String myName; + + private AnsiElementType(String name) { + myName = name; + } + + @Override + public String toString() { + return "ANSI: " + myName; + } + } +} diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java new file mode 100644 index 000000000000..5ede1f42465f --- /dev/null +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java @@ -0,0 +1,31 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.process; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +/** + * Interface to work with ANSI-defined terminal colors + */ +interface AnsiTerminalColor { + /** + * @return command part for serializing this color. + * @implSpec this method MUST NOT return an escape sequence. Only the part that should be wrapped to {@link #SGR_COMMAND_FG_COLOR_ENCODED} or + * {@link #SGR_COMMAND_BG_COLOR_ENCODED}. E.g. {@code 2;255;255;255 } + */ + @NotNull + String getAnsiEncodedColor(); + + /** + * @return a {@link java.awt.Color color} representing this one or null if this is a pre-set configurable color 0-15 + */ + @Nullable + Color getColor(); + + /** + * @return a color index for this terminal color if available. Returns {@code -1} for pure RGB encoded color + */ + int getColorIndex(); +} diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java new file mode 100644 index 000000000000..fd1fc7c77b5c --- /dev/null +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java @@ -0,0 +1,702 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.process; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.markup.EffectType; +import com.intellij.openapi.util.ClearableLazyValue; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.function.IntConsumer; + +import static com.intellij.execution.process.AnsiCommands.*; +import static com.intellij.execution.process.AnsiStreamingLexer.SGR_SUFFIX; +import static com.intellij.execution.process.AnsiTerminalEmulator.BlinkSpeed.RAPID_BLINK; +import static com.intellij.execution.process.AnsiTerminalEmulator.BlinkSpeed.SLOW_BLINK; +import static com.intellij.execution.process.AnsiTerminalEmulator.Boldness.BOLD; +import static com.intellij.execution.process.AnsiTerminalEmulator.Boldness.FAINT; +import static com.intellij.execution.process.AnsiTerminalEmulator.FrameType.*; +import static com.intellij.execution.process.AnsiTerminalEmulator.Underline.DOUBLE_UNDERLINE; +import static com.intellij.execution.process.AnsiTerminalEmulator.Underline.SINGLE_UNDERLINE; +import static com.intellij.openapi.editor.markup.EffectType.BOLD_LINE_UNDERSCORE; +import static com.intellij.openapi.editor.markup.EffectType.LINE_UNDERSCORE; + +/** + * Emulates the ANSI terminal state + */ +class AnsiTerminalEmulator { + private static final Logger LOG = Logger.getInstance(AnsiTerminalEmulator.class); + + private static final AnsiTerminalEmulator EMPTY_EMULATOR = new AnsiTerminalEmulator(); + private static final int MAX_8BIT_COLOR_INDEX = 15; + private static final int COLOR_CUBE_MIN_INDEX = MAX_8BIT_COLOR_INDEX + 1; + private static final int GRAY_MIN_INDEX = 232; + + @NotNull + private Font myFont = Font.DEFAULT; + @NotNull + private Boldness myBoldness = Boldness.DEFAULT; + @NotNull + private Underline myUnderline = Underline.DEFAULT; + @NotNull + private BlinkSpeed myBlink = BlinkSpeed.DEFAULT; + @NotNull + private FrameType myFrameType = FrameType.DEFAULT; + + private boolean myIsItalic; + private boolean myIsInverse; + private boolean myIsConseal; + private boolean myIsCrossedOut; + private boolean myIsFraktur; + private boolean myIsOverlined; + + private AnsiTerminalColor myBackgroundColor; + private AnsiTerminalColor myForegroundColor; + + private final ClearableLazyValue mySerializedSgrStateProvider = ClearableLazyValue.create( + () -> computeAnsiSerializedSGRState()); + + /** + * Consumes SGR - Select Graphic Rendition control sequence and changes emulator's state accordingly + */ + public void processSgr(@NotNull String sgrSequenceBody) { + /* + The ITU's T.416 Information technology - Open Document Architecture (ODA) and interchange format: + https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.416-199303-I!!PDF-E&type=items + uses ':' as separator characters instead * + */ + List sgrSequenceParts = StringUtil.split(sgrSequenceBody, StringUtil.containsChar(sgrSequenceBody, ':') ? ":" : ";"); + Iterator sgrCodesIterator = ContainerUtil.map(sgrSequenceParts, it -> { + try { + return it.isEmpty() ? 0 : Integer.parseInt(it); + } + catch (NumberFormatException e) { + LOG.warn("Could not parse integer: " + it + " in " + sgrSequenceBody); + return null; + } + }).iterator(); + + while (sgrCodesIterator.hasNext()) { + Integer command = sgrCodesIterator.next(); + if (command == null) { + break; + } + processSgr(command, sgrCodesIterator); + } + } + + /** + * Changes terminal state according to {@code commandCode} + * @param sgrCodesIterator iterator of subsequent codes if any. May be necessary for multi-param sgr sequences, like setting color + */ + private void processSgr(int commandCode, Iterator sgrCodesIterator) { + switch (commandCode) { + case SGR_COMMAND_RESET: + resetTerminal(); + break; + case SGR_COMMAND_BOLD: + myBoldness = BOLD; + break; + case SGR_COMMAND_FAINT: + myBoldness = FAINT; + break; + case SGR_COMMAND_ITALIC: + myIsItalic = true; + break; + case SGR_COMMAND_UNDERLINE: + myUnderline = SINGLE_UNDERLINE; + break; + case SGR_COMMAND_BLINK_SLOW: + myBlink = SLOW_BLINK; + break; + case SGR_COMMAND_BLINK_RAPID: + myBlink = RAPID_BLINK; + break; + case SGR_COMMAND_INVERSE: + myIsInverse = true; + break; + case SGR_COMMAND_CONCEAL: + myIsConseal = true; + break; + case SGR_COMMAND_CROSS_OUT: + myIsCrossedOut = true; + break; + case SGR_COMMAND_PRIMARY_FONT: + myFont = Font.DEFAULT; + break; + case SGR_COMMAND_FRAKTUR: + myIsFraktur = true; + break; + case SGR_COMMAND_DOUBLE_UNDERLINE: + myBoldness = Boldness.DEFAULT; + // this is ECMA-48 behaviour. Probably we could make this configurable via flag? + myUnderline = DOUBLE_UNDERLINE; + break; + case SGR_COMMAND_NO_BOLD_FAINT: + myBoldness = Boldness.DEFAULT; + break; + case SGR_COMMAND_NO_ITALIC_FRAKTUR: + myIsFraktur = false; + myIsItalic = false; + break; + case SGR_COMMAND_NO_UNDERLINE: + myUnderline = Underline.DEFAULT; + break; + case SGR_COMMAND_NO_BLINK: + myBlink = BlinkSpeed.DEFAULT; + break; + case SGR_COMMAND_NO_INVERSE: + myIsInverse = false; + break; + case SGR_COMMAND_REVEAL: + myIsConseal = false; + break; + case SGR_COMMAND_NO_CROSS_OUT: + myIsCrossedOut = false; + break; + case SGR_COMMAND_FG_COLOR_ENCODED: + myForegroundColor = decodeColor(sgrCodesIterator); + break; + case SGR_COMMAND_FG_COLOR_DEFAULT: + myForegroundColor = null; + break; + case SGR_COMMAND_BG_COLOR_ENCODED: + myBackgroundColor = decodeColor(sgrCodesIterator); + break; + case SGR_COMMAND_BG_COLOR_DEFAULT: + myBackgroundColor = null; + break; + case SGR_COMMAND_FRAMED: + myFrameType = FRAMED; + break; + case SGR_COMMAND_ENCIRCLED: + myFrameType = ENCIRCLED; + break; + case SGR_COMMAND_OVERLINED: + myIsOverlined = true; + break; + case SGR_COMMAND_NO_FRAMED_ENCIRCLED: + myFrameType = NO_FRAME; + break; + case SGR_COMMAND_NO_OVERLINED: + myIsOverlined = false; + break; + default: + if (commandCode >= SGR_COMMAND_FONT1 && commandCode <= SGR_COMMAND_FONT9) { + myFont = Font.values()[commandCode - 10]; + } + else if (commandCode >= SGR_COMMAND_FG_COLOR0 && commandCode <= SGR_COMMAND_FG_COLOR7) { + myForegroundColor = new EightBitColor(commandCode - SGR_COMMAND_FG_COLOR0); + } + else if (commandCode >= SGR_COMMAND_BG_COLOR0 && commandCode <= SGR_COMMAND_BG_COLOR7) { + myBackgroundColor = new EightBitColor(commandCode - SGR_COMMAND_BG_COLOR0); + } + else if (commandCode >= SGR_COMMAND_IDEOGRAM_UNDER_RIGHT && commandCode <= SGR_COMMAND_IDEOGRAM_OFF) { + LOG.debug("Ignore no-op ideogram sequence: " + commandCode); + } + else if (commandCode >= SGR_COMMAND_FG_COLOR8 && commandCode <= SGR_COMMAND_FG_COLOR15) { + myForegroundColor = new EightBitColor(commandCode - SGR_COMMAND_FG_COLOR8 + 8); + } + else if (commandCode >= SGR_COMMAND_BG_COLOR8 && commandCode <= SGR_COMMAND_BG_COLOR15) { + myBackgroundColor = new EightBitColor(commandCode - SGR_COMMAND_BG_COLOR8 + 8); + } + else { + LOG.warn("Unknown command " + commandCode); + return; + } + } + mySerializedSgrStateProvider.drop(); + } + + /** + * @return an ANSI string representing the SGR state of the current emulator. Same state is always represented with the same string. + */ + @NotNull + public String getAnsiSerializedSGRState() { + return Objects.requireNonNull(mySerializedSgrStateProvider.getValue()); + } + + /** + * @return an ANSI string representing the SGR state of the current emulator. Same state is always represented with the same string. + */ + @NotNull + public String computeAnsiSerializedSGRState() { + List state = new ArrayList<>(); + IntConsumer codeConsumer = it -> state.add(Integer.toString(it)); + + codeConsumer.accept(SGR_COMMAND_RESET); + if (myFont != Font.DEFAULT) { + codeConsumer.accept(myFont.sgrCode); + } + if (myBoldness != Boldness.DEFAULT) { + codeConsumer.accept(myBoldness.sgrCode); + } + if (myUnderline != Underline.DEFAULT) { + codeConsumer.accept(myUnderline.sgrCode); + } + if (myFont != Font.DEFAULT) { + codeConsumer.accept(myFont.sgrCode); + } + if (myBlink != BlinkSpeed.DEFAULT) { + codeConsumer.accept(myBlink.sgrCode); + } + if (myIsInverse) { + codeConsumer.accept(SGR_COMMAND_INVERSE); + } + if (myBackgroundColor != null) { + codeConsumer.accept(SGR_COMMAND_BG_COLOR_ENCODED); + state.add(myBackgroundColor.getAnsiEncodedColor()); + } + if (myForegroundColor != null) { + codeConsumer.accept(SGR_COMMAND_FG_COLOR_ENCODED); + state.add(myForegroundColor.getAnsiEncodedColor()); + } + if (myIsItalic) { + codeConsumer.accept(SGR_COMMAND_ITALIC); + } + if (myIsConseal) { + codeConsumer.accept(SGR_COMMAND_CONCEAL); + } + if (myIsCrossedOut) { + codeConsumer.accept(SGR_COMMAND_CROSS_OUT); + } + if (myIsFraktur) { + codeConsumer.accept(SGR_COMMAND_FRAKTUR); + } + if (myFrameType != FrameType.DEFAULT) { + codeConsumer.accept(myFrameType.sgrCode); + } + if (myIsOverlined) { + codeConsumer.accept(SGR_COMMAND_OVERLINED); + } + return AnsiStreamingLexer.CSI + StringUtil.join(state, ";") + SGR_SUFFIX; + } + + /** + * Reset terminal values to defaults + */ + private void resetTerminal() { + myFont = EMPTY_EMULATOR.myFont; + myBoldness = EMPTY_EMULATOR.myBoldness; + myUnderline = EMPTY_EMULATOR.myUnderline; + myBackgroundColor = EMPTY_EMULATOR.myBackgroundColor; + myForegroundColor = EMPTY_EMULATOR.myForegroundColor; + myFrameType = EMPTY_EMULATOR.myFrameType; + myBlink = EMPTY_EMULATOR.myBlink; + myIsInverse = EMPTY_EMULATOR.myIsInverse; + myIsItalic = EMPTY_EMULATOR.myIsItalic; + myIsConseal = EMPTY_EMULATOR.myIsConseal; + myIsCrossedOut = EMPTY_EMULATOR.myIsCrossedOut; + myIsFraktur = EMPTY_EMULATOR.myIsFraktur; + myIsOverlined = EMPTY_EMULATOR.myIsOverlined; + mySerializedSgrStateProvider.drop(); + } + + /** + * @return true if emulator is in it's initial state + * @see #resetTerminal() + */ + public boolean isInitialState() { + return EMPTY_EMULATOR.equals(this); + } + + @Nullable + public Color getBackgroundColor() { + return myBackgroundColor == null ? null : myBackgroundColor.getColor(); + } + + public int getBackgroundColorIndex() { + return myBackgroundColor == null ? -1 : myBackgroundColor.getColorIndex(); + } + + @Nullable + public Color getForegroundColor() { + return myForegroundColor == null ? null : myForegroundColor.getColor(); + } + + public int getForegroundColorIndex() { + return myForegroundColor == null ? -1 : myForegroundColor.getColorIndex(); + } + + public boolean isInverse() { + return myIsInverse; + } + + @NotNull + public Underline getUnderline() { + return myUnderline; + } + + @NotNull + public FrameType getFrameType() { + return myFrameType; + } + + public boolean isCrossedOut() { + return myIsCrossedOut; + } + + @NotNull + public Boldness getBoldness() { + return myBoldness; + } + + public boolean isItalic() { + return myIsItalic; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AnsiTerminalEmulator emulator = (AnsiTerminalEmulator)o; + + if (myIsItalic != emulator.myIsItalic) return false; + if (myIsInverse != emulator.myIsInverse) return false; + if (myIsConseal != emulator.myIsConseal) return false; + if (myIsCrossedOut != emulator.myIsCrossedOut) return false; + if (myIsFraktur != emulator.myIsFraktur) return false; + if (myIsOverlined != emulator.myIsOverlined) return false; + if (myFont != emulator.myFont) return false; + if (myBoldness != emulator.myBoldness) return false; + if (myUnderline != emulator.myUnderline) return false; + if (myBlink != emulator.myBlink) return false; + if (myFrameType != emulator.myFrameType) return false; + if (!Objects.equals(myBackgroundColor, emulator.myBackgroundColor)) { + return false; + } + if (!Objects.equals(myForegroundColor, emulator.myForegroundColor)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = myFont.hashCode(); + result = 31 * result + myBoldness.hashCode(); + result = 31 * result + myUnderline.hashCode(); + result = 31 * result + myBlink.hashCode(); + result = 31 * result + myFrameType.hashCode(); + result = 31 * result + (myIsItalic ? 1 : 0); + result = 31 * result + (myIsInverse ? 1 : 0); + result = 31 * result + (myIsConseal ? 1 : 0); + result = 31 * result + (myIsCrossedOut ? 1 : 0); + result = 31 * result + (myIsFraktur ? 1 : 0); + result = 31 * result + (myIsOverlined ? 1 : 0); + result = 31 * result + (myBackgroundColor != null ? myBackgroundColor.hashCode() : 0); + result = 31 * result + (myForegroundColor != null ? myForegroundColor.hashCode() : 0); + return result; + } + + /** + * Decodes ANSI SGR sequences 38 && 48. Encodings may be: + *
    + *
  • 5;n - with index-based encoding
  • + *
  • 2;r;g;b - with red, green and blue parts
  • + *
+ */ + private static AnsiTerminalColor decodeColor(@NotNull Iterator encodedColorIterator) { + if (!encodedColorIterator.hasNext()) { + return null; + } + int encodingType = encodedColorIterator.next(); + if (encodingType == SGR_COLOR_ENCODING_RGB) { + Integer redCode = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null; + Integer greenCode = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null; + Integer blueCode = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null; + if (redCode != null && greenCode != null && blueCode != null) { + return new RGBColor(redCode, greenCode, blueCode); + } + } + else if (encodingType == SGR_COLOR_ENCODING_INDEXED) { + Integer encodedColor = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null; + if (encodedColor != null) { + return decode8BitColor(encodedColor); + } + } + + return null; + } + + /** + * Decodes index-encoded color from SGR + * + * @see 5;n - with index-based encoding + */ + private static AnsiTerminalColor decode8BitColor(int encodedColor) { + if (encodedColor >= 0 && encodedColor <= MAX_8BIT_COLOR_INDEX) { + return new EightBitColor(encodedColor); + } + else if (encodedColor >= COLOR_CUBE_MIN_INDEX && encodedColor <= 255) { + //16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) + //232-255: grayscale from black to white in 24 steps + return new EightBitRGBColor(encodedColor); + } + return null; + } + + public enum FrameType { + NO_FRAME(SGR_COMMAND_NO_FRAMED_ENCIRCLED, null), + FRAMED(SGR_COMMAND_FRAMED, EffectType.BOXED), + ENCIRCLED(SGR_COMMAND_ENCIRCLED, EffectType.ROUNDED_BOX); + + private static final FrameType DEFAULT = NO_FRAME; + /** + * SGR sequence code that should be used to switch to this option + */ + public final int sgrCode; + + @Nullable + public final EffectType effectType; + + FrameType(int sgrCode, @Nullable EffectType effectType) { + this.sgrCode = sgrCode; + this.effectType = effectType; + } + } + + public enum BlinkSpeed { + NO_BLINK(SGR_COMMAND_NO_BLINK), + SLOW_BLINK(SGR_COMMAND_BLINK_SLOW), + RAPID_BLINK(SGR_COMMAND_BLINK_RAPID); + + private static final BlinkSpeed DEFAULT = NO_BLINK; + /** + * SGR sequence code that should be used to switch to this option + */ + public final int sgrCode; + + BlinkSpeed(int sgrCode) { + this.sgrCode = sgrCode; + } + } + + public enum Boldness { + FAINT(SGR_COMMAND_FAINT), + NORMAL(SGR_COMMAND_NO_BOLD_FAINT), + BOLD(SGR_COMMAND_BOLD); + + private static final Boldness DEFAULT = NORMAL; + /** + * SGR sequence code that should be used to switch to this option + */ + public final int sgrCode; + + Boldness(int sgrCode) { + this.sgrCode = sgrCode; + } + } + + public enum Underline { + NO_UNDERLINE(SGR_COMMAND_NO_UNDERLINE, null), + SINGLE_UNDERLINE(SGR_COMMAND_UNDERLINE, LINE_UNDERSCORE), + DOUBLE_UNDERLINE(SGR_COMMAND_DOUBLE_UNDERLINE, BOLD_LINE_UNDERSCORE); + + private static final Underline DEFAULT = NO_UNDERLINE; + /** + * SGR sequence code that should be used to switch to this option + */ + public final int sgrCode; + + @Nullable + public final EffectType effectType; + + Underline(int sgrCode, @Nullable EffectType effectType) { + this.sgrCode = sgrCode; + this.effectType = effectType; + } + } + + public enum Font { + DEFAULT(SGR_COMMAND_PRIMARY_FONT), + ALT1(SGR_COMMAND_FONT1), + ALT2(SGR_COMMAND_FONT2), + ALT3(SGR_COMMAND_FONT3), + ALT4(SGR_COMMAND_FONT4), + ALT5(SGR_COMMAND_FONT5), + ALT6(SGR_COMMAND_FONT6), + ALT7(SGR_COMMAND_FONT7), + ALT8(SGR_COMMAND_FONT8), + ALT9(SGR_COMMAND_FONT9); + /** + * SGR sequence code that should be used to switch to this option + */ + public final int sgrCode; + + Font(int sgrCode) { + this.sgrCode = sgrCode; + } + } + + /** + * Represents a 24 bit color, encoded with {@link AnsiCommands#SGR_COLOR_ENCODING_RGB} + */ + private static final class RGBColor implements AnsiTerminalColor { + private final int myRed; + private final int myGreen; + private final int myBlue; + + private RGBColor(int red, int green, int blue) { + myRed = red; + myGreen = green; + myBlue = blue; + } + + @NotNull + @Override + public String getAnsiEncodedColor() { + return SGR_COLOR_ENCODING_RGB + ";" + myRed + ";" + myGreen + ";" + myBlue; + } + + + @Override + public int getColorIndex() { + return -1; + } + + @NotNull + @Override + public Color getColor() { + //noinspection UseJBColor + return new Color(myRed, myGreen, myBlue); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RGBColor color = (RGBColor)o; + + if (myRed != color.myRed) return false; + if (myGreen != color.myGreen) return false; + if (myBlue != color.myBlue) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myRed; + result = 31 * result + myGreen; + result = 31 * result + myBlue; + return result; + } + } + + /** + * Base class for index-based colors - 8bit and 8bit rgb colors + */ + private abstract static class IndexedAnsiTerminalColor implements AnsiTerminalColor { + private final int myColorIndex; + + protected IndexedAnsiTerminalColor(int colorIndex) { + myColorIndex = colorIndex; + } + + @Override + public int getColorIndex() { + return myColorIndex; + } + + @NotNull + @Override + public String getAnsiEncodedColor() { + return SGR_COLOR_ENCODING_INDEXED + ";" + getColorIndex(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + IndexedAnsiTerminalColor color = (IndexedAnsiTerminalColor)o; + + if (myColorIndex != color.myColorIndex) return false; + + return true; + } + + @Override + public int hashCode() { + return myColorIndex; + } + } + + /** + * Represents a simple indexed color for SGR commands: + *
    + *
  • {@link AnsiCommands#SGR_COMMAND_FG_COLOR0} - {@link AnsiCommands#SGR_COMMAND_FG_COLOR7}
  • + *
  • {@link AnsiCommands#SGR_COMMAND_BG_COLOR0} - {@link AnsiCommands#SGR_COMMAND_BG_COLOR7}
  • + *
  • {@link AnsiCommands#SGR_COMMAND_FG_COLOR8} - {@link AnsiCommands#SGR_COMMAND_FG_COLOR15}
  • + *
  • {@link AnsiCommands#SGR_COMMAND_BG_COLOR8} - {@link AnsiCommands#SGR_COMMAND_BG_COLOR15}
  • + *
+ * Also used for first 15 indexed colors from {@link AnsiCommands#SGR_COMMAND_FG_COLOR_ENCODED} and {@link AnsiCommands#SGR_COMMAND_BG_COLOR_ENCODED} + */ + private static class EightBitColor extends IndexedAnsiTerminalColor { + + private EightBitColor(int colorIndex) { + super(colorIndex); + if (colorIndex < 0 || colorIndex > MAX_8BIT_COLOR_INDEX) { + LOG.error("Wrong 8bit color index: " + colorIndex); + } + } + + @Nullable + @Override + public Color getColor() { + return null; + } + } + + /** + * Represents rgb colors encoded with {@link AnsiCommands#SGR_COLOR_ENCODING_INDEXED} from 16-231 and 232-255 + */ + private static final class EightBitRGBColor extends IndexedAnsiTerminalColor { + + // 8-bit color encoding for range 16-231 + private static final int[] CUBE_STEPS = { + 0x0, 0x5f, 0x87, 0xaf, 0xd7, 0xff + }; + // 8-bit grayscale encoding for range 232-255 + private static final int[] GRAYSCALE_STEPS = { + 0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e, + 0x58, 0x62, 0x6c, 0x76, 0x80, 0x8a, 0x94, 0x9e, + 0xa8, 0xb2, 0xbc, 0xc6, 0xd0, 0xda, 0xe4, 0xee + }; + + private EightBitRGBColor(int colorIndex) { + super(colorIndex); + if (colorIndex < COLOR_CUBE_MIN_INDEX || colorIndex > 255) { + LOG.error("Wrong indexed RGB color index: " + colorIndex); + } + } + + @Nullable + @Override + public Color getColor() { + int colorIndex = getColorIndex(); + if (colorIndex >= COLOR_CUBE_MIN_INDEX && colorIndex < GRAY_MIN_INDEX) { + int encodedColor = colorIndex - COLOR_CUBE_MIN_INDEX; + //noinspection UseJBColor + return new Color(CUBE_STEPS[(encodedColor / 36) % 6], CUBE_STEPS[(encodedColor / 6) % 6], CUBE_STEPS[encodedColor % 6]); + } + else if (colorIndex >= GRAY_MIN_INDEX && colorIndex <= 255) { + int colorPart = GRAYSCALE_STEPS[colorIndex - GRAY_MIN_INDEX]; + //noinspection UseJBColor + return new Color(colorPart, colorPart, colorPart); + } + return null; + } + } +} diff --git a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java index 68e39cc501ca..7669e9af0500 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java +++ b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java @@ -30,6 +30,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Map; /** @@ -113,12 +116,33 @@ public class ColoredOutputTypeRegistry { return streamOutputType; } ProcessOutputType newKey = new ProcessOutputType(completeAttribute, streamOutputType); - AnsiConsoleViewContentType contentType = createAnsiConsoleViewContentType(attribute); - ConsoleViewContentType.registerNewConsoleViewType(newKey, contentType); + ConsoleViewContentType.registerNewConsoleViewType(newKey, createAnsiConsoleViewContentType(attribute)); attrsToKeyMap.put(completeAttribute, newKey); return newKey; } + /** + * Creates an {@link ProcessOutputType} from the {@link AnsiTerminalEmulator terminal emulator state} and stream type. Output type may be used + * later to print to the console + */ + @NotNull + public ProcessOutputType getOutputType(@NotNull AnsiTerminalEmulator terminal, @NotNull Key streamType) { + Map attrsToKeyMap = ProcessOutputType.isStdout(streamType) ? myStdoutAttrsToKeyMap : myStderrAttrsToKeyMap; + String ansiSerializedState = terminal.getAnsiSerializedSGRState(); + ProcessOutputType key = attrsToKeyMap.get(ansiSerializedState); + if (key != null) { + return key; + } + + ProcessOutputType streamOutputType = streamType instanceof ProcessOutputType ? + (ProcessOutputType)streamType : (ProcessOutputType)ProcessOutputTypes.STDOUT; + + ProcessOutputType newKey = new ProcessOutputType(ansiSerializedState, streamOutputType); + ConsoleViewContentType.registerNewConsoleViewType(newKey, new AnsiConsoleViewContentType(terminal)); + attrsToKeyMap.put(ansiSerializedState, newKey); + return newKey; + } + /** * @deprecated use {@link #getOutputType(String, Key)} instead */ @@ -165,7 +189,7 @@ public class ColoredOutputTypeRegistry { } @NotNull - private static AnsiConsoleViewContentType createAnsiConsoleViewContentType(@NotNull String attribute) { + private static ConsoleViewContentType createAnsiConsoleViewContentType(@NotNull String attribute) { int foregroundColor = -1; int backgroundColor = -1; boolean inverse = false; @@ -224,30 +248,100 @@ public class ColoredOutputTypeRegistry { } private static class AnsiConsoleViewContentType extends ConsoleViewContentType { - private final int myBackgroundColor; - private final int myForegroundColor; + private final int myBackgroundColorIndex; + private final int myForegroundColorIndex; + @Nullable + private final Color myEnforcedBackgroundColor; + @Nullable + private final Color myEnforcedForegroundColor; private final boolean myInverse; - private final EffectType myEffectType; + @NotNull + private final List myEffectTypes; private final int myFontType; + private AnsiConsoleViewContentType(@NotNull String attribute, + int backgroundColorIndex, + int foregroundColorIndex, + @Nullable Color enforcedBackgroundColor, + @Nullable Color enforcedForegroundColor, + boolean inverse, + @NotNull List effectTypes, + int fontType) { + super(attribute, ConsoleViewContentType.NORMAL_OUTPUT_KEY); + myBackgroundColorIndex = backgroundColorIndex; + myEnforcedBackgroundColor = enforcedBackgroundColor; + myForegroundColorIndex = foregroundColorIndex; + myEnforcedForegroundColor = enforcedForegroundColor; + myInverse = inverse; + myEffectTypes = effectTypes.isEmpty() ? ContainerUtil.emptyList() : ContainerUtil.immutableList(effectTypes); + myFontType = fontType; + } + private AnsiConsoleViewContentType(@NotNull String attribute, int backgroundColor, int foregroundColor, boolean inverse, @Nullable EffectType effectType, int fontType) { - super(attribute, ConsoleViewContentType.NORMAL_OUTPUT_KEY); - myBackgroundColor = backgroundColor; - myForegroundColor = foregroundColor; - myInverse = inverse; - myEffectType = effectType; - myFontType = fontType; + this(attribute, backgroundColor, foregroundColor, null, null, inverse, + effectType == null ? Collections.emptyList() : Collections.singletonList(effectType), fontType); + } + + private AnsiConsoleViewContentType(@NotNull AnsiTerminalEmulator terminalEmulator) { + this(terminalEmulator.getAnsiSerializedSGRState(), + terminalEmulator.getBackgroundColorIndex(), + terminalEmulator.getForegroundColorIndex(), + terminalEmulator.getBackgroundColor(), + terminalEmulator.getForegroundColor(), + terminalEmulator.isInverse(), + computeEffectTypes(terminalEmulator), + computeAwtFont(terminalEmulator)); + } + + /** + * Computes effect types that can be represented by our editor + */ + @NotNull + private static List computeEffectTypes(@NotNull AnsiTerminalEmulator terminalEmulator) { + ArrayList result = ContainerUtil.newArrayList(); + AnsiTerminalEmulator.Underline underline = terminalEmulator.getUnderline(); + if (underline == AnsiTerminalEmulator.Underline.SINGLE_UNDERLINE) { + result.add(EffectType.LINE_UNDERSCORE); + } + else if (underline == AnsiTerminalEmulator.Underline.DOUBLE_UNDERLINE) { + result.add(EffectType.BOLD_LINE_UNDERSCORE); + } + if (terminalEmulator.isCrossedOut()) { + result.add(EffectType.STRIKEOUT); + } + AnsiTerminalEmulator.FrameType frameType = terminalEmulator.getFrameType(); + if (frameType == AnsiTerminalEmulator.FrameType.FRAMED) { + result.add(EffectType.BOXED); + } + else if (frameType == AnsiTerminalEmulator.FrameType.ENCIRCLED) { + result.add(EffectType.ROUNDED_BOX); + } + return result; + } + + /** + * Computes font style from boldness/italic flags + */ + private static int computeAwtFont(@NotNull AnsiTerminalEmulator terminalEmulator) { + int result = 0; + if (terminalEmulator.getBoldness() == AnsiTerminalEmulator.Boldness.BOLD) { + result = Font.BOLD; + } + if (terminalEmulator.isItalic()) { + result |= Font.ITALIC; + } + return result; } @Override public TextAttributes getAttributes() { TextAttributes attrs = new TextAttributes(); - attrs.setEffectType(myEffectType); + attrs.setEffectType(null); // re-setting default BOX if (myFontType != -1) { attrs.setFontType(myFontType); } @@ -257,21 +351,25 @@ public class ColoredOutputTypeRegistry { attrs.setForegroundColor(backgroundColor); attrs.setEffectColor(backgroundColor); attrs.setBackgroundColor(foregroundColor); + myEffectTypes.forEach(it -> attrs.withAdditionalEffect(it, backgroundColor)); } else { attrs.setForegroundColor(foregroundColor); attrs.setEffectColor(foregroundColor); attrs.setBackgroundColor(backgroundColor); + myEffectTypes.forEach(it -> attrs.withAdditionalEffect(it, foregroundColor)); } return attrs; } private Color getForegroundColor() { - return myForegroundColor != -1 ? getAnsiColor(myForegroundColor) : getDefaultForegroundColor(); + return myEnforcedForegroundColor != null ? myEnforcedForegroundColor : + myForegroundColorIndex != -1 ? getAnsiColor(myForegroundColorIndex) : getDefaultForegroundColor(); } private Color getBackgroundColor() { - return myBackgroundColor != -1 ? getAnsiColor(myBackgroundColor) : getDefaultBackgroundColor(); + return myEnforcedBackgroundColor != null ? myEnforcedBackgroundColor : + myBackgroundColorIndex != -1 ? getAnsiColor(myBackgroundColorIndex) : getDefaultBackgroundColor(); } } } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 9d0b065093d6..cca1f4753de9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -676,10 +676,15 @@ public abstract class DialogWrapper { return myCheckBoxDoNotShowDialog != null && myCheckBoxDoNotShowDialog.isVisible() ? myCheckBoxDoNotShowDialog : null; } - private final JBValue BASE_BUTTON_GAP = new JBValue.Float(UIUtil.isUnderWin10LookAndFeel() ? 8 : 12); + private static final JBValue BASE_BUTTON_GAP = new JBValue.Float(UIUtil.isUnderWin10LookAndFeel() ? 8 : 12); @NotNull protected JPanel createButtonsPanel(@NotNull List buttons) { + return layoutButtonsPanel(buttons); + } + + @NotNull + public static JPanel layoutButtonsPanel(@NotNull List buttons) { JPanel buttonsPanel = new NonOpaquePanel(); buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS)); @@ -727,6 +732,26 @@ public abstract class DialogWrapper { * @see DialogWrapper#DEFAULT_ACTION */ protected JButton createJButtonForAction(Action action) { + JButton button = createJButtonForAction(action, getRootPane()); + + int mnemonic = button.getMnemonic(); + final Object name = action.getValue(Action.NAME); + if (mnemonic == KeyEvent.VK_Y && "Yes".equals(name)) { + myYesAction = action; + } + else if (mnemonic == KeyEvent.VK_N && "No".equals(name)) { + myNoAction = action; + } + + if (action.getValue(FOCUSED_ACTION) != null) { + myPreferredFocusedComponent = button; + } + + return button; + } + + @NotNull + public static JButton createJButtonForAction(@NotNull Action action, @Nullable JRootPane rootPane) { JButton button; if (action instanceof OptionAction && UISettings.getShadowInstance().getAllowMergeButtons()) { button = createJOptionsButton((OptionAction)action); @@ -749,24 +774,12 @@ public abstract class DialogWrapper { } button.setMnemonic(mnemonic); - final Object name = action.getValue(Action.NAME); - if (mnemonic == KeyEvent.VK_Y && "Yes".equals(name)) { - myYesAction = action; - } - else if (mnemonic == KeyEvent.VK_N && "No".equals(name)) { - myNoAction = action; - } - if (action.getValue(DEFAULT_ACTION) != null) { - if (!myPeer.isHeadless()) { - getRootPane().setDefaultButton(button); + if (rootPane != null) { + rootPane.setDefaultButton(button); } } - if (action.getValue(FOCUSED_ACTION) != null) { - myPreferredFocusedComponent = button; - } - return button; } diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index 51d5f0fbd057..735b7ba238c9 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -109,6 +109,13 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co return new MyIterator(); } + @NotNull + public ColoredIterator iterator(int fromIndex) { + MyIterator iterator = new MyIterator(); + iterator.myIndex = fromIndex - 1; + return iterator; + } + @SuppressWarnings("unused") public boolean isIconOnTheRight() { return myIconOnTheRight; @@ -859,7 +866,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co else if (attributes.isClickable()) { fgColor = ObjectUtils.notNull(attributes.getFgColor(), UIUtil.getLabelForeground()); Color bg = ObjectUtils.notNull(attributes.getBgColor(), UIUtil.getLabelBackground()); - drawClickableFrag(g, x1, x2, height, bg); + drawClickableFrag(g, x1, x2, height, bg, attributes.isHovered()); } else { continue; @@ -885,15 +892,17 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co g.fillRect(x, y, width, height); } - private static void drawClickableFrag(Graphics2D g, float x1, float x2, int height, Color bg) { + private static void drawClickableFrag(Graphics2D g, float x1, float x2, int height, Color bg, boolean hovered) { boolean darcula = UIUtil.isUnderDarcula(); Color c1 = darcula ? bg.brighter() : bg; Color c2 = darcula ? bg : bg.darker(); GraphicsConfig c = GraphicsUtil.setupRoundedBorderAntialiasing(g); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); - g.setPaint(UIUtil.getGradientPaint(x1 + 1, 2, c1, x1 + 1, height - 5, c2)); RoundRectangle2D.Float shape = new RoundRectangle2D.Float(x1 + 1, 2, x2 - x1 - 2, height - 4, 4, 4); - g.fill(shape); + if (hovered) { + g.setPaint(UIUtil.getGradientPaint(x1 + 1, 2, c1, x1 + 1, height - 5, c2)); + g.fill(shape); + } g.setColor(new JBColor(Gray.xCC, new Color(0x757b80))); g.draw(shape); c.restore(); diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java index 3d6b6132559d..7489aa63bc38 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java @@ -271,7 +271,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene if (myAssigneeVisible) { myAssigneeCombo = new ComboBox<>(); - myAssigneeCombo.setRenderer((list, value, i, selected, focused) -> new JBLabel(value == null ? "" : value.getDisplayText())); + myAssigneeCombo.setRenderer(SimpleListCellRenderer.create("", Developer::getDisplayText)); myAssigneeCombo.setPrototypeDisplayValue(new Developer(0, StringUtil.repeatSymbol('-', 30))); myAssigneeCombo.addItemListener(e -> { if (e.getStateChange() == ItemEvent.SELECTED) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 922854cb8833..ee3978a6f8fc 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -84,6 +84,7 @@ import static javax.swing.KeyStroke.getKeyStroke; public class Switcher extends AnAction implements DumbAware { private static final Key SWITCHER_KEY = Key.create("SWITCHER_KEY"); private static final Color SEPARATOR_COLOR = JBColor.namedColor("Popup.separatorColor", new JBColor(Gray.xC0, Gray.x4B)); + private static final String TOGGLE_CHECK_BOX_ACTION_ID = "SwitcherToggleCheckBox"; private static final int MINIMUM_HEIGHT = JBUI.scale(100); @@ -143,17 +144,17 @@ public class Switcher extends AnAction implements DumbAware { SwitcherPanel switcher = SWITCHER_KEY.get(project); if (switcher != null) { boolean sameShortcut = Comparing.equal(switcher.myTitle, title); - if (switcher.isCheckboxMode()) { - if (sameShortcut) { + if (sameShortcut) { + if (switcher.isCheckboxMode() && !ToggleCheckBoxAction.isEnabled()) { switcher.toggleShowEditedFiles(); } else { - switcher.setShowOnlyEditedFiles(onlyEdited); + switcher.goForward(); } return null; } - else if (sameShortcut) { - switcher.goForward(); + else if (switcher.isCheckboxMode()) { + switcher.setShowOnlyEditedFiles(onlyEdited); return null; } } @@ -171,6 +172,27 @@ public class Switcher extends AnAction implements DumbAware { return switcher; } + public static class ToggleCheckBoxAction extends DumbAwareAction implements DumbAware { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + Project project = e.getProject(); + SwitcherPanel switcherPanel = SWITCHER_KEY.get(project); + if (switcherPanel != null) { + switcherPanel.toggleShowEditedFiles(); + } + } + + @Override + public void update(@NotNull AnActionEvent e) { + Project project = e.getProject(); + e.getPresentation().setEnabledAndVisible(SWITCHER_KEY.get(project) != null); + } + + static boolean isEnabled() { + return getActiveKeymapShortcuts(TOGGLE_CHECK_BOX_ACTION_ID).getShortcuts().length > 0; + } + } + public static class SwitcherPanel extends JPanel implements KeyListener, MouseListener, MouseMotionListener, DataProvider, QuickSearchComponent { final JBPopup myPopup; @@ -188,7 +210,6 @@ public class Switcher extends AnAction implements DumbAware { final Alarm myAlarm; final SwitcherSpeedSearch mySpeedSearch; final String myTitle; - final String myActionId; final int myBaseModifier; private JBPopup myHint; @@ -293,7 +314,6 @@ public class Switcher extends AnAction implements DumbAware { setLayout(new SwitcherLayouter()); this.project = project; myTitle = title; - myActionId = actionId; myPinned = pinned; mySpeedSearch = pinned ? new SwitcherSpeedSearch(this) : null; @@ -469,7 +489,9 @@ public class Switcher extends AnAction implements DumbAware { myClickListener.installOn(files); ScrollingUtil.ensureSelectionExists(files); - myShowOnlyEditedFilesCheckBox = new MyCheckBox(actionId, onlyEdited); + myShowOnlyEditedFilesCheckBox = new MyCheckBox(ToggleCheckBoxAction.isEnabled() ? TOGGLE_CHECK_BOX_ACTION_ID + : actionId, + onlyEdited); myTopPanel = createTopPanel(myShowOnlyEditedFilesCheckBox, isCheckboxMode() ? IdeBundle.message("title.popup.recent.files") : title, pinned); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java index deeaff4b1285..0245f52dc8a2 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java @@ -5,8 +5,13 @@ import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.DumbAwareToggleAction; import com.intellij.openapi.wm.impl.IdeBackgroundUtil; +import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.*; + /** * @author gregsh */ @@ -23,6 +28,14 @@ public class ViewInplaceCommentsAction extends DumbAwareToggleAction { @Override public void setSelected(@NotNull AnActionEvent e, boolean state) { UISettings.getInstance().setShowInplaceComments(state); + updateAllTreesCellsWidth(); IdeBackgroundUtil.repaintAllWindows(); } + + private static void updateAllTreesCellsWidth() { + for (JTree tree : UIUtil.uiTraverser(null).withRoots(Window.getWindows()).filter(JTree.class)) { + //noinspection deprecation + TreeUtil.invalidateCacheAndRepaint(tree.getUI()); + } + } } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java index 51a1bb840b11..920ee4ed2a87 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java @@ -108,7 +108,7 @@ public class PluginManagerConfigurableNewLayout private LinkComponent myMarketplaceSortByAction; private DefaultActionGroup myInstalledSearchGroup; - private Runnable myInstalledSearchCallback; + private Consumer myInstalledSearchCallback; private boolean myInstalledSearchSetState = true; @NotNull @@ -344,10 +344,10 @@ public class PluginManagerConfigurableNewLayout Map> customRepositoriesMap = pair.second; try { - addGroup(groups, allRepositoriesMap, "Featured", "is_featured_search=true", "sortBy:featured"); - addGroup(groups, allRepositoriesMap, "New and Updated", "orderBy=update+date", "sortBy:updated"); - addGroup(groups, allRepositoriesMap, "Top Downloads", "orderBy=downloads", "sortBy:downloads"); - addGroup(groups, allRepositoriesMap, "Top Rated", "orderBy=rating", "sortBy:rating"); + addGroup(groups, allRepositoriesMap, "Featured", "is_featured_search=true", "/sortBy:featured"); + addGroup(groups, allRepositoriesMap, "New and Updated", "orderBy=update+date", "/sortBy:updated"); + addGroup(groups, allRepositoriesMap, "Top Downloads", "orderBy=downloads", "/sortBy:downloads"); + addGroup(groups, allRepositoriesMap, "Top Rated", "orderBy=rating", "/sortBy:rating"); } catch (IOException e) { PluginManagerMain.LOG @@ -548,8 +548,8 @@ public class PluginManagerConfigurableNewLayout List queries = new ArrayList<>(); new SearchQueryParser.Marketplace(searchTextField.getText()) { @Override - protected void setSearchQuery(@NotNull String query) { - super.setSearchQuery(query); + protected void addToSearchQuery(@NotNull String query) { + super.addToSearchQuery(query); queries.add(query); } @@ -858,56 +858,38 @@ public class PluginManagerConfigurableNewLayout PluginsGroupComponent panel = new PluginsGroupComponent(new PluginListLayout(), new MultiSelectionEventHandler(), myNameListener, PluginManagerConfigurableNewLayout.this.mySearchListener, - descriptor -> new NewListPluginComponent(myPluginModel, descriptor, - false)); + descriptor -> new NewListPluginComponent(myPluginModel, descriptor, false)); panel.setSelectionListener(selectionListener); PluginManagerConfigurableNew.registerCopyProvider(panel); - myInstalledSearchCallback = () -> { - StringBuilder queryBuilder = new StringBuilder(); - - for (AnAction action : myInstalledSearchGroup.getChildren(null)) { - InstalledSearchOptionAction optionAction = (InstalledSearchOptionAction)action; - - if (optionAction.myState) { - if (queryBuilder.length() > 0) { - queryBuilder.append(" "); - } - - switch (optionAction.myOption) { - case Enabled: - queryBuilder.append("/enabled"); - break; - case Disabled: - queryBuilder.append("/disabled"); - break; - case Custom: - queryBuilder.append("/custom"); - break; - case Bundled: - queryBuilder.append("/bundled"); - break; - case Invalid: - queryBuilder.append("/invalid"); - break; - case NeedUpdate: - queryBuilder.append("/outdated"); - break; - case Deleted: - queryBuilder.append("/uninstalled"); - break; - case NeedRestart: - queryBuilder.append("/inactive"); - break; - } + myInstalledSearchCallback = updateAction -> { + List queries = new ArrayList<>(); + new SearchQueryParser.InstalledWithVendor(searchTextField.getText()) { + @Override + protected void addToSearchQuery(@NotNull String query) { + super.addToSearchQuery(query); + queries.add(query); } + + @Override + protected void handleAttribute(@NotNull String name, @NotNull String value, boolean invert) { + super.handleAttribute(name, value, invert); + queries.add("/" + name + (value.isEmpty() ? "" : ":" + value)); + } + }; + + if (updateAction.myState) { + queries.add(updateAction.getQuery()); + } + else { + queries.remove(updateAction.getQuery()); } try { myInstalledSearchSetState = false; - String query = queryBuilder.toString(); + String query = StringUtil.join(queries, " "); searchTextField.setTextIgnoreEvents(query); if (query.isEmpty()) { myInstalledTab.hideSearchPanel(); @@ -1079,7 +1061,7 @@ public class PluginManagerConfigurableNewLayout @Override public void setSelected(@NotNull AnActionEvent e, boolean state) { myState = state; - myInstalledSearchCallback.run(); + myInstalledSearchCallback.accept(this); } public void setState(@Nullable SearchQueryParser.Installed parser) { @@ -1115,6 +1097,29 @@ public class PluginManagerConfigurableNewLayout break; } } + + @NotNull + public String getQuery() { + switch (myOption) { + case Enabled: + return "/enabled"; + case Disabled: + return "/disabled"; + case Custom: + return "/custom"; + case Bundled: + return "/bundled"; + case Invalid: + return "/invalid"; + case NeedUpdate: + return "/outdated"; + case Deleted: + return "/uninstalled"; + case NeedRestart: + default: + return "/inactive"; + } + } } private static class GroupByActionGroup extends DefaultActionGroup implements CheckedActionGroup { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java index ba44bab91f2c..765776414964 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java @@ -14,6 +14,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.ui.JBColor; +import com.intellij.util.ArrayUtil; import com.intellij.util.Url; import com.intellij.util.Urls; import com.intellij.util.io.HttpRequests; @@ -51,11 +52,6 @@ public class PluginLogo { }); } - @NotNull - public static Icon getIcon(@NotNull IdeaPluginDescriptor descriptor, int width, int height) { - return null; - } - @NotNull public static Icon getIcon(@NotNull IdeaPluginDescriptor descriptor, boolean big, boolean jb, boolean error, boolean disabled) { return getIcon(descriptor).getIcon(big, jb, error, disabled); @@ -151,7 +147,7 @@ public class PluginLogo { } File[] files = libFile.listFiles(); - if (files == null || files.length == 0) { + if (ArrayUtil.isEmpty(files)) { putIcon(idPlugin, lazyIcon, null, null); return; } @@ -212,8 +208,8 @@ public class PluginLogo { } private static boolean tryLoadDirIcons(@NotNull String idPlugin, @NotNull LazyPluginLogoIcon lazyIcon, @NotNull File path) { - PluginLogoIconProvider light = tryLoadIcon(new File(path, PluginManagerCore.META_INF + PLUGIN_ICON)); - PluginLogoIconProvider dark = tryLoadIcon(new File(path, PluginManagerCore.META_INF + PLUGIN_ICON_DARK)); + PluginLogoIconProvider light = tryLoadIcon(path, true); + PluginLogoIconProvider dark = tryLoadIcon(path, false); if (light != null || dark != null) { putIcon(idPlugin, lazyIcon, light, dark); @@ -231,8 +227,8 @@ public class PluginLogo { return false; } try (ZipFile zipFile = new ZipFile(path)) { - PluginLogoIconProvider light = tryLoadIcon(zipFile, PLUGIN_ICON); - PluginLogoIconProvider dark = tryLoadIcon(zipFile, PLUGIN_ICON_DARK); + PluginLogoIconProvider light = tryLoadIcon(zipFile, true); + PluginLogoIconProvider dark = tryLoadIcon(zipFile, false); if (put || light != null || dark != null) { putIcon(idPlugin, lazyIcon, light, dark); return true; @@ -283,6 +279,11 @@ public class PluginLogo { }, ModalityState.any()); } + @Nullable + private static PluginLogoIconProvider tryLoadIcon(@NotNull File dirFile, boolean light) { + return tryLoadIcon(new File(dirFile, getIconFileName(light))); + } + @Nullable private static PluginLogoIconProvider tryLoadIcon(@NotNull File iconFile) { //noinspection IOResourceOpenedButNotSafelyClosed @@ -290,11 +291,16 @@ public class PluginLogo { } @Nullable - private static PluginLogoIconProvider tryLoadIcon(@NotNull ZipFile zipFile, @NotNull String name) { - ZipEntry iconEntry = zipFile.getEntry(PluginManagerCore.META_INF + name); + private static PluginLogoIconProvider tryLoadIcon(@NotNull ZipFile zipFile, boolean light) { + ZipEntry iconEntry = zipFile.getEntry(getIconFileName(light)); return iconEntry == null ? null : loadFileIcon(() -> zipFile.getInputStream(iconEntry)); } + @NotNull + static String getIconFileName(boolean light) { + return PluginManagerCore.META_INF + (light ? PLUGIN_ICON : PLUGIN_ICON_DARK); + } + @Nullable private static PluginLogoIconProvider loadFileIcon(@NotNull ThrowableComputable provider) { try { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java new file mode 100644 index 000000000000..f3464214fb8e --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java @@ -0,0 +1,174 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.ide.plugins.newui; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.openapi.application.JetBrainsProtocolHandler; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.JBColor; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * @author Alexander Lobas + */ +public class PluginLogoApi { + /** + * Direct load image from local dir or jar based plugin without background task and caches. + */ + @NotNull + public static Icon getIcon(@NotNull IdeaPluginDescriptor descriptor, int width, int height, @Nullable Logger logger) { + return new PluginLogoApi(width, height, logger).getIcon(descriptor); + } + + private final int myWidth; + private final int myHeight; + + private final Logger myLogger; + + private PluginLogoApi(int width, int height, @Nullable Logger logger) { + myWidth = width; + myHeight = height; + myLogger = logger; + } + + @NotNull + private Icon getIcon(@NotNull IdeaPluginDescriptor descriptor) { + File path = descriptor.getPath(); + + if (path == null) { + return getDefaultIcon(); + } + + if (path.isDirectory()) { + if (System.getProperty(JetBrainsProtocolHandler.REQUIRED_PLUGINS_KEY) != null) { + Icon icon = tryLoadDirIcon(new File(path, "classes")); + if (icon != null) { + return icon; + } + } + + Icon icon = tryLoadDirIcon(path); + if (icon != null) { + return icon; + } + + File libFile = new File(path, "lib"); + if (!libFile.exists() || !libFile.isDirectory()) { + return getDefaultIcon(); + } + + File[] files = libFile.listFiles(); + if (ArrayUtil.isEmpty(files)) { + return getDefaultIcon(); + } + + for (File file : files) { + Icon dirIcon = tryLoadDirIcon(file); + if (dirIcon != null) { + return dirIcon; + } + + Icon jarIcon = tryLoadJarIcon(file); + if (jarIcon != null) { + return jarIcon; + } + } + } + else { + Icon icon = tryLoadJarIcon(path); + if (icon != null) { + return icon; + } + } + + return getDefaultIcon(); + } + + @Nullable + private Icon tryLoadDirIcon(@NotNull File path) { + boolean light = JBColor.isBright(); + Icon icon = tryLoadIcon(path, light); + return icon == null ? tryLoadIcon(path, !light) : icon; + } + + @Nullable + private Icon tryLoadJarIcon(@NotNull File path) { + if (!FileUtil.isJarOrZip(path) || !path.exists()) { + return null; + } + try (ZipFile zipFile = new ZipFile(path)) { + boolean light = JBColor.isBright(); + Icon icon = tryLoadIcon(zipFile, light); + return icon == null ? tryLoadIcon(zipFile, !light) : icon; + } + catch (Exception e) { + if (myLogger != null) { + myLogger.error(e); + } + } + return null; + } + + @Nullable + private Icon tryLoadIcon(@NotNull File dirFile, boolean light) { + try { + File iconFile = new File(dirFile, PluginLogo.getIconFileName(light)); + return iconFile.exists() && iconFile.length() > 0 ? loadFileIcon(new FileInputStream(iconFile)) : null; + } + catch (IOException e) { + if (myLogger != null) { + myLogger.error(e); + } + return null; + } + } + + @Nullable + private Icon tryLoadIcon(@NotNull ZipFile zipFile, boolean light) { + try { + ZipEntry iconEntry = zipFile.getEntry(PluginLogo.getIconFileName(light)); + return iconEntry == null ? null : loadFileIcon(zipFile.getInputStream(iconEntry)); + } + catch (IOException e) { + if (myLogger != null) { + myLogger.error(e); + } + return null; + } + } + + @NotNull + private Icon loadFileIcon(@NotNull InputStream stream) throws IOException { + return HiDPIPluginLogoIcon.loadSVG(stream, myWidth, myHeight); + } + + private Icon getDefaultIcon() { + if (AllIcons.Plugins.PluginLogo instanceof IconLoader.CachedImageIcon) { + URL url = ((IconLoader.CachedImageIcon)AllIcons.Plugins.PluginLogo).getURL(); + if (url != null) { + try { + return HiDPIPluginLogoIcon.loadSVG(url.openStream(), myWidth, myHeight); + } + catch (IOException e) { + if (myLogger != null) { + myLogger.error(e); + } + } + } + } + return AllIcons.Plugins.PluginLogo; + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java index d9e9b453d2b7..d0487704e24e 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java @@ -94,7 +94,7 @@ public abstract class SearchQueryParser { return; } if (size == 1) { - setSearchQuery(words.get(0)); + addToSearchQuery(words.get(0)); return; } @@ -108,22 +108,23 @@ public abstract class SearchQueryParser { handleAttribute(name, words.get(index++), invert); } else { - searchQuery = query; + addToSearchQuery(query); return; } } - else if (searchQuery == null) { - setSearchQuery(name); - } else { - setSearchQuery(query); - return; + addToSearchQuery(name); } } } - protected void setSearchQuery(@NotNull String query) { - searchQuery = query; + protected void addToSearchQuery(@NotNull String query) { + if (searchQuery == null) { + searchQuery = query; + } + else { + searchQuery += " " + query; + } } protected abstract void handleAttribute(@NotNull String name, @NotNull String value, boolean invert); @@ -244,12 +245,8 @@ public abstract class SearchQueryParser { else if (word.startsWith("-#")) { handleAttribute(word.substring(2), "", true); } - else if (searchQuery == null) { - searchQuery = word; - } else { - searchQuery = query; - break; + addToSearchQuery(word); } } parseEnd(); @@ -319,7 +316,7 @@ public abstract class SearchQueryParser { vendors.add(words.get(index++)); } else { - searchQuery = query; + addToSearchQuery(query); break; } } @@ -327,12 +324,8 @@ public abstract class SearchQueryParser { handleAttribute(name.substring(1), "", false); } } - else if (searchQuery == null) { - searchQuery = name; - } else { - searchQuery = query; - break; + addToSearchQuery(name); } } 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 29cdff3a3e4d..d3d22f4b9034 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -546,7 +546,7 @@ public class AppearanceConfigurable implements SearchableConfigurable { } } - private static class AAListCellRenderer extends JLabel implements ListCellRenderer { + private static class AAListCellRenderer extends SimpleListCellRenderer { private static final Object SUBPIXEL_HINT = GraphicsUtil.createAATextInfo(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); private static final Object GREYSCALE_HINT = GraphicsUtil.createAATextInfo(RenderingHints.VALUE_TEXT_ANTIALIAS_ON); @@ -557,7 +557,7 @@ public class AppearanceConfigurable implements SearchableConfigurable { } @Override - public Component getListCellRendererComponent(JList list, AntialiasingType value, int i, boolean s, boolean f) { + public void customize(JList list, AntialiasingType value, int index, boolean selected, boolean hasFocus) { if (value == AntialiasingType.SUBPIXEL) { GraphicsUtil.setAntialiasingType(this, SUBPIXEL_HINT); } @@ -574,8 +574,6 @@ public class AppearanceConfigurable implements SearchableConfigurable { } setText(String.valueOf(value)); - - return this; } } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index cb91f6ee83ea..df88daadf1fd 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -539,18 +539,26 @@ public final class LafManagerImpl extends LafManager implements PersistentStateC defaults.put("TreeUI", "com.intellij.ui.tree.ui.DefaultTreeUI"); defaults.put("Tree.repaintWholeRow", true); } - Icon collapsedIcon = defaults.getIcon("Tree.collapsedIcon"); - if (collapsedIcon == null || collapsedIcon instanceof UIResource) { + if (isUnsupported(defaults.getIcon("Tree.collapsedIcon"))) { defaults.put("Tree.collapsedIcon", LafIconLookup.getIcon("treeCollapsed")); defaults.put("Tree.collapsedSelectedIcon", LafIconLookup.getSelectedIcon("treeCollapsed")); } - Icon expandedIcon = defaults.getIcon("Tree.expandedIcon"); - if (expandedIcon == null || collapsedIcon instanceof UIResource) { + if (isUnsupported(defaults.getIcon("Tree.expandedIcon"))) { defaults.put("Tree.expandedIcon", LafIconLookup.getIcon("treeExpanded")); defaults.put("Tree.expandedSelectedIcon", LafIconLookup.getSelectedIcon("treeExpanded")); } } + /** + * @param icon an icon retrieved from L&F + * @return {@code true} if an icon is not specified or if it is declared in some Swing L&F + * (such icons do not have a variant to paint in selected row) + */ + private static boolean isUnsupported(@Nullable Icon icon) { + String name = icon == null ? null : icon.getClass().getName(); + return name == null || name.startsWith("javax.swing.plaf.") || name.startsWith("com.sun.java.swing.plaf."); + } + private static void patchHiDPI(UIDefaults defaults) { Object prevScaleVal = defaults.get("hidpi.scaleFactor"); // used to normalize previously patched values diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties index 659607a77057..9185b800e6a9 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties @@ -207,6 +207,10 @@ Spinner.editorBorderPainted=false SplitPane.highlight=3c3f41 TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI +Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeCollapsed.svg +Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeExpanded.svg +Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeCollapsedSelected.svg +Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeExpandedSelected.svg Tree.paintLines=false Tree.hash=505355 @@ -279,4 +283,8 @@ DragAndDrop.areaBackground=404a57 DragAndDrop.areaBorderColor=4f73a8 DragAndDrop.areaForeground=bababa -CompletionPopup.nonFocusedState=true \ No newline at end of file +CompletionPopup.nonFocusedState=true + +NewClass.Panel.background=45494a +NewClass.SearchField.background=3c3f41 +NewClass.separatorWidth=10 \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties index 7863d29e6b83..608865362543 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties @@ -184,6 +184,10 @@ SplitPane.highlight=f2f2f2 TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI Tree.background=ffffff +Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeCollapsed.svg +Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeExpanded.svg +Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeCollapsedSelected.svg +Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeExpandedSelected.svg Tree.paintLines=false Tree.hash=E6E6E6 Tree.textBackground=ffffff @@ -277,4 +281,8 @@ DragAndDrop.areaBackground=e1ebf5 DragAndDrop.areaBorderColor=8ab2de DragAndDrop.areaForeground=787878 -CompletionPopup.nonFocusedState=true \ No newline at end of file +CompletionPopup.nonFocusedState=true + +NewClass.Panel.background=f2f2f2 +NewClass.SearchField.background=ffffff +NewClass.separatorWidth=10 \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties index ab5768ea381d..280456daaece 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties @@ -101,6 +101,10 @@ TabbedPane.tabFillStyle=underline TableHeader.cellBorder=2,2,2,2 +Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/treeCollapsed.svg +Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/treeExpanded.svg +Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/treeCollapsedSelected.svg +Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/treeExpandedSelected.svg Tree.paintLines=false Tree.hash=E6E6E6 Tree.rowHeight=20 diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties index ab4a05f19aab..dea0423e848e 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties @@ -174,6 +174,10 @@ SearchEverywhere.shortcutForeground=a7c1db TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI Tree.background=ffffff +Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/win10/treeCollapsed.svg +Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/win10/treeExpanded.svg +Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/win10/treeCollapsedSelected.svg +Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/win10/treeExpandedSelected.svg Tree.paintLines=false Tree.hash=E6E6E6 Tree.rowHeight=0 @@ -264,4 +268,8 @@ SearchEverywhere.SearchField.infoForeground=808080 SearchEverywhere.Advertiser.foreground=808080 SearchEverywhere.Advertiser.background=f2f2f2 -CompletionPopup.nonFocusedState=true \ No newline at end of file +CompletionPopup.nonFocusedState=true + +NewClass.Panel.background=f2f2f2 +NewClass.SearchField.background=ffffff +NewClass.separatorWidth=10 \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java index dd4502024f01..fdaed9107432 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.diff.impl.mergeTool; -import com.intellij.configurationStore.StoreReloadManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.undo.DocumentReference; @@ -14,17 +13,12 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.projectImport.ProjectOpenProcessor; -import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Collection; -import java.util.Set; @Deprecated public interface MergeVersion { @@ -88,31 +82,6 @@ public interface MergeVersion { setDocumentText(myDocument, text, DiffBundle.message("save.merge.result.command.name"), project); FileDocumentManager.getInstance().saveDocument(myDocument); - reportProjectFileChangeIfNeeded(project, getFile()); - } - - public static void reportProjectFileChangeIfNeeded(@Nullable Project project, @Nullable VirtualFile file) { - if (project != null && file != null && !file.isDirectory() && (ProjectUtil.isProjectOrWorkspaceFile(file) || isProjectFile(file))) { - StoreReloadManager.getInstance().saveChangedProjectFile(file, project); - } - } - - @Nullable - public static Runnable prepareToReportChangedProjectFiles(@NotNull final Project project, @NotNull Collection files) { - final Set vfs = new THashSet<>(); - for (VirtualFile file : files) { - if (file != null && !file.isDirectory()) { - if (ProjectUtil.isProjectOrWorkspaceFile(file) || isProjectFile(file)) { - vfs.add(file); - } - } - } - return vfs.isEmpty() ? null : () -> { - StoreReloadManager storeReloadManager = StoreReloadManager.getInstance(); - for (VirtualFile vf : vfs) { - storeReloadManager.saveChangedProjectFile(vf, project); - } - }; } @Override @@ -120,11 +89,6 @@ public interface MergeVersion { ApplicationManager.getApplication().runWriteAction(() -> doRestoreOriginalContent(project)); } - public static boolean isProjectFile(VirtualFile file) { - final ProjectOpenProcessor importProvider = ProjectOpenProcessor.getImportProvider(file); - return importProvider != null && importProvider.lookForProjectsInDirectory(); - } - protected void doRestoreOriginalContent(@Nullable Project project) { setDocumentText(myDocument, myTextBeforeMerge, "", project); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index a41aa9a06531..98a804c06184 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -591,12 +591,13 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse AffineTransform old = setMirrorTransformIfNeeded(g, getLineNumberAreaOffset(), getLineNumberAreaWidth()); try { - int caretLine = convertor.execute(myEditor.getCaretModel().getLogicalPosition().line); + int caretLogicalLine = myEditor.getCaretModel().getLogicalPosition().line; VisualLinesIterator visLinesIterator = new VisualLinesIterator(myEditor, startVisualLine); while (!visLinesIterator.atEnd() && visLinesIterator.getVisualLine() <= endVisualLine) { if (!visLinesIterator.startsWithSoftWrap()) { - int logLine = convertor.execute(visLinesIterator.getStartLogicalLine()); - if (logLine >= 0) { + int logicalLine = visLinesIterator.getStartLogicalLine(); + int lineToDisplay = convertor.execute(logicalLine); + if (lineToDisplay >= 0) { int startY = visLinesIterator.getY(); if (myEditor.isInDistractionFreeMode()) { Color fgColor = myTextFgColors.get(visLinesIterator.getVisualLine()); @@ -605,11 +606,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse g.setColor(color); } - if (colorUnderCaretRow != null && caretLine == logLine) { + if (colorUnderCaretRow != null && caretLogicalLine == logicalLine) { g.setColor(colorUnderCaretRow); } - String s = String.valueOf(logLine + 1); + String s = String.valueOf(lineToDisplay + 1); int textOffset = isMirrored() ? offset - getLineNumberAreaWidth() - 1 : offset - g.getFontMetrics().stringWidth(s); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index f9161251ecff..c421c10c563c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -212,7 +212,7 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab @Override public void paintIcon(Component c, Graphics g, int x, int y) { - if (expanded != null) control.paint(g, x, y, getIconWidth(), getIconHeight(), expanded, false); + if (expanded != null) control.paint(c, g, x, y, getIconWidth(), getIconHeight(), expanded, false); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java index 2a19a27ee772..aa3193cb524e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java @@ -14,10 +14,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; import com.intellij.openapi.ui.popup.util.PopupUtil; -import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.WindowStateService; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.*; import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt; @@ -51,6 +48,7 @@ public class FrameWrapper implements Disposable, DataProvider { private String myTitle = ""; private List myImages = null; private boolean myCloseOnEsc = false; + private BooleanGetter myOnCloseHandler; private Window myFrame; private final Map myDataMap = ContainerUtil.newHashMap(); private Project myProject; @@ -119,10 +117,17 @@ public class FrameWrapper implements Disposable, DataProvider { } if (frame instanceof JFrame) { - ((JFrame)frame).setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } else { - ((JDialog)frame).setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + ((JFrame)frame).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); } + else { + ((JDialog)frame).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + } + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + close(); + } + }); UIUtil.decorateWindowHeader(((RootPaneContainer)frame).getRootPane()); @@ -180,6 +185,13 @@ public class FrameWrapper implements Disposable, DataProvider { } public void close() { + if (myOnCloseHandler != null && !myOnCloseHandler.get()) return; + + // if you remove this line problems will start happen on Mac OS X + // 2 projects opened, call Cmd+D on the second opened project and then Esc. + // Weird situation: 2nd IdeFrame will be active, but focus will be somewhere inside the 1st IdeFrame + // App is unusable until Cmd+Tab, Cmd+tab + FrameWrapper.this.myFrame.setVisible(false); Disposer.dispose(this); } @@ -240,11 +252,6 @@ public class FrameWrapper implements Disposable, DataProvider { @Override public void actionPerformed(ActionEvent e) { if (!PopupUtil.handleEscKeyEvent()) { - // if you remove this line problems will start happen on Mac OS X - // 2 projects opened, call Cmd+D on the second opened project and then Esc. - // Weird situation: 2nd IdeFrame will be active, but focus will be somewhere inside the 1st IdeFrame - // App is unusable until Cmd+Tab, Cmd+tab - FrameWrapper.this.myFrame.setVisible(false); close(); } } @@ -313,6 +320,10 @@ public class FrameWrapper implements Disposable, DataProvider { myImages = images; } + public void setOnCloseHandler(BooleanGetter onCloseHandler) { + myOnCloseHandler = onCloseHandler; + } + protected void loadFrameState() { final Window frame = getFrame(); if (myDimensionKey != null && !WindowStateService.getInstance().loadStateFor(myProject, myDimensionKey, frame)) { @@ -361,7 +372,6 @@ public class FrameWrapper implements Disposable, DataProvider { MouseGestureManager.getInstance().add(this); setFocusTraversalPolicy(new LayoutFocusTraversalPolicyExt()); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); } @Override @@ -452,7 +462,6 @@ public class FrameWrapper implements Disposable, DataProvider { setBackground(UIUtil.getPanelBackground()); MouseGestureManager.getInstance().add(this); setFocusTraversalPolicy(new LayoutFocusTraversalPolicyExt()); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java b/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java index 800dc5786130..5a30f79c0b68 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java @@ -3,6 +3,7 @@ package com.intellij.openapi.ui; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.WindowWrapper.Mode; +import com.intellij.openapi.util.BooleanGetter; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; @@ -26,6 +27,7 @@ public class WindowWrapperBuilder { @Nullable private Computable myPreferredFocusedComponent; @Nullable private String myDimensionServiceKey; @Nullable private Runnable myOnShowCallback; + @Nullable private BooleanGetter myOnCloseHandler; public WindowWrapperBuilder(@NotNull Mode mode, @NotNull JComponent component) { myMode = mode; @@ -74,6 +76,12 @@ public class WindowWrapperBuilder { return this; } + @NotNull + public WindowWrapperBuilder setOnCloseHandler(@NotNull BooleanGetter handler) { + myOnCloseHandler = handler; + return this; + } + @NotNull public WindowWrapper build() { switch (myMode) { @@ -107,7 +115,7 @@ public class WindowWrapperBuilder { myDialog = builder.myParent != null ? new MyDialogWrapper(builder.myParent, builder.myComponent) : new MyDialogWrapper(builder.myProject, builder.myComponent); - myDialog.setParameters(builder.myDimensionServiceKey, builder.myPreferredFocusedComponent); + myDialog.setParameters(builder.myDimensionServiceKey, builder.myPreferredFocusedComponent, builder.myOnCloseHandler); installOnShowCallback(myDialog.getWindow(), builder.myOnShowCallback); @@ -178,6 +186,7 @@ public class WindowWrapperBuilder { @NotNull private final JComponent myComponent; @Nullable private String myDimensionServiceKey; @Nullable private Computable myPreferredFocusedComponent; + @Nullable private BooleanGetter myOnCloseHandler; MyDialogWrapper(@Nullable Project project, @NotNull JComponent component) { super(project, true); @@ -190,9 +199,11 @@ public class WindowWrapperBuilder { } public void setParameters(@Nullable String dimensionServiceKey, - @Nullable Computable preferredFocusedComponent) { + @Nullable Computable preferredFocusedComponent, + @Nullable BooleanGetter onCloseHandler) { myDimensionServiceKey = dimensionServiceKey; myPreferredFocusedComponent = preferredFocusedComponent; + myOnCloseHandler = onCloseHandler; } @Nullable @@ -231,6 +242,12 @@ public class WindowWrapperBuilder { if (myPreferredFocusedComponent != null) return myPreferredFocusedComponent.compute(); return super.getPreferredFocusedComponent(); } + + @Override + public void doCancelAction() { + if (myOnCloseHandler != null && !myOnCloseHandler.get()) return; + super.doCancelAction(); + } } } @@ -251,6 +268,7 @@ public class WindowWrapperBuilder { myFrame = new MyFrameWrapper(builder.myProject, builder.myDimensionServiceKey); myFrame.setParameters(builder.myPreferredFocusedComponent); + myFrame.setOnCloseHandler(builder.myOnCloseHandler); myOnShowCallback = builder.myOnShowCallback; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java index 296edf3b41f4..93c906557c19 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java @@ -81,7 +81,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable { myEventCounter.eventHappened(session); } - private void doScan(RefreshSessionImpl session) { + private void doScan(@NotNull RefreshSessionImpl session) { try { updateSessionMap(session, true); session.scan(); @@ -91,7 +91,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable { } } - private void updateSessionMap(RefreshSession session, boolean add) { + private void updateSessionMap(@NotNull RefreshSession session, boolean add) { long id = session.getId(); if (id != 0) { synchronized (mySessions) { @@ -135,5 +135,9 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable { } @Override - public void dispose() { } + public void dispose() { + synchronized (mySessions) { + mySessions.forEachValue(session -> { ((RefreshSessionImpl)session).cancel(); return true; }); + } + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java index 87a55a0130e5..bc69bf3dbe73 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java @@ -144,6 +144,7 @@ public class RefreshWorker { @NotNull TObjectHashingStrategy strategy, @NotNull VirtualDirectoryImpl dir) { while (true) { + checkCancelled(dir); // obtaining directory snapshot Pair result = LocalFileSystemRefreshWorker.getDirectorySnapshot(persistence, dir); if (result == null) return; @@ -189,6 +190,7 @@ public class RefreshWorker { // generating events unless a directory was changed in between boolean hasEvents = ReadAction.compute(() -> { + checkCancelled(dir); if (!Arrays.equals(persistedNames, persistence.list(dir)) || !Arrays.equals(children, dir.getChildren())) { if (LOG.isTraceEnabled()) LOG.trace("retry: " + dir); return false; @@ -206,6 +208,7 @@ public class RefreshWorker { } for (Pair pair : updatedMap) { + checkCancelled(dir); VirtualFile child = pair.first; FileAttributes childAttributes = pair.second; if (childAttributes != null) { @@ -229,6 +232,7 @@ public class RefreshWorker { @NotNull TObjectHashingStrategy strategy, @NotNull VirtualDirectoryImpl dir) { while (true) { + checkCancelled(dir); // obtaining directory snapshot Pair, List> result = ReadAction.compute(() -> pair(dir.getCachedChildren(), dir.getSuspiciousNames())); @@ -263,6 +267,7 @@ public class RefreshWorker { // generating events unless a directory was changed in between boolean hasEvents = ReadAction.compute(() -> { + checkCancelled(dir); if (!cached.equals(dir.getCachedChildren()) || !wanted.equals(dir.getSuspiciousNames())) { if (LOG.isTraceEnabled()) LOG.trace("retry: " + dir); return false; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt index 11ee9c6171e8..a21598be3d3b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt @@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons import com.intellij.jdkEx.JdkEx import com.intellij.openapi.Disposable import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.io.WindowsRegistryUtil import com.intellij.openapi.wm.impl.IdeRootPane import com.intellij.openapi.wm.impl.customFrameDecorations.CustomFrameTitleButtons import com.intellij.ui.AppUIUtil @@ -97,7 +98,7 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable { onClose() } - override fun windowStateChanged(e: java.awt.event.WindowEvent?) { + override fun windowStateChanged(e: WindowEvent?) { windowStateChanged() } } @@ -216,9 +217,12 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable { inner class CustomFrameTopBorder(val isTopNeeded: ()-> Boolean = {true}, val isBottomNeeded: ()-> Boolean = {false}) : Border { val thickness = 1 private val menuBarBorderColor: Color = JBColor.namedColor("MenuBar.borderColor", JBColor(Gray.xCD, Gray.x51)) + private val affectsBorders: Boolean = Toolkit.getDefaultToolkit().getDesktopProperty("win.dwm.colorizationColor.affects.borders") as Boolean? ?: true private val activeColor = Toolkit.getDefaultToolkit().getDesktopProperty("win.dwm.colorizationColor") as Color? ?: Toolkit.getDefaultToolkit().getDesktopProperty("win.frame.activeBorderColor") as Color? ?: menuBarBorderColor + private val windowsVersion = WindowsRegistryUtil.readRegistryValue("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ReleaseId") + fun repaintBorder() { val borderInsets = getBorderInsets(this@CustomHeader) @@ -227,7 +231,7 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable { } override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) { - if (isTopNeeded() && myActive) { + if (isTopNeeded() && myActive && isAffectsBorder()) { g.color = activeColor LinePainter2D.paint(g as Graphics2D, x.toDouble(), y.toDouble(), width.toDouble(), y.toDouble()) } @@ -239,9 +243,16 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable { } } + private fun isAffectsBorder(): Boolean { + if(windowsVersion.isNullOrEmpty()) return true + + val winVersion = windowsVersion.toIntOrNull() ?: return affectsBorders + return if(winVersion >= 1809) affectsBorders else true + } + override fun getBorderInsets(c: Component): Insets { val scale = JBUI.scale(thickness) - return Insets(if (isTopNeeded()) thickness else 0, 0, if (isBottomNeeded()) scale else 0, 0) + return Insets(if (isTopNeeded() && isAffectsBorder()) thickness else 0, 0, if (isBottomNeeded()) scale else 0, 0) } override fun isBorderOpaque(): Boolean { diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java index e71ff6f2a7d0..0cdd69290578 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java @@ -8,6 +8,7 @@ import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; @@ -50,7 +51,7 @@ final class ClassicPainter implements Control.Painter { } @Override - public void paint(@NotNull Graphics g, int x, int y, int width, int height, + public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, @NotNull Control control, int depth, boolean leaf, boolean expanded, boolean selected) { if (depth <= 0) return; // do not paint boolean paintLines = getPaintLines(); @@ -72,7 +73,7 @@ final class ClassicPainter implements Control.Painter { } } if (leaf) return; // do not paint control for a leaf node - control.paint(g, controlX, y, controlWidth, height, expanded, selected); + control.paint(c, g, controlX, y, controlWidth, height, expanded, selected); } private boolean getPaintLines() { diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java index 3b342274b2db..8775a5c61cca 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java @@ -5,6 +5,7 @@ import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.Component; import java.awt.Graphics; final class CompactPainter implements Control.Painter { @@ -39,7 +40,7 @@ final class CompactPainter implements Control.Painter { } @Override - public void paint(@NotNull Graphics g, int x, int y, int width, int height, + public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, @NotNull Control control, int depth, boolean leaf, boolean expanded, boolean selected) { if (depth <= 0) return; // do not paint if (!paintLines && leaf) return; // nothing to paint @@ -61,7 +62,7 @@ final class CompactPainter implements Control.Painter { } } if (leaf) return; // do not paint control for a leaf node - control.paint(g, controlX, y, controlWidth, height, expanded, selected); + control.paint(c, g, controlX, y, controlWidth, height, expanded, selected); } private int getLeftIndent() { diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java index e9b62a20c0d7..4f71ffa843a6 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java @@ -4,6 +4,7 @@ package com.intellij.ui.tree.ui; import com.intellij.ui.JBColor; import org.jetbrains.annotations.NotNull; +import java.awt.Component; import java.awt.Graphics; import javax.swing.Icon; @@ -15,7 +16,7 @@ public interface Control { int getHeight(); - void paint(@NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected); + void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected); interface Painter { @@ -25,7 +26,7 @@ public interface Control { int getControlOffset(@NotNull Control control, int depth, boolean leaf); - void paint(@NotNull Graphics g, int x, int y, int width, int height, + void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, @NotNull Control control, int depth, boolean leaf, boolean expanded, boolean selected); } } diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java index e2b767527d87..3696c9bf5a9c 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java @@ -4,6 +4,7 @@ package com.intellij.ui.tree.ui; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import java.awt.Component; import java.awt.Graphics; import javax.swing.Icon; @@ -36,7 +37,7 @@ public final class DefaultControl implements Control { } @Override - public void paint(@NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected) { + public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected) { Icon icon = getIcon(expanded, selected); icon.paintIcon(null, g, x + (width - icon.getIconWidth()) / 2, diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java index 97f4616d3f1c..1450493d5ed1 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java @@ -210,7 +210,7 @@ public final class DefaultTreeUI extends BasicTreeUI { g.fillRect(viewportX, bounds.y, viewportWidth, bounds.height); } int offset = painter.getRendererOffset(control, depth, leaf); - painter.paint(g, insets.left, bounds.y, offset, bounds.height, control, depth, leaf, expanded, selected && focused); + painter.paint(tree, g, insets.left, bounds.y, offset, bounds.height, control, depth, leaf, expanded, selected && focused); // TODO: editingComponent, editingRow ??? if (editingComponent == null || editingRow != row) { int width = viewportX + viewportWidth - insets.left - offset - vsbWidth; diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index aa611a4a96d2..09f0cd19857f 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -579,7 +579,7 @@ Second Cmd/Ctrl+E switches to Recently Edited Files - + Use popups (instead of dialogs) for creating new items (files, classes, etc.) diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 737f8f913924..7aa798419558 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -612,6 +612,8 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java index 759200d6a116..c5faf3b9f375 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java @@ -2,6 +2,7 @@ package com.intellij.execution.process; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.Consumer; @@ -18,6 +19,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +/** + * important: ansi decoder returns indexed colors set using 30-37, 40-47, 90-97 and 100-107 codes using 38;5;color_number/48;5;color_number + */ public class AnsiEscapeDecoderTest extends LightPlatformTestCase { private static final String STDOUT_KEY = ProcessOutputTypes.STDOUT.toString(); @@ -28,105 +32,162 @@ public class AnsiEscapeDecoderTest extends LightPlatformTestCase { check(new ColoredText("simple text", ProcessOutputTypes.STDOUT).addExpected("simple text", STDOUT_KEY)); } + public void testSequentialSgr() { + check(new ColoredText("This is \u001B[1;3mItalic Bold", ProcessOutputTypes.STDOUT) + .addExpected("This is ", STDOUT_KEY) + .addExpected("Italic Bold", "1;3m") + ); + } + + public void testSequentialSgrOneByOne() { + check(new ColoredText("This is \u001B[1m\u001B[3mItalic Bold", ProcessOutputTypes.STDOUT) + .addExpected("This is ", STDOUT_KEY) + .addExpected("Italic Bold", "1;3m") + ); + } + public void testSingleColoredChunk() { check(new ColoredText("Chrome 35.0.1916 (Linux): Executed 0 of 1\u001B[32m SUCCESS\u001B[39m (0 secs / 0 secs)\n", ProcessOutputTypes.STDOUT) .addExpected("Chrome 35.0.1916 (Linux): Executed 0 of 1", STDOUT_KEY) - .addExpected(" SUCCESS", "\u001B[32m") - .addExpected(" (0 secs / 0 secs)\n", "\u001B[39m")); + .addExpected(" SUCCESS", "38;5;2m") + .addExpected(" (0 secs / 0 secs)\n", STDOUT_KEY)); } public void testCompoundEscSeq() { check(new ColoredText("E\u001B[41m\u001B[37mE\u001B[0mE", ProcessOutputTypes.STDOUT) .addExpected("E", STDOUT_KEY) - .addExpected("E", "\u001B[41;37m") + .addExpected("E", "48;5;1;38;5;7m") .addExpected("E", STDOUT_KEY)); } public void testOtherEscSeq() { check(new ColoredText("Plain\u001B[32mGreen\u001B[39mNormal\u001B[1A\u001B[2K\u001B[31mRed\u001B[39m", ProcessOutputTypes.STDOUT) .addExpected("Plain", STDOUT_KEY) - .addExpected("Green", "\u001B[32m") - .addExpected("Normal", "\u001B[39m") - .addExpected("Red", "\u001B[31m")); + .addExpected("Green", "38;5;2m") + .addExpected("Normal", STDOUT_KEY) + .addExpected("Red", "38;5;1m")); } public void testPrivateSequence() { - check(new ColoredText("\u001B[0;32mgreen\u001B[0m\u001B[0K\u001B[?25l\n", ProcessOutputTypes.STDOUT) - .addExpected("green", "\u001B[0;32m") + check(new ColoredText("\u001B[0m\u001B[32mgreen\u001B[0m\u001B[0K\u001B[?25l\n", ProcessOutputTypes.STDOUT) + .addExpected("green", "38;5;2m") .addExpected("\n", STDOUT_KEY) ); } - public void testMalformedSequence() { + public void testMalformedSequence1() { check(false, Collections.singletonList(new ColoredText("\u001B[32mGreen\u001B[\1World\n", ProcessOutputTypes.STDOUT) - .addExpected("Green\u001B[\1World\n", "\u001B[32m") - )); - check(false, Collections.singletonList(new ColoredText("\u001B\n", ProcessOutputTypes.STDOUT) - .addExpected("\u001B\n", ProcessOutputTypes.STDOUT.toString()) - )); - check(false, Collections.singletonList(new ColoredText("\u001B[\n", ProcessOutputTypes.STDOUT) - .addExpected("\u001B[\n", ProcessOutputTypes.STDOUT.toString()) - )); - check(false, ContainerUtil.newArrayList( - new ColoredText("\u001B\nHello,", ProcessOutputTypes.STDOUT) - .addExpected("\u001B\nHello,", ProcessOutputTypes.STDOUT.toString()), - new ColoredText("\u001B[31mWorld", ProcessOutputTypes.STDOUT) - .addExpected("World", "\u001B[31m") - )); - check(false, ContainerUtil.newArrayList( - new ColoredText("\u001BHello,", ProcessOutputTypes.STDOUT) - .addExpected("\u001BHello,", ProcessOutputTypes.STDOUT.toString()) - )); - check(false, ContainerUtil.newArrayList( - new ColoredText("\u001B[Hello,", ProcessOutputTypes.STDOUT) - .addExpected("ello,", ProcessOutputTypes.STDOUT.toString()) - )); - check(false, ContainerUtil.newArrayList( - new ColoredText("something[\u001B]asdf[\u001B[]", ProcessOutputTypes.STDOUT) - .addExpected("something[\u001B]asdf[\u001B[]", ProcessOutputTypes.STDOUT.toString()) + .addExpected("Green", "38;5;2m") + .addExpected("\u001B[\1World\n", "38;5;2m") )); } - public void testIncompleteEscapeSequences() { + public void testMalformedSequence2() { + check(false, Collections.singletonList(new ColoredText("\u001B\n", ProcessOutputTypes.STDOUT) + .addExpected("\u001B\n", ProcessOutputTypes.STDOUT.toString()) + )); + } + + public void testMalformedSequence3() { + check(false, Collections.singletonList(new ColoredText("\u001B[\n", ProcessOutputTypes.STDOUT) + .addExpected("\u001B[\n", ProcessOutputTypes.STDOUT.toString()) + )); + } + + public void testMalformedSequence4() { + check(false, ContainerUtil.newArrayList( + new ColoredText("\u001B\nHello,", ProcessOutputTypes.STDOUT) + .addExpected("\u001B\nHello,", STDOUT_KEY), + new ColoredText("\u001B[31mWorld", ProcessOutputTypes.STDOUT) + .addExpected("World", "38;5;1m") + )); + } + + public void testMalformedSequence5() { + check(false, ContainerUtil.newArrayList( + new ColoredText("\u001BHello,", ProcessOutputTypes.STDOUT) + .addExpected("\u001BHello,", STDOUT_KEY) + )); + } + + public void testMalformedSequence6() { + check(false, ContainerUtil.newArrayList( + new ColoredText("\u001B[Hello,", ProcessOutputTypes.STDOUT) + .addExpected("ello,", STDOUT_KEY) + )); + } + + public void testMalformedSequence7() { + check(false, ContainerUtil.newArrayList( + new ColoredText("something[\u001B]asdf[\u001B[]", ProcessOutputTypes.STDOUT) + .addExpected("something[", STDOUT_KEY) + .addExpected("\u001B]asdf[", STDOUT_KEY) + )); + } + + public void testIncompleteEscapeSequence1() { check(true, ContainerUtil.newArrayList( new ColoredText("\u001B", ProcessOutputTypes.STDOUT), - new ColoredText("[33m Hello\u001B[3", ProcessOutputTypes.STDOUT).addExpected(" Hello", "\u001B[33m"), - new ColoredText("4m, Work!", ProcessOutputTypes.STDOUT).addExpected(", Work!", "\u001B[34m") + new ColoredText("[33m Hello\u001B[3", ProcessOutputTypes.STDOUT) + .addExpected(" Hello", "38;5;3m"), + new ColoredText("4m, Work!", ProcessOutputTypes.STDOUT) + .addExpected(", Work!", "38;5;4m") )); + } + + public void testIncompleteEscapeSequence2() { check(true, ContainerUtil.newArrayList( - new ColoredText("\u001B[1;33m<\u001B[34mnamespace\u001B[1", ProcessOutputTypes.STDOUT) - .addExpected("<", "\u001B[1;33m") - .addExpected("namespace", "\u001B[34m"), - new ColoredText( - ";33m:abcd\u001B[0m\u001B[1;33m>\u001B[0m0\u001B[1;33m\u001B[0m", - ProcessOutputTypes.STDOUT) - .addExpected(":abcd", "\u001B[1;33m") - .addExpected(">", "\u001B[0;1;33m") - .addExpected("0", "stdout") - .addExpected("", "\u001B[0;1;33m") + new ColoredText("\u001B[1m\u001B[33m<" + + "\u001B[34mnamespace" + + "\u001B[1m", ProcessOutputTypes.STDOUT) + .addExpected("<", "1;38;5;3m") + .addExpected("namespace", "1;38;5;4m"), + new ColoredText("\u001B[33m:abcd" + + "\u001B[0m" + + "\u001B[1;33m>" + + "\u001B[0m0" + + "\u001B[1;33m" + + "\u001B[0m", + ProcessOutputTypes.STDOUT) + .addExpected(":abcd", "1;38;5;3m") + .addExpected(">", "1;38;5;3m") + .addExpected("0", STDOUT_KEY) + .addExpected("", "1;38;5;3m") )); + } + + public void testIncompleteEscapeSequence3() { check(false, ContainerUtil.newArrayList( - new ColoredText("\u001B[1;31m red\u001B[0m normal\u001B[1;32m green\u001B", ProcessOutputTypes.STDOUT) - .addExpected(" red", "\u001B[1;31m") + new ColoredText("\u001B[1m\u001B[31m red" + + "\u001B[0m normal" + + "\u001B[1m\u001B[32m green" + + "\u001B", ProcessOutputTypes.STDOUT) + .addExpected(" red", "1;38;5;1m") .addExpected(" normal", STDOUT_KEY) - .addExpected(" green", "\u001B[1;32m"), - new ColoredText("[0m\n", ProcessOutputTypes.STDOUT).addExpected("\n", STDOUT_KEY) + .addExpected(" green", "1;38;5;2m"), + new ColoredText("[0m\n", ProcessOutputTypes.STDOUT) + .addExpected("\n", STDOUT_KEY) )); } public void testStderr() { check(true, ContainerUtil.newArrayList( - new ColoredText("\u001B[33m Hello,", ProcessOutputTypes.STDOUT).addExpected(" Hello,", "\u001B[33m"), - new ColoredText("World!\n", ProcessOutputTypes.STDERR).addExpected("World!\n", STDERR_KEY), + new ColoredText("\u001B[33m Hello,", ProcessOutputTypes.STDOUT) + .addExpected(" Hello,", "38;5;3m"), + new ColoredText("World!\n", ProcessOutputTypes.STDERR) + .addExpected("World!\n", STDERR_KEY), new ColoredText("\u001B[41m Changed stderr background", ProcessOutputTypes.STDERR) - .addExpected(" Changed stderr background", "\u001B[41m"), + .addExpected(" Changed stderr background", "48;5;1m"), new ColoredText("Unchanged stdout background", ProcessOutputTypes.STDOUT) - .addExpected("Unchanged stdout background", "\u001B[33m") + .addExpected("Unchanged stdout background", "38;5;3m") )); } @@ -137,10 +198,8 @@ public class AnsiEscapeDecoderTest extends LightPlatformTestCase { private static void check(boolean testCharByCharProcessing, @NotNull List texts) { AnsiEscapeDecoder decoder = new AnsiEscapeDecoder(); List> actualColoredChunks = ContainerUtil.newArrayList(); - //noinspection CodeBlock2Expr - AnsiEscapeDecoder.ColoredTextAcceptor acceptor = (text, attributes) -> { - actualColoredChunks.add(Pair.create(text, attributes.toString())); - }; + AnsiEscapeDecoder.ColoredTextAcceptor acceptor = (text, attributes) -> + actualColoredChunks.add(Pair.create(text, StringUtil.trimStart(attributes.toString(), "\u001b[0;"))); for (ColoredText text : texts) { decoder.escapeText(text.myRawText, text.myOutputType, acceptor); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java index 7bcbb90ccebb..6eaa1a616411 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java @@ -24,10 +24,7 @@ import com.intellij.openapi.editor.impl.view.IterationState; import com.intellij.openapi.editor.markup.HighlighterLayer; import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.fileTypes.PlainTextFileType; import com.intellij.testFramework.EditorTestUtil; -import com.intellij.testFramework.fixtures.EditorMouseFixture; -import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; import org.junit.Assert; @@ -37,7 +34,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; -public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase { +public class IterationStateTest extends AbstractEditorTest { private Color DEFAULT_BACKGROUND; private Color CARET_ROW_BACKGROUND; private Color SELECTION_BACKGROUND; @@ -159,7 +156,7 @@ public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase init("abc"); getEditor().getColorsScheme().setAttributes(HighlighterColors.TEXT, new TextAttributes(Color.black, Color.white, null, null, Font.BOLD)); - IterationState it = new IterationState(getEditor(), 0, 3, null, false, false, true, false); + IterationState it = new IterationState((EditorEx)getEditor(), 0, 3, null, false, false, true, false); assertFalse(it.atEnd()); assertEquals(0, it.getStartOffset()); assertEquals(3, it.getEndOffset()); @@ -173,7 +170,7 @@ public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase assertNotNull(getEditor().getSoftWrapModel().getSoftWrap(2)); addRangeHighlighter(1, 3, 0, Color.red); addRangeHighlighter(1, 2, 1, Color.blue); - IterationState it = new IterationState(getEditor(), 0, 4, null, false, false, false, false); + IterationState it = new IterationState((EditorEx)getEditor(), 0, 4, null, false, false, false, false); it.advance(); it.advance(); assertFalse(it.atEnd()); @@ -183,19 +180,15 @@ public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase assertEquals(Color.red, it.getBeforeLineStartBackgroundAttributes().getBackgroundColor()); } - private EditorImpl getEditor() { - return (EditorImpl)myFixture.getEditor(); - } - - private void addRangeHighlighter(int startOffset, int endOffset, int layer, Color bgColor) { + private static void addRangeHighlighter(int startOffset, int endOffset, int layer, Color bgColor) { getEditor().getMarkupModel().addRangeHighlighter(startOffset, endOffset, layer, - new TextAttributes(null, bgColor, null, null, 0), + new TextAttributes(null, bgColor, null, null, Font.PLAIN), HighlighterTargetArea.EXACT_RANGE); } - private void verifySplitting(boolean checkForegroundColor, @NotNull Segment... expectedSegments) { - EditorEx editor = getEditor(); + private static void verifySplitting(boolean checkForegroundColor, @NotNull Segment... expectedSegments) { + EditorEx editor = (EditorEx)getEditor(); IterationState.CaretData caretData = IterationState.createCaretData(editor); IterationState iterationState = new IterationState(editor, 0, editor.getDocument().getTextLength(), caretData, false, false, true, false); @@ -214,16 +207,12 @@ public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase } private void init(String text) { - myFixture.configureByText(PlainTextFileType.INSTANCE, text); + configureFromFileText(getTestName(true) + ".txt", text); EditorTestUtil.setEditorVisibleSize(getEditor(), 1000, 1000); } - private void setColumnModeOn() { - getEditor().setColumnMode(true); - } - - private EditorMouseFixture mouse() { - return new EditorMouseFixture(getEditor()); + private static void setColumnModeOn() { + ((EditorEx)getEditor()).setColumnMode(true); } private static class Segment { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java index d0447268c4a6..825097dc7c93 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java @@ -40,6 +40,10 @@ public class SoftWrapTest extends AbstractEditorTest { doTestSoftWraps(10, "foo\nvery long text"); } + public void testNoWrapInsideFoldRegion() { + doTestSoftWraps(10, "starttext with spaceend"); + } + private static final String TAGS_PATTERN = "()|()|"; private void doTestSoftWraps(int wrapWidth, String text) { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index f66cde73f06a..fbbb588ee7cc 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -78,21 +78,18 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT } } - public void testLongLineOfIdSymbolsIsNotSoftWrapped() { + public void testLongLineOfIdSymbolsIsSoftWrapped() { String text = "abcdefghijklmnopqrstuvwxyz\n" + "123\n" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; init(15, text); - assertTrue(getSoftWrapModel().getRegisteredSoftWraps().isEmpty()); + verifySoftWrapPositions(14, 45); type('1'); - assertTrue(getSoftWrapModel().getRegisteredSoftWraps().isEmpty()); - - int offset = myEditor.getDocument().getText().indexOf("\n"); + verifySoftWrapPositions(14, 46); type(" test"); - assertEquals(1, getSoftWrapModel().getRegisteredSoftWraps().size()); - assertNotNull(getSoftWrapModel().getSoftWrap(offset)); + verifySoftWrapPositions(14, 27, 51); } public void testFoldRegionCollapsing() { @@ -164,23 +161,6 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT assertEquals(new VisualPosition(2, 4), myEditor.getCaretModel().getVisualPosition()); } - public void testTypingThatExceedsRightMarginOnLastSoftWrappedLine() { - String text = - "line1\n" + - "long line"; - - init(69, text, 10); - - int softWrapsBefore = getSoftWrapModel().getRegisteredSoftWraps().size(); - assertTrue(softWrapsBefore > 0); - - for (int i = 0; i < 10; i++) { - type(String.valueOf(i)); - assertEquals(softWrapsBefore, getSoftWrapModel().getRegisteredSoftWraps().size()); - assertEquals(myEditor.getDocument().getTextLength(), myEditor.getCaretModel().getOffset()); - } - } - public void testTrailingFoldRegionRemoval() { String text = "public class BrokenAlignment {\n" + @@ -451,7 +431,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT "line4\n" + "line5"; - init(43, text, 10); + init(63, text, 10); int start = text.indexOf("line3") - 1; addCollapsedFoldRegion(start, text.length(), "..."); assertEquals(1, getSoftWrapModel().getRegisteredSoftWraps().size()); @@ -718,7 +698,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT "444"; init(15, text); - assertEquals(new LogicalPosition(3, 0), myEditor.visualToLogicalPosition(new VisualPosition(4, 0))); + assertEquals(new LogicalPosition(3, 0), myEditor.visualToLogicalPosition(new VisualPosition(6, 0))); } public void testDeleteThatEndsOnLineWithMultiLineFoldRegion() { @@ -743,7 +723,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT assertEquals(new VisualPosition(1, 8), getEditor().offsetToVisualPosition(getEditor().getDocument().getTextLength() - 1)); } - public void testNoWrapAtFirstNonWsSymbolWithCustomIndent() { + public void testWrapAtFirstNonWsSymbolWithCustomIndent() { String text = " 1111111111111111111111111111111"; init(10, text); @@ -752,9 +732,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT //Trigger soft wraps recalculation. ((SoftWrapModelImpl)myEditor.getSoftWrapModel()).prepareToMapping(); - // Don't expect soft wraps to be registered as there is no point in wrapping at the first non-white space symbol position - // in all cases when soft wrap is located at the left screen edge. - assertEmpty(getSoftWrapModel().getRegisteredSoftWraps()); + verifySoftWrapPositions(3, 11, 19, 27); } public void testLeadingTabWithShiftedWidth() { @@ -836,7 +814,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT } public void testMultiLineFoldRegionBeforeWrapPosition() { - final String text = + final String text = "package org.denis;\n" + "\n" + "\n" + @@ -866,7 +844,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT final List wraps = getSoftWrapModel().getRegisteredSoftWraps(); assertEquals(1, wraps.size()); - assertEquals(end, wraps.get(0).getStart()); + assertEquals(start, wraps.get(0).getStart()); assertEquals(myEditor.offsetToVisualPosition(start), myEditor.offsetToVisualPosition(start + 1)); assertEquals(myEditor.offsetToVisualPosition(start).line, myEditor.offsetToVisualPosition(end - 1).line); } @@ -985,9 +963,9 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT } public void testOnlyMinimalRangeIsRecalculatedOnDocumentChange() { - init("aa bb cc dd ee ff gg hh ii jj", TestFileType.TEXT); + init("aa bb cc dd ee ff gg hh ii jj", TestFileType.TEXT); EditorTestUtil.configureSoftWraps(myEditor, 8); - verifySoftWrapPositions(6, 12, 18, 24); + verifySoftWrapPositions(8, 15, 21); final IncrementalCacheUpdateEvent[] event = new IncrementalCacheUpdateEvent[1]; ((SoftWrapModelImpl)myEditor.getSoftWrapModel()).getApplianceManager().addListener(new SoftWrapAwareDocumentParsingListenerAdapter() { @@ -1000,10 +978,10 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT type(' '); - verifySoftWrapPositions(6, 12, 19, 25); + verifySoftWrapPositions(8, 15, 22); assertNotNull(event[0]); - assertEquals(6, event[0].getStartOffset()); - assertEquals(19, event[0].getActualEndOffset()); + assertEquals(8, event[0].getStartOffset()); + assertEquals(22, event[0].getActualEndOffset()); } public void testPositionsAreCorrectAfterIncrementalRecalculation() { @@ -1035,17 +1013,17 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT initText("unbreakableLine\nshort line"); configureSoftWraps(10); - verifySoftWrapPositions(); + verifySoftWrapPositions(10); } public void testFoldRegionPreventsLaterWrapping() { initText("unbreakableText.txt"); configureSoftWraps(10); - verifySoftWrapPositions(15); + verifySoftWrapPositions(10); addCollapsedFoldRegion(12, 13, "."); - verifySoftWrapPositions(12); + verifySoftWrapPositions(10); assertEquals(1, myEditor.offsetToVisualPosition(19).line); } diff --git a/platform/platform-tests/testSrc/com/intellij/ui/tree/ui/TreeControlPainterTest.java b/platform/platform-tests/testSrc/com/intellij/ui/tree/ui/TreeControlPainterTest.java index 64bcc55794a9..c8c927849d70 100644 --- a/platform/platform-tests/testSrc/com/intellij/ui/tree/ui/TreeControlPainterTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ui/tree/ui/TreeControlPainterTest.java @@ -8,6 +8,7 @@ import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; +import java.awt.Component; import java.awt.Graphics; import javax.swing.Icon; @@ -180,7 +181,7 @@ public class TreeControlPainterTest { } @Override - public void paint(@NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected) { + public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected) { } } } diff --git a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BackgroundTaskQueueTest.java b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BackgroundTaskQueueTest.java index 3504ca5a1d5d..598902a90c10 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BackgroundTaskQueueTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BackgroundTaskQueueTest.java @@ -282,7 +282,7 @@ public class BackgroundTaskQueueTest extends PlatformTestCase { private static void waitForTasks(TestTask... tasks) throws InterruptedException { for (TestTask task : tasks) { - task.waitFor(1, TimeUnit.SECONDS); + task.waitFor(1, TimeUnit.MINUTES); } } diff --git a/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java b/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java index a8c89ca98f4f..c5a4e5a47bb6 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java @@ -27,6 +27,7 @@ import com.intellij.openapi.roots.ContentIterator; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -49,15 +50,13 @@ public class LightProjectDescriptor { public static final String TEST_MODULE_NAME = "light_idea_test_case"; public void setUpProject(@NotNull Project project, @NotNull SetupHandler handler) throws Exception { - WriteAction.run(() -> { - Module module = createMainModule(project); - handler.moduleCreated(module); - VirtualFile sourceRoot = createSourcesRoot(module); - if (sourceRoot != null) { - handler.sourceRootCreated(sourceRoot); - createContentEntry(module, sourceRoot); - } - }); + Module module = createMainModule(project); + handler.moduleCreated(module); + VirtualFile sourceRoot = WriteAction.compute((ThrowableComputable)() -> createSourcesRoot(module)); + if (sourceRoot != null) { + handler.sourceRootCreated(sourceRoot); + createContentEntry(module, sourceRoot); + } } @NotNull diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 9492c2371a53..42dbe57cdf9e 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1179,7 +1179,8 @@ git.process.ignored=true git.process.ignored.description=Process and highlight Git ignored files. git.update.incoming.outgoing.info=true git.update.incoming.outgoing.info.description=Update branches info that have incoming/outgoing commits in the Branches popup. - +git.merge.conflicts.toolwindow=false +git.merge.conflicts.toolwindow.description=Show dedicated toolwindow for git merge conflicts hg4idea.process.ignored=true hg4idea.process.ignored.description=Process and highlight mercurial ignored files. \ @@ -1190,6 +1191,11 @@ github.action.pullrequest.state.useapi=false github.action.pullrequest.state.useapi.description=If enabled merge/close API actions will be available instead of browser link. \ Reopen toolwindow to apply. +# todo: deliberately left here for now as it's used in an IDE wizard step (before registry extensions are collected) +cidr.cygwin.cmakePermissionsFix=true +cidr.cygwin.cmakePermissionsFix.description=Update permissions for the bin/ folder inside the installed IDE so that the bundled CMake could run + + # via ExternalSystemApiUtil.isInProcessMode # suppress inspection "UnusedProperty" CompDB.system.in.process=true @@ -1706,7 +1712,7 @@ clipboard.history.max.items.description=Maximum number of items in clipboard his clipboard.history.max.memory=10000000 clipboard.history.max.memory.description=Amount of memory (approximate, order-of-magnitude) clipboard history is allowed to take -editor.old.soft.wrap.logic=true +editor.old.soft.wrap.logic=false editor.old.soft.wrap.logic.description=Restores legacy soft wrap placement logic plugins.show.implementation.details=false diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 5408decbb241..0494209ed163 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -15,6 +15,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.IntFunction; @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") public class ContainerUtil extends ContainerUtilRt { @@ -555,6 +556,27 @@ public class ContainerUtil extends ContainerUtilRt { return elements.size() > i ? elements.get(i) : defaultValue; } + @NotNull + @Contract(pure=true) + public static Iterator mapIterator(@NotNull TIntIterator iterator, @NotNull IntFunction mapper) { + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public U next() { + return mapper.apply(iterator.next()); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + public static class ImmutableMapBuilder { private final Map myMap = new THashMap<>(); diff --git a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java index 8ed59e2ff484..63b4015f5009 100644 --- a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java +++ b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java @@ -119,8 +119,13 @@ public abstract class FilteredTraverserBase roots) { - return newInstance(myMeta.withRoots(roots)); + public final Self withRoots(@Nullable T... roots) { + return newInstance(myMeta.withRoots(JBIterable.of(roots))); + } + + @NotNull + public final Self withRoots(@Nullable Iterable roots) { + return newInstance(myMeta.withRoots(roots != null ? roots : JBIterable.empty())); } @NotNull diff --git a/platform/util/src/com/intellij/util/io/IOUtil.java b/platform/util/src/com/intellij/util/io/IOUtil.java index ae45f9cce1c2..731002dcf52c 100644 --- a/platform/util/src/com/intellij/util/io/IOUtil.java +++ b/platform/util/src/com/intellij/util/io/IOUtil.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.io.*; import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -119,14 +120,6 @@ public class IOUtil { } } - private static final ThreadLocalCachedValue spareBufferLocal = new ThreadLocalCachedValue() { - @NotNull - @Override - protected char[] create() { - return new char[STRING_LENGTH_THRESHOLD]; - } - }; - public static String readUTFFast(@NotNull byte[] buffer, @NotNull DataInput storage) throws IOException { int len = 0xFF & (int)storage.readByte(); if (len == 0xFF) { @@ -141,9 +134,7 @@ public class IOUtil { if (len == 0) return ""; storage.readFully(buffer, 0, len); - char[] chars = spareBufferLocal.getValue(); - for (int i = 0; i < len; ++i) chars[i] = (char)(buffer[i] & 0xFF); - return new String(chars, 0, len); + return new String(buffer, 0, len, StandardCharsets.ISO_8859_1); } public static boolean isAscii(@NotNull String str) { diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 3a8aed5bacb6..8f4fae34320a 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -1139,6 +1139,31 @@ public class JBUI { : UIUtil.getPanelBackground(); } } + + public static class NewClassDialog { + @NotNull + public static Color searchFieldBackground() { + return JBColor.namedColor("NewClass.SearchField.background", 0xffffff); + } + + @NotNull + public static Color panelBackground() { + return JBColor.namedColor("NewClass.Panel.background", 0xf2f2f2); + } + + @NotNull + public static Color bordersColor() { + return JBColor.namedColor( + "TextField.borderColor", + JBColor.namedColor("Component.borderColor", new JBColor(0xbdbdbd, 0x646464)) + ); + } + + @NotNull + public static int fieldsSeparatorWidth() { + return getInt("NewClass.separatorWidth", JBUI.scale(10)); + } + } } diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java index dad1ad6a7406..1ae1607ef0a3 100644 --- a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java +++ b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java @@ -23,7 +23,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; +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.util.Comparing; import com.intellij.openapi.util.Ref; @@ -37,6 +39,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.*; import com.intellij.openapi.wm.StatusBar; import com.intellij.util.Function; +import com.intellij.util.ThrowableConvertor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -416,6 +419,19 @@ public class VcsUtil { return result; } + public static T computeWithModalProgress(@Nullable Project project, + @NotNull String title, + boolean canBeCancelled, + @NotNull ThrowableConvertor computable) + throws VcsException { + return ProgressManager.getInstance().run(new Task.WithResult(project, title, canBeCancelled) { + @Override + protected T compute(@NotNull ProgressIndicator indicator) throws VcsException { + return computable.convert(indicator); + } + }); + } + @Deprecated @Nullable public static VirtualFile waitForTheFile(@NotNull String path) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipAndQueue.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipAndQueue.java index 745ea954c999..1c276fd91873 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipAndQueue.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipAndQueue.java @@ -21,7 +21,6 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.SomeQueue; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.ZipperUpdater; import org.jetbrains.annotations.NotNull; @@ -35,9 +34,13 @@ public class ZipAndQueue { private final Runnable myInZipper; private Task.Backgroundable myInvokedOnQueue; - public ZipAndQueue(@NotNull Project project, final int interval, final String title, final Runnable runnable) { + public ZipAndQueue(@NotNull Project project, + final int interval, + final String title, + @NotNull Disposable parentDisposable, + final Runnable runnable) { final int correctedInterval = interval <= 0 ? 300 : interval; - myZipperUpdater = new ZipperUpdater(correctedInterval, project); + myZipperUpdater = new ZipperUpdater(correctedInterval, parentDisposable); myQueue = new BackgroundTaskQueue(project, title); myInZipper = () -> myQueue.run(myInvokedOnQueue); myInvokedOnQueue = new Task.Backgroundable(project, title, false) { @@ -46,19 +49,9 @@ public class ZipAndQueue { runnable.run(); } }; - Disposer.register(project, new Disposable() { - @Override - public void dispose() { - myZipperUpdater.stop(); - } - }); } public void request() { myZipperUpdater.queue(myInZipper); } - - public void stop() { - myZipperUpdater.stop(); - } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchBaseVersionProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchBaseVersionProvider.java index d16fceded8e0..20d85ec519d2 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchBaseVersionProvider.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchBaseVersionProvider.java @@ -19,11 +19,7 @@ package com.intellij.openapi.vcs.changes.patch; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; import com.intellij.openapi.progress.ProcessCanceledException; -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.util.ThrowableComputable; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.ProjectLevelVcsManager; @@ -33,10 +29,8 @@ import com.intellij.openapi.vcs.diff.DiffProvider; import com.intellij.openapi.vcs.history.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Processor; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.CalledInAny; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Date; @@ -89,8 +83,8 @@ public class DefaultPatchBaseVersionProvider { final VcsRevisionNumber finalRevision = revision; try { if (finalRevision != null) { - final boolean loadedExactRevision = - computeInBackgroundTask(myProject, message("progress.text2.loading.revision", finalRevision.asString()), true, () -> { + String message = message("progress.text2.loading.revision", finalRevision.asString()); + boolean loadedExactRevision = VcsUtil.computeWithModalProgress(myProject, message, true, indicator -> { if (historyProvider instanceof VcsBaseRevisionAdviser) { VcsBaseRevisionAdviser revisionAdviser = (VcsBaseRevisionAdviser)historyProvider; return revisionAdviser.getBaseVersionContent(filePath, processor, finalRevision.asString()); @@ -131,8 +125,8 @@ public class DefaultPatchBaseVersionProvider { final VcsHistorySession historySession; try { - historySession = computeInBackgroundTask(myProject, message("loading.file.history.progress"), true, - () -> historyProvider.createSessionFor(filePath)); + historySession = VcsUtil.computeWithModalProgress(myProject, message("loading.file.history.progress"), true, + indicator -> historyProvider.createSessionFor(filePath)); } catch (ProcessCanceledException e) { return; @@ -203,16 +197,4 @@ public class DefaultPatchBaseVersionProvider { } return null; } - - public static T computeInBackgroundTask(@Nullable Project project, - @Nls(capitalization = Nls.Capitalization.Title) @NotNull String title, - boolean canBeCancelled, - @NotNull ThrowableComputable computable) throws E { - return ProgressManager.getInstance().run(new Task.WithResult(project, title, canBeCancelled) { - @Override - protected T compute(@NotNull ProgressIndicator indicator) throws E { - return computable.compute(); - } - }); - } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/PatchDiffRequestFactory.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/PatchDiffRequestFactory.java index 676d2f8d7d06..6055402570aa 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/PatchDiffRequestFactory.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/PatchDiffRequestFactory.java @@ -20,6 +20,7 @@ import com.intellij.diff.DiffRequestFactory; import com.intellij.diff.InvalidDiffRequestException; import com.intellij.diff.chains.DiffRequestProducerException; import com.intellij.diff.contents.DocumentContent; +import com.intellij.diff.merge.MergeCallback; import com.intellij.diff.merge.MergeRequest; import com.intellij.diff.merge.MergeResult; import com.intellij.diff.requests.DiffRequest; @@ -209,8 +210,9 @@ public class PatchDiffRequestFactory { if (patchTitle == null) patchTitle = VcsBundle.message("patch.apply.conflict.patch"); DocumentContent resultContent = DiffContentFactory.getInstance().create(project, document, file); - return new ApplyPatchMergeRequest(project, resultContent, textPatch, localContent, - windowTitle, localTitle, resultTitle, patchTitle, callback); + ApplyPatchMergeRequest request = new ApplyPatchMergeRequest(project, resultContent, textPatch, localContent, + windowTitle, localTitle, resultTitle, patchTitle); + return MergeCallback.register(request, callback); } @NotNull diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeRequest.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeRequest.java index 67bd6b70ab04..9c5f37ad206e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeRequest.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeRequest.java @@ -16,13 +16,14 @@ package com.intellij.openapi.vcs.changes.patch.tool; import com.intellij.diff.contents.DocumentContent; +import com.intellij.diff.merge.MergeCallback; import com.intellij.diff.merge.MergeRequest; import com.intellij.diff.merge.MergeResult; +import com.intellij.diff.merge.MergeUtil; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.changes.patch.AppliedTextPatch; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,8 +41,6 @@ public class ApplyPatchMergeRequest extends MergeRequest implements ApplyPatchRe @NotNull private final String myResultTitle; @NotNull private final String myPatchTitle; - @Nullable private final Consumer myCallback; - public ApplyPatchMergeRequest(@Nullable Project project, @NotNull DocumentContent resultContent, @NotNull AppliedTextPatch appliedPatch, @@ -49,8 +48,7 @@ public class ApplyPatchMergeRequest extends MergeRequest implements ApplyPatchRe @Nullable String windowTitle, @NotNull String localTitle, @NotNull String resultTitle, - @NotNull String patchTitle, - @Nullable Consumer callback) { + @NotNull String patchTitle) { myProject = project; myResultContent = resultContent; myAppliedPatch = appliedPatch; @@ -62,8 +60,6 @@ public class ApplyPatchMergeRequest extends MergeRequest implements ApplyPatchRe myLocalTitle = localTitle; myResultTitle = resultTitle; myPatchTitle = patchTitle; - - myCallback = callback; } @Nullable @@ -118,7 +114,7 @@ public class ApplyPatchMergeRequest extends MergeRequest implements ApplyPatchRe final CharSequence applyContent; switch (result) { case CANCEL: - applyContent = myOriginalContent; + applyContent = MergeUtil.shouldRestoreOriginalContentOnCancel(this) ? myOriginalContent : null; break; case LEFT: applyContent = myLocalContent; @@ -136,6 +132,6 @@ public class ApplyPatchMergeRequest extends MergeRequest implements ApplyPatchRe WriteCommandAction.writeCommandAction(myProject).run(() -> myResultContent.getDocument().setText(applyContent)); } - if (myCallback != null) myCallback.consume(result); + MergeCallback.getCallback(this).applyResult(result); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNodeRenderer.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNodeRenderer.java index 7c546828d098..f32e54872772 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNodeRenderer.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNodeRenderer.java @@ -49,7 +49,7 @@ public class ChangesBrowserNodeRenderer extends ColoredTreeCellRenderer { SpeedSearchUtil.applySpeedSearchHighlighting(tree, this, true, selected); } - protected void appendFileName(@Nullable VirtualFile vFile, @NotNull String fileName, Color color) { + public void appendFileName(@Nullable VirtualFile vFile, @NotNull String fileName, Color color) { ChangesFileNameDecorator decorator = myProject != null && !myProject.isDefault() ? ChangesFileNameDecorator.getInstance(myProject) : null; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java index 95dbd4e1f0a9..a764afe10c11 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java @@ -22,7 +22,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.CountDownLatch; public class ChangesViewContentManager implements ChangesViewContentI { @@ -65,9 +67,8 @@ public class ChangesViewContentManager implements ChangesViewContentI { loadExtensionTabs(); myContentManager = contentManager; - final List ordered = doPresetOrdering(myAddedContents); - for(Content content: ordered) { - myContentManager.addContent(content); + for (Content content : myAddedContents) { + addIntoCorrectPlace(content); } myAddedContents.clear(); if (contentManager.getContentCount() > 0) { @@ -257,54 +258,66 @@ public class ChangesViewContentManager implements ChangesViewContentI { } } + public static final Key ORDER_WEIGHT_KEY = Key.create("ChangesView.ContentOrderWeight"); public static final String LOCAL_CHANGES = "Local Changes"; public static final String REPOSITORY = "Repository"; public static final String INCOMING = "Incoming"; public static final String SHELF = "Shelf"; - private static final String[] ourPresetOrder = {LOCAL_CHANGES, REPOSITORY, INCOMING, SHELF}; - private static List doPresetOrdering(final List contents) { - final List result = new ArrayList<>(contents.size()); - for (final String preset : ourPresetOrder) { - for (Iterator iterator = contents.iterator(); iterator.hasNext();) { - final Content current = iterator.next(); - if (preset.equals(current.getTabName())) { - iterator.remove(); - result.add(current); - } - } + + public enum TabOrderWeight { + LOCAL_CHANGES(ChangesViewContentManager.LOCAL_CHANGES, 10), + REPOSITORY(ChangesViewContentManager.REPOSITORY, 20), + INCOMING(ChangesViewContentManager.INCOMING, 30), + SHELF(ChangesViewContentManager.SHELF, 40), + OTHER(null, 100); + + @Nullable private final String myName; + private final int myWeight; + + TabOrderWeight(@Nullable String name, int weight) { + myName = name; + myWeight = weight; + } + + @Nullable + private String getName() { + return myName; + } + + public int getWeight() { + return myWeight; } - result.addAll(contents); - return result; } private void addIntoCorrectPlace(final Content content) { - final String name = content.getTabName(); + int weight = getContentWeight(content); + final Content[] contents = myContentManager.getContents(); - int idxOfBeingInserted = -1; - for (int i = 0; i < ourPresetOrder.length; i++) { - final String s = ourPresetOrder[i]; - if (s.equals(name)) { - idxOfBeingInserted = i; + int index = -1; + for (int i = 0; i < contents.length; i++) { + int oldWeight = getContentWeight(contents[i]); + if (oldWeight > weight) { + index = i; + break; } } - if (idxOfBeingInserted == -1) { - myContentManager.addContent(content); - return; - } - final Set existingNames = new HashSet<>(); - for (Content existingContent : contents) { - existingNames.add(existingContent.getTabName()); - } + if (index == -1) index = contents.length; + myContentManager.addContent(content, index); + } - int place = idxOfBeingInserted; - for (int i = 0; i < idxOfBeingInserted; i++) { - if (! existingNames.contains(ourPresetOrder[i])) { - -- place; + private static int getContentWeight(Content content) { + Integer userData = content.getUserData(ORDER_WEIGHT_KEY); + if (userData != null) return userData; + + String tabName = content.getTabName(); + for (TabOrderWeight value : TabOrderWeight.values()) { + if (value.getName() != null && value.getName().equals(tabName)) { + return value.getWeight(); } - } - myContentManager.addContent(content, place); + + return TabOrderWeight.OTHER.getWeight(); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MergeConflictsTreeTable.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MergeConflictsTreeTable.kt new file mode 100644 index 000000000000..d57d463a89e1 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MergeConflictsTreeTable.kt @@ -0,0 +1,48 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.vcs.merge + +import com.intellij.openapi.util.text.StringUtil +import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns +import com.intellij.ui.treeStructure.treetable.TreeTable +import com.intellij.util.ui.ColumnInfo +import com.intellij.util.ui.JBUI + +class MergeConflictsTreeTable(private val tableModel: ListTreeTableModelOnColumns) : TreeTable(tableModel) { + init { + getTableHeader().reorderingAllowed = false + tree.isRootVisible = false + if (tableModel.columnCount > 1) setShowColumns(true) + } + + override fun doLayout() { + if (getTableHeader().resizingColumn == null) { + updateColumnSizes() + } + super.doLayout() + } + + private fun updateColumnSizes() { + for ((index, columnInfo) in tableModel.columns.withIndex()) { + val column = columnModel.getColumn(index) + columnInfo.maxStringValue?.let { + val width = calcColumnWidth(it, columnInfo) + column.preferredWidth = width + } + } + + var size = width + val fileColumn = 0 + for (i in 0 until tableModel.columns.size) { + if (i == fileColumn) continue + size -= columnModel.getColumn(i).preferredWidth + } + + columnModel.getColumn(fileColumn).preferredWidth = Math.max(size, JBUI.scale(200)) + } + + private fun calcColumnWidth(maxStringValue: String, columnInfo: ColumnInfo): Int { + val columnName = StringUtil.shortenTextWithEllipsis(columnInfo.name, 15, 7, true) + return Math.max(getFontMetrics(font).stringWidth(maxStringValue), + getFontMetrics(tableHeader.font).stringWidth(columnName)) + columnInfo.additionalWidth + } +} \ No newline at end of file diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.kt index 28f801ac1395..56956d3f15b4 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.kt @@ -12,13 +12,11 @@ import com.intellij.diff.merge.MergeUtil import com.intellij.diff.util.DiffUtil import com.intellij.openapi.command.WriteCommandAction.writeCommandAction import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.diff.impl.mergeTool.MergeVersion import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.Messages import com.intellij.openapi.util.io.FileTooBigException -import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vcs.VcsBundle import com.intellij.openapi.vcs.VcsConfiguration import com.intellij.openapi.vcs.VcsException @@ -37,7 +35,6 @@ import com.intellij.ui.treeStructure.treetable.TreeTable import com.intellij.ui.treeStructure.treetable.TreeTableModel import com.intellij.util.containers.Convertor import com.intellij.util.ui.ColumnInfo -import com.intellij.util.ui.JBUI import com.intellij.util.ui.UIUtil import com.intellij.util.ui.tree.TreeUtil import org.jetbrains.annotations.NonNls @@ -125,13 +122,9 @@ open class MultipleFileMergeDialog( } row { - scrollPane(MyTable(tableModel).also { + scrollPane(MergeConflictsTreeTable(tableModel).also { table = it - it.tree.isRootVisible = false it.setTreeCellRenderer(virtualFileRenderer) - if (tableModel.columnCount > 1) { - it.setShowColumns(true) - } it.rowHeight = virtualFileRenderer.preferredSize.height }, growX, growY, pushX, pushY) @@ -195,45 +188,6 @@ open class MultipleFileMergeDialog( override fun getTooltipText() = base.tooltipText ?: columnName } - private class MyTable(private val tableModel: ListTreeTableModelOnColumns) : TreeTable(tableModel) { - - init { - getTableHeader().reorderingAllowed = false - } - - override fun doLayout() { - if (getTableHeader().resizingColumn == null) { - updateColumnSizes() - } - super.doLayout() - } - - private fun updateColumnSizes() { - for ((index, columnInfo) in tableModel.columns.withIndex()) { - val column = columnModel.getColumn(index) - columnInfo.maxStringValue?.let { - val width = calcColumnWidth(it, columnInfo) - column.preferredWidth = width - } - } - - var size = width - val fileColumn = 0 - for (i in 0 until tableModel.columns.size) { - if (i == fileColumn) continue - size -= columnModel.getColumn(i).preferredWidth - } - - columnModel.getColumn(fileColumn).preferredWidth = Math.max(size, JBUI.scale(200)) - } - - private fun calcColumnWidth(maxStringValue: String, columnInfo: ColumnInfo): Int { - val columnName = StringUtil.shortenTextWithEllipsis(columnInfo.name, 15, 7, true) - return Math.max(getFontMetrics(font).stringWidth(maxStringValue), - getFontMetrics(tableHeader.font).stringWidth(columnName)) + columnInfo.additionalWidth - } - } - private fun toggleGroupByDirectory(state: Boolean) { groupByDirectory = state val firstSelectedFile = getSelectedFiles().firstOrNull() @@ -456,7 +410,7 @@ open class MultipleFileMergeDialog( } private fun checkMarkModifiedProject(file: VirtualFile) { - MergeVersion.MergeDocumentVersion.reportProjectFileChangeIfNeeded(project, file) + MergeUtil.reportProjectFileChangeIfNeeded(project, file) } override fun getPreferredFocusedComponent(): JComponent? = table diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringEqualsCharSequenceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringEqualsCharSequenceInspection.java index c4e3603b56af..f2e8ae50d7ab 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringEqualsCharSequenceInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringEqualsCharSequenceInspection.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.siyeh.ig.bugs; import com.intellij.codeInspection.ProblemDescriptor; @@ -97,7 +83,8 @@ public class StringEqualsCharSequenceInspection extends BaseInspection { if (!leftType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { return; } - if (rightType.equalsToText(CommonClassNames.JAVA_LANG_STRING) || !InheritanceUtil.isInheritor(rightType, "java.lang.CharSequence")) { + if (rightType.equalsToText(CommonClassNames.JAVA_LANG_STRING) || + !InheritanceUtil.isInheritor(rightType, CommonClassNames.JAVA_LANG_CHARSEQUENCE)) { return; } final PsiElement name = expression.getReferenceNameElement(); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java index ec93f85b7e5d..a97106a51af4 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java @@ -33,6 +33,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.intellij.psi.CommonClassNames.JAVA_LANG_CHARSEQUENCE; import static com.intellij.util.ObjectUtils.tryCast; /** @@ -329,7 +330,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { final PsiExpression argument = arguments[0]; final PsiType type = argument.getType(); if (!PsiType.INT.equals(type)) { - if (type != null && type.equalsToText("java.lang.CharSequence")) { + if (type != null && type.equalsToText(JAVA_LANG_CHARSEQUENCE)) { result.append("String.valueOf(").append(tracker.textWithComments(argument)).append(')'); } else { diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java index 141b02cf8055..6900a790d800 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java @@ -24,6 +24,7 @@ import com.intellij.cvsSupport2.cvsIgnore.IgnoredFilesInfo; import com.intellij.cvsSupport2.cvsIgnore.UserDirIgnores; import com.intellij.cvsSupport2.cvsstatuses.CvsEntriesListener; import com.intellij.cvsSupport2.util.CvsVfsUtil; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -63,7 +64,6 @@ public class CvsEntriesManager implements VirtualFileListener { private final Map myStringToSettingsMap = new THashMap<>(); private final UserDirIgnores myUserDirIgnores = new UserDirIgnores(); - private final MyVirtualFileManagerListener myVirtualFileManagerListener = new MyVirtualFileManagerListener(); private final CvsApplicationLevelConfiguration myApplicationLevelConfiguration; public static CvsEntriesManager getInstance() { @@ -85,10 +85,10 @@ public class CvsEntriesManager implements VirtualFileListener { } } - public void registerAsVirtualFileListener() { + public void registerAsVirtualFileListener(@NotNull Disposable listenerDisposable) { if (myIsActive == 0) { - VirtualFileManager.getInstance().addVirtualFileListener(this); - VirtualFileManager.getInstance().addVirtualFileManagerListener(myVirtualFileManagerListener); + VirtualFileManager.getInstance().addVirtualFileListener(this, listenerDisposable); + VirtualFileManager.getInstance().addVirtualFileManagerListener(new MyVirtualFileManagerListener(), listenerDisposable); } myIsActive++; } @@ -97,8 +97,6 @@ public class CvsEntriesManager implements VirtualFileListener { LOG.assertTrue(isActive()); myIsActive--; if (myIsActive == 0) { - VirtualFileManager.getInstance().removeVirtualFileListener(this); - VirtualFileManager.getInstance().removeVirtualFileManagerListener(myVirtualFileManagerListener); myInfoByParentDirectoryPath.clear(); } } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsStorageSupportingDeletionComponent.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsStorageSupportingDeletionComponent.java index a01ae14aa326..0b7a8aa33686 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsStorageSupportingDeletionComponent.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsStorageSupportingDeletionComponent.java @@ -46,7 +46,7 @@ public class CvsStorageSupportingDeletionComponent implements VirtualFileListene myProject = project; initializeDeletedStorage(); VirtualFileManager.getInstance().addVirtualFileListener(this, myListenerDisposable); - CvsEntriesManager.getInstance().registerAsVirtualFileListener(); + CvsEntriesManager.getInstance().registerAsVirtualFileListener(myListenerDisposable); project.getMessageBus().connect(myListenerDisposable).subscribe(CommandListener.TOPIC, new CommandListener() { @Override public void commandStarted(@NotNull CommandEvent event) { diff --git a/plugins/git4idea/resources/META-INF/plugin.xml b/plugins/git4idea/resources/META-INF/plugin.xml index 5fbd28114ac8..ce1d3846637d 100644 --- a/plugins/git4idea/resources/META-INF/plugin.xml +++ b/plugins/git4idea/resources/META-INF/plugin.xml @@ -256,6 +256,7 @@ + + + + + git4idea.conflicts.GitConflictsToolWindowManager + + diff --git a/plugins/git4idea/src/git4idea/conflicts/GitConflictsToolWindowManager.java b/plugins/git4idea/src/git4idea/conflicts/GitConflictsToolWindowManager.java new file mode 100644 index 000000000000..f9906790032f --- /dev/null +++ b/plugins/git4idea/src/git4idea/conflicts/GitConflictsToolWindowManager.java @@ -0,0 +1,69 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package git4idea.conflicts; + +import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.vcs.changes.ui.ChangesViewContentI; +import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentFactory; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.update.MergingUpdateQueue; +import com.intellij.util.ui.update.Update; +import git4idea.repo.GitConflictsHolder; +import git4idea.repo.GitRepository; +import git4idea.repo.GitRepositoryManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class GitConflictsToolWindowManager implements ProjectComponent { + public static final String TAB_NAME = "Conflicts"; + + @NotNull private final Project myProject; + @NotNull private final ChangesViewContentI myContentManager; + @NotNull private final GitRepositoryManager myRepositoryManager; + + private final MergingUpdateQueue myQueue; + + @Nullable private Content myContent; + + public GitConflictsToolWindowManager(@NotNull Project project, + @NotNull ChangesViewContentI contentManager, + @NotNull GitRepositoryManager repositoryManager) { + myProject = project; + myContentManager = contentManager; + myRepositoryManager = repositoryManager; + + myQueue = new MergingUpdateQueue("GitConflictsToolWindowManager", 300, true, null, myProject); + + project.getMessageBus().connect().subscribe(GitConflictsHolder.CONFLICTS_CHANGE, new GitConflictsHolder.ConflictsListener() { + @Override + public void conflictsChanged(@NotNull GitRepository repository) { + myQueue.queue(Update.create("update", () -> updateToolWindow())); + } + }); + } + + private void updateToolWindow() { + if (!Registry.is("git.merge.conflicts.toolwindow")) return; + + boolean hasConflicts = ContainerUtil.exists(myRepositoryManager.getRepositories(), + repo -> !repo.getConflictsHolder().getConflicts().isEmpty()); + if (hasConflicts && myContent == null) { + GitConflictsView panel = new GitConflictsView(myProject); + myContent = ContentFactory.SERVICE.getInstance().createContent(panel.getComponent(), TAB_NAME, false); + myContent.putUserData(ChangesViewContentManager.ORDER_WEIGHT_KEY, + ChangesViewContentManager.TabOrderWeight.REPOSITORY.getWeight() + 1); + myContent.setCloseable(false); + myContent.setPreferredFocusedComponent(() -> panel.getPreferredFocusableComponent()); + Disposer.register(myContent, panel); + myContentManager.addContent(myContent); + } + if (!hasConflicts && myContent != null) { + myContentManager.removeContent(myContent); + myContent = null; + } + } +} diff --git a/plugins/git4idea/src/git4idea/conflicts/GitConflictsView.kt b/plugins/git4idea/src/git4idea/conflicts/GitConflictsView.kt new file mode 100644 index 000000000000..cff4a301cb82 --- /dev/null +++ b/plugins/git4idea/src/git4idea/conflicts/GitConflictsView.kt @@ -0,0 +1,270 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package git4idea.conflicts + +import com.intellij.icons.AllIcons +import com.intellij.openapi.Disposable +import com.intellij.openapi.actionSystem.* +import com.intellij.openapi.application.runInEdt +import com.intellij.openapi.progress.runBackgroundableTask +import com.intellij.openapi.project.DumbAwareAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.SimpleToolWindowPanel +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vcs.FileStatus +import com.intellij.openapi.vcs.changes.ChangesUtil +import com.intellij.openapi.vcs.changes.ui.* +import com.intellij.openapi.vcs.changes.ui.ChangesTree.DEFAULT_GROUPING_KEYS +import com.intellij.openapi.vcs.merge.MergeConflictsTreeTable +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.ui.DoubleClickListener +import com.intellij.ui.ScrollPaneFactory +import com.intellij.ui.TableSpeedSearch +import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns +import com.intellij.ui.treeStructure.treetable.TreeTableModel +import com.intellij.util.Alarm +import com.intellij.util.containers.Convertor +import com.intellij.util.ui.ColumnInfo +import com.intellij.util.ui.UIUtil +import com.intellij.util.ui.tree.TreeUtil +import com.intellij.util.ui.update.MergingUpdateQueue +import com.intellij.util.ui.update.Update +import git4idea.GitUtil +import git4idea.merge.GitMergeUtil +import git4idea.repo.GitConflict +import git4idea.repo.GitConflict.ConflictSide +import git4idea.repo.GitConflictsHolder +import git4idea.repo.GitRepository +import git4idea.repo.GitRepositoryChangeListener +import java.awt.BorderLayout +import java.awt.event.MouseEvent +import java.beans.PropertyChangeListener +import javax.swing.JComponent +import javax.swing.JPanel +import javax.swing.tree.DefaultMutableTreeNode +import javax.swing.tree.TreeNode + +class GitConflictsView(private val project: Project) : Disposable { + private val mergeHandler: GitMergeHandler = GitMergeHandler(project) + + private val panel: SimpleToolWindowPanel + private val table: MergeConflictsTreeTable + private val tableModel: ListTreeTableModelOnColumns + + private val conflicts: MutableList = ArrayList() + private val reversedRoots: MutableSet = HashSet() + + private val updateQueue: MergingUpdateQueue + private val groupingSupport: ChangesGroupingSupport = ChangesGroupingSupport(project, this, false) + + init { + tableModel = ListTreeTableModelOnColumns(DefaultMutableTreeNode(), arrayOf(PathColumn(), YoursColumn(), TheirsColumn())) + table = MergeConflictsTreeTable(tableModel) + updateQueue = MergingUpdateQueue("GitConflictsView", 300, true, table, this, null, Alarm.ThreadToUse.POOLED_THREAD) + + val renderer = ChangesBrowserNodeRenderer(project, { !groupingSupport.isDirectory }, false) + renderer.font = UIUtil.getListFont() + table.setTreeCellRenderer(renderer) + table.rowHeight = renderer.preferredSize.height + + groupingSupport.addPropertyChangeListener(PropertyChangeListener { rebuildTree() }) + groupingSupport.setGroupingKeysOrSkip(DEFAULT_GROUPING_KEYS.toSet()) + + TableSpeedSearch(table, Convertor { (it as? GitConflict)?.filePath?.name }) + + + val actionManager = ActionManager.getInstance() + val toolbarGroup = DefaultActionGroup() + toolbarGroup.addAction(actionManager.getAction("ChangesView.Refresh")) + toolbarGroup.addAction(ResolveAction()) + toolbarGroup.addAction(AcceptSideAction(false)) + toolbarGroup.addAction(AcceptSideAction(true)) + toolbarGroup.addAction(actionManager.getAction(ChangesTree.GROUP_BY_ACTION_GROUP)) + val toolbar = actionManager.createActionToolbar("GitConflictsView", toolbarGroup, false) + toolbar.setTargetComponent(table) + + val mainPanel = MainPanel() + mainPanel.add(ScrollPaneFactory.createScrollPane(table), BorderLayout.CENTER) + + panel = SimpleToolWindowPanel(false, true) + panel.toolbar = toolbar.component + panel.setContent(mainPanel) + + + object : DoubleClickListener() { + override fun onDoubleClick(event: MouseEvent): Boolean { + showMergeWindowForSelection() + return true + } + }.installOn(table) + + val connection = project.messageBus.connect(this) + connection.subscribe(GitConflictsHolder.CONFLICTS_CHANGE, GitConflictsHolder.ConflictsListener { updateConflicts() }) + connection.subscribe(GitRepository.GIT_REPO_CHANGE, GitRepositoryChangeListener { updateConflicts() }) + + updateConflicts() + } + + val component: JComponent? get() = panel + val preferredFocusableComponent: JComponent? get() = table + + override fun dispose() { + } + + private fun getSelectedConflicts(): List { + return TreeUtil.collectSelectedObjectsOfType(table.tree, GitConflict::class.java) + } + + private fun updateConflicts() { + updateQueue.queue(Update.create("update") { + val newConflicts = ArrayList() + val newReversedRoots = ArrayList() + + val repos = GitUtil.getRepositories(project) + for (repo in repos) { + if (GitMergeUtil.isReverseRoot(repo)) newReversedRoots.add(repo.root) + newConflicts.addAll(repo.conflictsHolder.conflicts) + } + + runInEdt { + conflicts.clear() + conflicts.addAll(newConflicts) + + reversedRoots.clear() + reversedRoots.addAll(newReversedRoots) + + rebuildTree() + } + }) + } + + private fun rebuildTree() { + val builder = MyTreeModelBuilder(project, groupingSupport.grouping) + builder.addConflicts(conflicts) + val newRoot = builder.build().root + + tableModel.setRoot(newRoot as TreeNode) + TreeUtil.expandAll(table.tree) + } + + private fun showMergeWindowForSelection() { + val conflicts = getSelectedConflicts().filter { mergeHandler.canResolveConflict(it) }.toList() + if (conflicts.isEmpty()) return + + val reversed = HashSet(reversedRoots) + + for (conflict in conflicts) { + val file = conflict.filePath.virtualFile + MergeConflictResolveUtil.showMergeWindow(project, file) { + mergeHandler.resolveConflict(conflict, reversed.contains(conflict.root)) + } + } + } + + private fun acceptConflictSideForSelection(takeTheirs: Boolean) { + val conflicts = getSelectedConflicts() + if (conflicts.isEmpty()) return + + val reversed = HashSet(reversedRoots) + + runBackgroundableTask(StringUtil.pluralize("Resolving Conflict", conflicts.size), project, true) { + mergeHandler.acceptOneVersion(conflicts, reversed, takeTheirs) + } + } + + + private class PathColumn : ColumnInfo, Any?>("Path") { + override fun valueOf(node: ChangesBrowserNode<*>): Any? = node.userObject + override fun getColumnClass(): Class<*> = TreeTableModel::class.java + } + + private inner class YoursColumn : BaseColumn("Yours") { + override fun valueOf(o: ChangesBrowserNode<*>): String? { + val c = o.conflict ?: return null + val status = c.getStatus(ConflictSide.OURS, reversedRoots.contains(c.root)) + return status.name + } + } + + private inner class TheirsColumn : BaseColumn("Theirs") { + override fun valueOf(o: ChangesBrowserNode<*>): String? { + val c = o.conflict ?: return null + val status = c.getStatus(ConflictSide.THEIRS, reversedRoots.contains(c.root)) + return status.name + } + } + + private abstract class BaseColumn(name: String) : ColumnInfo, String>(name) { + protected val ChangesBrowserNode<*>.conflict: GitConflict? + get() = when (this) { + is ConflictChangesBrowserNode -> this.userObject + else -> null + } + } + + private inner class ResolveAction : DumbAwareAction("Resolve", null, AllIcons.Vcs.Merge) { + override fun actionPerformed(e: AnActionEvent) { + showMergeWindowForSelection() + } + } + + private inner class AcceptSideAction(val takeTheirs: Boolean) : + DumbAwareAction(if (takeTheirs) "Accept Theirs" else "Accept Yours", null, + if (takeTheirs) AllIcons.Vcs.Arrow_left else AllIcons.Vcs.Arrow_right) { + override fun actionPerformed(e: AnActionEvent) { + acceptConflictSideForSelection(takeTheirs) + } + } + + private inner class MainPanel : JPanel(BorderLayout()), DataProvider { + override fun getData(dataId: String): Any? { + if (ChangesGroupingSupport.KEY.`is`(dataId)) { + return groupingSupport + } + else if (CommonDataKeys.NAVIGATABLE_ARRAY.`is`(dataId)) { + return ChangesUtil.getNavigatableArray(project, getSelectedConflicts().mapNotNull { it.filePath.virtualFile }.stream()) + } + return null + } + } +} + +private class MyTreeModelBuilder(project: Project, grouping: ChangesGroupingPolicyFactory) : TreeModelBuilder(project, grouping) { + fun addConflicts(conflicts: List) { + for (conflict in conflicts) { + insertChangeNode(conflict.filePath, myRoot, ConflictChangesBrowserNode(conflict)) + } + } +} + +private class ConflictChangesBrowserNode(conflict: GitConflict) : ChangesBrowserNode(conflict) { + override fun isFile(): Boolean = true + override fun isDirectory(): Boolean = false + + override fun render(renderer: ChangesBrowserNodeRenderer, selected: Boolean, expanded: Boolean, hasFocus: Boolean) { + val filePath = getUserObject().filePath + renderer.appendFileName(filePath.virtualFile, filePath.name, FileStatus.MERGED_WITH_CONFLICTS.color) + + if (renderer.isShowFlatten) { + appendParentPath(renderer, filePath.parentPath) + } + + if (!renderer.isShowFlatten && fileCount != 1 || directoryCount != 0) { + appendCount(renderer) + } + + renderer.setIcon(filePath.fileType, filePath.isDirectory || !isLeaf) + } + + override fun getTextPresentation(): String { + return getUserObject().filePath.name + } + + override fun toString(): String { + return FileUtil.toSystemDependentName(getUserObject().filePath.path) + } + + override fun compareUserObjects(o2: GitConflict): Int { + return compareFilePaths(getUserObject().filePath, o2.filePath) + } +} diff --git a/plugins/git4idea/src/git4idea/conflicts/GitMergeHandler.java b/plugins/git4idea/src/git4idea/conflicts/GitMergeHandler.java new file mode 100644 index 000000000000..84f3cb562a54 --- /dev/null +++ b/plugins/git4idea/src/git4idea/conflicts/GitMergeHandler.java @@ -0,0 +1,197 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package git4idea.conflicts; + +import com.intellij.diff.merge.MergeCallback; +import com.intellij.diff.merge.MergeResult; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; +import com.intellij.openapi.vcs.merge.MergeData; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; +import git4idea.merge.GitDefaultMergeDialogCustomizer; +import git4idea.merge.GitMergeUtil; +import git4idea.repo.GitConflict; +import git4idea.repo.GitConflict.ConflictSide; +import git4idea.repo.GitConflict.Status; +import git4idea.repo.GitConflictsHolder; +import git4idea.repo.GitRepository; +import git4idea.repo.GitRepositoryManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +public class GitMergeHandler { + private static final Logger LOG = Logger.getInstance(GitMergeHandler.class); + + @NotNull private final Project myProject; + @NotNull private final GitDefaultMergeDialogCustomizer myDialogCustomizer; + + public GitMergeHandler(@NotNull Project project) { + myProject = project; + myDialogCustomizer = new GitDefaultMergeDialogCustomizer(project); + } + + public boolean canResolveConflict(@NotNull GitConflict conflict) { + VirtualFile file = conflict.getFilePath().getVirtualFile(); + if (file == null) return false; + if (file.isDirectory()) return false; // Can't handle conflicts in submodules + return conflict.getStatus(ConflictSide.OURS) != Status.DELETED || + conflict.getStatus(ConflictSide.THEIRS) != Status.DELETED; + } + + @NotNull + public Resolver resolveConflict(@NotNull GitConflict conflict, boolean isReversed) throws VcsException { + VirtualFile root = conflict.getRoot(); + FilePath path = conflict.getFilePath(); + + VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path.getPath()); + if (file == null) throw new VcsException("Can't find file for " + path); + + MergeData mergeData = GitMergeUtil.loadMergeData(myProject, root, path, isReversed); + + String windowTitle = myDialogCustomizer.getMergeWindowTitle(file); + String leftTitle = myDialogCustomizer.getLeftPanelTitle(file); + String centerTitle = myDialogCustomizer.getCenterPanelTitle(file); + String rightTitle = myDialogCustomizer.getRightPanelTitle(file, mergeData.LAST_REVISION_NUMBER); + + return new Resolver(myProject, conflict, isReversed, file, mergeData, + windowTitle, ContainerUtil.list(leftTitle, centerTitle, rightTitle)); + } + + public void acceptOneVersion(@NotNull Collection conflicts, + @NotNull Collection reversedRoots, + boolean takeTheirs) throws VcsException { + try { + MultiMap byRoot = groupConflictsByRoot(conflicts); + + for (VirtualFile root : byRoot.keySet()) { + Collection rootConflicts = byRoot.get(root); + boolean isReversed = reversedRoots.contains(root); + ConflictSide side = isReversed == takeTheirs ? ConflictSide.OURS : ConflictSide.THEIRS; + + GitMergeUtil.acceptOneVersion(myProject, root, rootConflicts, side); + GitMergeUtil.markConflictResolved(myProject, root, rootConflicts, side); + } + } + finally { + VcsDirtyScopeManager.getInstance(myProject).filePathsDirty(ContainerUtil.map(conflicts, GitConflict::getFilePath), null); + } + } + + @NotNull + public static MultiMap groupConflictsByRoot(@NotNull Collection conflicts) { + MultiMap byRoot = MultiMap.create(); + for (GitConflict conflict : conflicts) { + byRoot.putValue(conflict.getRoot(), conflict); + } + return byRoot; + } + + public static class Resolver { + @NotNull private final Project myProject; + @NotNull private final GitConflict myConflict; + private final boolean myIsReversed; + @NotNull private final MergeData myMergeData; + @NotNull private final VirtualFile myFile; + + @NotNull private final String myWindowTitle; + @NotNull private final List myContentTitles; + + private volatile boolean myIsValid = true; + + private Resolver(@NotNull Project project, + @NotNull GitConflict conflict, + boolean isReversed, + @NotNull VirtualFile file, + @NotNull MergeData mergeData, + @NotNull String windowTitle, + @NotNull List contentTitles) { + myProject = project; + myConflict = conflict; + myIsReversed = isReversed; + myMergeData = mergeData; + myFile = file; + myWindowTitle = windowTitle; + myContentTitles = contentTitles; + } + + @NotNull + public Project getProject() { + return myProject; + } + + @NotNull + public VirtualFile getVirtualFile() { + return myFile; + } + + @NotNull + public MergeData getMergeData() { + return myMergeData; + } + + public void onConflictResolved(@NotNull MergeResult result) { + if (result != MergeResult.CANCEL) { + try { + GitMergeUtil.markConflictResolved(myProject, myConflict.getRoot(), singletonList(myConflict), getResolutionSide(result)); + } + catch (VcsException e) { + LOG.error(String.format("Unexpected exception during the git operation: file - %s)", myConflict.getFilePath()), e); + } + } + VcsDirtyScopeManager.getInstance(myProject).filesDirty(singletonList(myFile), emptyList()); + } + + @Nullable + private ConflictSide getResolutionSide(@NotNull MergeResult result) { + switch (result) { + case LEFT: + return !myIsReversed ? ConflictSide.OURS : ConflictSide.THEIRS; + case RIGHT: + return myIsReversed ? ConflictSide.OURS : ConflictSide.THEIRS; + default: + return null; + } + } + + @NotNull + public String getWindowTitle() { + return myWindowTitle; + } + + @NotNull + public List getContentTitles() { + return myContentTitles; + } + + public boolean checkIsValid() { + if (myIsValid) { + GitRepository repository = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(myConflict.getRoot()); + if (repository == null) return true; + myIsValid = repository.getConflictsHolder().findConflict(myConflict.getFilePath()) != null; + } + return myIsValid; + } + + public void addListener(@NotNull MergeCallback.Listener listener, @NotNull Disposable disposable) { + myProject.getMessageBus().connect(disposable).subscribe(GitConflictsHolder.CONFLICTS_CHANGE, (repo) -> { + if (myIsValid && myConflict.getRoot().equals(repo.getRoot())) { + if (!checkIsValid()) { + listener.fireConflictInvalid(); + } + } + }); + } + } +} diff --git a/plugins/git4idea/src/git4idea/conflicts/MergeConflictResolveUtil.kt b/plugins/git4idea/src/git4idea/conflicts/MergeConflictResolveUtil.kt new file mode 100644 index 000000000000..b79d30408a5d --- /dev/null +++ b/plugins/git4idea/src/git4idea/conflicts/MergeConflictResolveUtil.kt @@ -0,0 +1,139 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package git4idea.conflicts + +import com.intellij.diff.DiffDialogHints +import com.intellij.diff.DiffManagerEx +import com.intellij.diff.DiffRequestFactory +import com.intellij.diff.chains.DiffRequestProducerException +import com.intellij.diff.merge.* +import com.intellij.openapi.Disposable +import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.FileEditor +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.runBackgroundableTask +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.WindowWrapper +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.UserDataHolder +import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.ui.EditorNotificationPanel +import com.intellij.ui.EditorNotifications +import com.intellij.ui.LightColors +import com.intellij.util.Consumer +import com.intellij.util.ui.UIUtil +import org.jetbrains.annotations.CalledInAwt +import java.awt.event.WindowAdapter +import java.awt.event.WindowEvent +import javax.swing.JFrame + +object MergeConflictResolveUtil { + private val ACTIVE_MERGE_WINDOW = Key.create("ResolveConflictsWindow") + + @CalledInAwt + fun showMergeWindow(project: Project, file: VirtualFile?, resolverComputer: () -> GitMergeHandler.Resolver) { + if (focusActiveMergeWindow(file)) return + + val title = if (file != null) MergeDialogCustomizer().getMergeWindowTitle(file) else "Merge" + + val windowHandler = Consumer { wrapper -> putActiveWindowKey(project, wrapper, file) } + val hints = DiffDialogHints(WindowWrapper.Mode.FRAME, null, windowHandler) + + val producer = MyProducer(project, title, resolverComputer) + + DiffManagerEx.getInstance().showMergeBuiltin(project, producer, hints) + } + + private class MyProducer(val project: Project, + val title: String, + val resolverComputer: () -> GitMergeHandler.Resolver) : MergeRequestProducer { + override fun getName(): String = title + + override fun process(context: UserDataHolder, indicator: ProgressIndicator): MergeRequest { + try { + val resolver = resolverComputer() + + val mergeData = resolver.mergeData + val byteContents = listOf(mergeData.CURRENT, mergeData.ORIGINAL, mergeData.LAST) + + val request = runReadAction { + DiffRequestFactory.getInstance().createMergeRequest(project, resolver.virtualFile, byteContents, + resolver.windowTitle, resolver.contentTitles) + } + MergeUtil.putRevisionInfos(request, mergeData) + MergeCallback.register(request, MyMergeCallback(resolver)) + return request + } + catch (e: Throwable) { + throw DiffRequestProducerException(e) + } + } + } + + private fun putActiveWindowKey(project: Project, wrapper: WindowWrapper, file: VirtualFile?) { + if (file == null) return + val window = wrapper.window + if (window !is JFrame) return + + file.putUserData(ACTIVE_MERGE_WINDOW, wrapper) + EditorNotifications.getInstance(project).updateNotifications(file) + + window.addWindowListener(object : WindowAdapter() { + override fun windowClosed(e: WindowEvent?) { + window.removeWindowListener(this) + file.putUserData(ACTIVE_MERGE_WINDOW, null) + EditorNotifications.getInstance(project).updateNotifications(file) + } + }) + } + + private fun focusActiveMergeWindow(file: VirtualFile?): Boolean { + val wrapper = file?.getUserData(ACTIVE_MERGE_WINDOW) ?: return false + UIUtil.toFront(wrapper.window) + return true + } + + private class MyMergeCallback(private val resolver: GitMergeHandler.Resolver) : MergeCallback() { + override fun applyResult(result: MergeResult) { + val project = resolver.project + val file = resolver.virtualFile + + val document = FileDocumentManager.getInstance().getCachedDocument(file) + if (document != null) FileDocumentManager.getInstance().saveDocument(document) + + MergeUtil.reportProjectFileChangeIfNeeded(project, file) + + if (result != MergeResult.CANCEL) { + runBackgroundableTask("Finishing Conflict Resolve", project, false) { + resolver.onConflictResolved(result) + } + } + } + + override fun checkIsValid(): Boolean { + return resolver.checkIsValid() + } + + override fun addListener(listener: Listener, disposable: Disposable) { + resolver.addListener(listener, disposable) + } + } + + + class NotificationProvider : EditorNotifications.Provider() { + private val KEY = Key.create("MergeConflictResolveUtil.NotificationProvider") + + override fun getKey(): Key = KEY + + override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor, project: Project): EditorNotificationPanel? { + val wrapper = file.getUserData(ACTIVE_MERGE_WINDOW) ?: return null + val panel = EditorNotificationPanel(LightColors.SLIGHTLY_GREEN) + panel.setText("Merge conflicts resolve in progress.") + panel.createActionLabel("Focus Window") { UIUtil.toFront(wrapper.window) } + panel.createActionLabel("Cancel Resolve") { wrapper.close() } + return panel + } + } +} \ No newline at end of file diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java index 61d334b3a728..5b22a56872c7 100644 --- a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java +++ b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java @@ -17,9 +17,10 @@ import com.intellij.vcsUtil.VcsUtil; import git4idea.GitUtil; import git4idea.commands.Git; import git4idea.commands.GitCommand; -import git4idea.commands.GitCommandResult; import git4idea.commands.GitLineHandler; import git4idea.i18n.GitBundle; +import git4idea.repo.GitConflict; +import git4idea.repo.GitConflict.ConflictSide; import git4idea.repo.GitRepository; import git4idea.util.GitFileUtils; import git4idea.util.StringScanner; @@ -74,7 +75,7 @@ public class GitMergeProvider implements MergeProvider2 { for (GitRepository repository : GitUtil.getRepositoryManager(project).getRepositories()) { boolean reverse; if (reverseOrDetect == ReverseRequest.DETECT) { - reverse = repository.getState().equals(GitRepository.State.REBASING); + reverse = isReverseRoot(repository); } else { reverse = reverseOrDetect == ReverseRequest.REVERSE; @@ -96,7 +97,7 @@ public class GitMergeProvider implements MergeProvider2 { VcsRunnable runnable = new VcsRunnable() { @Override public void run() throws VcsException { - mergeDataRef.set(GitMergeUtil.loadMergeData(myProject, root, path, myReverseRoots.contains(root))); + mergeDataRef.set(loadMergeData(myProject, root, path, myReverseRoots.contains(root))); } }; VcsUtil.runVcsProcessWithProgress(runnable, GitBundle.message("merge.load.files"), false, myProject); @@ -147,25 +148,6 @@ public class GitMergeProvider implements MergeProvider2 { GitConflict.Status myStatusYours; } - private static class GitConflict { - @NotNull public final FilePath myPath; - @NotNull public final VirtualFile myRoot; - @NotNull public final Status myStatusTheirs; - @NotNull public final Status myStatusYours; - - private GitConflict(@NotNull FilePath path, @NotNull VirtualFile root, @NotNull Status statusTheirs, @NotNull Status statusYours) { - myPath = path; - myRoot = root; - myStatusTheirs = statusTheirs; - myStatusYours = statusYours; - } - - enum Status { - MODIFIED, // modified on the branch - DELETED // deleted on the branch - } - } - /** * The merge session, it queries conflict information. */ @@ -230,7 +212,7 @@ public class GitMergeProvider implements MergeProvider2 { if (c.myStatusYours == null) { c.myStatusYours = GitConflict.Status.DELETED; } - myConflicts.put(f, new GitConflict(VcsUtil.getFilePath(f), root, c.myStatusTheirs, c.myStatusYours)); + myConflicts.put(f, new GitConflict(root, VcsUtil.getFilePath(f), c.myStatusYours, c.myStatusTheirs)); } } currentBranchName = GitDefaultMergeDialogCustomizerKt.getSingleCurrentBranchName(filesByRoot.keySet()); @@ -264,42 +246,14 @@ public class GitMergeProvider implements MergeProvider2 { for (VirtualFile root : byRoot.keySet()) { Collection conflicts = byRoot.get(root); - - List toAdd = new ArrayList<>(); - List toDelete = new ArrayList<>(); - - for (GitConflict c : conflicts) { - boolean isReversed = myReverseRoots.contains(c.myRoot); - - GitConflict.Status status; - switch (resolution) { - case AcceptedTheirs: - status = !isReversed ? c.myStatusTheirs : c.myStatusYours; - break; - case AcceptedYours: - status = isReversed ? c.myStatusTheirs : c.myStatusYours; - break; - case Merged: - status = GitConflict.Status.MODIFIED; - break; - default: - throw new IllegalArgumentException("Unsupported resolution: " + resolution); - } - - if (status == GitConflict.Status.MODIFIED) { - toAdd.add(c.myPath); - } - else { - toDelete.add(c.myPath); - } - } + ConflictSide resolutionSide = resolution != Resolution.Merged ? getAcceptedConflictSide(resolution, root) : null; try { - GitFileUtils.addPathsForce(myProject, root, toAdd); - GitFileUtils.deletePaths(myProject, root, toDelete); + markConflictResolved(myProject, root, conflicts, resolutionSide); } catch (VcsException e) { - LOG.error(String.format("Unexpected exception during the git operation: modified - %s deleted - %s)", toAdd, toDelete), e); + LOG.error(String.format("Unexpected exception during the git operation. Files - %s", + ContainerUtil.map(conflicts, GitConflict::getFilePath)), e); } } } @@ -312,28 +266,21 @@ public class GitMergeProvider implements MergeProvider2 { for (VirtualFile root : byRoot.keySet()) { Collection conflicts = byRoot.get(root); - boolean isReversed = myReverseRoots.contains(root); - boolean acceptYours = !isReversed ? resolution == Resolution.AcceptedYours - : resolution == Resolution.AcceptedTheirs; + ConflictSide conflictSide = getAcceptedConflictSide(resolution, root); - List filesToCheckout = ContainerUtil.mapNotNull(conflicts, c -> { - GitConflict.Status status = acceptYours ? c.myStatusYours : c.myStatusTheirs; - return status == GitConflict.Status.MODIFIED ? c.myPath : null; - }); - - String parameter = acceptYours ? "--ours" : "--theirs"; - - for (List paths : VcsFileUtil.chunkPaths(root, filesToCheckout)) { - GitLineHandler handler = new GitLineHandler(myProject, root, GitCommand.CHECKOUT); - handler.addParameters(parameter); - handler.endOptions(); - handler.addParameters(paths); - GitCommandResult result = Git.getInstance().runCommand(handler); - if (!result.success()) throw new VcsException(result.getErrorOutputAsJoinedString()); - } + acceptOneVersion(myProject, root, conflicts, conflictSide); } } + @NotNull + private ConflictSide getAcceptedConflictSide(@NotNull Resolution resolution, @NotNull VirtualFile root) { + assert resolution == Resolution.AcceptedYours || resolution == Resolution.AcceptedTheirs; + boolean isReversed = myReverseRoots.contains(root); + boolean acceptYours = !isReversed ? resolution == Resolution.AcceptedYours + : resolution == Resolution.AcceptedTheirs; + return acceptYours ? ConflictSide.OURS : ConflictSide.THEIRS; + } + @NotNull private MultiMap groupConflictsByRoot(@NotNull List files) { MultiMap byRoot = MultiMap.create(); @@ -344,7 +291,7 @@ public class GitMergeProvider implements MergeProvider2 { continue; } - byRoot.putValue(c.myRoot, c); + byRoot.putValue(c.getRoot(), c); } return byRoot; } @@ -352,7 +299,7 @@ public class GitMergeProvider implements MergeProvider2 { /** * The column shows either "yours" or "theirs" status */ - class StatusColumn extends ColumnInfo { + private class StatusColumn extends ColumnInfo { private final boolean myIsLast; StatusColumn(boolean isLast, @Nullable String branchName) { @@ -367,9 +314,9 @@ public class GitMergeProvider implements MergeProvider2 { LOG.error("No conflict for the file " + file); return ""; } - boolean isReversed = myReverseRoots.contains(c.myRoot); - GitConflict.Status currentStatus = !isReversed ? c.myStatusYours : c.myStatusTheirs; - GitConflict.Status lastStatus = isReversed ? c.myStatusYours : c.myStatusTheirs; + boolean isReversed = myReverseRoots.contains(c.getRoot()); + GitConflict.Status currentStatus = c.getStatus(ConflictSide.OURS, isReversed); + GitConflict.Status lastStatus = c.getStatus(ConflictSide.THEIRS, isReversed); GitConflict.Status status = myIsLast ? lastStatus : currentStatus; switch (status) { case MODIFIED: diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeUtil.java b/plugins/git4idea/src/git4idea/merge/GitMergeUtil.java index a3f809f5c10e..80ad1a3f73fa 100644 --- a/plugins/git4idea/src/git4idea/merge/GitMergeUtil.java +++ b/plugins/git4idea/src/git4idea/merge/GitMergeUtil.java @@ -33,13 +33,11 @@ import com.intellij.vcsUtil.VcsFileUtil; import git4idea.GitRevisionNumber; import git4idea.GitUtil; import git4idea.GitVcs; -import git4idea.commands.Git; -import git4idea.commands.GitCommand; -import git4idea.commands.GitLineHandler; -import git4idea.commands.GitLineHandlerListener; +import git4idea.commands.*; import git4idea.history.GitHistoryUtils; import git4idea.i18n.GitBundle; import git4idea.index.GitIndexUtil; +import git4idea.repo.GitConflict; import git4idea.repo.GitRepository; import git4idea.util.GitFileUtils; import git4idea.util.StringScanner; @@ -50,6 +48,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -450,4 +449,65 @@ public class GitMergeUtil { if (pathAmbiguous[0]) return null; return result[0]; } + + public static void acceptOneVersion(@NotNull Project project, + @NotNull VirtualFile root, + @NotNull Collection conflicts, + @NotNull GitConflict.ConflictSide side) throws VcsException { + boolean isCurrent = side == GitConflict.ConflictSide.OURS; + + for (GitConflict conflict : conflicts) { + assert root.equals(conflict.getRoot()); + } + + List toCheckout = new ArrayList<>(); + + for (GitConflict conflict : conflicts) { + GitConflict.Status status = conflict.getStatus(side); + FilePath filePath = conflict.getFilePath(); + + if (status == GitConflict.Status.MODIFIED) { + toCheckout.add(filePath); + } + } + + for (List paths : VcsFileUtil.chunkPaths(root, toCheckout)) { + GitLineHandler handler = new GitLineHandler(project, root, GitCommand.CHECKOUT); + handler.addParameters(isCurrent ? "--ours" : "--theirs"); + handler.endOptions(); + handler.addParameters(paths); + + GitCommandResult result = Git.getInstance().runCommand(handler); + if (!result.success()) throw new VcsException(result.getErrorOutputAsJoinedString()); + } + } + + /** + * + */ + public static void markConflictResolved(@NotNull Project project, + @NotNull VirtualFile root, + @NotNull Collection conflicts, + @Nullable GitConflict.ConflictSide side) throws VcsException { + List toAdd = new ArrayList<>(); + List toDelete = new ArrayList<>(); + + for (GitConflict conflict : conflicts) { + FilePath filePath = conflict.getFilePath(); + + if (side == null || conflict.getStatus(side) == GitConflict.Status.MODIFIED) { + toAdd.add(filePath); + } + else { + toDelete.add(filePath); + } + } + + GitFileUtils.addPathsForce(project, root, toAdd); + GitFileUtils.deletePaths(project, root, toDelete); + } + + public static boolean isReverseRoot(@NotNull GitRepository repository) { + return repository.getState().equals(GitRepository.State.REBASING); + } } diff --git a/plugins/git4idea/src/git4idea/repo/GitConflict.java b/plugins/git4idea/src/git4idea/repo/GitConflict.java new file mode 100644 index 000000000000..edf4cde9cad1 --- /dev/null +++ b/plugins/git4idea/src/git4idea/repo/GitConflict.java @@ -0,0 +1,62 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package git4idea.repo; + +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +public class GitConflict { + @NotNull private final VirtualFile myRoot; + @NotNull private final FilePath myFilePath; + @NotNull private final Status myOurStatus; + @NotNull private final Status myTheirStatus; + + public GitConflict(@NotNull VirtualFile root, + @NotNull FilePath filePath, + @NotNull Status ourStatus, + @NotNull Status theirStatus) { + myRoot = root; + myFilePath = filePath; + myOurStatus = ourStatus; + myTheirStatus = theirStatus; + } + + @NotNull + public VirtualFile getRoot() { + return myRoot; + } + + @NotNull + public FilePath getFilePath() { + return myFilePath; + } + + @NotNull + public Status getStatus(@NotNull ConflictSide side) { + return getStatus(side, false); + } + + @NotNull + public Status getStatus(@NotNull ConflictSide side, boolean isReversed) { + if (side == ConflictSide.OURS) { + return !isReversed ? myOurStatus : myTheirStatus; + } + else { + return !isReversed ? myTheirStatus : myOurStatus; + } + } + + public enum Status { + MODIFIED, // modified on the branch + DELETED // deleted on the branch + } + + /** + * Conflict side in Git terms (--ours or --theirs), ignoring IDE-level visible sides reversal. + * + * @see git4idea.merge.GitMergeUtil#isReverseRoot(GitRepository) + */ + public enum ConflictSide { + OURS, THEIRS + } +} diff --git a/plugins/git4idea/src/git4idea/repo/GitConflictsHolder.java b/plugins/git4idea/src/git4idea/repo/GitConflictsHolder.java new file mode 100644 index 000000000000..7e5f76cd8ac0 --- /dev/null +++ b/plugins/git4idea/src/git4idea/repo/GitConflictsHolder.java @@ -0,0 +1,69 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package git4idea.repo; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.progress.util.BackgroundTaskUtil; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.changes.VcsDirtyScope; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class GitConflictsHolder implements Disposable { + public static final Topic CONFLICTS_CHANGE = Topic.create("GitConflictsHolder change", ConflictsListener.class); + + @NotNull private final GitRepository myRepository; + @NotNull private final List myConflicts = new ArrayList<>(); + + private final Object LOCK = new Object(); + + public GitConflictsHolder(@NotNull GitRepository repository) { + myRepository = repository; + } + + @NotNull + public List getConflicts() { + synchronized (LOCK) { + return new ArrayList<>(myConflicts); + } + } + + @Override + public void dispose() { + synchronized (LOCK) { + myConflicts.clear(); + } + } + + @Nullable + public GitConflict findConflict(@NotNull FilePath path) { + synchronized (LOCK) { + return ContainerUtil.find(myConflicts, it -> it.getFilePath().equals(path)); + } + } + + public void refresh(@NotNull VcsDirtyScope scope, @NotNull Collection conflicts) { + synchronized (LOCK) { + Map map = new HashMap<>(); + for (GitConflict conflict : myConflicts) { + if (scope.belongsTo(conflict.getFilePath())) continue; + map.put(conflict.getFilePath(), conflict); + } + + for (GitConflict conflict : conflicts) { + map.put(conflict.getFilePath(), conflict); + } + + myConflicts.clear(); + myConflicts.addAll(map.values()); + } + BackgroundTaskUtil.syncPublisher(myRepository.getProject(), CONFLICTS_CHANGE).conflictsChanged(myRepository); + } + + public interface ConflictsListener { + void conflictsChanged(@NotNull GitRepository repository); + } +} diff --git a/plugins/git4idea/src/git4idea/repo/GitRepository.java b/plugins/git4idea/src/git4idea/repo/GitRepository.java index b6a8c04bc45a..6c64f267efd6 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepository.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepository.java @@ -63,6 +63,9 @@ public interface GitRepository extends Repository { @NotNull GitUntrackedFilesHolder getUntrackedFilesHolder(); + @NotNull + GitConflictsHolder getConflictsHolder(); + @NotNull GitRepoInfo getInfo(); diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java index 155ff0a2f444..d46fee1bd46f 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java @@ -32,7 +32,6 @@ import static com.intellij.util.containers.ContainerUtil.newHashMap; import static com.intellij.util.containers.ContainerUtil.newLinkedHashSet; public class GitRepositoryImpl extends RepositoryImpl implements GitRepository { - @NotNull private final GitVcs myVcs; @NotNull private final GitRepositoryReader myReader; @NotNull private final VirtualFile myGitDir; @@ -40,6 +39,7 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository { @Nullable private final GitUntrackedFilesHolder myUntrackedFilesHolder; @Nullable private final GitRepositoryIgnoredFilesHolder myIgnoredRepositoryFilesHolder; + @Nullable private final GitConflictsHolder myConflictsHolder; @NotNull private volatile GitRepoInfo myInfo; @@ -58,14 +58,19 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository { if (!light) { myUntrackedFilesHolder = new GitUntrackedFilesHolder(this, myRepositoryFiles); Disposer.register(this, myUntrackedFilesHolder); + myIgnoredRepositoryFilesHolder = new GitRepositoryIgnoredFilesHolder(project, this, GitRepositoryManager.getInstance(project), Git.getInstance()); Disposer.register(this, myIgnoredRepositoryFilesHolder); myIgnoredRepositoryFilesHolder.addUpdateStateListener(new MyRepositoryIgnoredHolderUpdateListener(getProject())); + + myConflictsHolder = new GitConflictsHolder(this); + Disposer.register(this, myConflictsHolder); } else { myUntrackedFilesHolder = null; myIgnoredRepositoryFilesHolder = null; + myConflictsHolder = null; } } @@ -121,6 +126,15 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository { return myUntrackedFilesHolder; } + @NotNull + @Override + public GitConflictsHolder getConflictsHolder() { + if (myConflictsHolder == null) { + throw new IllegalStateException("Using conflicts holder with light git repository instance " + this); + } + return myConflictsHolder; + } + @Override @NotNull public GitRepoInfo getInfo() { diff --git a/plugins/git4idea/src/git4idea/status/GitChangeProvider.java b/plugins/git4idea/src/git4idea/status/GitChangeProvider.java index a131747c90f7..3fca13b206ea 100644 --- a/plugins/git4idea/src/git4idea/status/GitChangeProvider.java +++ b/plugins/git4idea/src/git4idea/status/GitChangeProvider.java @@ -19,6 +19,7 @@ import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.changes.GitChangeUtils; import git4idea.commands.Git; +import git4idea.repo.GitConflictsHolder; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; @@ -95,6 +96,9 @@ public class GitChangeProvider implements ChangeProvider { builder.processUnversionedFile(f); holder.unversioned(f); } + + GitConflictsHolder conflictsHolder = repo.getConflictsHolder(); + conflictsHolder.refresh(dirtyScope, collector.getConflicts()); } holder.feedBuilder(builder); diff --git a/plugins/git4idea/src/git4idea/status/GitChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitChangesCollector.java index 748ad0a5d2ac..a063ccb1a6b7 100644 --- a/plugins/git4idea/src/git4idea/status/GitChangesCollector.java +++ b/plugins/git4idea/src/git4idea/status/GitChangesCollector.java @@ -15,7 +15,6 @@ */ package git4idea.status; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -35,6 +34,8 @@ import git4idea.commands.Git; import git4idea.commands.GitCommand; import git4idea.commands.GitHandler; import git4idea.commands.GitLineHandler; +import git4idea.repo.GitConflict; +import git4idea.repo.GitConflict.Status; import git4idea.repo.GitRepository; import git4idea.repo.GitUntrackedFilesHolder; import org.jetbrains.annotations.NotNull; @@ -54,28 +55,31 @@ import java.util.*; * @author Kirill Likhodedov */ class GitChangesCollector { - private static final Logger LOG = Logger.getInstance(GitChangesCollector.class); @NotNull private final Project myProject; - @NotNull private final VirtualFile myVcsRoot; - - @NotNull private final VcsDirtyScope myDirtyScope; + @NotNull private final Git myGit; @NotNull private final ChangeListManager myChangeListManager; @NotNull private final ProjectLevelVcsManager myVcsManager; @NotNull private final AbstractVcs myVcs; - + @NotNull private final VcsDirtyScope myDirtyScope; @NotNull private final GitRepository myRepository; + @NotNull private final VirtualFile myVcsRoot; + private final Collection myChanges = new HashSet<>(); private final Set myUnversionedFiles = new HashSet<>(); - @NotNull private final Git myGit; + private final Collection myConflicts = new HashSet<>(); /** * Collects the changes from git command line and returns the instance of GitNewChangesCollector from which these changes can be retrieved. * This may be lengthy. */ @NotNull - static GitChangesCollector collect(@NotNull Project project, @NotNull Git git, @NotNull ChangeListManager changeListManager, - @NotNull ProjectLevelVcsManager vcsManager, @NotNull AbstractVcs vcs, - @NotNull VcsDirtyScope dirtyScope, @NotNull GitRepository repository) throws VcsException { + static GitChangesCollector collect(@NotNull Project project, + @NotNull Git git, + @NotNull ChangeListManager changeListManager, + @NotNull ProjectLevelVcsManager vcsManager, + @NotNull AbstractVcs vcs, + @NotNull VcsDirtyScope dirtyScope, + @NotNull GitRepository repository) throws VcsException { return new GitChangesCollector(project, git, changeListManager, vcsManager, vcs, dirtyScope, repository); } @@ -89,17 +93,25 @@ class GitChangesCollector { return myChanges; } - private GitChangesCollector(@NotNull Project project, @NotNull Git git, @NotNull ChangeListManager changeListManager, - @NotNull ProjectLevelVcsManager vcsManager, @NotNull AbstractVcs vcs, - @NotNull VcsDirtyScope dirtyScope, @NotNull GitRepository repository) throws VcsException { + Collection getConflicts() { + return myConflicts; + } + + private GitChangesCollector(@NotNull Project project, + @NotNull Git git, + @NotNull ChangeListManager changeListManager, + @NotNull ProjectLevelVcsManager vcsManager, + @NotNull AbstractVcs vcs, + @NotNull VcsDirtyScope dirtyScope, + @NotNull GitRepository repository) throws VcsException { myProject = project; + myGit = git; myChangeListManager = changeListManager; myVcsManager = vcsManager; myVcs = vcs; myDirtyScope = dirtyScope; - myVcsRoot = repository.getRoot(); - myGit = git; myRepository = repository; + myVcsRoot = repository.getRoot(); Collection dirtyPaths = dirtyPaths(); if (!dirtyPaths.isEmpty()) { @@ -236,7 +248,7 @@ class GitChangesCollector { } else if (yStatus == 'T') { reportTypeChanged(filepath, head); } else if (yStatus == 'U') { - reportConflict(filepath, head); + reportConflict(filepath, head, Status.MODIFIED, Status.MODIFIED); } else { throwYStatus(output, handler, line, xStatus, yStatus); } @@ -263,7 +275,7 @@ class GitChangesCollector { } else if (yStatus == 'D') { // added + deleted => no change (from IDEA point of view). } else if (yStatus == 'U' || yStatus == 'A') { // AU - unmerged, added by us; AA - unmerged, both added - reportConflict(filepath, head); + reportConflict(filepath, head, Status.MODIFIED, Status.MODIFIED); } else { throwYStatus(output, handler, line, xStatus, yStatus); } @@ -273,21 +285,22 @@ class GitChangesCollector { if (yStatus == 'M' || yStatus == ' ' || yStatus == 'T') { reportDeleted(filepath, head); } else if (yStatus == 'U') { // DU - unmerged, deleted by us - reportConflict(filepath, head); + reportConflict(filepath, head, Status.DELETED, Status.MODIFIED); } else if (yStatus == 'D') { // DD - unmerged, both deleted - // TODO - // currently not displaying, because "both deleted" conflicts can't be handled by our conflict resolver. - // see IDEA-63156 + reportConflict(filepath, head, Status.DELETED, Status.DELETED); } else { throwYStatus(output, handler, line, xStatus, yStatus); } break; case 'U': - if (yStatus == 'U' || yStatus == 'A' || yStatus == 'D' || yStatus == 'T') { - // UU - unmerged, both modified; UD - unmerged, deleted by them; UA - unmerged, added by them - reportConflict(filepath, head); - } else { + if (yStatus == 'U' || yStatus == 'A' || yStatus == 'T') { // UU - unmerged, both modified; UA - unmerged, added by them + reportConflict(filepath, head, Status.MODIFIED, Status.MODIFIED); + } + else if (yStatus == 'D') { // UD - unmerged, deleted by them + reportConflict(filepath, head, Status.MODIFIED, Status.DELETED); + } + else { throwYStatus(output, handler, line, xStatus, yStatus); } break; @@ -379,10 +392,15 @@ class GitChangesCollector { reportChange(FileStatus.MODIFIED, before, after); } - private void reportConflict(FilePath filepath, VcsRevisionNumber head) { - ContentRevision before = GitContentRevision.createRevision(filepath, head, myProject); - ContentRevision after = GitContentRevision.createRevision(filepath, null, myProject); - reportChange(FileStatus.MERGED_WITH_CONFLICTS, before, after); + private void reportConflict(FilePath filepath, VcsRevisionNumber head, Status oursStatus, Status theirsStatus) { + myConflicts.add(new GitConflict(myVcsRoot, filepath, oursStatus, theirsStatus)); + + // TODO: currently not displaying "both deleted" conflicts, because they can't be handled by GitMergeProvider (see IDEA-63156) + if (oursStatus != Status.DELETED || theirsStatus != Status.DELETED) { + ContentRevision before = GitContentRevision.createRevision(filepath, head, myProject); + ContentRevision after = GitContentRevision.createRevision(filepath, null, myProject); + reportChange(FileStatus.MERGED_WITH_CONFLICTS, before, after); + } } private void reportChange(FileStatus status, ContentRevision before, ContentRevision after) { diff --git a/plugins/git4idea/tests/git4idea/test/MockGitRepository.java b/plugins/git4idea/tests/git4idea/test/MockGitRepository.java index fe8bf5265f14..13e30e879845 100644 --- a/plugins/git4idea/tests/git4idea/test/MockGitRepository.java +++ b/plugins/git4idea/tests/git4idea/test/MockGitRepository.java @@ -55,6 +55,12 @@ public class MockGitRepository implements GitRepository { throw new UnsupportedOperationException(); } + @NotNull + @Override + public GitConflictsHolder getConflictsHolder() { + throw new UnsupportedOperationException(); + } + @NotNull @Override public GitRepoInfo getInfo() { diff --git a/plugins/gradle/java/resources/META-INF/gradle-groovy-integration.xml b/plugins/gradle/java/resources/META-INF/gradle-groovy-integration.xml index 22dce1242e39..5d79e3b7af0c 100644 --- a/plugins/gradle/java/resources/META-INF/gradle-groovy-integration.xml +++ b/plugins/gradle/java/resources/META-INF/gradle-groovy-integration.xml @@ -58,6 +58,7 @@ + @@ -66,10 +67,10 @@ + - diff --git a/plugins/gradle/java/resources/META-INF/gradle-java-integration.xml b/plugins/gradle/java/resources/META-INF/gradle-java-integration.xml index 23223407ba4d..8d3f5f1508ba 100644 --- a/plugins/gradle/java/resources/META-INF/gradle-java-integration.xml +++ b/plugins/gradle/java/resources/META-INF/gradle-java-integration.xml @@ -36,8 +36,6 @@ - diff --git a/plugins/gradle/java/src/execution/build/output/GradleJavaOutputParserProvider.java b/plugins/gradle/java/src/execution/build/output/GradleJavaOutputParserProvider.java deleted file mode 100644 index 999248a2579b..000000000000 --- a/plugins/gradle/java/src/execution/build/output/GradleJavaOutputParserProvider.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package org.jetbrains.plugins.gradle.execution.build.output; - -import com.intellij.build.output.BuildOutputParser; -import com.intellij.build.output.JavacOutputParser; -import com.intellij.build.output.KotlincOutputParser; -import com.intellij.openapi.externalSystem.model.ProjectSystemId; -import com.intellij.openapi.externalSystem.model.task.ExternalSystemTask; -import com.intellij.openapi.externalSystem.service.execution.ExternalSystemOutputParserProvider; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.plugins.gradle.util.GradleConstants; - -import java.util.List; - -/** - * @author Vladislav.Soroka - */ -public class GradleJavaOutputParserProvider implements ExternalSystemOutputParserProvider { - @Override - public ProjectSystemId getExternalSystemId() { - return GradleConstants.SYSTEM_ID; - } - - @Override - public List getBuildOutputParsers(ExternalSystemTask task) { - // use javac, kotlinc output parsers for the sync tasks also to handle the compilation output of the 'buildSrc' sources - return ContainerUtil.list(new JavacOutputParser(), new KotlincOutputParser()); - } -} diff --git a/plugins/gradle/java/src/service/resolve/GradleDomainObjectProperty.kt b/plugins/gradle/java/src/service/resolve/GradleDomainObjectProperty.kt new file mode 100644 index 000000000000..49189ac19719 --- /dev/null +++ b/plugins/gradle/java/src/service/resolve/GradleDomainObjectProperty.kt @@ -0,0 +1,10 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.service.resolve + +import com.intellij.ide.presentation.Presentation +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.jetbrains.plugins.groovy.lang.resolve.api.SimpleGroovyProperty + +@Presentation(typeName = "Gradle Domain Object") +class GradleDomainObjectProperty(name: String, type: PsiType?, context: PsiElement) : SimpleGroovyProperty(name, type, context) diff --git a/plugins/gradle/java/src/service/resolve/GradleExtensionsContributor.kt b/plugins/gradle/java/src/service/resolve/GradleExtensionsContributor.kt index 39f4759e3b9a..c2a580779ea5 100644 --- a/plugins/gradle/java/src/service/resolve/GradleExtensionsContributor.kt +++ b/plugins/gradle/java/src/service/resolve/GradleExtensionsContributor.kt @@ -35,7 +35,7 @@ import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil -import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_KEY +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_TYPE_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_STRATEGY_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo import org.jetbrains.plugins.groovy.lang.resolve.getName @@ -47,35 +47,6 @@ import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessProperties */ class GradleExtensionsContributor : GradleMethodContextContributor { - override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { - val extensionsData = getExtensionsFor(closure) ?: return null - for (extension in extensionsData.extensions.values) { - val extensionClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, extension.name)) - if (extensionClosure.accepts(closure)) { - return DelegatesToInfo(TypesUtil.createType(extension.rootTypeFqn, closure), Closure.DELEGATE_FIRST) - } - val objectTypeFqn = extension.namedObjectTypeFqn?.let { if (it.isNotBlank()) it else null } ?: continue - val objectType = TypesUtil.createType(objectTypeFqn, closure) - val objectClosure = groovyClosure().withAncestor(2, extensionClosure) - if (objectClosure.accepts(closure)) { - return DelegatesToInfo(objectType, Closure.DELEGATE_FIRST) - } - - val objectReference = object : ElementPattern { - override fun getCondition() = null - override fun accepts(o: Any?) = false - override fun accepts(o: Any?, context: ProcessingContext): Boolean { - return o is GrExpression && o.type?.isAssignableFrom(objectType) ?: false - } - } - if (psiElement().withParent( - psiElement().withFirstChild(objectReference)).accepts(closure)) { - return DelegatesToInfo(objectType, Closure.DELEGATE_FIRST) - } - } - return null - } - override fun process(methodCallInfo: MutableList, processor: PsiScopeProcessor, state: ResolveState, @@ -109,15 +80,6 @@ class GradleExtensionsContributor : GradleMethodContextContributor { } } - extensionsData.extensions[name]?.let { - if (!processExtensionMethodProperty(processor, state, place, it)) return false - } - - for (extension in extensionsData.extensions.values) { - if (!processExtension(processor, state, place, extension)) return false - if (name == extension.name) break - } - if (place.getUserData(RESOLVED_CODE).let { it == null || !it }) { if (psiElement().withAncestor(2, groovyClosure().with(object : PatternCondition("withDelegatesToInfo") { override fun accepts(t: GrClosableBlock, context: ProcessingContext?): Boolean { @@ -144,7 +106,7 @@ class GradleExtensionsContributor : GradleMethodContextContributor { addOptionalParameter("args", JAVA_UTIL_MAP) } val closureParam = addAndGetOptionalParameter("configuration", GROOVY_LANG_CLOSURE) - closureParam.putUserData(DELEGATES_TO_KEY, it.typeFqn) + closureParam.putUserData(DELEGATES_TO_TYPE_KEY, it.typeFqn) closureParam.putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.OWNER_FIRST) } if (!processor.execute(methodBuilder, state)) return false @@ -268,41 +230,6 @@ class GradleExtensionsContributor : GradleMethodContextContributor { } } -private fun processExtensionMethodProperty(processor: PsiScopeProcessor, - state: ResolveState, - place: PsiElement, - extension: GradleExtension): Boolean { - val processMethods = processor.shouldProcessMethods() - val processProperties = processor.shouldProcessProperties() - if (!processMethods && !processProperties) { - return true - } - - place.putUserData(RESOLVED_CODE, true) - - val resolveScope = place.resolveScope - val javaPsiFacade = JavaPsiFacade.getInstance(place.project) - val type = javaPsiFacade.elementFactory.createTypeByFQClassName(extension.rootTypeFqn, resolveScope) - - if (processMethods) { - val extensionMethod = GrLightMethodBuilder(place.manager, extension.name).apply { - containingClass = javaPsiFacade.findClass(GRADLE_API_PROJECT, resolveScope) - returnType = type - addParameter("configuration", GROOVY_LANG_CLOSURE) - } - if (!processor.execute(extensionMethod, state)) { - return false - } - } - if (processProperties) { - val extensionProperty = GradleExtensionProperty(extension.name, type, place) - if (!processor.execute(extensionProperty, state)) { - return false - } - } - return true -} - fun processExtension(processor: PsiScopeProcessor, state: ResolveState, place: PsiElement, diff --git a/plugins/gradle/java/src/service/resolve/GradleIdeaSettingsContributor.kt b/plugins/gradle/java/src/service/resolve/GradleIdeaSettingsContributor.kt index f773c5481f57..112074d41565 100644 --- a/plugins/gradle/java/src/service/resolve/GradleIdeaSettingsContributor.kt +++ b/plugins/gradle/java/src/service/resolve/GradleIdeaSettingsContributor.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.gradle.service.resolve import com.intellij.openapi.externalSystem.service.project.settings.ConfigurationDataService @@ -12,7 +12,7 @@ import groovy.lang.Closure import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames -import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_KEY +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_TYPE_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_STRATEGY_KEY import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessMethods @@ -49,7 +49,7 @@ class GradleIdeaSettingsContributor : GradleMethodContextContributor { containingClass = ideaProjectClass returnType = projectSettingsType addAndGetParameter("configuration", GroovyCommonClassNames.GROOVY_LANG_CLOSURE).apply { - putUserData(DELEGATES_TO_KEY, PROJECT_SETTINGS_FQN) + putUserData(DELEGATES_TO_TYPE_KEY, PROJECT_SETTINGS_FQN) putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.DELEGATE_FIRST) } } @@ -66,7 +66,7 @@ class GradleIdeaSettingsContributor : GradleMethodContextContributor { containingClass = ideaModuleClass returnType = moduleSettingsType addAndGetParameter("configuration", GroovyCommonClassNames.GROOVY_LANG_CLOSURE).apply { - putUserData(DELEGATES_TO_KEY, MODULE_SETTINGS_FQN) + putUserData(DELEGATES_TO_TYPE_KEY, MODULE_SETTINGS_FQN) putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.DELEGATE_FIRST) } } diff --git a/plugins/gradle/java/src/service/resolve/GradleMiscContributor.kt b/plugins/gradle/java/src/service/resolve/GradleMiscContributor.kt index 6a8268ed37d5..abd4f4e70b4e 100644 --- a/plugins/gradle/java/src/service/resolve/GradleMiscContributor.kt +++ b/plugins/gradle/java/src/service/resolve/GradleMiscContributor.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.gradle.service.resolve import com.intellij.patterns.PsiJavaPatterns.psiElement @@ -21,7 +21,7 @@ import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil -import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_KEY +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_TYPE_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo /** @@ -91,7 +91,7 @@ class GradleMiscContributor : GradleMethodContextContributor { containingClass = pluginsDependenciesClass returnType = returnClass } - methodBuilder.addAndGetParameter("configuration", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, pluginDependenciesSpecFqn) + methodBuilder.addAndGetParameter("configuration", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, pluginDependenciesSpecFqn) place.putUserData(RESOLVED_CODE, true) if (!processor.execute(methodBuilder, state)) return false } diff --git a/plugins/gradle/java/src/service/resolve/GradleNamedDomainCollectionContributor.kt b/plugins/gradle/java/src/service/resolve/GradleNamedDomainCollectionContributor.kt new file mode 100644 index 000000000000..4c3b68d69299 --- /dev/null +++ b/plugins/gradle/java/src/service/resolve/GradleNamedDomainCollectionContributor.kt @@ -0,0 +1,58 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.service.resolve + +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import com.intellij.psi.util.PsiUtil.substituteTypeParameter +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_NAMED_DOMAIN_OBJECT_CONTAINER +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE +import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor +import org.jetbrains.plugins.groovy.lang.resolve.getName +import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessMethods +import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessProperties + +class GradleNamedDomainCollectionContributor : NonCodeMembersContributor() { + + override fun getParentClassName(): String? = GRADLE_API_NAMED_DOMAIN_OBJECT_CONTAINER + + override fun processDynamicElements(qualifierType: PsiType, + clazz: PsiClass?, + processor: PsiScopeProcessor, + place: PsiElement, + state: ResolveState) { + if (clazz == null) return + if (state[DELEGATED_TYPE] == true) return + + val domainObjectName = processor.getName(state) ?: return // don't complete anything because we don't know what is in container + val processProperties = processor.shouldProcessProperties() + val processMethods = processor.shouldProcessMethods() + if (!processProperties && !processMethods) { + return + } + val domainObjectType = substituteTypeParameter(qualifierType, GRADLE_API_NAMED_DOMAIN_OBJECT_CONTAINER, 0, false) ?: return + + val containingFile = place.containingFile + val manager = containingFile.manager + + if (processProperties) { + val property = GradleDomainObjectProperty(domainObjectName, domainObjectType, containingFile) + if (!processor.execute(property, state)) { + return + } + } + if (processMethods) { + val method = GrLightMethodBuilder(manager, domainObjectName).apply { + returnType = domainObjectType + addParameter("configuration", createType(GROOVY_LANG_CLOSURE, containingFile)) + } + if (!processor.execute(method, state)) { + return + } + } + } +} diff --git a/plugins/gradle/java/src/service/resolve/GradleNonCodeMembersContributor.kt b/plugins/gradle/java/src/service/resolve/GradleNonCodeMembersContributor.kt index fb8cbb410b03..450aab62ffe1 100644 --- a/plugins/gradle/java/src/service/resolve/GradleNonCodeMembersContributor.kt +++ b/plugins/gradle/java/src/service/resolve/GradleNonCodeMembersContributor.kt @@ -27,7 +27,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightVariable import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil -import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_KEY +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_TYPE_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_STRATEGY_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.getDelegatesToInfo import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessProperties @@ -92,63 +92,6 @@ class GradleNonCodeMembersContributor : NonCodeMembersContributor() { if (!shouldSkipDeclarationsAndSetters(aClass.qualifiedName)) { processDeclarations(aClass, processor, state, place) } - if (state[DELEGATED_TYPE] == true) return - val propCandidate = place.references.singleOrNull()?.canonicalText ?: return - val domainObjectType = (qualifierType.superTypes.firstOrNull { it is PsiClassType } as? PsiClassType)?.parameters?.singleOrNull() - ?: return - if (!InheritanceUtil.isInheritor(qualifierType, GRADLE_API_NAMED_DOMAIN_OBJECT_CONTAINER)) return - - val classHint = processor.getHint(com.intellij.psi.scope.ElementClassHint.KEY) - val shouldProcessMethods = ResolveUtil.shouldProcessMethods(classHint) - val shouldProcessProperties = ResolveUtil.shouldProcessProperties(classHint) - if (GradleResolverUtil.canBeMethodOf(propCandidate, aClass)) return - - val domainObjectFqn = TypesUtil.getQualifiedName(domainObjectType) ?: return - val javaPsiFacade = JavaPsiFacade.getInstance(place.project) - val domainObjectPsiClass = javaPsiFacade.findClass(domainObjectFqn, place.resolveScope) ?: return - if (GradleResolverUtil.canBeMethodOf(propCandidate, domainObjectPsiClass)) return - if (GradleResolverUtil.canBeMethodOf("get" + propCandidate.capitalize(), domainObjectPsiClass)) return - if (GradleResolverUtil.canBeMethodOf("set" + propCandidate.capitalize(), domainObjectPsiClass)) return - - val closure = PsiTreeUtil.getParentOfType(place, GrClosableBlock::class.java) - val typeToDelegate = closure?.let { getDelegatesToInfo(it)?.typeToDelegate } - if (typeToDelegate != null) { - val fqNameToDelegate = TypesUtil.getQualifiedName(typeToDelegate) ?: return - val classToDelegate = javaPsiFacade.findClass(fqNameToDelegate, place.resolveScope) ?: return - if (classToDelegate !== aClass) { - val parent = place.parent - if (parent is GrMethodCall) { - if (canBeMethodOf(propCandidate, parent, typeToDelegate)) return - } - } - } - - if (!shouldProcessMethods && shouldProcessProperties && place is GrReferenceExpression && place.parent !is GrApplicationStatement) { - val variable = GrLightField(propCandidate, domainObjectFqn, place) - place.putUserData(RESOLVED_CODE, true) - if (!processor.execute(variable, state)) return - } - if (shouldProcessMethods && place is GrReferenceExpression) { - val call = PsiTreeUtil.getParentOfType(place, GrMethodCall::class.java) ?: return - val args = call.argumentList - var argsCount = GradleResolverUtil.getGrMethodArumentsCount(args) - argsCount += call.closureArguments.size - argsCount++ // Configuration name is delivered as an argument. - - // at runtime, see org.gradle.internal.metaobject.ConfigureDelegate.invokeMethod - val wrappedBase = GrLightMethodBuilder(place.manager, propCandidate).apply { - returnType = domainObjectType - containingClass = aClass - val closureParam = addAndGetOptionalParameter("configuration", GROOVY_LANG_CLOSURE) - closureParam.putUserData(DELEGATES_TO_KEY, domainObjectFqn) - closureParam.putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.DELEGATE_FIRST) - - val method = aClass.findMethodsByName("create", true).firstOrNull { it.parameterList.parametersCount == argsCount } - if (method != null) navigationElement = method - } - place.putUserData(RESOLVED_CODE, true) - if (!processor.execute(wrappedBase, state)) return - } } } diff --git a/plugins/gradle/java/src/service/resolve/GradleProjectExtensionContributor.kt b/plugins/gradle/java/src/service/resolve/GradleProjectExtensionContributor.kt new file mode 100644 index 000000000000..038f96e638b2 --- /dev/null +++ b/plugins/gradle/java/src/service/resolve/GradleProjectExtensionContributor.kt @@ -0,0 +1,66 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.service.resolve + +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE +import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor +import org.jetbrains.plugins.groovy.lang.resolve.getName +import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessMethods +import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessProperties + +class GradleProjectExtensionContributor : NonCodeMembersContributor() { + + override fun getParentClassName(): String? = GRADLE_API_PROJECT + + override fun processDynamicElements(qualifierType: PsiType, + aClass: PsiClass?, + processor: PsiScopeProcessor, + place: PsiElement, + state: ResolveState) { + if (qualifierType !is GradleProjectAwareType) return + + val processMethods = processor.shouldProcessMethods() + val processProperties = processor.shouldProcessProperties() + if (!processMethods && !processProperties) { + return + } + + val containingFile = place.containingFile + val extensionsData = GradleExtensionsContributor.getExtensionsFor(containingFile) ?: return + + val name = processor.getName(state) + val allExtensions = extensionsData.extensions + val extensions = if (name == null) allExtensions.values else listOf(allExtensions[name] ?: return) + if (extensions.isEmpty()) return + + val factory = GroovyPsiElementFactory.getInstance(containingFile.project) + val manager = containingFile.manager + + for (extension in extensions) { + val type = factory.createTypeElement(extension.rootTypeFqn, containingFile).type + if (processProperties) { + val extensionProperty = GradleExtensionProperty(extension.name, type, containingFile) + if (!processor.execute(extensionProperty, state)) { + return + } + } + if (processMethods) { + val extensionMethod = GrLightMethodBuilder(manager, extension.name).apply { + returnType = type + addParameter("configuration", createType(GROOVY_LANG_CLOSURE, containingFile)) + } + if (!processor.execute(extensionMethod, state)) { + return + } + } + } + } +} diff --git a/plugins/gradle/java/src/service/resolve/GradleUnresolvedReferenceFilter.java b/plugins/gradle/java/src/service/resolve/GradleUnresolvedReferenceFilter.java index c1d546e9865a..65fc37afa810 100644 --- a/plugins/gradle/java/src/service/resolve/GradleUnresolvedReferenceFilter.java +++ b/plugins/gradle/java/src/service/resolve/GradleUnresolvedReferenceFilter.java @@ -1,33 +1,15 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.gradle.service.resolve; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.PsiType; import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.gradle.settings.GradleExtensionsSettings; import org.jetbrains.plugins.groovy.extensions.GroovyUnresolvedHighlightFilter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import java.util.HashSet; import java.util.Set; import static com.intellij.util.containers.ContainerUtil.newHashSet; @@ -63,15 +45,6 @@ public class GradleUnresolvedReferenceFilter extends GroovyUnresolvedHighlightFi return false; } - Set toIgnore = new HashSet<>(IGNORE_SET); - GradleExtensionsSettings.GradleExtensionsData extensionsData = GradleExtensionsContributor.Companion.getExtensionsFor(expression); - if (extensionsData != null) { - for (GradleExtensionsSettings.GradleExtension extension : extensionsData.extensions.values()) { - if (StringUtil.isNotEmpty(extension.namedObjectTypeFqn)) { - toIgnore.add(extension.namedObjectTypeFqn); - } - } - } - return toIgnore.contains(TypesUtil.getQualifiedName(psiType)); + return false; } } diff --git a/plugins/gradle/java/src/service/resolve/NamedDomainObjectCollectionTypeEnhancer.java b/plugins/gradle/java/src/service/resolve/NamedDomainObjectCollectionTypeEnhancer.java deleted file mode 100644 index b25fa8cda07b..000000000000 --- a/plugins/gradle/java/src/service/resolve/NamedDomainObjectCollectionTypeEnhancer.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 org.jetbrains.plugins.gradle.service.resolve; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiType; -import com.intellij.psi.impl.source.PsiClassReferenceType; -import com.intellij.psi.util.InheritanceUtil; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.gradle.settings.GradleExtensionsSettings; -import org.jetbrains.plugins.groovy.extensions.GroovyMapContentProvider; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrReferenceTypeEnhancer; - -/** - * @author Vladislav.Soroka - */ -public class NamedDomainObjectCollectionTypeEnhancer extends GrReferenceTypeEnhancer { - @Override - public PsiType getReferenceType(GrReferenceExpression ref, @Nullable PsiElement resolved) { - if (resolved != null) return null; - - GrExpression qualifierExpression = ref.getQualifierExpression(); - if (qualifierExpression == null) return null; - - PsiType namedDomainCollectionType = GradleResolverUtil.getTypeOf(qualifierExpression); - - if (!InheritanceUtil.isInheritor(namedDomainCollectionType, GradleCommonClassNames.GRADLE_API_NAMED_DOMAIN_OBJECT_COLLECTION)) { - return null; - } - - PsiElement qResolved; - - if (qualifierExpression instanceof GrReferenceExpression) { - qResolved = ((GrReferenceExpression)qualifierExpression).resolve(); - } - else if (qualifierExpression instanceof GrMethodCall) { - qResolved = ((GrMethodCall)qualifierExpression).resolveMethod(); - } - else { - return null; - } - - String key = ref.getReferenceName(); - if (key == null) return null; - - for (GroovyMapContentProvider provider : GroovyMapContentProvider.EP_NAME.getExtensions()) { - PsiType type = provider.getValueType(qualifierExpression, qResolved, key); - if (type != null) { - return type; - } - } - - if (namedDomainCollectionType instanceof PsiClassReferenceType) { - final PsiClassReferenceType referenceType = (PsiClassReferenceType)namedDomainCollectionType; - final String fqName = TypesUtil.getQualifiedName(referenceType); - if (GradleCommonClassNames.GRADLE_API_SOURCE_SET_CONTAINER.equals(fqName)) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(ref.getProject()); - return psiManager.createTypeByFQClassName(GradleCommonClassNames.GRADLE_API_SOURCE_SET, ref.getResolveScope()); - } - else if (GradleCommonClassNames.GRADLE_API_CONFIGURATION_CONTAINER.equals(fqName)) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(ref.getProject()); - return psiManager.createTypeByFQClassName(GradleCommonClassNames.GRADLE_API_CONFIGURATION, ref.getResolveScope()); - } - else if (GradleCommonClassNames.GRADLE_API_TASK_CONTAINER.equals(fqName)) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(ref.getProject()); - return psiManager.createTypeByFQClassName(GradleCommonClassNames.GRADLE_API_TASK, ref.getResolveScope()); - } - else if (GradleCommonClassNames.GRADLE_API_DISTRIBUTION_CONTAINER.equals(fqName)) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(ref.getProject()); - return psiManager.createTypeByFQClassName(GradleCommonClassNames.GRADLE_API_DISTRIBUTION, ref.getResolveScope()); - } - else { - GradleExtensionsSettings.GradleExtensionsData extensionsData = GradleExtensionsContributor.Companion.getExtensionsFor(ref); - if (extensionsData != null) { - for (GradleExtensionsSettings.GradleExtension extension : extensionsData.extensions.values()) { - if (StringUtil.isNotEmpty(extension.namedObjectTypeFqn) && extension.rootTypeFqn.equals(fqName)) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(ref.getProject()); - return psiManager.createTypeByFQClassName(extension.namedObjectTypeFqn, ref.getResolveScope()); - } - } - } - } - } - - return null; - } -} diff --git a/plugins/gradle/java/testSources/dsl/GradleDistributionsTest.groovy b/plugins/gradle/java/testSources/dsl/GradleDistributionsTest.groovy index 99d644f7d138..1ab00dc66b9a 100644 --- a/plugins/gradle/java/testSources/dsl/GradleDistributionsTest.groovy +++ b/plugins/gradle/java/testSources/dsl/GradleDistributionsTest.groovy @@ -1,24 +1,29 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.gradle.dsl +import com.intellij.psi.PsiMethod import com.intellij.testFramework.RunAll import groovy.transform.CompileStatic import org.jetbrains.plugins.gradle.highlighting.GradleHighlightingBaseTest -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression -import org.jetbrains.plugins.groovy.util.ResolveTest +import org.jetbrains.plugins.gradle.service.resolve.GradleDomainObjectProperty +import org.jetbrains.plugins.gradle.service.resolve.GradleExtensionProperty +import org.jetbrains.plugins.groovy.util.ExpressionTest import org.junit.Test import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_DISTRIBUTION import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_FILE_COPY_SPEC @CompileStatic -class GradleDistributionsTest extends GradleHighlightingBaseTest implements ResolveTest { +class GradleDistributionsTest extends GradleHighlightingBaseTest implements ExpressionTest { @Test void distributionsTest() { importProject("apply plugin: 'distribution'") new RunAll().append { + 'distributions container'() + } append { + 'distributions call'() + } append { 'distributions closure delegate'() } append { 'distribution via unqualified property reference'() @@ -43,9 +48,26 @@ class GradleDistributionsTest extends GradleHighlightingBaseTest implements Reso @Override protected List getParentCalls() { +// return [] return super.getParentCalls() + 'buildscript' } + void 'distributions container'() { + def type = isGradleAtLeast("3.5") ? "org.gradle.api.NamedDomainObjectContainer" + : "org.gradle.api.distribution.internal.DefaultDistributionContainer" + doTest('distributions') { + referenceExpressionTest(GradleExtensionProperty, type) + } + } + + void 'distributions call'() { + def type = isGradleAtLeast("3.5") ? "org.gradle.api.NamedDomainObjectContainer" + : "org.gradle.api.distribution.internal.DefaultDistributionContainer" + doTest('distributions {}') { + methodCallTest(PsiMethod, type) + } + } + void 'distributions closure delegate'() { def type = isGradleAtLeast("3.5") ? "org.gradle.api.NamedDomainObjectContainer" : "org.gradle.api.distribution.internal.DefaultDistributionContainer" @@ -56,17 +78,13 @@ class GradleDistributionsTest extends GradleHighlightingBaseTest implements Reso void 'distribution via unqualified property reference'() { doTest('distributions { foo }') { - def ref = elementUnderCaret(GrReferenceExpression) - assert ref.resolve() != null - assert ref.type.equalsToText("org.gradle.api.distribution.internal.DefaultDistribution") + referenceExpressionTest(GradleDomainObjectProperty, GRADLE_API_DISTRIBUTION) } } void 'distribution via unqualified method call'() { doTest('distributions { foo {} }') { - def call = elementUnderCaret(GrMethodCall) - assert call.resolveMethod() != null - assert call.type.equalsToText(GRADLE_API_DISTRIBUTION) + methodCallTest(PsiMethod, GRADLE_API_DISTRIBUTION) } } @@ -78,40 +96,32 @@ class GradleDistributionsTest extends GradleHighlightingBaseTest implements Reso void 'distribution member via unqualified method call closure delegate'() { doTest('distributions { foo { getBaseName() } }') { - def call = elementUnderCaret(GrMethodCall) - def method = call.resolveMethod() - assert method != null + def method = resolveMethodTest(PsiMethod) assert method.containingClass.qualifiedName == GRADLE_API_DISTRIBUTION } } void 'distribution via qualified property reference'() { - doTest('distributions { foo }; distributions.foo') { - def ref = elementUnderCaret(GrReferenceExpression) - assert ref.resolve() != null - assert ref.type.equalsToText(GRADLE_API_DISTRIBUTION) + doTest('distributions.foo') { + referenceExpressionTest(GradleDomainObjectProperty, GRADLE_API_DISTRIBUTION) } } void 'distribution via qualified method call'() { - doTest('distributions { foo }; distributions.foo {}') { - def call = elementUnderCaret(GrMethodCall) - assert call.resolveMethod() != null - assert call.type.equalsToText(GRADLE_API_DISTRIBUTION) + doTest('distributions.foo {}') { + methodCallTest(PsiMethod, GRADLE_API_DISTRIBUTION) } } void 'distribution closure delegate in qualified method call'() { - doTest('distributions { foo }; distributions.foo { }') { + doTest('distributions.foo { }') { closureDelegateTest(GRADLE_API_DISTRIBUTION, 1) } } void 'distribution member via qualified method call closure delegate'() { - doTest('distributions { foo }; distributions.foo { getBaseName() }') { - def call = elementUnderCaret(GrMethodCall) - def method = call.resolveMethod() - assert method != null + doTest('distributions.foo { getBaseName() }') { + def method = resolveMethodTest(PsiMethod) assert method.containingClass.qualifiedName == GRADLE_API_DISTRIBUTION } } diff --git a/plugins/gradle/java/testSources/dsl/GradleTasksTest.groovy b/plugins/gradle/java/testSources/dsl/GradleTasksTest.groovy index 57c7720f7312..4ede26024249 100644 --- a/plugins/gradle/java/testSources/dsl/GradleTasksTest.groovy +++ b/plugins/gradle/java/testSources/dsl/GradleTasksTest.groovy @@ -1,18 +1,18 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.gradle.dsl +import com.intellij.psi.PsiMethod import com.intellij.testFramework.RunAll import groovy.transform.CompileStatic import org.jetbrains.plugins.gradle.highlighting.GradleHighlightingBaseTest -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression -import org.jetbrains.plugins.groovy.lang.resolve.api.GroovyProperty -import org.jetbrains.plugins.groovy.util.ResolveTest +import org.jetbrains.plugins.gradle.service.resolve.GradleTaskProperty +import org.jetbrains.plugins.groovy.util.ExpressionTest import org.junit.Test import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* @CompileStatic -class GradleTasksTest extends GradleHighlightingBaseTest implements ResolveTest { +class GradleTasksTest extends GradleHighlightingBaseTest implements ExpressionTest { @Override protected List getParentCalls() { @@ -24,6 +24,8 @@ class GradleTasksTest extends GradleHighlightingBaseTest implements ResolveTest importProject("apply plugin:'java'") new RunAll().append { 'task via script'() + } append { + 'task container vs task'() } append { 'task via TaskContainer'() } append { @@ -41,6 +43,12 @@ class GradleTasksTest extends GradleHighlightingBaseTest implements ResolveTest } } + void 'task container vs task'() { + doTest('tasks') { + referenceExpressionTest(PsiMethod, GRADLE_API_TASK_CONTAINER) + } + } + void 'task via TaskContainer'() { doTest('tasks.tasks') { testTask('tasks', GRADLE_API_TASKS_DIAGNOSTICS_TASK_REPORT_TASK) @@ -66,11 +74,7 @@ class GradleTasksTest extends GradleHighlightingBaseTest implements ResolveTest } private void testTask(String name, String type) { - def expression = elementUnderCaret(GrReferenceExpression) - def results = expression.resolve(false) - assert results.size() == 1 - def property = assertInstanceOf(results[0].element, GroovyProperty) + def property = referenceExpressionTest(GradleTaskProperty, type) assert property.name == name - assert expression.type.equalsToText(type) } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleBuildScriptErrorParser.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleBuildScriptErrorParser.kt index 0d4ea5a1f41b..e3dabc949914 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleBuildScriptErrorParser.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleBuildScriptErrorParser.kt @@ -37,7 +37,7 @@ class GradleBuildScriptErrorParser : BuildOutputParser { parentId = reason.substringAfter("Execution failed for task '").substringBefore("'.") } else { - parentId = reader.buildId + parentId = reader.parentEventId } description.appendln(reason) loop@ while (true) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputDispatcherFactory.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputDispatcherFactory.kt index 9d3092cdaf21..837948140c8a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputDispatcherFactory.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputDispatcherFactory.kt @@ -7,7 +7,6 @@ import com.intellij.build.events.StartEvent import com.intellij.build.output.BuildOutputInstantReaderImpl import com.intellij.build.output.BuildOutputParser import com.intellij.build.output.LineProcessor -import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.externalSystem.service.execution.ExternalSystemOutputDispatcherFactory import com.intellij.openapi.externalSystem.service.execution.ExternalSystemOutputMessageDispatcher import org.gradle.api.logging.LogLevel @@ -31,13 +30,11 @@ class GradleOutputDispatcherFactory : ExternalSystemOutputDispatcherFactory { private val lineProcessor: LineProcessor private val myRootReader: BuildOutputInstantReaderImpl private var myCurrentReader: BuildOutputInstantReaderImpl - private val tasksOutputReaders: MutableMap - private val tasksEventIds: MutableMap + private val tasksOutputReaders = mutableMapOf() + private val tasksEventIds = mutableMapOf() init { - tasksOutputReaders = mutableMapOf() - tasksEventIds = mutableMapOf() - myRootReader = BuildOutputInstantReaderImpl(buildId, BuildProgressListener() { + myRootReader = BuildOutputInstantReaderImpl(buildId, BuildProgressListener { var buildEvent = it val parentId = buildEvent.parentId if (parentId != buildId && parentId is String) { @@ -67,16 +64,10 @@ class GradleOutputDispatcherFactory : ExternalSystemOutputDispatcherFactory { override fun onEvent(event: BuildEvent) { myBuildProgressListener.onEvent(event) if (event is StartEvent && event.parentId == buildId) { - val taskReader = tasksOutputReaders[event.message] - if (taskReader != null) { // multiple invocations of the same task during the build session - taskReader.close() - } + tasksOutputReaders[event.message]?.close() // multiple invocations of the same task during the build session val parentEventId = event.id - tasksOutputReaders[event.message] = BuildOutputInstantReaderImpl(buildId, BuildProgressListener() { - val buildEvent = if (it.parentId == buildId) BuildEventInvocationHandler.wrap(it, parentEventId) else it - myBuildProgressListener.onEvent(buildEvent) - }, parsers) + tasksOutputReaders[event.message] = BuildOutputInstantReaderImpl(parentEventId, myBuildProgressListener, parsers) tasksEventIds[event.message] = parentEventId } } @@ -134,17 +125,13 @@ class GradleOutputDispatcherFactory : ExternalSystemOutputDispatcherFactory { companion object { fun wrap(buildEvent: BuildEvent, parentEventId: Any): BuildEvent { - val classLoader = buildEvent.javaClass.getClassLoader() - val interfaces = buildEvent.javaClass.getInterfaces() + val classLoader = buildEvent.javaClass.classLoader + val interfaces = buildEvent.javaClass.interfaces val invocationHandler = BuildEventInvocationHandler(buildEvent, parentEventId) return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler) as BuildEvent } } } } - - companion object { - private val LOG = logger() - } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputParserProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputParserProvider.java index 92388a756e7a..73c8f112ac5d 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputParserProvider.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleOutputParserProvider.java @@ -2,14 +2,15 @@ package org.jetbrains.plugins.gradle.execution.build.output; import com.intellij.build.output.BuildOutputParser; +import com.intellij.build.output.JavacOutputParser; +import com.intellij.build.output.KotlincOutputParser; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTask; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemOutputParserProvider; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.SmartList; import org.jetbrains.plugins.gradle.util.GradleConstants; -import java.util.Collections; import java.util.List; /** @@ -23,11 +24,13 @@ public class GradleOutputParserProvider implements ExternalSystemOutputParserPro @Override public List getBuildOutputParsers(ExternalSystemTask task) { + List parsers = new SmartList<>(); if (task.getId().getType().equals(ExternalSystemTaskType.RESOLVE_PROJECT)) { - return ContainerUtil.list(new GradleSyncOutputParser(), new GradleBuildScriptErrorParser()); - } - else { - return ContainerUtil.list(new GradleBuildScriptErrorParser()); + parsers.add(new GradleSyncOutputParser()); } + parsers.add(new GradleBuildScriptErrorParser()); + parsers.add(new JavacOutputParser()); + parsers.add(new KotlincOutputParser()); + return parsers; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleSyncOutputParser.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleSyncOutputParser.java index a86282414c4a..dc26a46ef067 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleSyncOutputParser.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/build/output/GradleSyncOutputParser.java @@ -6,6 +6,7 @@ import com.intellij.build.events.MessageEvent; import com.intellij.build.events.impl.MessageEventImpl; import com.intellij.build.output.BuildOutputInstantReader; import com.intellij.build.output.BuildOutputParser; +import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; @@ -18,7 +19,7 @@ public class GradleSyncOutputParser implements BuildOutputParser { private static final String WARNING_PREFIX = "[sync warning]"; @Override - public boolean parse(String line, BuildOutputInstantReader reader, Consumer messageConsumer) { + public boolean parse(@NotNull String line, @NotNull BuildOutputInstantReader reader, @NotNull Consumer messageConsumer) { MessageEvent.Kind kind = MessageEvent.Kind.ERROR; String prefix = ERROR_PREFIX; int prefixIndex = line.indexOf(ERROR_PREFIX); @@ -32,7 +33,7 @@ public class GradleSyncOutputParser implements BuildOutputParser { } String text = line.substring(prefixIndex + prefix.length()).trim(); - messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), kind, null, text, text)); + messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), kind, null, text, text)); return true; } } diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java index 3d0b2c5c58ad..16f91f2a05d8 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java @@ -43,6 +43,35 @@ import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.get */ public class GradleFoldersImportingTest extends GradleImportingTestCase { + @Test + public void testUnsupportedTypesInDsl() throws Exception { + importProject( + new GradleBuildScriptBuilderEx().addPostfix( + "import org.gradle.api.internal.FactoryNamedDomainObjectContainer;", + "import org.gradle.internal.reflect.Instantiator;", + "class MyObj implements Named {", + " String myName;", + " public MyObj(String name) {", + " myName = namse", + " }", + " ", + " public String getName() {", + " return myName", + " }", + "}", + "project.extensions.create(", + " \"sourceSets\",", + " FactoryNamedDomainObjectContainer,", + " MyObj,", + " services.get(Instantiator),", + " {action -> }", + " ) ", + "sourceSets {", + " println \"Hello World!\"", + "}" + ).generate()); + } + @Test public void testBaseJavaProject() throws Exception { getCurrentExternalProjectSettings().setDelegatedBuild(ThreeState.NO); diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalTestsModelBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalTestsModelBuilderImpl.groovy index e05b300b597f..eb12c6afaf58 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalTestsModelBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalTestsModelBuilderImpl.groovy @@ -22,10 +22,16 @@ class ExternalTestsModelBuilderImpl implements ModelBuilderService { @Override Object buildAll(String modelName, Project project) { def defaultTestsModel = new DefaultExternalTestsModel() - defaultTestsModel.sourceTestMappings = getMapping(project) + if (javaPluginIsApplied(project)) { + defaultTestsModel.sourceTestMappings = getMapping(project) + } return defaultTestsModel } + private static boolean javaPluginIsApplied(Project project) { + return project.pluginManager.findPlugin('java-base') != null + } + private static List getMapping(Project project) { def taskToClassesDirs = new LinkedHashMap>() for (def task : project.tasks) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonBuilderContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonBuilderContributor.java index 4a2ecb5700c5..9f16a314413e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonBuilderContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonBuilderContributor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.builder; import com.intellij.psi.PsiClass; @@ -14,7 +14,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder import static com.intellij.psi.CommonClassNames.JAVA_UTIL_MAP; import static org.jetbrains.plugins.groovy.builder.JsonDelegateContributor.DELEGATE_FQN; import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE; -import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_KEY; +import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_TYPE_KEY; public class JsonBuilderContributor extends BuilderMethodsContributor { @@ -41,7 +41,7 @@ public class JsonBuilderContributor extends BuilderMethodsContributor { // (Closure) method = createMethod(name, clazz, place); - method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, DELEGATE_FQN); + method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, DELEGATE_FQN); if (!processor.process(method)) return false; // (Map) @@ -52,19 +52,19 @@ public class JsonBuilderContributor extends BuilderMethodsContributor { // (Map, Closure) method = createMethod(name, clazz, place); method.addParameter("map", JAVA_UTIL_MAP); - method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, DELEGATE_FQN); + method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, DELEGATE_FQN); if (!processor.process(method)) return false; // (Iterable, Closure) method = createMethod(name, clazz, place); method.addParameter("value", TypesUtil.createIterableType(place, null)); - method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, DELEGATE_FQN); + method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, DELEGATE_FQN); if (!processor.process(method)) return false; // (Object[], Closure) method = createMethod(name, clazz, place); method.addParameter("value", TypesUtil.getJavaLangObject(place).createArrayType()); - method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, DELEGATE_FQN); + method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, DELEGATE_FQN); return processor.process(method); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java index f46bd5804330..adb39b97f3b3 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.builder; import com.intellij.psi.*; @@ -9,7 +9,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE; -import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_KEY; +import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_TYPE_KEY; public class JsonDelegateContributor extends BuilderMethodsContributor { @@ -48,7 +48,7 @@ public class JsonDelegateContributor extends BuilderMethodsContributor { method = createMethod(name, clazz, place); genericType = facade.getElementFactory().createType(method.addTypeParameter("T")); method.addParameter("values", genericType.createArrayType()); - method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, DELEGATE_FQN); + method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, DELEGATE_FQN); method.setReturnType(TypesUtil.createListType(place, genericType)); if (!processor.process(method)) return false; @@ -56,7 +56,7 @@ public class JsonDelegateContributor extends BuilderMethodsContributor { method = createMethod(name, clazz, place); genericType = facade.getElementFactory().createType(method.addTypeParameter("T")); method.addParameter("values", TypesUtil.createIterableType(place, genericType)); - method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, DELEGATE_FQN); + method.addAndGetParameter("c", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, DELEGATE_FQN); method.setReturnType(TypesUtil.createListType(place, genericType)); if (!processor.process(method)) return false; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderContributor.java index 8e5da3b1b2cc..33258685ad58 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderContributor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.builder; import com.intellij.psi.PsiClass; @@ -15,7 +15,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; import static com.intellij.psi.CommonClassNames.JAVA_UTIL_MAP; import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE; -import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_KEY; +import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_TYPE_KEY; import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_STRATEGY_KEY; public class StreamingJsonBuilderContributor extends BuilderMethodsContributor { @@ -89,7 +89,7 @@ public class StreamingJsonBuilderContributor extends BuilderMethodsContributor { protected void addClosureParameter(GrLightMethodBuilder method) { GrLightParameter closureParam = method.addAndGetParameter("closure", GROOVY_LANG_CLOSURE); - closureParam.putUserData(DELEGATES_TO_KEY, getDelegateClassName()); + closureParam.putUserData(DELEGATES_TO_TYPE_KEY, getDelegateClassName()); closureParam.putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.OWNER_FIRST); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/XmlMarkupBuilderNonCodeMemberContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/XmlMarkupBuilderNonCodeMemberContributor.java index 1ed731538b1f..dc1e0f146034 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/XmlMarkupBuilderNonCodeMemberContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/XmlMarkupBuilderNonCodeMemberContributor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.builder; import com.intellij.psi.PsiClass; @@ -12,7 +12,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder import static com.intellij.psi.CommonClassNames.*; import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE; -import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_KEY; +import static org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToUtilKt.DELEGATES_TO_TYPE_KEY; public class XmlMarkupBuilderNonCodeMemberContributor extends BuilderMethodsContributor { @@ -39,19 +39,19 @@ public class XmlMarkupBuilderNonCodeMemberContributor extends BuilderMethodsCont // (Closure) res = createMethod(name, clazz, place); - res.addAndGetParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, FQN); + res.addAndGetParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, FQN); if (!processor.process(res)) return false; // (Object, Closure) res = createMethod(name, clazz, place); res.addParameter("value", JAVA_LANG_OBJECT); - res.addAndGetParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, FQN); + res.addAndGetParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, FQN); if (!processor.process(res)) return false; // (Map, Closure) res = createMethod(name, clazz, place); res.addParameter("attributes", JAVA_UTIL_MAP); - res.addAndGetParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, FQN); + res.addAndGetParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, FQN); if (!processor.process(res)) return false; // (Map) @@ -60,7 +60,7 @@ public class XmlMarkupBuilderNonCodeMemberContributor extends BuilderMethodsCont res = createMethod(name, clazz, place); res.addParameter("attributes", JAVA_UTIL_MAP); res.addOptionalParameter("value", JAVA_LANG_OBJECT); - res.addAndGetOptionalParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, FQN); + res.addAndGetOptionalParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, FQN); for (GrReflectedMethod method : res.getReflectedMethods()) { if (!processor.process(method)) return false; } @@ -71,7 +71,7 @@ public class XmlMarkupBuilderNonCodeMemberContributor extends BuilderMethodsCont res = createMethod(name, clazz, place); res.addParameter("value", JAVA_LANG_OBJECT); res.addOptionalParameter("attributes", JAVA_UTIL_MAP); - res.addAndGetOptionalParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_KEY, FQN); + res.addAndGetOptionalParameter("body", GROOVY_LANG_CLOSURE).putUserData(DELEGATES_TO_TYPE_KEY, FQN); for (GrReflectedMethod method : res.getReflectedMethods()) { if (!processor.process(method)) return false; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java index b8907e26f629..1a89577d2573 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java @@ -12,7 +12,6 @@ import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ConcurrencyUtil; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -30,6 +29,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; /** * @author ven @@ -131,7 +131,7 @@ public class GroovyPsiManager { PsiType type = map.get(key); if (type == null) { RecursionGuard.StackStamp stamp = RecursionManager.markStack(); - type = calculator.fun(key); + type = calculator.apply(key); if (type == null) { type = UNKNOWN_TYPE; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java index 8ed4f48ff228..b91643865cba 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.openapi.util.Computable; @@ -8,7 +8,6 @@ import com.intellij.psi.PsiType; import com.intellij.psi.ResolveResult; import com.intellij.psi.impl.source.resolve.ResolveCache.AbstractResolver; import com.intellij.psi.impl.source.resolve.ResolveCache.PolyVariantResolver; -import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; @@ -19,6 +18,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.GroovyResolver; import java.util.Collection; import java.util.Collections; +import java.util.function.Function; /** * @author peter diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PartialContext.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PartialContext.kt index 75d9c4579b21..2472419445b6 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PartialContext.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PartialContext.kt @@ -5,13 +5,13 @@ import com.intellij.openapi.util.Computable import com.intellij.psi.PsiReference import com.intellij.psi.PsiType import com.intellij.psi.impl.source.resolve.ResolveCache.AbstractResolver -import com.intellij.util.Function import gnu.trove.THashMap import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression import org.jetbrains.plugins.groovy.lang.psi.controlFlow.VariableDescriptor import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.createDescriptor import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAType +import java.util.function.Function class PartialContext(private val types: Map) : InferenceContext { @@ -49,7 +49,7 @@ class PartialContext(private val types: Map) : Infe override fun getExpressionType(element: T, calculator: Function): PsiType? { return doGetCachedValue(Pair(element, "type")) { - calculator.`fun`(element) + calculator.apply(element) } } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/TopInferenceContext.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/TopInferenceContext.kt index c1843b7ddd75..6a0cd5d28e96 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/TopInferenceContext.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/TopInferenceContext.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi.impl import com.intellij.openapi.util.Computable @@ -9,10 +9,10 @@ import com.intellij.psi.impl.source.resolve.ResolveCache.AbstractResolver import com.intellij.psi.util.CachedValueProvider.Result import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiModificationTracker -import com.intellij.util.Function import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper +import java.util.function.Function class TopInferenceContext : InferenceContext { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java index 975153219414..55157fdd8c8b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java @@ -9,9 +9,7 @@ import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.NullableFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; @@ -32,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.MethodTypeInferencer; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import static com.intellij.psi.util.CachedValueProvider.Result.create; import static org.jetbrains.plugins.groovy.lang.psi.impl.FunctionalExpressionsKt.*; @@ -174,7 +173,7 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock } private static final Function ourTypesCalculator = - (NullableFunction)block -> GroovyPsiManager.inferType(block, new MethodTypeInferencer(block)); + block -> GroovyPsiManager.inferType(block, new MethodTypeInferencer(block)); @Override @Nullable diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/ClassUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/ClassUtil.java index c74edafc207e..60db0bd56880 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/ClassUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/ClassUtil.java @@ -1,13 +1,13 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions; import com.intellij.psi.PsiClass; import com.intellij.psi.util.InheritanceUtil; -import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.util.LightCacheKey; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -17,7 +17,7 @@ public class ClassUtil { public static Map getSuperClassesWithCache(@NotNull PsiClass aClass) { Map superClassNames = PARENT_CACHE_KEY.getCachedValue(aClass); if (superClassNames == null) { - Set superClasses = new THashSet<>(); + Set superClasses = new LinkedHashSet<>(); superClasses.add(aClass); InheritanceUtil.getSuperClasses(aClass, superClasses, true); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java index 1ac0c2ceb824..56fca9fb9728 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java @@ -5,7 +5,6 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import com.intellij.psi.tree.IElementType; -import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; @@ -20,6 +19,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.references.GrOperatorReference; import org.jetbrains.plugins.groovy.util.SafePublicationClearableLazyValue; import java.util.Objects; +import java.util.function.Function; import static org.jetbrains.plugins.groovy.lang.psi.GroovyTokenSets.ASSIGNMENTS; import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.getLeastUpperBoundNullable; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java index 16dd29ab281a..eb933409d949 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java @@ -15,7 +15,6 @@ import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.ui.RowIcon; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; @@ -62,6 +61,7 @@ import javax.swing.*; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Function; import static org.jetbrains.plugins.groovy.lang.resolve.ResolveUtilKt.shouldProcessLocals; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java index d5edf2e7d13e..5867a4b8af42 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic; import com.intellij.navigation.NavigationItem; @@ -21,7 +7,6 @@ import com.intellij.psi.PsiIntersectionType; import com.intellij.psi.PsiType; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,6 +17,8 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrVariableEnhancer; +import java.util.function.Function; + /** * @author ven */ diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/api/SimpleGroovyProperty.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/api/SimpleGroovyProperty.kt new file mode 100644 index 000000000000..a0ff62cb15c4 --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/api/SimpleGroovyProperty.kt @@ -0,0 +1,11 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.groovy.lang.resolve.api + +import com.intellij.ide.presentation.Presentation +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType + +open class SimpleGroovyProperty(name: String, private val type: PsiType?, context: PsiElement) : GroovyPropertyBase(name, context) { + + final override fun getPropertyType(): PsiType? = type +} diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/DefaultDelegatesToProvider.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/DefaultDelegatesToProvider.kt index 6f5c34a18acf..aa0fc3c71a0d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/DefaultDelegatesToProvider.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/DefaultDelegatesToProvider.kt @@ -42,7 +42,11 @@ class DefaultDelegatesToProvider : GrDelegatesToProvider { val parameterList = method.parameterList val parameter = findParameter(parameterList, expression, map) ?: return null - val delegateFqnData = parameter.getUserData(DELEGATES_TO_KEY) + parameter.getUserData(DELEGATES_TO_KEY)?.let { + return it + } + + val delegateFqnData = parameter.getUserData(DELEGATES_TO_TYPE_KEY) val strategyData = parameter.getUserData(DELEGATES_TO_STRATEGY_KEY) if (delegateFqnData != null) { return DelegatesToInfo( diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/grDelegatesToUtil.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/grDelegatesToUtil.kt index 03ed50da15de..aced2344a5db 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/grDelegatesToUtil.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/delegatesTo/grDelegatesToUtil.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve.delegatesTo import com.intellij.openapi.util.Key @@ -11,8 +11,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.GrFunctionalExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall -@JvmField val DELEGATES_TO_KEY: Key = Key.create("groovy.closure.delegatesTo.type") -@JvmField val DELEGATES_TO_STRATEGY_KEY: Key = Key.create("groovy.closure.delegatesTo.strategy") +@JvmField +val DELEGATES_TO_KEY: Key = Key.create("groovy.closure.delegatesTo") +@JvmField +val DELEGATES_TO_TYPE_KEY: Key = Key.create("groovy.closure.delegatesTo.type") +@JvmField +val DELEGATES_TO_STRATEGY_KEY: Key = Key.create("groovy.closure.delegatesTo.strategy") val defaultDelegatesToInfo: DelegatesToInfo = DelegatesToInfo(null, Closure.OWNER_ONLY) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/ext/logback/LogbackDelegateMemberContributor.kt b/plugins/groovy/src/org/jetbrains/plugins/groovy/ext/logback/LogbackDelegateMemberContributor.kt index 31b871b2b0af..cd451c60df9c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/ext/logback/LogbackDelegateMemberContributor.kt +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/ext/logback/LogbackDelegateMemberContributor.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.ext.logback import com.intellij.openapi.util.Key @@ -19,7 +19,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil -import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_KEY +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_TYPE_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_STRATEGY_KEY import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.getContainingCall import org.jetbrains.plugins.groovy.lang.resolve.shouldProcessMethods @@ -108,7 +108,7 @@ class LogbackDelegateMemberContributor : NonCodeMembersContributor() { wrappedBase.copy().apply { addParameter("clazz", classType) addAndGetOptionalParameter("configuration", GROOVY_LANG_CLOSURE).apply { - putUserData(DELEGATES_TO_KEY, componentDelegateFqn) + putUserData(DELEGATES_TO_TYPE_KEY, componentDelegateFqn) putUserData(DELEGATES_TO_STRATEGY_KEY, DELEGATE_FIRST) } }.let { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GrMainCompletionProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GrMainCompletionProvider.java index f415f5022c16..82d28f4b63af 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GrMainCompletionProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GrMainCompletionProvider.java @@ -356,7 +356,7 @@ public class GrMainCompletionProvider extends CompletionProvider overloads, + protected LookupElement createLookupElement(@NotNull List overloads, @NotNull PsiClass containingClass, boolean shouldImport) { shouldImport |= originalPosition != null && PsiTreeUtil.isAncestor(containingClass, originalPosition, false); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyGotoDeclarationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyGotoDeclarationTest.groovy index 48404b0ce742..960adc71fca1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyGotoDeclarationTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyGotoDeclarationTest.groovy @@ -1,4 +1,4 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy import com.intellij.testFramework.LightProjectDescriptor @@ -10,7 +10,7 @@ class GroovyGotoDeclarationTest extends LightGroovyTestCase { final String basePath = TestUtils.testDataPath + "gotoDeclaration/" - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST private void doTest() { def name = getTestName() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy deleted file mode 100644 index f4a365e03e85..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package org.jetbrains.plugins.groovy - -import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.ContentEntry -import com.intellij.openapi.roots.ModifiableRootModel -import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.roots.libraries.Library -import com.intellij.openapi.vfs.JarFileSystem -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor -import groovy.transform.CompileStatic -import org.jetbrains.annotations.NotNull - -/** - * @author Max Medvedev - */ -@CompileStatic -class GroovyLightProjectDescriptor extends DefaultLightProjectDescriptor { - public static final LightProjectDescriptor GROOVY_LATEST = GroovyProjectDescriptors.GROOVY_LATEST - public static final LightProjectDescriptor GROOVY_LATEST_REAL_JDK = GroovyProjectDescriptors.GROOVY_LATEST_REAL_JDK - private final String myLibPath - - GroovyLightProjectDescriptor(String libPath) { - myLibPath = libPath - } - - @Override - void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) { - super.configureModule(module, model, contentEntry) - final Library.ModifiableModel modifiableModel = model.moduleLibraryTable.createLibrary("GROOVY").modifiableModel - final VirtualFile groovyJar = JarFileSystem.instance.refreshAndFindFileByPath("${myLibPath}!/") - assert groovyJar != null - modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES) - modifiableModel.commit() - } -} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/SetupRule.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/SetupRule.groovy index 15ec7c73f199..f51f71ec8697 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/SetupRule.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/SetupRule.groovy @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy import com.intellij.testFramework.EdtTestUtil @@ -22,11 +8,13 @@ import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement +import static org.jetbrains.plugins.groovy.GroovyProjectDescriptors.GROOVY_LATEST_REAL_JDK + @CompileStatic class SetupRule implements TestRule { final LightGroovyTestCase testCase = new LightGroovyTestCase() { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST_REAL_JDK + LightProjectDescriptor projectDescriptor = GROOVY_LATEST_REAL_JDK } @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/JsonBuilderTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/JsonBuilderTest.groovy index 2b2a9e0a5f61..6195a1391e0a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/JsonBuilderTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/JsonBuilderTest.groovy @@ -1,23 +1,10 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.builder import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -26,13 +13,11 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression import org.junit.Test -import static org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor.GROOVY_LATEST - // TODO rewrite into Spock test @CompileStatic class JsonBuilderTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test highlighting'() { fixture.configureByText 'a.groovy', '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderTest.groovy index c7dfea525611..dc06bb0c3c16 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/builder/StreamingJsonBuilderTest.groovy @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.builder import com.intellij.psi.PsiMethod @@ -20,7 +6,7 @@ import com.intellij.psi.impl.compiled.ClsMethodImpl import com.intellij.psi.impl.light.LightElement import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -32,7 +18,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe @CompileStatic class StreamingJsonBuilderTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test highlighting'() { myFixture.configureByText 'a.groovy', ''' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/editorActions/GroovyMoveLeftRightHandlerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/editorActions/GroovyMoveLeftRightHandlerTest.groovy index 6a0c3d459f1f..19f800ef6862 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/editorActions/GroovyMoveLeftRightHandlerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/editorActions/GroovyMoveLeftRightHandlerTest.groovy @@ -1,16 +1,16 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.codeInsight.editorActions import com.intellij.openapi.actionSystem.IdeActions import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase @CompileStatic class GroovyMoveLeftRightHandlerTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST private void doTest(String before, String after = null) { fixture.with { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyInlayParameterHintsProviderTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyInlayParameterHintsProviderTest.groovy index 90941c5fda11..7641cd93fd41 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyInlayParameterHintsProviderTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyInlayParameterHintsProviderTest.groovy @@ -6,13 +6,13 @@ import com.intellij.codeInsight.hints.settings.ParameterNameHintsSettings import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic import org.jdom.Element -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase @CompileStatic class GroovyInlayParameterHintsProviderTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIdenticalBranchesInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIdenticalBranchesInspectionTest.groovy index 8e6793d60365..b6fa2b755f8c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIdenticalBranchesInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIdenticalBranchesInspectionTest.groovy @@ -1,31 +1,17 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.codeInspection.control import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase import org.jetbrains.plugins.groovy.util.TestUtils @CompileStatic class GroovyIdenticalBranchesInspectionTest extends GrHighlightingTestBase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST String basePath = TestUtils.testDataPath + "inspections/identicalBranches/" @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryDefModifierInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryDefModifierInspectionTest.groovy index c34ff0006ad5..7d5cd8068864 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryDefModifierInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryDefModifierInspectionTest.groovy @@ -1,30 +1,16 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.codeInspection.style import com.intellij.codeInspection.actions.CleanupAllIntention import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase @CompileStatic class GrUnnecessaryDefModifierInspectionTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final GrUnnecessaryDefModifierInspection inspection = new GrUnnecessaryDefModifierInspection() @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryPublicModifierInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryPublicModifierInspectionTest.groovy index 2c7f2b7309ab..312a374965e1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryPublicModifierInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessaryPublicModifierInspectionTest.groovy @@ -1,32 +1,15 @@ -/* - * 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. - */ - - - +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.codeInspection.style import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase @CompileStatic class GrUnnecessaryPublicModifierInspectionTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test highlighting and fix'() { fixture.with { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy index d562d1c03afb..55d544e7c905 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy @@ -1,16 +1,16 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.codeInspection.style import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @CompileStatic class GrUnnecessarySemicolonInspectionTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test simple'() { doTest '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/unused/defaultParameter/GrUnusedDefaultParameterInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/unused/defaultParameter/GrUnusedDefaultParameterInspectionTest.groovy index 6d4d198bee1e..0b8f24df4e96 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/unused/defaultParameter/GrUnusedDefaultParameterInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/unused/defaultParameter/GrUnusedDefaultParameterInspectionTest.groovy @@ -1,25 +1,12 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.codeInspection.unused.defaultParameter -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import com.intellij.testFramework.LightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors class GrUnusedDefaultParameterInspectionTest /*extends LightGroovyTestCase*/ { - final GroovyLightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test simple 0'() { testHighlighting '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/GrBuilderTransformationCompletionTestBase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/GrBuilderTransformationCompletionTestBase.groovy index 46840e270341..002c7b9869b9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/GrBuilderTransformationCompletionTestBase.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/GrBuilderTransformationCompletionTestBase.groovy @@ -1,24 +1,10 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.completion.builder import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.completion.CompletionResult import org.jetbrains.plugins.groovy.completion.GroovyCompletionTestBase @@ -30,7 +16,7 @@ abstract class GrBuilderTransformationCompletionTestBase extends GroovyCompletio @Override @NotNull protected LightProjectDescriptor getProjectDescriptor() { - return GroovyLightProjectDescriptor.GROOVY_LATEST + return GroovyProjectDescriptors.GROOVY_LATEST } void doVariantableTest(String text, String... args) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/MiscBuilderTransformationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/MiscBuilderTransformationTest.groovy index 222977be4979..233b889a5cd5 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/MiscBuilderTransformationTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/builder/MiscBuilderTransformationTest.groovy @@ -1,32 +1,18 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.completion.builder import com.intellij.psi.OriginInfoAwareElement import com.intellij.psi.impl.light.LightElement import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderAnnotationContributor @CompileStatic class MiscBuilderTransformationTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test resolve inner class from java'() { myFixture.addFileToProject 'sample/Bean.groovy', '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifyResolveTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifyResolveTest.groovy index 7efe9f412b29..3eb2aff63863 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifyResolveTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifyResolveTest.groovy @@ -1,15 +1,15 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.ext.newify import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.resolve.GroovyResolveTestCase class NewifyResolveTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifySupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifySupportTest.groovy index febab34bdb4c..fae4c119c33f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifySupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/newify/NewifySupportTest.groovy @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.ext.newify import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase @@ -11,7 +11,7 @@ import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase @CompileStatic class NewifySupportTest extends GrHighlightingTestBase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/spock/SpockLineMarkersTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/spock/SpockLineMarkersTest.groovy index 4c5ef0576b45..a07da273d38b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/spock/SpockLineMarkersTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/ext/spock/SpockLineMarkersTest.groovy @@ -1,31 +1,17 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.ext.spock import com.intellij.codeInsight.TestFrameworks import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.GroovyFile @CompileStatic class SpockLineMarkersTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateConstantFromJavaUsageTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateConstantFromJavaUsageTest.groovy index 49fa17428e22..6b9d765fcb60 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateConstantFromJavaUsageTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateConstantFromJavaUsageTest.groovy @@ -1,14 +1,15 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.fixes import com.intellij.psi.impl.source.PostprocessReformattingAspect import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase import org.jetbrains.plugins.groovy.util.TestUtils +import static org.jetbrains.plugins.groovy.GroovyProjectDescriptors.GROOVY_LATEST_REAL_JDK + @CompileStatic class CreateConstantFromJavaUsageTest extends GrHighlightingTestBase { final String getBasePath() { @@ -18,7 +19,7 @@ class CreateConstantFromJavaUsageTest extends GrHighlightingTestBase { @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() { - return GroovyLightProjectDescriptor.GROOVY_LATEST_REAL_JDK + return GROOVY_LATEST_REAL_JDK } private void doTest(String action = 'Create constant', int actionsCount = 1) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrLoosePrecisionFixTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrLoosePrecisionFixTest.groovy index cd0d6e864298..0aa33686f9da 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrLoosePrecisionFixTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrLoosePrecisionFixTest.groovy @@ -1,13 +1,13 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.fixes import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase class GrLoosePrecisionFixTest extends GrHighlightingTestBase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrMultipleAssignmentTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrMultipleAssignmentTest.groovy index c78f7774ef8d..1419400e5ed0 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrMultipleAssignmentTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrMultipleAssignmentTest.groovy @@ -1,15 +1,15 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.fixes import com.intellij.codeInspection.InspectionProfileEntry import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase class GrMultipleAssignmentTest extends GrHighlightingTestBase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST InspectionProfileEntry[] getCustomInspections() { [new GroovyAssignabilityCheckInspection()] } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrSpreadArgumentTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrSpreadArgumentTest.groovy index 469ac2191c42..480f7c59536c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrSpreadArgumentTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/GrSpreadArgumentTest.groovy @@ -1,27 +1,13 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.fixes import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase class GrSpreadArgumentTest extends GrHighlightingTestBase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy deleted file mode 100644 index ab7d58acaab3..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 org.jetbrains.plugins.groovy.geb - -import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.ContentEntry -import com.intellij.openapi.roots.ModifiableRootModel -import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.roots.libraries.Library -import com.intellij.openapi.vfs.JarFileSystem -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.util.TestUtils -/** - * @author Sergey Evdokimov - */ -abstract class AbstractGebLightTestCase extends LightCodeInsightFixtureTestCase { - - static descriptor = new GebProjectDescriptor() - - @NotNull - @Override - protected LightProjectDescriptor getProjectDescriptor() { - return descriptor - } - - -} - -class GebProjectDescriptor extends DefaultLightProjectDescriptor { - void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) { - final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel() - - def fs = JarFileSystem.instance - modifiableModel.addRoot(fs.findFileByPath("$TestUtils.mockGroovyLibraryHome/$TestUtils.GROOVY_JAR!/"), OrderRootType.CLASSES) - - def gebJarFolder = new File(TestUtils.absoluteTestDataPath + "/mockGeb") - for (File gebJar : gebJarFolder.listFiles()) { - if (gebJar.name.endsWith('sources.jar')) { - modifiableModel.addRoot(fs.findFileByPath("${gebJar.path}!/"), OrderRootType.SOURCES) - } - else if (gebJar.name.endsWith(".jar")) { - modifiableModel.addRoot(fs.findFileByPath("${gebJar.path}!/"), OrderRootType.CLASSES) - } - } - - modifiableModel.commit() - } -} \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy index 2bf06728a5fa..0ab36a718cc4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy @@ -1,13 +1,33 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.geb +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.annotations.NotNull +import org.jetbrains.plugins.groovy.LibraryLightProjectDescriptor +import org.jetbrains.plugins.groovy.RepositoryTestLibrary +import org.jetbrains.plugins.groovy.TestLibrary import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.util.TestUtils -/** - * @author Sergey Evdokimov - */ -class GebTestsTest extends AbstractGebLightTestCase { +import static org.jetbrains.plugins.groovy.GroovyProjectDescriptors.LIB_GROOVY_1_6 + +class GebTestsTest extends LightCodeInsightFixtureTestCase { + + private static final TestLibrary LIB_GEB = new RepositoryTestLibrary( + 'org.codehaus.geb:geb-core:0.7.2', + 'org.codehaus.geb:geb-junit4:0.7.2', + 'org.codehaus.geb:geb-spock:0.7.2', + 'org.codehaus.geb:geb-testng:0.7.2' + ) + + public static final LightProjectDescriptor DESCRIPTOR = new LibraryLightProjectDescriptor(LIB_GROOVY_1_6 + LIB_GEB) + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return DESCRIPTOR + } void testSpockTestMemberCompletion() { myFixture.configureByText("FooTest.groovy", """ @@ -33,7 +53,7 @@ class FooTest extends geb.junit4.GebReportingTest { TestUtils.checkCompletionContains(myFixture, "\$()", "to()", "go()", "currentWindow", "verifyAt()", "title") } - + void testTestNGTestMemberCompletion() { myFixture.configureByText("FooTest.groovy", """ class FooTest extends geb.testng.GebReportingTest { @@ -263,5 +283,4 @@ class A extends geb.Page { } """) } - } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovyRunLineMarkerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovyRunLineMarkerTest.groovy index 1f75c5ba65c2..c2a5a0bb19b9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovyRunLineMarkerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovyRunLineMarkerTest.groovy @@ -1,16 +1,16 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.ide import com.intellij.openapi.util.registry.Registry import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase @CompileStatic class GroovyRunLineMarkerTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToMethodTest.groovy index 5650e38f1e74..f53865d9014c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToMethodTest.groovy @@ -1,39 +1,10 @@ -/* - * 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. - */ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.inspections import com.intellij.psi.PsiElement import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.changeToMethod.ChangeToMethodInspection import org.jetbrains.plugins.groovy.lang.psi.GroovyFile @@ -44,7 +15,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryE @CompileStatic class GrChangeToMethodTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final ChangeToMethodInspection inspection = new ChangeToMethodInspection() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToOperatorTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToOperatorTest.groovy index 04bb66beea65..c05cf7b40697 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToOperatorTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrChangeToOperatorTest.groovy @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.inspections import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.changeToOperator.ChangeToOperatorInspection import org.jetbrains.plugins.groovy.lang.psi.GroovyFile @@ -15,7 +15,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryE @CompileStatic class GrChangeToOperatorTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final ChangeToOperatorInspection inspection = new ChangeToOperatorInspection() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy index ee6ef3aec994..32b23ea47bf3 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy @@ -1,23 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.inspections import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.declaration.GrMethodMayBeStaticInspection @@ -27,7 +13,7 @@ import org.jetbrains.plugins.groovy.codeInspection.declaration.GrMethodMayBeStat @CompileStatic class GrMethodMayBeStaticTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final GrMethodMayBeStaticInspection inspection = new GrMethodMayBeStaticInspection() void testSimple() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrClosureParamsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrClosureParamsTest.groovy index 645c149eef0a..2cb689148144 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrClosureParamsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrClosureParamsTest.groovy @@ -3,14 +3,14 @@ package org.jetbrains.plugins.groovy.lang.highlighting import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @CompileStatic class GrClosureParamsTest extends GrHighlightingTestBase { final String basePath = super.basePath + 'closureParams/' - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test from string with non-fqn options no error'() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrHighlightingAttributesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrHighlightingAttributesTest.groovy index ba55c711e1c4..440d27ccbea9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrHighlightingAttributesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrHighlightingAttributesTest.groovy @@ -1,14 +1,14 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.highlighting import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors @CompileStatic class GrHighlightingAttributesTest extends GrHighlightingTestBase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test highlighting attributes'() { fixture.testHighlighting false, true, false, "highlightingAttributes/test.groovy" diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrLatestHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrLatestHighlightingTest.groovy index 07be2c5658a0..5c0451d155fc 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrLatestHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrLatestHighlightingTest.groovy @@ -5,17 +5,19 @@ import com.intellij.codeInspection.InspectionProfileEntry import com.intellij.openapi.util.RecursionManager import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.bugs.GroovyAccessibilityInspection import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection +import static org.jetbrains.plugins.groovy.GroovyProjectDescriptors.GROOVY_LATEST_REAL_JDK + class GrLatestHighlightingTest extends GrHighlightingTestBase { + @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() { - return GroovyLightProjectDescriptor.GROOVY_LATEST_REAL_JDK + return GROOVY_LATEST_REAL_JDK } @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightUsagesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightUsagesTest.groovy index 6122b6db91a9..b28d4d3d78db 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightUsagesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightUsagesTest.groovy @@ -5,7 +5,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType import com.intellij.codeInsight.daemon.impl.SeveritiesProvider import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.util.TestUtils @@ -20,7 +20,7 @@ class GroovyHighlightUsagesTest extends LightGroovyTestCase { final List severitiesHighlightInfoTypes = [ELEMENT_UNDER_CARET_READ, ELEMENT_UNDER_CARET_WRITE] } - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final String basePath = TestUtils.testDataPath + 'highlighting/usages/' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/ModifiersTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/ModifiersTest.groovy index b7a1d5ae4211..16a9b5ef4ae8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/ModifiersTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/ModifiersTest.groovy @@ -1,18 +1,16 @@ -/* - * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi import com.intellij.psi.PsiModifier import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase @CompileStatic class ModifiersTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test top level enum is not static'() { fixture.addFileToProject 'classes.groovy', 'enum E {}' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsTest.groovy index d45829063f5d..3cddcbb3f154 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsTest.groovy @@ -1,29 +1,15 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection class FromAbstractTypeMethodsTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test stuff'() { fixture.with { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ConstantExpressionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ConstantExpressionTest.groovy index 623ee29747e0..e33c4c67b890 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ConstantExpressionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ConstantExpressionTest.groovy @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import static org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil.getStringArrayValue @@ -12,7 +12,7 @@ import static org.jetbrains.plugins.groovy.util.TestUtils.disableAstLoading @CompileStatic class ConstantExpressionTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST private void addJavaAnnotation() { fixture.addClass '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/CustomMapPropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/CustomMapPropertyTest.groovy index f8b8115b86c7..f698121d1820 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/CustomMapPropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/CustomMapPropertyTest.groovy @@ -7,14 +7,14 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrClassDefin import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod import org.jetbrains.plugins.groovy.lang.resolve.api.GroovyMapProperty import org.jetbrains.plugins.groovy.util.GroovyLatestTest -import org.jetbrains.plugins.groovy.util.ReferenceExpressionTest +import org.jetbrains.plugins.groovy.util.ExpressionTest import org.junit.Before import org.junit.Test import static com.intellij.psi.CommonClassNames.JAVA_LANG_INTEGER @CompileStatic -class CustomMapPropertyTest extends GroovyLatestTest implements ReferenceExpressionTest { +class CustomMapPropertyTest extends GroovyLatestTest implements ExpressionTest { @Before void addClasses() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/DelegatesToSupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/DelegatesToSupportTest.groovy index 2755d1400502..6cc39382f5f0 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/DelegatesToSupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/DelegatesToSupportTest.groovy @@ -1,23 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -25,7 +11,7 @@ import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnr @CompileStatic class DelegatesToSupportTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrImportContributorTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrImportContributorTest.groovy index 92924c67746d..22079ba72b8a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrImportContributorTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrImportContributorTest.groovy @@ -3,14 +3,14 @@ package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @CompileStatic class GrImportContributorTest extends LightGroovyTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrNumericLUBTypeTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrNumericLUBTypeTest.groovy index 677ae95aeb65..ef7040b345b2 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrNumericLUBTypeTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GrNumericLUBTypeTest.groovy @@ -1,23 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression @@ -25,7 +11,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres @CompileStatic class GrNumericLUBTypeTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy index 12163fcd3a29..08fa0ba9a63b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.codeInsight.completion.CompletionType @@ -20,13 +6,13 @@ import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.plugins.groovy.GroovyFileType -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod class GroovyTraitCoercionTest extends GroovyResolveTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/MapPropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/MapPropertyTest.groovy index 00b1aa65dd23..e44b0467c3e9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/MapPropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/MapPropertyTest.groovy @@ -1,11 +1,11 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import groovy.transform.CompileStatic import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod import org.jetbrains.plugins.groovy.lang.resolve.api.GroovyMapProperty import org.jetbrains.plugins.groovy.util.GroovyLatestTest -import org.jetbrains.plugins.groovy.util.ReferenceExpressionTest +import org.jetbrains.plugins.groovy.util.ExpressionTest import org.junit.Test import static com.intellij.psi.CommonClassNames.JAVA_LANG_INTEGER @@ -13,7 +13,7 @@ import static com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_META_CLASS @CompileStatic -class MapPropertyTest extends GroovyLatestTest implements ReferenceExpressionTest { +class MapPropertyTest extends GroovyLatestTest implements ExpressionTest { @Test void 'arbitrary property in instance context'() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy index dc788403c463..ea3cf25af9ad 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy @@ -1,45 +1,18 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.codeInsight.TargetElementUtil -import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.ContentEntry -import com.intellij.openapi.roots.ModifiableRootModel -import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.roots.libraries.Library -import com.intellij.openapi.vfs.JarFileSystem -import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor import org.jetbrains.plugins.groovy.LightGroovyTestCase +import org.jetbrains.plugins.groovy.geb.GebTestsTest import org.jetbrains.plugins.groovy.util.TestUtils -import static org.jetbrains.plugins.groovy.util.TestUtils.getAbsoluteTestDataPath - -/** - * @author Max Medvedev - */ class NavigateDelegatedClsMethodsTest extends LightGroovyTestCase { + final String basePath = TestUtils.testDataPath + 'resolve/clsMethod' - final LightProjectDescriptor projectDescriptor = new GroovyLightProjectDescriptor(TestUtils.mockGroovy2_1LibraryName) { - @Override - void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) { - super.configureModule(module, model, contentEntry) - - Library.ModifiableModel gebModel = model.moduleLibraryTable.createLibrary("Geb").modifiableModel - VirtualFile gebJar = JarFileSystem.instance.refreshAndFindFileByPath(absoluteTestDataPath + 'mockGeb/geb-core-0.7.1.jar!/') - assert gebJar != null - gebModel.addRoot(gebJar, OrderRootType.CLASSES) - VirtualFile gebSource = JarFileSystem.instance.refreshAndFindFileByPath(absoluteTestDataPath + 'mockGeb/geb-core-0.7.1-sources.jar!/') - assert gebSource != null - gebModel.addRoot(gebSource, OrderRootType.SOURCES) - - gebModel.commit() - } - } + final LightProjectDescriptor projectDescriptor = GebTestsTest.DESCRIPTOR void testNavigationInGroovy() { myFixture.with { @@ -55,7 +28,7 @@ class A extends Page { def instance = TargetElementUtil.getInstance() def resolved = instance.findTargetElement(editor, instance.allAccepted, editor.caretModel.offset) assertInstanceOf resolved, PsiMethod - assertEquals('NavigableSupport', (resolved as PsiMethod).containingClass.name) + assertEquals('Page', (resolved as PsiMethod).containingClass.name) } } @@ -73,7 +46,7 @@ class A extends Page { def instance = TargetElementUtil.getInstance() def resolved = instance.findTargetElement(editor, instance.allAccepted, editor.caretModel.offset).navigationElement assertInstanceOf resolved, PsiMethod - assertEquals('NavigableSupport', (resolved as PsiMethod).containingClass.name) + assertEquals('Page', (resolved as PsiMethod).containingClass.name) } } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NumberMathTypingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NumberMathTypingTest.groovy index 1b4302b1c45c..a0e9dfa74f7f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NumberMathTypingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NumberMathTypingTest.groovy @@ -3,7 +3,7 @@ package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.PsiClassType import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -12,7 +12,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres class NumberMathTypingTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveAttributeTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveAttributeTest.groovy index cbb75723857e..998bf9abc097 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveAttributeTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveAttributeTest.groovy @@ -1,15 +1,15 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import groovy.transform.CompileStatic import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField import org.jetbrains.plugins.groovy.util.GroovyLatestTest -import org.jetbrains.plugins.groovy.util.ReferenceExpressionTest +import org.jetbrains.plugins.groovy.util.ExpressionTest import org.junit.Before import org.junit.Test @CompileStatic -class ResolveAttributeTest extends GroovyLatestTest implements ReferenceExpressionTest { +class ResolveAttributeTest extends GroovyLatestTest implements ExpressionTest { @Before void addClasses() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassInNewTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassInNewTest.groovy index 3ec35bcda4c2..afd7f9b3bdd1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassInNewTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassInNewTest.groovy @@ -1,10 +1,10 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.PsiClass import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.util.TestUtils @@ -13,7 +13,7 @@ import static com.intellij.openapi.util.RecursionManager.assertOnRecursionPreven @CompileStatic class ResolveClassInNewTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final String basePath = TestUtils.testDataPath + '/resolve/classInNew' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveFieldVsAccessorTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveFieldVsAccessorTest.groovy index 22bdcc75132e..66f61856eb6f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveFieldVsAccessorTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveFieldVsAccessorTest.groovy @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod @@ -13,7 +13,7 @@ import static org.jetbrains.plugins.groovy.util.ThrowingTransformation.disableTr @CompileStatic class ResolveFieldVsAccessorTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test implicit this'() { disableTransformations testRootDisposable diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveIndexPropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveIndexPropertyTest.groovy index f35df31e8e6f..f164d2162b8d 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveIndexPropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveIndexPropertyTest.groovy @@ -1,10 +1,10 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty @@ -15,7 +15,7 @@ import static org.jetbrains.plugins.groovy.lang.resolve.ResolveUtilKt.valid @CompileStatic class ResolveIndexPropertyTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test prefer single parameter'() { fixture.addFileToProject 'classes.groovy', '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveOperatorAssignmentTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveOperatorAssignmentTest.groovy index 02bad9e4274f..d3eb7968740d 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveOperatorAssignmentTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveOperatorAssignmentTest.groovy @@ -1,30 +1,16 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression class ResolveOperatorAssignmentTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test resolve both getter & setter'() { fixture.with { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyViaAliasedImportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyViaAliasedImportTest.groovy index 4d1b4712cf33..e315ec09b447 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyViaAliasedImportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyViaAliasedImportTest.groovy @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase @@ -12,7 +12,7 @@ import org.jetbrains.plugins.groovy.util.TestUtils @CompileStatic class ResolvePropertyViaAliasedImportTest extends GrHighlightingTestBase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST final String basePath = TestUtils.testDataPath + 'resolve/imports' @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToOnLambdaTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToOnLambdaTest.groovy index 7320604c550c..1c04c4834a0a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToOnLambdaTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToOnLambdaTest.groovy @@ -5,7 +5,7 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression @@ -20,7 +20,7 @@ import static org.jetbrains.plugins.groovy.util.ThrowingTransformation.disableTr @CompileStatic class ResolveWithDelegatesToOnLambdaTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test owner first method'() { assertScript '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy index 7c73660eef0b..80f9aeb780ab 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy @@ -1,11 +1,11 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.PsiClass import com.intellij.psi.PsiMethod import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression @@ -20,7 +20,7 @@ import static org.jetbrains.plugins.groovy.util.ThrowingTransformation.disableTr @CompileStatic class ResolveWithDelegatesToTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test owner first method'() { assertScript '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/SelfTypeSupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/SelfTypeSupportTest.groovy index 8d44c205bf53..2216fcd65723 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/SelfTypeSupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/SelfTypeSupportTest.groovy @@ -1,24 +1,10 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.PsiElement import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod @@ -26,7 +12,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe @CompileStatic class SelfTypeSupportTest extends LightGroovyTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST String defaultImports = '''\ import groovy.transform.SelfType ''' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveDGMMethodLatestTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveDGMMethodLatestTest.groovy index f06c17b5d588..d08aac55847a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveDGMMethodLatestTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveDGMMethodLatestTest.groovy @@ -1,30 +1,16 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve.dgm import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod import org.jetbrains.plugins.groovy.lang.resolve.GroovyResolveTestCase @CompileStatic class ResolveDGMMethodLatestTest extends GroovyResolveTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void testCloseable() { myFixture.addClass('package java.io; class Closeable {}') diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveExtensionMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveExtensionMethodTest.groovy index 8cc5e923ef7f..789d884d210e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveExtensionMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/dgm/ResolveExtensionMethodTest.groovy @@ -6,7 +6,7 @@ import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic import org.intellij.lang.annotations.Language import org.jetbrains.plugins.groovy.GroovyFileType -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod import org.jetbrains.plugins.groovy.lang.resolve.GroovyResolveTestCase @@ -16,7 +16,7 @@ import static org.jetbrains.plugins.groovy.dgm.DGMUtil.ORG_CODEHAUS_GROOVY_RUNTI @CompileStatic class ResolveExtensionMethodTest extends GroovyResolveTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST private void addExtension(String directory = "services", @Language("Groovy") String text) { def factory = PsiFileFactory.getInstance(project) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/modifiers/GrVisibilityTestBase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/modifiers/GrVisibilityTestBase.groovy index 6abfadee5faf..d154a91986b8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/modifiers/GrVisibilityTestBase.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/modifiers/GrVisibilityTestBase.groovy @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.resolve.modifiers import com.intellij.extapi.psi.PsiFileBase @@ -20,7 +6,7 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiModifierListOwner import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.GroovyFile @@ -31,7 +17,7 @@ abstract class GrVisibilityTestBase extends LightGroovyTestCase { private static final String[] VISIBILITY_MODIFIERS = [PUBLIC, PRIVATE, PROTECTED, PACKAGE_LOCAL] - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST protected PsiClass addClass(String packageName = "pckg", String text) { def file = fixture.addFileToProject("$packageName/_.groovy", """\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy index 768f0b9abd17..da4d7ad8bcab 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy @@ -1,31 +1,17 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.refactoring.rename import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.fixtures.CodeInsightTestUtil import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.refactoring.rename.inplace.GrMethodInplaceRenameHandler @CompileStatic class InplaceRenameTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST private void doTest(String before, String newName, String after) { fixture.configureByText '_.groovy', before diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/BaseScriptTransformationSupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/BaseScriptTransformationSupportTest.groovy index 51283820fddb..afcb7578955b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/BaseScriptTransformationSupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/BaseScriptTransformationSupportTest.groovy @@ -1,25 +1,11 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations import com.intellij.psi.PsiClass import com.intellij.psi.util.InheritanceUtil import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass @@ -27,7 +13,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass @CompileStatic class BaseScriptTransformationSupportTest extends LightGroovyTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST private void doTest(String text) { fixture.addFileToProject 'base.groovy', 'abstract class MyBaseScript extends Script {}' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrAutoCloneTransformationSupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrAutoCloneTransformationSupportTest.groovy index 6f055c986a44..43fbb640e0e1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrAutoCloneTransformationSupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrAutoCloneTransformationSupportTest.groovy @@ -2,13 +2,13 @@ package org.jetbrains.plugins.groovy.transformations import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression class GrAutoCloneTransformationSupportTest extends LightGroovyTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test clone() return type'() { doExpressionTypeTest '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrNoTransformationsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrNoTransformationsTest.groovy index 3f950187d570..0f4ccee9e0c9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrNoTransformationsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrNoTransformationsTest.groovy @@ -1,11 +1,9 @@ -/* - * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter import org.jetbrains.plugins.groovy.lang.resolve.GroovyResolveTestCase @@ -15,7 +13,7 @@ import static org.jetbrains.plugins.groovy.util.ThrowingTransformation.disableTr @CompileStatic class GrNoTransformationsTest extends GroovyResolveTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrTransformationsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrTransformationsTest.groovy index 1e8fbc1eee91..6958bb07992e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrTransformationsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/GrTransformationsTest.groovy @@ -1,16 +1,16 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod import org.jetbrains.plugins.groovy.lang.resolve.GroovyResolveTestCase @CompileStatic class GrTransformationsTest extends GroovyResolveTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test skip compiled classes while checking if to include synthetic members'() { def resolved = resolveByText(''' diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/SynchronizedTransformationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/SynchronizedTransformationTest.groovy index bf7e2a322950..d9e2e0cfa1e7 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/SynchronizedTransformationTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/SynchronizedTransformationTest.groovy @@ -1,25 +1,11 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations import com.intellij.codeInspection.InspectionProfileEntry import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField @@ -27,7 +13,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField @CompileStatic class SynchronizedTransformationTest extends LightGroovyTestCase { - LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test $lock is used by annotated instance method'() { testHighlighting '''\ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/immutable/ImmutableTransformationSupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/immutable/ImmutableTransformationSupportTest.groovy index bd03cd8920bd..0e146f3fe856 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/immutable/ImmutableTransformationSupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/immutable/ImmutableTransformationSupportTest.groovy @@ -1,10 +1,10 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations.immutable import com.intellij.codeInsight.completion.CompletionType import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -14,7 +14,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrM @CompileStatic class ImmutableTransformationSupportTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/indexedProperty/IndexedPropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/indexedProperty/IndexedPropertyTest.groovy index f1664ae37f6d..2dacdc724bd4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/indexedProperty/IndexedPropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/indexedProperty/IndexedPropertyTest.groovy @@ -1,23 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations.indexedProperty import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -25,7 +11,7 @@ import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnr @CompileStatic class IndexedPropertyTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test all methods resolved'() { fixture.with { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/listenerList/ListenerListTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/listenerList/ListenerListTest.groovy index 489f17a3ed31..ba0956ff2bd7 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/listenerList/ListenerListTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/listenerList/ListenerListTest.groovy @@ -1,23 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations.listenerList import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl @@ -25,7 +11,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl @CompileStatic class ListenerListTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST @Override void setUp() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonConstructorInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonConstructorInspectionTest.groovy index 1ac32add9080..9e9b21aa2afe 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonConstructorInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonConstructorInspectionTest.groovy @@ -1,30 +1,16 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations.singleton import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.transformations.GroovyTransformationsBundle @CompileStatic class SingletonConstructorInspectionTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void setUp() { super.setUp() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonNewInstanceInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonNewInstanceInspectionTest.groovy index 8149ebc01b9e..9e7b0d9319a3 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonNewInstanceInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonNewInstanceInspectionTest.groovy @@ -1,29 +1,15 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations.singleton import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle import org.jetbrains.plugins.groovy.codeInspection.bugs.NewInstanceOfSingletonInspection class SingletonNewInstanceInspectionTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void setUp() { super.setUp() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupportTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupportTest.groovy index 3da2960f5624..3aa6b7eae37f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupportTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupportTest.groovy @@ -1,23 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.transformations.singleton import com.intellij.testFramework.LightProjectDescriptor import groovy.transform.CompileStatic -import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl @@ -25,7 +11,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl @CompileStatic class SingletonTransformationSupportTest extends LightGroovyTestCase { - final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_LATEST void 'test highlighting'() { fixture.with { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/ExpressionTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/ExpressionTest.java new file mode 100644 index 000000000000..aa7c3f0dd361 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/ExpressionTest.java @@ -0,0 +1,54 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.groovy.util; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import org.intellij.lang.annotations.Language; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; + +import static com.intellij.testFramework.UsefulTestCase.*; + +public interface ExpressionTest extends ResolveTest, TypingTest { + + default void referenceExpressionTest(@Language("Groovy") String text, + @Nullable Class resolved, + String expectedType) { + GrReferenceExpression expression = lastExpression(text, GrReferenceExpression.class); + resolveTest(expression, resolved); + typingTest(expression, expectedType); + } + + default T referenceExpressionTest(@Nullable Class clazz, @Nullable String expectedType) { + GrReferenceExpression expression = elementUnderCaret(GrReferenceExpression.class); + T resolved = resolveTest(expression, clazz); + typingTest(expression, expectedType); + return resolved; + } + + @NotNull + default T resolveMethodTest(@NotNull Class clazz) { + GrMethodCall expression = elementUnderCaret(GrMethodCall.class); + GroovyResolveResult[] results = expression.multiResolve(false); + PsiElement resolved = assertOneElement(results).getElement(); + return assertInstanceOf(resolved, clazz); + } + + default T methodCallTest(@Nullable Class clazz, @Nullable String expectedType) { + GrMethodCall expression = elementUnderCaret(GrMethodCall.class); + GroovyResolveResult[] results = expression.multiResolve(false); + final T resolved; + if (clazz == null) { + assertEmpty(results); + resolved = null; + } + else { + resolved = assertInstanceOf(assertOneElement(results).getElement(), clazz); + } + typingTest(expression, expectedType); + return resolved; + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/ReferenceExpressionTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/ReferenceExpressionTest.java deleted file mode 100644 index e11520b072b2..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/ReferenceExpressionTest.java +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package org.jetbrains.plugins.groovy.util; - -import com.intellij.psi.PsiElement; -import org.intellij.lang.annotations.Language; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; - -public interface ReferenceExpressionTest extends ResolveTest, TypingTest { - - default void referenceExpressionTest(@Language("Groovy") String text, @Nullable Class resolved, String expectedType) { - GrReferenceExpression expression = lastExpression(text, GrReferenceExpression.class); - resolveTest(expression, resolved); - typingTest(expression, expectedType); - } -} diff --git a/plugins/groovy/testdata/mockGeb/geb-core-0.7.1-sources.jar b/plugins/groovy/testdata/mockGeb/geb-core-0.7.1-sources.jar deleted file mode 100644 index 1bf12be7e9a8..000000000000 Binary files a/plugins/groovy/testdata/mockGeb/geb-core-0.7.1-sources.jar and /dev/null differ diff --git a/plugins/groovy/testdata/mockGeb/geb-core-0.7.1.jar b/plugins/groovy/testdata/mockGeb/geb-core-0.7.1.jar deleted file mode 100644 index 0a1785f08f70..000000000000 Binary files a/plugins/groovy/testdata/mockGeb/geb-core-0.7.1.jar and /dev/null differ diff --git a/plugins/groovy/testdata/mockGeb/geb-junit4-0.7.0.jar b/plugins/groovy/testdata/mockGeb/geb-junit4-0.7.0.jar deleted file mode 100644 index cdb9b0bacea1..000000000000 Binary files a/plugins/groovy/testdata/mockGeb/geb-junit4-0.7.0.jar and /dev/null differ diff --git a/plugins/groovy/testdata/mockGeb/geb-spock-0.7.1.jar b/plugins/groovy/testdata/mockGeb/geb-spock-0.7.1.jar deleted file mode 100644 index bb768e84f3f9..000000000000 Binary files a/plugins/groovy/testdata/mockGeb/geb-spock-0.7.1.jar and /dev/null differ diff --git a/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar b/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar deleted file mode 100644 index c61f665bb38c..000000000000 Binary files a/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar and /dev/null differ diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/output/MavenImportOutputParser.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/output/MavenImportOutputParser.java index 0ce6b83185cd..4acf073b8611 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/output/MavenImportOutputParser.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/output/MavenImportOutputParser.java @@ -2,15 +2,17 @@ package org.jetbrains.idea.maven.importing.output; import com.intellij.build.events.BuildEvent; -import com.intellij.build.events.MessageEvent; import com.intellij.build.output.BuildOutputInstantReader; import com.intellij.build.output.BuildOutputParser; +import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; public class MavenImportOutputParser implements BuildOutputParser { @Override - public boolean parse(String line, BuildOutputInstantReader reader, Consumer messageConsumer) { + public boolean parse(@NotNull String line, + @NotNull BuildOutputInstantReader reader, + @NotNull Consumer messageConsumer) { return false; } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/externalSystemIntegration/output/MavenBuildToolLogTestUtils.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/externalSystemIntegration/output/MavenBuildToolLogTestUtils.java index 2d2d30aff34a..22ae2d145499 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/externalSystemIntegration/output/MavenBuildToolLogTestUtils.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/externalSystemIntegration/output/MavenBuildToolLogTestUtils.java @@ -227,7 +227,7 @@ public abstract class MavenBuildToolLogTestUtils extends UsefulTestCase { } @Override - public Object getBuildId() { + public Object getParentEventId() { throw new UnsupportedOperationException(); } diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index 4d9bbff479d3..6a6d4046d13f 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -107,7 +107,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document private final JPanel myValuesPanel; private final JPanel myStructureViewPanel; private volatile boolean myDisposed; - private ResourceBundleEditorFileListener myVfsListener; + private final ResourceBundleEditorFileListener myVfsListener; private Editor mySelectedEditor; private String myPropertyToSelectWhenVisible; private final ResourceBundleEditorHighlighter myHighlighter; @@ -200,7 +200,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document } myDataProviderPanel = new DataProviderPanel(splitPanel); - installPropertiesChangeListeners(); + myVfsListener = installPropertiesChangeListeners(); myProject.getMessageBus().connect(myProject).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() { @Override @@ -505,12 +505,10 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document } } - private void installPropertiesChangeListeners() { + @NotNull + private ResourceBundleEditorFileListener installPropertiesChangeListeners() { final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance(); - if (myVfsListener != null) { - throw new AssertionError("Listeners can't be initialized twice"); - } - myVfsListener = new ResourceBundleEditorFileListener(this); + ResourceBundleEditorFileListener myVfsListener = new ResourceBundleEditorFileListener(this); virtualFileManager.addVirtualFileListener(myVfsListener, this); PsiTreeChangeAdapter psiTreeChangeAdapter = new PsiTreeChangeAdapter() { @@ -544,7 +542,9 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document } }; PsiManager.getInstance(myProject).addPsiTreeChangeListener(psiTreeChangeAdapter, this); + return myVfsListener; } + private void selectionChanged() { myBackSlashPressed.clear(); UIUtil.invokeLaterIfNeeded(() -> { @@ -782,7 +782,6 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document } } } - VirtualFileManager.getInstance().removeVirtualFileListener(myVfsListener); myDisposed = true; Disposer.dispose(myStructureViewComponent); releaseAllEditors(); diff --git a/python/helpers/pydev/_pydev_bundle/pydev_monkey.py b/python/helpers/pydev/_pydev_bundle/pydev_monkey.py index bdb9fc67c1f6..1ce5db4f9c65 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_monkey.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_monkey.py @@ -9,6 +9,8 @@ except: xrange = range +PYTHON_NAMES = ['python', 'jython', 'pypy'] + #=============================================================================== # Things that are dependent on having the pydevd debugger #=============================================================================== @@ -73,15 +75,35 @@ def is_python_args(args): return len(args) > 0 and is_python(args[0]) +def is_executable(path): + return os.access(os.path.abspath(path), os.EX_OK) + + +def starts_with_python_shebang(path): + try: + with open(path) as f: + for line in f: + line = line.strip() + if line: + for name in PYTHON_NAMES: + if line.startswith('#!/usr/bin/env %s' % name): + return True + return False + except UnicodeDecodeError: + return False + except: + traceback.print_exc() + return False + + def is_python(path): if path.endswith("'") or path.endswith('"'): path = path[1:len(path) - 1] filename = os.path.basename(path).lower() - for name in ['python', 'jython', 'pypy']: + for name in PYTHON_NAMES: if filename.find(name) != -1: return True - - return False + return sys.platform != 'win32' and is_executable(path) and starts_with_python_shebang(path) def remove_quotes_from_args(args): @@ -140,6 +162,14 @@ def patch_args(args): return args if is_python(args[0]): + + for name in PYTHON_NAMES: + if args[0].find(name) != -1: + break + else: + # Executable file with Python shebang. + args.insert(0, sys.executable) + ind_c = get_c_option_index(args) if ind_c != -1: @@ -314,6 +344,29 @@ def patch_arg_str_win(arg_str): log_debug("New args: %s" % arg_str) return arg_str + +def patch_fork_exec_executable_list(args, other_args): + # When calling a Python executable script with `subprocess.call` the latest uses the first argument as an executable for `fork_exec`. + # This leads to `subprocess.call(["foo.py", "bar", "baz"])` after patching the args will be transformed into something like + # foo.py pydevd.py --port 59043 --client 127.0.0.1 --multiproc --file foo.py bar baz. + # To fix the issue we need to look inside the `fork_exec` executable list and, if necessary, replace an executable script with Python. + i = 0 + for arg in args: + i += 1 + if arg == '--file': + break + else: + return other_args + executable_list = other_args[0] + if args[i].encode() in executable_list: + return ((sys.executable.encode(),),) + other_args[1:] + return other_args + + +def patch_path(path): + return sys.executable if is_python(path) else path + + def monkey_patch_module(module, funcname, create_func): if hasattr(module, funcname): original_name = 'original_' + funcname @@ -354,7 +407,7 @@ def create_execl(original_name): args = patch_args(args) if is_python_args(args): send_process_will_be_substituted() - return getattr(os, original_name)(path, *args) + return getattr(os, original_name)(patch_path(path), *args) return new_execl @@ -367,7 +420,7 @@ def create_execv(original_name): import os if is_python_args(args): send_process_will_be_substituted() - return getattr(os, original_name)(path, patch_args(args)) + return getattr(os, original_name)(patch_path(path), patch_args(args)) return new_execv @@ -380,7 +433,7 @@ def create_execve(original_name): import os if is_python_args(args): send_process_will_be_substituted() - return getattr(os, original_name)(path, patch_args(args), env) + return getattr(os, original_name)(patch_path(path), patch_args(args), env) return new_execve @@ -429,7 +482,7 @@ def create_fork_exec(original_name): import _posixsubprocess # @UnresolvedImport args = patch_args(args) send_process_created_message() - return getattr(_posixsubprocess, original_name)(args, *other_args) + return getattr(_posixsubprocess, original_name)(args, *patch_fork_exec_executable_list(args, other_args)) return new_fork_exec diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index ccf4568daf2f..5746616bd1df 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -43,7 +43,7 @@ import static com.jetbrains.python.psi.PyUtil.as; /** * @author yole */ -public class PyBlock implements ASTBlock { +public class PyBlock implements ASTBlock, ReadOnlyBlockContainer { private static final TokenSet ourListElementTypes = TokenSet.create(PyElementTypes.LIST_LITERAL_EXPRESSION, PyElementTypes.LIST_COMP_EXPRESSION, PyElementTypes.DICT_LITERAL_EXPRESSION, diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java index 11c241e87d86..62232759b7e4 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java @@ -113,13 +113,15 @@ public class PythonSdkUpdater implements StartupActivity { */ public static boolean update(@NotNull Sdk sdk, @Nullable SdkModificator sdkModificator, @Nullable final Project project, @Nullable final Component ownerComponent) { + + final Application application = ApplicationManager.getApplication(); + assert !application.isWriteAccessAllowed() : "Can't update SDK under write action, not allowed in background"; + final String key = PythonSdkType.getSdkKey(sdk); synchronized (ourLock) { ourScheduledToRefresh.add(key); } - final Application application = ApplicationManager.getApplication(); - String sdkHome = sdk.getHomePath(); if (sdkHome != null && (PythonSdkType.isVirtualEnv(sdkHome) || PythonSdkType.isConda(sdk))) { final Future updateSdkFeature = application.executeOnPooledThread(() -> { @@ -247,7 +249,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Changes the version string of an SDK if it's out of date. - * + *

* May be invoked from any thread. May freeze the current thread while evaluating the run-time Python version. */ private static void updateLocalSdkVersion(@NotNull Sdk sdk, @Nullable SdkModificator sdkModificator) { @@ -265,7 +267,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Updates the paths of a local SDK. - * + *

* May be invoked from any thread. May freeze the current thread while evaluating sys.path. */ private static boolean updateLocalSdkPaths(@NotNull Sdk sdk, @Nullable SdkModificator sdkModificator, @Nullable Project project) { @@ -288,9 +290,9 @@ public class PythonSdkUpdater implements StartupActivity { /** * Updates the paths of a remote SDK. - * + *

* Requires the skeletons refresh steps to be run before it in order to get remote paths mappings in the additional SDK data. - * + *

* You may invoke it from any thread. Blocks until the commit is done in the AWT thread. */ private static void updateRemoteSdkPaths(@NotNull Sdk sdk, @Nullable Project project) { @@ -326,7 +328,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Returns all the paths for a remote SDK. - * + *

* Requires the skeletons refresh steps to be run before it in order to get remote paths mappings in the additional SDK data. */ @NotNull @@ -352,7 +354,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Returns local paths for a remote SDK that have been mapped to remote paths during the skeleton refresh step. - * + *

* Returns all the existing paths except those manually excluded by the user. */ @NotNull @@ -439,7 +441,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Evaluates sys.path by running the Python interpreter from a local SDK. - * + *

* Returns all the existing paths except those manually excluded by the user. */ @NotNull @@ -455,7 +457,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Commits new SDK paths using an SDK modificator if the paths have been changed. - * + *

* You may invoke it from any thread. Blocks until the commit is done in the AWT thread. */ private static void commitSdkPathsIfChanged(@NotNull Sdk sdk, @@ -477,7 +479,7 @@ public class PythonSdkUpdater implements StartupActivity { /** * Applies a processor to an SDK modificator or an SDK and commits it. - * + *

* You may invoke it from any threads. Blocks until the commit is done in the AWT thread. */ private static void changeSdkModificator(@NotNull Sdk sdk, @Nullable SdkModificator sdkModificator, @@ -488,7 +490,7 @@ public class PythonSdkUpdater implements StartupActivity { final Sdk sdkInsideInvoke = PythonSdkType.findSdkByKey(key); final SdkModificator effectiveModificator = sdkModificator != null ? sdkModificator : sdkInsideInvoke != null ? sdkInsideInvoke.getSdkModificator() : sdk.getSdkModificator(); - if (processor .process(effectiveModificator)) { + if (processor.process(effectiveModificator)) { effectiveModificator.commitChanges(); } }); diff --git a/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationProducer.java b/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationProducer.java index 91e813f26ca5..e0c3e29843dd 100644 --- a/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationProducer.java +++ b/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationProducer.java @@ -57,7 +57,7 @@ public final class PyToxConfigurationProducer extends LazyRunConfigurationProduc final String envName = PyToxTestLocator.getEnvNameFromElement(file); if (envName != null) { configuration.setRunOnlyEnvs(envName); - configuration.setName(String.format("Tox: run on %s", envName)); + configuration.setName(String.format("tox: run on %s", envName)); return true; } @@ -68,7 +68,7 @@ public final class PyToxConfigurationProducer extends LazyRunConfigurationProduc } configuration.setWorkingDirectory(directory.getVirtualFile().getCanonicalPath()); if (TOX_FILE_NAME.equals(file.getName())) { - configuration.setName("Tox"); + configuration.setName("tox"); return true; } return false; diff --git a/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationSettings.form b/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationSettings.form index 4f438059d92d..a9a761ce37db 100644 --- a/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationSettings.form +++ b/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationSettings.form @@ -13,7 +13,7 @@ - + diff --git a/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationType.java b/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationType.java index d11bceb55a9e..cf91ce4ddf05 100644 --- a/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationType.java +++ b/python/src/com/jetbrains/python/testing/tox/PyToxConfigurationType.java @@ -34,7 +34,7 @@ public final class PyToxConfigurationType implements ConfigurationType { @Override public String getConfigurationTypeDescription() { - return "Tox runner"; + return "tox runner"; } @Override diff --git a/python/testData/debug/test_executable_script_debug.py b/python/testData/debug/test_executable_script_debug.py new file mode 100644 index 000000000000..c2c98ea71573 --- /dev/null +++ b/python/testData/debug/test_executable_script_debug.py @@ -0,0 +1,7 @@ +from __future__ import print_function +import os +import subprocess + +ret = subprocess.call([os.path.abspath('test_executable_script_debug_helper.py')], stderr=subprocess.PIPE) + +print("Subprocess exited with return code: %d" % ret) diff --git a/python/testData/debug/test_executable_script_debug_helper.py b/python/testData/debug/test_executable_script_debug_helper.py new file mode 100644 index 000000000000..8d8241462543 --- /dev/null +++ b/python/testData/debug/test_executable_script_debug_helper.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from __future__ import print_function + +x = 42 +print(x) diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index 7895516664d0..e2a3a9a08d5b 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -1951,4 +1951,28 @@ public class PythonDebuggerTest extends PyEnvTestCase { } }); } + + @Test + @StagingOn(os = TestEnv.WINDOWS) + public void testExecutableScriptDebug() { + runPythonTest(new PyDebuggerTask("/debug", "test_executable_script_debug.py") { + @Override + protected void init() { + setMultiprocessDebug(true); + } + + @Override + public void before() { + toggleBreakpoint(getFilePath("test_executable_script_debug_helper.py"), 4); + } + + @Override + public void testing() throws Exception { + waitForPause(); + eval("x").hasValue("42"); + resume(); + waitForOutput("Subprocess exited with return code: 0"); + } + }); + } } diff --git a/python/tools/src/com/jetbrains/python/tools/Utils.kt b/python/tools/src/com/jetbrains/python/tools/Utils.kt index b21cf1dac6c0..a0c09c825258 100644 --- a/python/tools/src/com/jetbrains/python/tools/Utils.kt +++ b/python/tools/src/com/jetbrains/python/tools/Utils.kt @@ -53,7 +53,7 @@ fun createPythonSdkProducer(sdkHome: String): (Project, Module) -> Sdk { run { val sdk = createSdkForPerformance(module, SdkCreationType.SDK_PACKAGES_AND_SKELETONS, sdkHome) UIUtil.invokeAndWaitIfNeeded(Runnable { - ApplicationManager.getApplication().runWriteAction({ PythonSdkUpdater.update(sdk, null, project, null) }) + PythonSdkUpdater.update(sdk, null, project, null) }) sdk } diff --git a/tools/index-tools/src/org/jetbrains/index/stubs/SdkUtils.kt b/tools/index-tools/src/org/jetbrains/index/stubs/SdkUtils.kt index 0195b8244805..55c2a4dfa2e9 100644 --- a/tools/index-tools/src/org/jetbrains/index/stubs/SdkUtils.kt +++ b/tools/index-tools/src/org/jetbrains/index/stubs/SdkUtils.kt @@ -14,6 +14,7 @@ import com.intellij.openapi.vfs.VfsUtil import com.intellij.testFramework.PlatformTestUtil import com.intellij.util.ui.UIUtil import java.io.File +import java.lang.IllegalArgumentException /** * @author traff @@ -60,7 +61,7 @@ fun getOrCreateModule(project: Project, projectPath: String, moduleTypeId: Strin Computable { ModuleManager.getInstance(project).newModule(projectPath, moduleTypeId) } ) - val root = VfsUtil.findFileByIoFile(File(projectPath), true)!! + val root = VfsUtil.findFileByIoFile(File(projectPath), true) ?: throw AssertionError("Can't find $projectPath") ModuleRootModificationUtil.updateModel(module, { t -> val e = t.addContentEntry(root)