diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml index 33740962d245..65b31a10b6d9 100644 --- a/.idea/libraries/Netty.xml +++ b/.idea/libraries/Netty.xml @@ -4,11 +4,11 @@ - + - + \ No newline at end of file diff --git a/build/asm/4_api_version.patch b/build/asm/4_api_version.patch new file mode 100644 index 000000000000..39637270c7c6 --- /dev/null +++ b/build/asm/4_api_version.patch @@ -0,0 +1,24 @@ +Index: org/objectweb/asm/ClassVisitor.java +=================================================================== +--- org/objectweb/asm/ClassVisitor.java ++++ org/objectweb/asm/ClassVisitor.java +@@ -78,7 +78,18 @@ + if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { + throw new IllegalArgumentException(); + } +- this.api = api; ++ this.api = Opcodes.ASM6; //[JB: use the latest API version] ++ this.cv = cv; ++ } ++ ++ //[JB: use the latest API version] ++ public ClassVisitor() { ++ this(null); ++ } ++ ++ //[JB: use the latest API version] ++ public ClassVisitor(final ClassVisitor cv) { ++ this.api = Opcodes.ASM6; + this.cv = cv; + } + diff --git a/build/asm/repackage.xml b/build/asm/repackage.xml index 2c8c60e1b868..845c29ecf986 100644 --- a/build/asm/repackage.xml +++ b/build/asm/repackage.xml @@ -42,6 +42,7 @@ + diff --git a/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy b/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy index ac13038d17e2..6d574e1cdcea 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy @@ -36,7 +36,7 @@ import org.jetbrains.jps.util.JpsPathUtil class BuildContextImpl extends BuildContext { private final JpsGlobal global private final boolean underTeamCity - final List outputDirectoriesToKeep = [] + final List outputDirectoriesToKeep //todo[nik] construct buildOutputRoot automatically based on product name static BuildContextImpl create(AntBuilder ant, JpsGantProjectBuilder projectBuilder, JpsProject project, JpsGlobal global, @@ -52,8 +52,9 @@ class BuildContextImpl extends BuildContext { LinuxDistributionCustomizer linuxDistributionCustomizer = productProperties.createLinuxCustomizer(paths.projectHome) MacDistributionCustomizer macDistributionCustomizer = productProperties.createMacCustomizer(paths.projectHome) + List outputDirectoriesToKeep = [] if (project.modules.isEmpty()) { - loadProject(paths, ant, project, global, projectBuilder, messages, options) + outputDirectoriesToKeep = loadProject(paths, ant, project, global, projectBuilder, messages, options) } else { //todo[nik] currently we need this to build IDEA CE from IDEA UI build scripts. It would be better to create a separate JpsProject instance instead @@ -62,15 +63,15 @@ class BuildContextImpl extends BuildContext { return new BuildContextImpl(ant, messages, paths, project, global, projectBuilder, productProperties, windowsDistributionCustomizer, linuxDistributionCustomizer, macDistributionCustomizer, - macHostProperties, options, - signTool, scrambleTool, underTeamCity) + macHostProperties, options, signTool, scrambleTool, underTeamCity, outputDirectoriesToKeep) } BuildContextImpl(AntBuilder ant, BuildMessages messages, BuildPaths paths, JpsProject project, JpsGlobal global, JpsGantProjectBuilder projectBuilder, ProductProperties productProperties, WindowsDistributionCustomizer windowsDistributionCustomizer, LinuxDistributionCustomizer linuxDistributionCustomizer, MacDistributionCustomizer macDistributionCustomizer, - MacHostProperties macHostProperties, BuildOptions options, SignTool signTool, ScrambleTool scrambleTool, boolean underTeamCity) { + MacHostProperties macHostProperties, BuildOptions options, SignTool signTool, ScrambleTool scrambleTool, boolean underTeamCity, + List outputDirectoriesToKeep) { this.ant = ant this.messages = messages this.paths = paths @@ -84,6 +85,7 @@ class BuildContextImpl extends BuildContext { this.signTool = signTool this.scrambleTool = scrambleTool this.underTeamCity = underTeamCity + this.outputDirectoriesToKeep = outputDirectoriesToKeep bundledJreManager = new BundledJreManager(this, paths.buildOutputRoot) this.windowsDistributionCustomizer = windowsDistributionCustomizer @@ -240,7 +242,7 @@ class BuildContextImpl extends BuildContext { def messages = messages.forkForParallelTask(taskName) def child = new BuildContextImpl(ant, messages, paths, project, global, projectBuilder, productProperties, windowsDistributionCustomizer, linuxDistributionCustomizer, macDistributionCustomizer, - macHostProperties, options, signTool, scrambleTool, underTeamCity) + macHostProperties, options, signTool, scrambleTool, underTeamCity, outputDirectoriesToKeep) child.bundledJreManager.baseDirectoryForJre = bundledJreManager.baseDirectoryForJre return child } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CustomFieldInplaceEditor.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CustomFieldInplaceEditor.java index 792533196b80..1dbb493660e5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CustomFieldInplaceEditor.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CustomFieldInplaceEditor.java @@ -46,9 +46,7 @@ public class CustomFieldInplaceEditor extends XDebuggerTreeInplaceEditor { super(node, "customField"); myDescriptor = descriptor; myRenderer = renderer; - if (descriptor != null) { - myExpressionEditor.setExpression(TextWithImportsImpl.toXExpression(descriptor.getEvaluationText())); - } + myExpressionEditor.setExpression(descriptor != null ? TextWithImportsImpl.toXExpression(descriptor.getEvaluationText()) : null); } public static void editNew(@NotNull XValueNodeImpl parentNode) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index d1a7cea73e24..c8aebbb89077 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -446,7 +446,7 @@ public class GenericsHighlightUtil { for (Set overrideEquivalentMethods : overrideEquivalent.values()) { if (overrideEquivalentMethods.size() <= 1) continue; List defaults = null; - List astracts = null; + List abstracts = null; boolean hasConcrete = false; for (PsiMethod method : overrideEquivalentMethods) { final boolean isDefault = method.hasModifierProperty(PsiModifier.DEFAULT); @@ -456,8 +456,8 @@ public class GenericsHighlightUtil { defaults.add(method); } if (isAbstract) { - if (astracts == null) astracts = new ArrayList<>(2); - astracts.add(method); + if (abstracts == null) abstracts = new ArrayList<>(2); + abstracts.add(method); } hasConcrete |= !isDefault && !isAbstract; } @@ -466,37 +466,38 @@ public class GenericsHighlightUtil { final PsiMethod defaultMethod = defaults.get(0); final PsiClass defaultMethodContainingClass = defaultMethod.getContainingClass(); if (defaultMethodContainingClass == null) continue; - final PsiMethod unrelatedMethod = astracts != null ? astracts.get(0) : defaults.get(1); + final PsiMethod unrelatedMethod = abstracts != null ? abstracts.get(0) : defaults.get(1); final PsiClass unrelatedMethodContainingClass = unrelatedMethod.getContainingClass(); if (unrelatedMethodContainingClass == null) continue; if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT) && !(aClass instanceof PsiTypeParameter) - && astracts != null && unrelatedMethodContainingClass.isInterface()) { + && abstracts != null && unrelatedMethodContainingClass.isInterface()) { if (defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true) && MethodSignatureUtil.isSubsignature(unrelatedMethod.getSignature(TypeConversionUtil.getSuperClassSubstitutor(unrelatedMethodContainingClass, defaultMethodContainingClass, PsiSubstitutor.EMPTY)), defaultMethod.getSignature(PsiSubstitutor.EMPTY))) { continue; } final String key = aClass instanceof PsiEnumConstantInitializer ? "enum.constant.should.implement.method" : "class.must.be.abstract"; - final String message = JavaErrorMessages.message(key, HighlightUtil.formatClass(aClass, false), JavaHighlightUtil.formatMethod(astracts.get(0)), + final String message = JavaErrorMessages.message(key, HighlightUtil.formatClass(aClass, false), JavaHighlightUtil.formatMethod(abstracts.get(0)), HighlightUtil.formatClass(unrelatedMethodContainingClass, false)); final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass)); return info; } - if (isInterface || astracts == null || unrelatedMethodContainingClass.isInterface()) { - if (defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true) || - unrelatedMethodContainingClass.isInheritor(defaultMethodContainingClass, true)) { + if (isInterface || abstracts == null || unrelatedMethodContainingClass.isInterface()) { + final List defaultContainingClasses = ContainerUtil.mapNotNull(defaults, PsiMethod::getContainingClass); + final String unrelatedDefaults = hasUnrelatedDefaults(defaultContainingClasses); + if (unrelatedDefaults == null && + (abstracts == null || !hasNotOverriddenAbstract(defaultContainingClasses, unrelatedMethodContainingClass))) { continue; } - final String message = astracts != null ? " inherits abstract and default for " : " inherits unrelated defaults for "; + + final String message = unrelatedDefaults != null ? " inherits unrelated defaults for " : " inherits abstract and default for "; final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip( HighlightUtil.formatClass(aClass) + message + - JavaHighlightUtil.formatMethod(defaultMethod) + - " from types " + - HighlightUtil.formatClass(defaultMethodContainingClass) + - " and " + - HighlightUtil.formatClass(unrelatedMethodContainingClass)) + JavaHighlightUtil.formatMethod(defaultMethod) + " from types " + + (unrelatedDefaults != null ? unrelatedDefaults + : HighlightUtil.formatClass(defaultMethodContainingClass) + " and " + HighlightUtil.formatClass(unrelatedMethodContainingClass))) .create(); QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass)); return info; @@ -506,6 +507,31 @@ public class GenericsHighlightUtil { return null; } + private static boolean belongToOneHierarchy(@NotNull PsiClass defaultMethodContainingClass, @NotNull PsiClass unrelatedMethodContainingClass) { + return defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true) || + unrelatedMethodContainingClass.isInheritor(defaultMethodContainingClass, true); + } + + private static boolean hasNotOverriddenAbstract(List defaultContainingClasses, @NotNull PsiClass abstractMethodContainingClass) { + return !defaultContainingClasses.stream().anyMatch(containingClass -> belongToOneHierarchy(containingClass, abstractMethodContainingClass)); + } + + private static String hasUnrelatedDefaults(List defaults) { + if (defaults.size() > 1) { + for (int i = 0; i < defaults.size(); i++) { + final PsiClass aClass1 = defaults.get(i); + for (int j = i + 1; j < defaults.size(); j++) { + final PsiClass aClass2 = defaults.get(j); + if (aClass2 != null && !belongToOneHierarchy(aClass1, aClass2)) { + return HighlightUtil.formatClass(aClass1) + " and " + HighlightUtil.formatClass(aClass2); + } + } + } + } + + return null; + } + static HighlightInfo checkUnrelatedConcrete(@NotNull PsiClass psiClass, @NotNull PsiIdentifier classIdentifier) { final PsiClass superClass = psiClass.getSuperClass(); diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java b/java/java-impl/src/com/intellij/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java index 737baa57e5b1..eceb704cdc19 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java @@ -19,16 +19,22 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.hierarchy.HierarchyNodeDescriptor; import com.intellij.ide.hierarchy.HierarchyTreeStructure; import com.intellij.openapi.project.Project; -import com.intellij.psi.*; +import com.intellij.psi.CommonClassNames; +import com.intellij.psi.PsiAnonymousClass; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiModifier; import com.intellij.psi.search.SearchScope; +import com.intellij.psi.search.searches.AnnotatedElementsSearch; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.util.ArrayUtil; -import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Set; public class SubtypesHierarchyTreeStructure extends HierarchyTreeStructure { private final String myCurrentScopeType; @@ -54,7 +60,7 @@ public class SubtypesHierarchyTreeStructure extends HierarchyTreeStructure { if (psiClass instanceof PsiAnonymousClass) return ArrayUtil.EMPTY_OBJECT_ARRAY; if (psiClass.hasModifierProperty(PsiModifier.FINAL)) return ArrayUtil.EMPTY_OBJECT_ARRAY; final SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); - final List classes = new ArrayList<>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); + final List classes = new ArrayList<>(searchInheritors(psiClass, searchScope)); final List descriptors = new ArrayList<>(classes.size()); for (PsiClass aClass : classes) { descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aClass, false)); @@ -65,4 +71,21 @@ public class SubtypesHierarchyTreeStructure extends HierarchyTreeStructure { }); return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); } + + @NotNull + private static Collection searchInheritors(@NotNull PsiClass psiClass, @NotNull SearchScope searchScope) { + if (psiClass.isAnnotationType()) { + final Set result = ContainerUtil.newHashSet(); + + AnnotatedElementsSearch.searchPsiClasses(psiClass, searchScope).forEach(processorResult -> { + if (processorResult.isAnnotationType()) { + result.add(processorResult); + } + return true; + }); + + return result; + } + return ClassInheritorsSearch.search(psiClass, searchScope, false).findAll(); + } } diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java b/java/java-impl/src/com/intellij/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java index 1f03bee08ec5..b2330920da6e 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java @@ -15,16 +15,19 @@ */ package com.intellij.ide.hierarchy.type; +import com.intellij.codeInsight.AnnotationTargetUtil; import com.intellij.ide.hierarchy.HierarchyNodeDescriptor; import com.intellij.ide.hierarchy.HierarchyTreeStructure; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.Set; public final class SupertypesHierarchyTreeStructure extends HierarchyTreeStructure { @@ -37,7 +40,7 @@ public final class SupertypesHierarchyTreeStructure extends HierarchyTreeStructu final Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); if (element instanceof PsiClass) { final PsiClass psiClass = (PsiClass)element; - final PsiClass[] supers = psiClass.getSupers(); + final PsiClass[] supers = getSupers(psiClass); final List descriptors = new ArrayList<>(); final PsiClass objectClass = JavaPsiFacade.getInstance(myProject).findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); for (PsiClass aSuper : supers) { @@ -54,4 +57,41 @@ public final class SupertypesHierarchyTreeStructure extends HierarchyTreeStructu } return ArrayUtil.EMPTY_OBJECT_ARRAY; } + + @NotNull + private static PsiClass[] getSupers(@NotNull PsiClass psiClass) { + if (psiClass.isAnnotationType()) { + return getMetaAnnotations(psiClass); + } + return psiClass.getSupers(); + } + + @NotNull + private static PsiClass[] getMetaAnnotations(@NotNull PsiClass psiClass) { + Set supers = ContainerUtil.newHashSet(); + final PsiModifierList modifierList = psiClass.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (isJavaLangAnnotation(annotation)) continue; + PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement(); + if (ref != null) { + PsiElement annotationType = ref.resolve(); + if (annotationType instanceof PsiClass) { + final PsiClass aClass = (PsiClass)annotationType; + final PsiAnnotation.TargetType target = AnnotationTargetUtil + .findAnnotationTarget(aClass, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.ANNOTATION_TYPE); + if (target != null && target != PsiAnnotation.TargetType.UNKNOWN) { + supers.add(aClass); + } + } + } + } + } + return supers.toArray(new PsiClass[supers.size()]); + } + + private static boolean isJavaLangAnnotation(@NotNull PsiAnnotation annotation) { + final String qualifiedName = annotation.getQualifiedName(); + return qualifiedName != null && qualifiedName.startsWith("java.lang.annotation"); + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java index 2503c530b495..1fd0373825f0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java @@ -35,6 +35,7 @@ import com.intellij.psi.util.*; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; +import com.intellij.util.text.UniqueNameGenerator; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -353,6 +354,10 @@ public class PsiDiamondTypeImpl extends PsiDiamondType { } buf.append("static "); buf.append("<"); + //it's possible that constructor type parameters and class type parameters are same named: + //it's important that class type parameters names are preserved(they are first in the list), + //though constructor parameters would be renamed in case of conflicts + final UniqueNameGenerator generator = new UniqueNameGenerator(); buf.append(StringUtil.join(params, new Function() { @Override public String fun(PsiTypeParameter psiTypeParameter) { @@ -369,7 +374,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType { extendsList = " extends " + StringUtil.join(extendsListTypes, canonicalTypePresentationFun, "&"); } } - return psiTypeParameter.getName() + extendsList; + return generator.generateUniqueName(psiTypeParameter.getName()) + extendsList; } }, ", ")); buf.append(">"); @@ -430,10 +435,10 @@ public class PsiDiamondTypeImpl extends PsiDiamondType { private static PsiTypeParameter[] getAllTypeParams(PsiTypeParameterListOwner listOwner, PsiClass containingClass) { Set params = new LinkedHashSet(); + Collections.addAll(params, containingClass.getTypeParameters()); if (listOwner != null) { Collections.addAll(params, listOwner.getTypeParameters()); } - Collections.addAll(params, containingClass.getTypeParameters()); return params.toArray(new PsiTypeParameter[params.size()]); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConflictingNamesInConstructorAndClassTypeParameters.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConflictingNamesInConstructorAndClassTypeParameters.java new file mode 100644 index 000000000000..cf77fb6fe017 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConflictingNamesInConstructorAndClassTypeParameters.java @@ -0,0 +1,12 @@ + +interface E {} +interface A {} +class N

implements A

{ +

N(P p) {} +} + +class K { + A f(J p) { + return new N<>(p); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AbstractOverriddenBySecondDefault.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AbstractOverriddenBySecondDefault.java new file mode 100644 index 000000000000..5a8731080442 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AbstractOverriddenBySecondDefault.java @@ -0,0 +1,22 @@ + +interface I { + void foo(); +} + +interface I1 extends I { + //void foo(); +} + +interface J { + default void foo() {} +} + +interface A extends J, I { + @Override + default void foo() {} +} + +interface O extends J { +} + +interface R extends O, A, I1{} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/UnrelatedDefaultsWhenAbstractIsOverridden.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/UnrelatedDefaultsWhenAbstractIsOverridden.java new file mode 100644 index 000000000000..5ac33fc84141 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/UnrelatedDefaultsWhenAbstractIsOverridden.java @@ -0,0 +1,22 @@ + +interface I { + void foo(); +} + +interface I1 extends I { +} + +interface J { + default void foo() {} +} + +interface A extends J, I { + @Override + default void foo() {} +} + +interface O extends J { + default void foo() {} +} + +interface R extends O, A, I1{} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java index aa1efd90c51c..ce03e07c4e91 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java @@ -69,6 +69,10 @@ public class Diamond8HighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testConflictingNamesInConstructorAndClassTypeParameters() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java index 365fdbf30fc9..7d9960cf1e8f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java @@ -107,6 +107,14 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe doTest(); } + public void testUnrelatedDefaultsWhenAbstractIsOverridden() throws Exception { + doTest(); + } + + public void testAbstractOverriddenBySecondDefault() throws Exception { + doTest(); + } + private void doTest() { doTest(false, false); } diff --git a/lib/asm-all.jar b/lib/asm-all.jar index f3d2cf9ee2e4..581e13583d3e 100644 Binary files a/lib/asm-all.jar and b/lib/asm-all.jar differ diff --git a/lib/netty-all-4.1.1.Final.jar b/lib/netty-all-4.1.4.Final.jar similarity index 51% rename from lib/netty-all-4.1.1.Final.jar rename to lib/netty-all-4.1.4.Final.jar index 28d8fdd1a4e2..4722a17b955d 100644 Binary files a/lib/netty-all-4.1.1.Final.jar and b/lib/netty-all-4.1.4.Final.jar differ diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index dc9fca43a0a1..35e36f0a0a99 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -51,7 +51,7 @@ miglayout-core-5.0.jar miglayout-swing-5.0.jar nanoxml-2.2.3.jar nekohtml-1.9.14.jar -netty-all-4.1.1.Final.jar +netty-all-4.1.4.Final.jar oromatcher.jar picocontainer.jar protobuf-2.5.0.jar diff --git a/lib/src/asm-src.zip b/lib/src/asm-src.zip index f9c89ab3b388..8984afd4150b 100644 Binary files a/lib/src/asm-src.zip and b/lib/src/asm-src.zip differ diff --git a/lib/src/netty-all-4.1.1.Final-sources.jar b/lib/src/netty-all-4.1.4.Final-sources.jar similarity index 71% rename from lib/src/netty-all-4.1.1.Final-sources.jar rename to lib/src/netty-all-4.1.4.Final-sources.jar index bf07fc1f4496..ceed0c9faeeb 100644 Binary files a/lib/src/netty-all-4.1.1.Final-sources.jar and b/lib/src/netty-all-4.1.4.Final-sources.jar differ diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionElementsMerger.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionElementsMerger.java index 2ce300b235dd..3b451a7bd7c6 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionElementsMerger.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionElementsMerger.java @@ -44,9 +44,18 @@ public abstract class InspectionElementsMerger { return ourMergers.get(shortName); } - public abstract String getMergedToolName(); + public abstract String getMergedToolName(); + + /** + * @return the shortNames of the merged inspections + */ public abstract String[] getSourceToolNames(); + /** + * The ids to check for suppression. + * If this returns an empty string array, the result of getSourceToolNames() is used instead. + * @return the suppressIds of the merged inspections. + */ public String[] getSuppressIds() { return ArrayUtilRt.EMPTY_STRING_ARRAY; } diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index e7b6c7c414d4..e0282038f75c 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -30,7 +30,10 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionUtil; @@ -49,6 +52,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import static com.intellij.openapi.extensions.Extensions.isComponentSuitableForOs; + public abstract class ComponentManagerImpl extends UserDataHolderBase implements ComponentManagerEx, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.components.ComponentManager"); @@ -272,32 +277,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements (!Boolean.parseBoolean(options.get("internal")) || ApplicationManager.getApplication().isInternal()); } - static boolean isComponentSuitableForOs(@Nullable String os) { - if (StringUtil.isEmpty(os)) { - return true; - } - - if (os.equals("mac")) { - return SystemInfoRt.isMac; - } - else if (os.equals("linux")) { - return SystemInfoRt.isLinux; - } - else if (os.equals("windows")) { - return SystemInfoRt.isWindows; - } - else if (os.equals("unix")) { - return SystemInfoRt.isUnix; - } - else if (os.equals("freebsd")) { - return SystemInfoRt.isFreeBSD; - } - else { - LOG.warn("Unknown OS " + os); - return true; - } - } - @Override public void dispose() { ApplicationManager.getApplication().assertIsDispatchThread(); diff --git a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java index ad57d231c27f..5191813b88bb 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -18,6 +18,8 @@ package com.intellij.openapi.extensions; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.SystemInfoRt; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -243,4 +245,30 @@ public class Extensions { t.printStackTrace(); } } + + public static boolean isComponentSuitableForOs(@Nullable String os) { + if (StringUtil.isEmpty(os)) { + return true; + } + + if (os.equals("mac")) { + return SystemInfoRt.isMac; + } + else if (os.equals("linux")) { + return SystemInfoRt.isLinux; + } + else if (os.equals("windows")) { + return SystemInfoRt.isWindows; + } + else if (os.equals("unix")) { + return SystemInfoRt.isUnix; + } + else if (os.equals("freebsd")) { + return SystemInfoRt.isFreeBSD; + } + else { + ourLogger.warn("Unknown OS " + os); + return true; + } + } } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index 7e7a8e7b019d..90c2d9d1f07a 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -32,6 +32,8 @@ import org.picocontainer.PicoContainer; import java.util.*; +import static com.intellij.openapi.extensions.Extensions.isComponentSuitableForOs; + @SuppressWarnings({"HardCodedStringLiteral"}) public class ExtensionsAreaImpl implements ExtensionsArea { private final LogProvider myLogger; @@ -137,6 +139,10 @@ public class ExtensionsAreaImpl implements ExtensionsArea { public void registerExtension(@NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement) { final PluginId pluginId = pluginDescriptor.getPluginId(); + if (!isComponentSuitableForOs(extensionElement.getAttributeValue("os"))) { + return; + } + String epName = extractEPName(extensionElement); ExtensionComponentAdapter adapter; diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java index e2c9adf8de9c..c51fef0c4b22 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java @@ -87,7 +87,7 @@ public class FileChooser { @Nullable final Project project, @Nullable final VirtualFile toSelect, @NotNull final Consumer> callback) { - chooseFiles(descriptor, project, IdeFocusManager.getInstance(project).getFocusOwner(), toSelect, callback); + chooseFiles(descriptor, project, KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), toSelect, callback); } /** diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/macOsKeychainLibrary.kt b/platform/platform-impl/src/com/intellij/ide/passwordSafe/macOsKeychainLibrary.kt index 33bc1b76f22b..c6d7a7047a91 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/macOsKeychainLibrary.kt +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/macOsKeychainLibrary.kt @@ -17,13 +17,14 @@ package com.intellij.ide.passwordSafe.macOs import com.intellij.ide.passwordSafe.LOG import com.intellij.openapi.util.SystemInfo +import com.sun.jna.Native import com.sun.jna.Pointer val isMacOsCredentialStoreSupported: Boolean get() = SystemInfo.isMacIntel64 && SystemInfo.isMacOSLeopard private val LIBRARY by lazy { - com.sun.jna.Native.loadLibrary("Security", MacOsKeychainLibrary::class.java) as MacOsKeychainLibrary + Native.loadLibrary("Security", MacOsKeychainLibrary::class.java) as MacOsKeychainLibrary } fun saveGenericPassword(serviceName: ByteArray, accountName: String, password: String) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java index 49243b5870e7..ee5e0d11e7d3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java @@ -80,7 +80,7 @@ public class ServiceManagerImpl implements BaseComponent { } } - if (!ComponentManagerImpl.isComponentSuitableForOs(descriptor.os)) { + if (!Extensions.isComponentSuitableForOs(descriptor.os)) { return; } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java b/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java index 65a467d6faa9..843caae83081 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java @@ -31,6 +31,8 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.WindowManager; import com.intellij.ui.UIBundle; import com.intellij.ui.popup.AbstractPopup; import com.intellij.util.ArrayUtil; @@ -178,6 +180,10 @@ public class MacPathChooserDialog implements PathChooserDialog { } else { if (owner instanceof Frame) { + if (owner instanceof IdeFrame.Child) { + IdeFrame.Child ideFrameChild = (IdeFrame.Child)owner; + owner = WindowManager.getInstance().getFrame(ideFrameChild.getProject()); + } fileDialog = new FileDialog((Frame)owner, title, mode); } else if (owner instanceof Dialog) { @@ -188,7 +194,7 @@ public class MacPathChooserDialog implements PathChooserDialog { } } - return fileDialog; + return fileDialog; } @NotNull diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index e2cbc37766fd..46d115378e82 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -444,6 +444,6 @@ - + diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MalformedSetUpTearDownInspectionMerger.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MalformedSetUpTearDownInspectionMerger.java index 57aad6c9efed..8f6bfef107c1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MalformedSetUpTearDownInspectionMerger.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MalformedSetUpTearDownInspectionMerger.java @@ -29,6 +29,11 @@ public class MalformedSetUpTearDownInspectionMerger extends InspectionElementsMe @Override public String[] getSourceToolNames() { + return new String[] { "TeardownIsPublicVoidNoArg", "SetupIsPublicVoidNoArg" }; + } + + @Override + public String[] getSuppressIds() { return new String[] { "TearDownWithIncorrectSignature", "SetUpWithIncorrectSignature" }; } } diff --git a/plugins/ant/tests/data/psi/completion/EndTagCompletion-out.xml b/plugins/ant/tests/data/psi/completion/EndTagCompletion-out.xml index e23ebf5d0627..fa30ad00c872 100644 --- a/plugins/ant/tests/data/psi/completion/EndTagCompletion-out.xml +++ b/plugins/ant/tests/data/psi/completion/EndTagCompletion-out.xml @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommit.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommit.java index edc035904c10..fa4a21e58efd 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommit.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommit.java @@ -33,6 +33,7 @@ public class GithubCommit extends GithubCommitSha { @Mandatory private List parents; + @RestModel public static class GitCommit { private String url; @Mandatory private String message; @@ -56,6 +57,7 @@ public class GithubCommit extends GithubCommitSha { } } + @RestModel public static class GitUser { @Mandatory private String name; @Mandatory private String email; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommitDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommitDetailed.java index 213d39ab2516..4cfc96207aa5 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommitDetailed.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubCommitDetailed.java @@ -27,6 +27,7 @@ public class GithubCommitDetailed extends GithubCommit { @Mandatory private CommitStats stats; @Mandatory private List files; + @RestModel public static class CommitStats { @Mandatory private Integer additions; @Mandatory private Integer deletions; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubErrorMessage.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubErrorMessage.java index c168f19a9372..77bdad469219 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubErrorMessage.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubErrorMessage.java @@ -27,6 +27,7 @@ public class GithubErrorMessage { private String message; private List errors; + @RestModel public static class Error { private String resource; private String field; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubGist.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubGist.java index bb71469ea09c..cdc8ebd74718 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubGist.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubGist.java @@ -47,6 +47,7 @@ public class GithubGist { private Date createdAt; + @RestModel public static class GistFile { private Long size; @Mandatory private String filename; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubPullRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubPullRequest.java index dff3cf255dfc..ae97e09f6042 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubPullRequest.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubPullRequest.java @@ -57,6 +57,7 @@ public class GithubPullRequest { @Mandatory private Link head; @Mandatory private Link base; + @RestModel public static class Link { @Mandatory private String label; @Mandatory private String ref; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubRepoOrg.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubRepoOrg.java index 7ecdce0fd254..43304d74b112 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubRepoOrg.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubRepoOrg.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; public class GithubRepoOrg extends GithubRepo { @Mandatory private Permissions permissions; + @RestModel public static class Permissions { @Mandatory private Boolean admin; @Mandatory private Boolean pull; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubUserDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubUserDetailed.java index de6ca7f49e60..6dff0a604a9b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubUserDetailed.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/data/GithubUserDetailed.java @@ -37,6 +37,7 @@ public class GithubUserDetailed extends GithubUser { private UserPlan plan; + @RestModel public static class UserPlan { private String name; private Long space; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyBrowserWindow.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyBrowserWindow.java index 77cea7b2cf1e..de066f0cfb05 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyBrowserWindow.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyBrowserWindow.java @@ -228,19 +228,21 @@ public class StudyBrowserWindow extends JFrame { if (domEventType.equals(EVENT_TYPE_CLICK)) { Element target = (Element)ev.getTarget(); String hrefAttribute = target.getAttribute("href"); - final Matcher matcher = IN_COURSE_LINK.matcher(hrefAttribute); - if (matcher.matches()) { - final String lessonName = matcher.group(1); - final String taskName = matcher.group(2); - StudyNavigator.navigateToTask(myProject, lessonName, taskName); - } - else { - myEngine.setJavaScriptEnabled(true); - myEngine.getLoadWorker().cancel(); - ev.preventDefault(); - final String href = getLink(target); - if (href == null) return; - BrowserUtil.browse(href); + if (hrefAttribute != null) { + final Matcher matcher = IN_COURSE_LINK.matcher(hrefAttribute); + if (matcher.matches()) { + final String lessonName = matcher.group(1); + final String taskName = matcher.group(2); + StudyNavigator.navigateToTask(myProject, lessonName, taskName); + } + else { + myEngine.setJavaScriptEnabled(true); + myEngine.getLoadWorker().cancel(); + ev.preventDefault(); + final String href = getLink(target); + if (href == null) return; + BrowserUtil.browse(href); + } } } } diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py b/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py index 67002d87f9c0..c1886183c69c 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py @@ -85,7 +85,7 @@ def process_net_command(py_db, cmd_id, seq, text): elif cmd_id == CMD_THREAD_SUSPEND: # Yes, thread suspend is still done at this point, not through an internal command! t = pydevd_find_thread_by_id(text) - if t: + if t and not hasattr(t, 'pydev_do_not_trace'): additional_info = None try: additional_info = t.additional_info diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 30e60a1686e3..3a90994fb244 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -405,6 +405,8 @@ class PyDB: for t in all_threads: if getattr(t, 'is_pydev_daemon_thread', False): pass # I.e.: skip the DummyThreads created from pydev daemon threads + elif hasattr(t, 'pydev_do_not_trace'): + pass # skip some other threads, i.e. ipython history saving thread from debug console else: if t is thread_suspended_at_bp: continue diff --git a/xml/impl/src/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java index 48cbe2a17932..c18de1878df2 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java @@ -16,18 +16,13 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.TailType; -import com.intellij.codeInsight.lookup.AutoCompletionPolicy; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.codeInsight.lookup.TailTypeDecorator; +import com.intellij.codeInsight.lookup.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.xml.SchemaPrefixReference; import com.intellij.psi.impl.source.xml.TagNameReference; import com.intellij.psi.xml.XmlTag; import com.intellij.util.Consumer; -import com.intellij.util.PairConsumer; import com.intellij.util.ProcessingContext; import com.intellij.xml.XmlTagNameProvider; import org.jetbrains.annotations.NotNull; @@ -83,8 +78,10 @@ public class TagNameReferenceCompletionProvider extends CompletionProvider')); + return LookupElementDecorator.withInsertHandler( + TailTypeDecorator.withTail(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE.applyPolicy(builder), + TailType.createSimpleTailType('>')), + XmlClosingTagInsertHandler.INSTANCE); } } diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlClosingTagInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlClosingTagInsertHandler.java new file mode 100644 index 000000000000..c8088a41209d --- /dev/null +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlClosingTagInsertHandler.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.completion; + +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementDecorator; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.codeStyle.CodeStyleManager; + +public class XmlClosingTagInsertHandler implements InsertHandler { + public final static XmlClosingTagInsertHandler INSTANCE = new XmlClosingTagInsertHandler(); + + private XmlClosingTagInsertHandler(){} + + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + Editor editor = context.getEditor(); + Document document = editor.getDocument(); + Project project = context.getProject(); + if (item instanceof LookupElementDecorator) { + ((LookupElementDecorator)item).getDelegate().handleInsert(context); + } + PsiDocumentManager.getInstance(project).commitDocument(document); + int lineOffset = document.getLineStartOffset(document.getLineNumber(editor.getCaretModel().getOffset())); + CodeStyleManager.getInstance(project).adjustLineIndent(document, lineOffset); + } +}