diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index ca721e9082fd..b08d1d94c241 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -61,7 +61,7 @@ IDE_BIN_HOME=`dirname "$SCRIPT_LOCATION"` # --------------------------------------------------------------------- if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then JDK="$@@product_uc@@_JDK" -elif [ -x "$IDE_HOME/jre/bin/java" ] && "$IDE_HOME/jre/bin/java" -version > /dev/null 2>&1 ; then +elif [ -x "$IDE_HOME/jre/jre/bin/java" ] && "$IDE_HOME/jre/jre/bin/java" -version > /dev/null 2>&1 ; then JDK="$IDE_HOME/jre" elif [ -n "$JDK_HOME" -a -x "$JDK_HOME/bin/java" ]; then JDK="$JDK_HOME" @@ -173,7 +173,7 @@ fi # --------------------------------------------------------------------- # Run the IDE. # --------------------------------------------------------------------- -LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JDK/bin/java" \ +LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JDK/jre/bin/java" \ $AGENT \ "-Xbootclasspath/a:$IDE_HOME/lib/boot.jar" \ -classpath "$CLASSPATH" \ diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 373b1e6512aa..dfe40cd92382 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -172,7 +172,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}.tar", [paths.distAll, paths.distUnix]) if (p("jdk.bundled.linux") != "false") { - buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/bin/*"]) + buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/jre/bin/*"]) } return info } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java index 709383481549..4c9e57aa13c7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java @@ -45,7 +45,6 @@ public class ResumeThreadAction extends DebuggerAction{ final ThreadReferenceProxyImpl thread = threadDescriptor.getThreadReference(); debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) { public void contextAction() throws Exception { - debugProcess.getSession().getXDebugSession().sessionResumed(); debugProcess.createResumeThreadCommand(getSuspendContext(), thread).run(); debuggerTreeNode.calcValue(); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 43149c603d8f..9da93a15cda6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -456,6 +456,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb catch (IllegalThreadStateException e) { LOG.info(e); // undocumented by JDI: may be thrown when querying thread status } + catch (ObjectCollectedException ignored) { + } } requestManager.deleteEventRequests(toDelete); } @@ -1694,6 +1696,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb final Set suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), myThread); for (SuspendContextImpl suspendContext : suspendingContexts) { if (suspendContext.getThread() == myThread) { + getSession().getXDebugSession().sessionResumed(); getManagerThread().invoke(createResumeCommand(suspendContext)); } else { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 77b1c44f093d..6ec3eefddb17 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -28,16 +28,14 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.NullableComputable; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.DocumentUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.EmptyIterable; @@ -285,13 +283,12 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio if (document == null || lineNumber >= document.getLineCount()) { return EmptyIterable.getInstance(); } - final int startOffset = document.getLineStartOffset(lineNumber); - final int endOffset = document.getLineEndOffset(lineNumber); + final TextRange lineRange = DocumentUtil.getLineTextRange(document, lineNumber); return new Iterable() { @Override public Iterator iterator() { return new Iterator() { - PsiElement myElement = file.findElementAt(startOffset); + PsiElement myElement = DebuggerUtilsEx.findElementAt(file, lineRange.getStartOffset()); @Override public boolean hasNext() { @@ -303,7 +300,7 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio PsiElement res = myElement; do { myElement = PsiTreeUtil.nextLeaf(myElement); - if (myElement == null || myElement.getTextOffset() > endOffset) { + if (myElement == null || myElement.getTextOffset() > lineRange.getEndOffset()) { myElement = null; break; } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java index 04bf6d8aa302..42d19808729e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java @@ -589,7 +589,9 @@ public class DebuggerSession implements AbstractDebuggerSession { @Override public void resumed(final SuspendContextImpl suspendContext) { - final SuspendContextImpl currentContext = isSteppingThrough(suspendContext.getThread()) ? null : getProcess().getSuspendManager().getPausedContext(); + final SuspendContextImpl currentContext = suspendContext != null && isSteppingThrough(suspendContext.getThread()) + ? null + : getProcess().getSuspendManager().getPausedContext(); DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() { @Override public void run() { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java index a200ebd04f89..b1c858b0d9bb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.impl.source.PsiClassImpl; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchHelper; @@ -135,14 +136,15 @@ public class UnusedSymbolUtil { } else { //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too - if (containingClass != null && method.isConstructor() + boolean isConstructor = method.isConstructor(); + if (containingClass != null && isConstructor && containingClass.getConstructors().length == 1 && isClassUsed(project, containingFile, containingClass, progress, helper)) { return true; } if (isImplicitUsage(project, method, progress)) return true; - if (method.findSuperMethods().length != 0) { + if (!isConstructor && FindSuperElementsHelper.findSuperElements(method).length != 0) { return true; } if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) { @@ -193,7 +195,7 @@ public class UnusedSymbolUtil { @NotNull PsiFile containingFile, @NotNull PsiMember member, @NotNull ProgressIndicator progress, - final PsiFile ignoreFile, + @Nullable PsiFile ignoreFile, @NotNull Processor usageInfoProcessor) { String name = member.getName(); if (name == null) { @@ -247,10 +249,8 @@ public class UnusedSymbolUtil { } else if (member instanceof PsiMethod) { PsiMethod method = (PsiMethod)member; - JavaMethodFindUsagesOptions o = new JavaMethodFindUsagesOptions(project); - //o.isIncludeOverloadUsages = true; - options = o; - options.isSearchForTextOccurrences = method.isConstructor();; + options = new JavaMethodFindUsagesOptions(project); + options.isSearchForTextOccurrences = method.isConstructor(); } else if (member instanceof PsiVariable) { options = new JavaVariableFindUsagesOptions(project); @@ -271,7 +271,7 @@ public class UnusedSymbolUtil { @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) { final PsiClass containingClass = member.getContainingClass(); - if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true; + if (!(containingClass instanceof PsiClassImpl)) return true; final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod(); return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index ad64ccac3f8e..5a3b720dc48e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -36,6 +36,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -663,8 +664,7 @@ public class AnnotationsHighlightUtil { if (methods.length == 1) { PsiType expected = new PsiImmediateClassType((PsiClass)target, PsiSubstitutor.EMPTY).createArrayType(); if (!expected.equals(methods[0].getReturnType())) { - return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil - .formatType(expected)); + return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil.formatType(expected)); } } @@ -698,6 +698,64 @@ public class AnnotationsHighlightUtil { return container; } + @Nullable + static HighlightInfo checkReceiverPlacement(PsiReceiverParameter parameter) { + PsiElement owner = parameter.getParent().getParent(); + if (owner == null) return null; + + if (!(owner instanceof PsiMethod)) { + String text = JavaErrorMessages.message("receiver.wrong.context"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter.getIdentifier()).descriptionAndTooltip(text).create(); + } + + PsiMethod method = (PsiMethod)owner; + if (isStatic(method) || (method).isConstructor() && isStatic(method.getContainingClass())) { + String text = JavaErrorMessages.message("receiver.static.context"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter.getIdentifier()).descriptionAndTooltip(text).create(); + } + + PsiElement leftNeighbour = PsiTreeUtil.skipSiblingsBackward(parameter, PsiWhiteSpace.class); + if (leftNeighbour != null && !PsiUtil.isJavaToken(leftNeighbour, JavaTokenType.LPARENTH)) { + String text = JavaErrorMessages.message("receiver.wrong.position"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter.getIdentifier()).descriptionAndTooltip(text).create(); + } + + return null; + } + + @Nullable + static HighlightInfo checkReceiverType(PsiReceiverParameter parameter) { + PsiElement owner = parameter.getParent().getParent(); + if (!(owner instanceof PsiMethod)) return null; + + PsiMethod method = (PsiMethod)owner; + PsiClass enclosingClass = method.getContainingClass(); + if (method.isConstructor() && enclosingClass != null) { + enclosingClass = enclosingClass.getContainingClass(); + } + + if (enclosingClass != null && !enclosingClass.equals(PsiUtil.resolveClassInType(parameter.getType()))) { + PsiElement range = ObjectUtils.notNull(parameter.getTypeElement(), parameter); + String text = JavaErrorMessages.message("receiver.type.mismatch"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(text).create(); + } + + PsiThisExpression identifier = parameter.getIdentifier(); + if (enclosingClass != null && !enclosingClass.equals(PsiUtil.resolveClassInType(identifier.getType()))) { + String text = JavaErrorMessages.message("receiver.name.mismatch"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(text).create(); + } + + return null; + } + + private static boolean isStatic(PsiModifierListOwner owner) { + if (owner == null) return false; + if (owner instanceof PsiClass && ((PsiClass)owner).getContainingClass() == null) return true; + PsiModifierList modifierList = owner.getModifierList(); + return modifierList != null && modifierList.hasModifierProperty(PsiModifier.STATIC); + } + @Nullable public static RetentionPolicy getRetentionPolicy(@NotNull PsiClass annotation) { PsiModifierList modifierList = annotation.getModifierList(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 02e2b1bc58b7..39ffd8c42e59 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -965,6 +965,9 @@ public class HighlightUtil extends HighlightUtilBase { else if (modifierOwner instanceof PsiLocalVariable || modifierOwner instanceof PsiParameter) { isAllowed = PsiModifier.FINAL.equals(modifier); } + else if (modifierOwner instanceof PsiReceiverParameter) { + isAllowed = false; + } isAllowed &= incompatibles != null; if (!isAllowed) { @@ -2899,7 +2902,8 @@ public class HighlightUtil extends HighlightUtilBase { EXTENSION_METHODS(LanguageLevel.JDK_1_8, "feature.extension.methods"), METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references"), LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"), - TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations"); + TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations"), + RECEIVERS(LanguageLevel.JDK_1_8, "feature.type.receivers"); private final LanguageLevel level; private final String key; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index b6110bf5ee92..7012c7603aec 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1460,12 +1460,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh @Override public void visitThisExpression(PsiThisExpression expr) { - myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel)); - if (!myHolder.hasErrorResults()) { - myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile)); - } - if (!myHolder.hasErrorResults()) { - visitExpression(expr); + if (!(expr.getParent() instanceof PsiReceiverParameter)) { + myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile)); + if (!myHolder.hasErrorResults()) visitExpression(expr); } } @@ -1580,6 +1578,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } + @Override + public void visitReceiverParameter(PsiReceiverParameter parameter) { + super.visitReceiverParameter(parameter); + if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(parameter, Feature.RECEIVERS)); + if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverPlacement(parameter)); + if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverType(parameter)); + } + @Nullable private HighlightInfo checkFeature(@NotNull PsiElement element, @NotNull Feature feature) { return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile); diff --git a/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java b/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java new file mode 100644 index 000000000000..f52bffd65b4c --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java @@ -0,0 +1,125 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl; + +import com.intellij.psi.*; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureUtil; +import com.intellij.psi.util.PsiSuperMethodUtil; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.Processor; +import com.intellij.util.containers.FactoryMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class FindSuperElementsHelper { + @NotNull + public static PsiElement[] findSuperElements(@NotNull PsiElement element) { + if (element instanceof PsiClass) { + PsiClass aClass = (PsiClass) element; + List allSupers = new ArrayList(Arrays.asList(aClass.getSupers())); + for (Iterator iterator = allSupers.iterator(); iterator.hasNext();) { + PsiClass superClass = iterator.next(); + if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) iterator.remove(); + } + return allSupers.toArray(new PsiClass[allSupers.size()]); + } + if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod) element; + if (method.isConstructor()) { + PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method); + if (constructorInSuper != null) { + return new PsiMethod[]{constructorInSuper}; + } + } + else { + PsiMethod[] superMethods = method.findSuperMethods(false); + if (superMethods.length == 0) { + PsiMethod superMethod = getSiblingInheritedViaSubClass(method); + if (superMethod != null) { + superMethods = new PsiMethod[]{superMethod}; + } + } + return superMethods; + } + } + return PsiElement.EMPTY_ARRAY; + } + + public static PsiMethod getSiblingInheritedViaSubClass(@NotNull PsiMethod method) { + return getSiblingInheritedViaSubClass(method, createSubClassCache()); + } + + public static PsiMethod getSiblingInheritedViaSubClass(@NotNull final PsiMethod method, + @NotNull Map subClassCache) { + if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null; + if (method.hasModifierProperty(PsiModifier.STATIC)) return null; + final PsiClass containingClass = method.getContainingClass(); + boolean hasSubClass = containingClass != null && !containingClass.isInterface() && subClassCache.get(containingClass) != null; + if (!hasSubClass) { + return null; + } + final Collection checkedInterfaces = new THashSet(); + final PsiMethod[] result = new PsiMethod[1]; + ClassInheritorsSearch.search(containingClass, true).forEach(new Processor() { + @Override + public boolean process(PsiClass inheritor) { + for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) { + PsiClassType.ClassResolveResult resolved = interfaceType.resolveGenerics(); + PsiClass anInterface = resolved.getElement(); + if (anInterface == null || !checkedInterfaces.add(anInterface)) continue; + for (PsiMethod superMethod : anInterface.findMethodsByName(method.getName(), true)) { + PsiClass superInterface = superMethod.getContainingClass(); + if (superInterface == null) { + continue; + } + + // calculate substitutor of containingClass --> inheritor + PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, inheritor, PsiSubstitutor.EMPTY); + // calculate substitutor of inheritor --> superInterface + substitutor = TypeConversionUtil.getSuperClassSubstitutor(superInterface, inheritor, substitutor); + + final MethodSignature superSignature = superMethod.getSignature(substitutor); + final MethodSignature derivedSignature = method.getSignature(PsiSubstitutor.EMPTY); + boolean isOverridden = MethodSignatureUtil.isSubsignature(superSignature, derivedSignature); + + if (isOverridden) { + result[0] = superMethod; + return false; + } + } + } + return true; + } + }); + return result[0]; + } + + @NotNull + public static Map createSubClassCache() { + return new FactoryMap() { + @Nullable + @Override + protected PsiClass create(PsiClass aClass) { + return ClassInheritorsSearch.search(aClass, false).findFirst(); + } + }; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java index 4c705206a0a1..4faf4245b8ba 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,8 +31,8 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.search.searches.AllOverridingMethodsSearch; -import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; @@ -48,12 +48,12 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; public class JavaLineMarkerProvider implements LineMarkerProvider { - - protected final DaemonCodeAnalyzerSettings myDaemonSettings; - protected final EditorColorsManager myColorsManager; + private final DaemonCodeAnalyzerSettings myDaemonSettings; + private final EditorColorsManager myColorsManager; public JavaLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) { myDaemonSettings = daemonSettings; @@ -72,19 +72,14 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { method.hasModifierProperty(PsiModifier.ABSTRACT) == superSignature.getMethod().hasModifierProperty(PsiModifier.ABSTRACT); final Icon icon = overrides ? AllIcons.Gutter.OverridingMethod : AllIcons.Gutter.ImplementingMethod; - final MarkerType type = MarkerType.OVERRIDING_METHOD; - ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(element, icon, type); - return NavigateAction.setNavigateAction(info, "Go to super method", "GotoSuperMethod"); + return createSuperMethodLineMarkerInfo(element, icon, Pass.UPDATE_ALL); } } final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element); final PsiElement firstChild = element.getFirstChild(); if (interfaceMethod != null && firstChild != null) { - final Icon icon = AllIcons.Gutter.ImplementingMethod; - final MarkerType type = MarkerType.OVERRIDING_METHOD; - ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(firstChild, icon, type); - return NavigateAction.setNavigateAction(info, "Go to super method", "GotoSuperMethod"); + return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_ALL); } if (myDaemonSettings.SHOW_METHOD_SEPARATORS && firstChild == null) { @@ -128,6 +123,12 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { return null; } + @NotNull + private static LineMarkerInfo createSuperMethodLineMarkerInfo(@NotNull PsiElement name, @NotNull Icon icon, int passId) { + ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(name, icon, MarkerType.OVERRIDING_METHOD, passId); + return NavigateAction.setNavigateAction(info, "Go to super method", IdeActions.ACTION_GOTO_SUPER); + } + private static int getCategory(@NotNull PsiElement element, @NotNull CharSequence documentChars) { if (element instanceof PsiField || element instanceof PsiTypeParameter) return 1; if (element instanceof PsiClass || element instanceof PsiClassInitializer) return 2; @@ -147,37 +148,87 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { @Override public void collectSlowLineMarkers(@NotNull final List elements, @NotNull final Collection result) { ApplicationManager.getApplication().assertReadAccessAllowed(); + Map subClassCache = FindSuperElementsHelper.createSubClassCache(); - Set methods = new HashSet(); + Collection methods = new THashSet(); //noinspection ForLoopReplaceableByForEach for (int i = 0; i < elements.size(); i++) { PsiElement element = elements.get(i); ProgressManager.checkCanceled(); - if (element instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)element; + if (!(element instanceof PsiIdentifier)) continue; + PsiElement parent = element.getParent(); + if (parent instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)parent; if (PsiUtil.canBeOverriden(method)) { methods.add(method); } } - else if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) { - collectInheritingClasses((PsiClass)element, result); + else if (parent instanceof PsiClass && !(parent instanceof PsiTypeParameter)) { + collectInheritingClasses((PsiClass)parent, result, subClassCache); } } if (!methods.isEmpty()) { - collectOverridingAccessors(methods, result); + collectOverridingMethods(methods, result); + collectSiblingInheritedMethods(methods, result, subClassCache); } } - public static void collectInheritingClasses(PsiClass aClass, Collection result) { + private static void collectSiblingInheritedMethods(@NotNull final Collection methods, + @NotNull Collection result, + @NotNull Map subClassCache) { + for (PsiMethod method : methods) { + ProgressManager.checkCanceled(); + PsiClass aClass = method.getContainingClass(); + if (aClass == null || aClass.hasModifierProperty(PsiModifier.FINAL) || aClass.isInterface()) continue; + + boolean canHaveSiblingSuper = !method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.hasModifierProperty(PsiModifier.STATIC) && method.hasModifierProperty(PsiModifier.PUBLIC)&& !method.hasModifierProperty(PsiModifier.FINAL)&& !method.hasModifierProperty(PsiModifier.NATIVE); + if (!canHaveSiblingSuper) continue; + + PsiMethod siblingInheritedViaSubClass = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache); + if (siblingInheritedViaSubClass == null) { + continue; + } + PsiElement range = getMethodRange(method); + LineMarkerInfo info = createSuperMethodLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_OVERRIDEN_MARKERS); + result.add(info); + PsiClass sClass = siblingInheritedViaSubClass.getContainingClass(); + String sName = sClass == null ? null : sClass.getQualifiedName(); + } + } + + @NotNull + private static PsiElement getMethodRange(@NotNull PsiMethod method) { + PsiElement range; + if (method.isPhysical()) { + range = method.getNameIdentifier(); + } + else { + final PsiElement navigationElement = method.getNavigationElement(); + range = navigationElement instanceof PsiNameIdentifierOwner + ? ((PsiNameIdentifierOwner)navigationElement).getNameIdentifier() + : navigationElement; + } + if (range == null) { + range = method; + } + return range; + } + + public static void collectInheritingClasses(@NotNull PsiClass aClass, + @NotNull Collection result, + @NotNull Map subClassCache) { if (aClass.hasModifierProperty(PsiModifier.FINAL)) { return; } if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object. - if (ClassInheritorsSearch.search(aClass, false).findFirst() != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { + PsiClass subClass = subClassCache.get(aClass); + if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod; PsiElement range = aClass.getNameIdentifier(); - if (range == null) range = aClass; + if (range == null) { + range = aClass; + } MarkerType type = MarkerType.SUBCLASSED_CLASS; LineMarkerInfo info = new LineMarkerInfo(range, range.getTextRange(), icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(), @@ -188,7 +239,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { } } - private static void collectOverridingAccessors(final Set methods, Collection result) { + private static void collectOverridingMethods(@NotNull final Collection methods, @NotNull Collection result) { final Set overridden = new HashSet(); Set classes = new THashSet(); for (PsiMethod method : methods) { @@ -229,22 +280,9 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { ProgressManager.checkCanceled(); boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT); - final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod; - PsiElement range; - if (method.isPhysical()) { - range = method.getNameIdentifier(); - } - else { - final PsiElement navigationElement = method.getNavigationElement(); - if (navigationElement instanceof PsiNameIdentifierOwner) { - range = ((PsiNameIdentifierOwner)navigationElement).getNameIdentifier(); - } - else { - range = navigationElement; - } - } - if (range == null) range = method; + PsiElement range = getMethodRange(method); final MarkerType type = MarkerType.OVERRIDDEN_METHOD; + final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod; LineMarkerInfo info = new LineMarkerInfo(range, range.getTextRange(), icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(), type.getNavigationHandler(), @@ -255,8 +293,8 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { } private static class ArrowUpLineMarkerInfo extends MergeableLineMarkerInfo { - private ArrowUpLineMarkerInfo(@NotNull PsiElement element, Icon icon, @NotNull MarkerType markerType) { - super(element, element.getTextRange(), icon, Pass.UPDATE_ALL, markerType.getTooltip(), + private ArrowUpLineMarkerInfo(@NotNull PsiElement element, @NotNull Icon icon, @NotNull MarkerType markerType, int passId) { + super(element, element.getTextRange(), icon, passId, markerType.getTooltip(), markerType.getNavigationHandler(), GutterIconRenderer.Alignment.LEFT); } @@ -274,6 +312,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { return myIcon; } + @NotNull @Override public Function getCommonTooltip(@NotNull List infos) { return new Function() { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index 89785c572d84..d956ddcc054d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; import com.intellij.psi.search.SearchScope; @@ -45,6 +46,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.CommonProcessors; import com.intellij.util.Function; import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -105,9 +107,9 @@ public class MarkerType { }); @Nullable - public static String calculateOverridingMethodTooltip(PsiMethod method, boolean acceptSelf) { + private static String calculateOverridingMethodTooltip(@NotNull PsiMethod method, boolean acceptSelf) { PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf); - if (superMethods == null) return null; + if (superMethods.length == 0) return null; PsiMethod superMethod = superMethods[0]; boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); @@ -121,10 +123,11 @@ public class MarkerType { else{ key = sameSignature ? "method.overrides" : "method.overrides.in"; } - return composeText(superMethods, "", DaemonBundle.message(key), "GotoSuperMethod"); + return composeText(superMethods, "", DaemonBundle.message(key), IdeActions.ACTION_GOTO_SUPER); } - private static String composeText(PsiElement[] methods, String start, String pattern, String actionId) { + @NotNull + private static String composeText(@NotNull PsiElement[] methods, @NotNull String start, @NotNull String pattern, @NotNull String actionId) { Shortcut[] shortcuts = ActionManager.getInstance().getAction(actionId).getShortcutSet().getShortcuts(); Shortcut shortcut = ArrayUtil.getFirstElement(shortcuts); String postfix = "
Click"; @@ -133,9 +136,9 @@ public class MarkerType { return GutterIconTooltipHelper.composeText(Arrays.asList(methods), start, pattern, postfix); } - public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method, boolean acceptSelf) { + private static void navigateToOverridingMethod(MouseEvent e, @NotNull PsiMethod method, boolean acceptSelf) { PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf); - if (superMethods == null) return; + if (superMethods.length == 0) return; boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods); PsiElementListNavigator.openTargets(e, superMethods, DaemonBundle.message("navigation.title.super.method", method.getName()), @@ -143,17 +146,23 @@ public class MarkerType { new MethodCellRenderer(showMethodNames)); } - @Nullable - private static PsiMethod[] composeSuperMethods(PsiMethod method, boolean acceptSelf) { - PsiMethod[] superMethods = method.findSuperMethods(false); + @NotNull + private static PsiMethod[] composeSuperMethods(@NotNull PsiMethod method, boolean acceptSelf) { + PsiElement[] superElements = FindSuperElementsHelper.findSuperElements(method); + + PsiMethod[] superMethods = ContainerUtil.map(superElements, new Function() { + @Override + public PsiMethod fun(PsiElement element) { + return (PsiMethod)element; + } + }, PsiMethod.EMPTY_ARRAY); if (acceptSelf) { superMethods = ArrayUtil.prepend(method, superMethods); } - if (superMethods.length == 0) return null; return superMethods; } - private static PsiElement getParentMethod(PsiElement element) { + private static PsiElement getParentMethod(@NotNull PsiElement element) { final PsiElement parent = element.getParent(); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(parent); return interfaceMethod != null ? interfaceMethod : parent; @@ -179,7 +188,7 @@ public class MarkerType { } }); - public static String getOverriddenMethodTooltip(final PsiMethod method) { + private static String getOverriddenMethodTooltip(@NotNull PsiMethod method) { PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); @@ -206,7 +215,7 @@ public class MarkerType { return composeText(overridings, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); } - public static void navigateToOverriddenMethod(MouseEvent e, final PsiMethod method) { + private static void navigateToOverriddenMethod(MouseEvent e, @NotNull final PsiMethod method) { if (DumbService.isDumb(method.getProject())) { DumbService.getInstance(method.getProject()).showDumbModeNotification( "Navigation to overriding classes is not possible during index update"); @@ -267,7 +276,7 @@ public class MarkerType { } }); - public static String getSubclassedClassTooltip(PsiClass aClass) { + private static String getSubclassedClassTooltip(@NotNull PsiClass aClass) { PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5, new THashSet()); ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(processor)); @@ -298,7 +307,7 @@ public class MarkerType { return composeText(subclasses, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); } - public static void navigateToSubclassedClass(MouseEvent e, final PsiClass aClass) { + private static void navigateToSubclassedClass(MouseEvent e, @NotNull final PsiClass aClass) { if (DumbService.isDumb(aClass.getProject())) { DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); return; @@ -331,7 +340,7 @@ public class MarkerType { private final PsiClass myClass; private final PsiClassOrFunctionalExpressionListCellRenderer myRenderer; - public SubclassUpdater(PsiClass aClass, PsiClassOrFunctionalExpressionListCellRenderer renderer) { + private SubclassUpdater(@NotNull PsiClass aClass, @NotNull PsiClassOrFunctionalExpressionListCellRenderer renderer) { super(aClass.getProject(), SEARCHING_FOR_OVERRIDDEN_METHODS); myClass = aClass; myRenderer = renderer; @@ -374,14 +383,13 @@ public class MarkerType { } }); } - } private static class OverridingMethodsUpdater extends ListBackgroundUpdaterTask { private final PsiMethod myMethod; private final PsiElementListCellRenderer myRenderer; - public OverridingMethodsUpdater(PsiMethod method, PsiElementListCellRenderer renderer) { + private OverridingMethodsUpdater(@NotNull PsiMethod method, @NotNull PsiElementListCellRenderer renderer) { super(method.getProject(), SEARCHING_FOR_OVERRIDING_METHODS); myMethod = method; myRenderer = renderer; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java index 4ab9d43fbc1d..1c6fd53e460f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.ApplicationManager; @@ -112,6 +113,9 @@ public class AddMethodQualifierFix implements IntentionAction { @Override public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().preparePsiElementsForWrite(file)) { + return; + } if (myCandidates.size() == 1 || UNIT_TEST_MODE) { qualify(myCandidates.get(0), editor); } diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/IfStatementSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/IfStatementSelectioner.java index 2acc887e1678..89cb30a2a305 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/IfStatementSelectioner.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/IfStatementSelectioner.java @@ -40,6 +40,14 @@ public class IfStatementSelectioner extends BasicSelectioner { final PsiKeyword elseKeyword = statement.getElseElement(); if (elseKeyword != null) { + final PsiStatement then = statement.getThenBranch(); + if (then != null) { + final TextRange thenRange = new TextRange(statement.getTextRange().getStartOffset(), then.getTextRange().getEndOffset()); + if (thenRange.contains(cursorOffset)) { + result.addAll(expandToWholeLine(editorText, thenRange, false)); + } + } + result.addAll(expandToWholeLine(editorText, new TextRange(elseKeyword.getTextRange().getStartOffset(), statement.getTextRange().getEndOffset()), @@ -50,10 +58,13 @@ public class IfStatementSelectioner extends BasicSelectioner { PsiIfStatement elseIf = (PsiIfStatement)branch; final PsiKeyword element = elseIf.getElseElement(); if (element != null) { - result.addAll(expandToWholeLine(editorText, - new TextRange(elseKeyword.getTextRange().getStartOffset(), - elseIf.getThenBranch().getTextRange().getEndOffset()), - false)); + final PsiStatement elseThen = elseIf.getThenBranch(); + if (elseThen != null) { + result.addAll(expandToWholeLine(editorText, + new TextRange(elseKeyword.getTextRange().getStartOffset(), + elseThen.getTextRange().getEndOffset()), + false)); + } } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java b/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java index 41aea6e9c181..11a101da3edd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,15 +29,11 @@ import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; public class ShowSiblingsAction extends ShowImplementationsAction { - public ShowSiblingsAction() { - super(); - } - @Override - public void performForContext(DataContext dataContext, final boolean invokedByShortcut) { + public void performForContext(@NotNull DataContext dataContext, final boolean invokedByShortcut) { final Project project = CommonDataKeys.PROJECT.getData(dataContext); final PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext); @@ -61,7 +57,7 @@ public class ShowSiblingsAction extends ShowImplementationsAction { } final NavigatablePsiElement[] superElements = (NavigatablePsiElement[])findSuperElements(element); - if (superElements == null || superElements.length == 0) return; + if (superElements.length == 0) return; final boolean isMethod = superElements[0] instanceof PsiMethod; final JBPopup popup = PsiElementListNavigator.navigateOrCreatePopup(superElements, "Choose super " + (isMethod ? "method" : "class or interface"), "Super " + (isMethod ? "methods" : "classes/interfaces"), @@ -81,11 +77,11 @@ public class ShowSiblingsAction extends ShowImplementationsAction { } private void showSiblings(boolean invokedByShortcut, - Project project, + @NotNull Project project, Editor editor, PsiFile file, boolean invokedFromEditor, - PsiElement element) { + @NotNull PsiElement element) { final PsiElement[] impls = getSelfAndImplementations(editor, element, createImplementationsSearcher(), false); final String text = SymbolPresentationUtil.getSymbolPresentableText(element); showImplementations(impls, project, text, editor, file, element, invokedFromEditor, invokedByShortcut); @@ -96,11 +92,11 @@ public class ShowSiblingsAction extends ShowImplementationsAction { return false; } - @Nullable + @NotNull private static PsiElement[] findSuperElements(final PsiElement element) { PsiNameIdentifierOwner parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClass.class); if (parent == null) { - return null; + return PsiElement.EMPTY_ARRAY; } return FindSuperElementsHelper.findSuperElements(parent); diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java index 95668b59fa69..1663d31da4a8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class JavaGotoSuperHandler implements CodeInsightActionHandler { @Override @@ -41,7 +40,7 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler { int offset = editor.getCaretModel().getOffset(); PsiElement[] superElements = findSuperElements(file, offset); - if (superElements == null || superElements.length == 0) return; + if (superElements.length == 0) return; if (superElements.length == 1) { PsiElement superElement = superElements[0].getNavigationElement(); final PsiFile containingFile = superElement.getContainingFile(); @@ -50,24 +49,25 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler { if (virtualFile == null) return; OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile, superElement.getTextOffset()); FileEditorManager.getInstance(project).openTextEditor(descriptor, true); - } else { - if (superElements[0] instanceof PsiMethod) { - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements); - PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements, - CodeInsightBundle.message("goto.super.method.chooser.title"), - CodeInsightBundle.message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()), - new MethodCellRenderer(showMethodNames)); - } - else { - NavigationUtil.getPsiElementPopup(superElements, CodeInsightBundle.message("goto.super.class.chooser.title")).showInBestPositionFor(editor); - } + } + else if (superElements[0] instanceof PsiMethod) { + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements); + PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements, + CodeInsightBundle.message("goto.super.method.chooser.title"), + CodeInsightBundle + .message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()), + new MethodCellRenderer(showMethodNames)); + } + else { + NavigationUtil.getPsiElementPopup(superElements, CodeInsightBundle.message("goto.super.class.chooser.title")) + .showInBestPositionFor(editor); } } - @Nullable - private PsiElement[] findSuperElements(PsiFile file, int offset) { + @NotNull + private PsiElement[] findSuperElements(@NotNull PsiFile file, int offset) { PsiElement element = getElement(file, offset); - if (element == null) return null; + if (element == null) return PsiElement.EMPTY_ARRAY; final PsiElement psiElement = PsiTreeUtil.getParentOfType(element, PsiFunctionalExpression.class, PsiMember.class); if (psiElement instanceof PsiFunctionalExpression) { @@ -79,13 +79,13 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler { final PsiNameIdentifierOwner parent = PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class); if (parent == null) { - return null; + return PsiElement.EMPTY_ARRAY; } return FindSuperElementsHelper.findSuperElements(parent); } - protected PsiElement getElement(PsiFile file, int offset) { + protected PsiElement getElement(@NotNull PsiFile file, int offset) { return file.findElementAt(offset); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java index 5b88af016709..9d90c20d2e5b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java @@ -50,7 +50,7 @@ public class FormatPostfixTemplate extends StringBasedPostfixTemplate { } @Override - protected boolean shouldRemoveParent() { - return false; + protected PsiElement getElementToRemove(PsiElement expr) { + return expr; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/AddMethodsDialog.java b/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/AddMethodsDialog.java index d84d67e879f4..376d3a38b82a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/AddMethodsDialog.java +++ b/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/AddMethodsDialog.java @@ -36,6 +36,7 @@ import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.LinkedMultiMap; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -151,11 +152,11 @@ public class AddMethodsDialog extends DialogWrapper { final DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel)myMethodNameCombo.getModel(); comboBoxModel.removeAllElements(); if (aClass == null) { - myMethodNameCombo.setEnabled(false); + enable(false); } else { final List possibleTemplates = PseudoLambdaReplaceTemplate.getAllTemplates(); - final MultiMap nameToMethod = new MultiMap(); + final LinkedMultiMap nameToMethod = new LinkedMultiMap(); for (PsiMethod m : ContainerUtil.filter(aClass.getMethods(), new Condition() { @Override public boolean value(PsiMethod method) { @@ -181,15 +182,27 @@ public class AddMethodsDialog extends DialogWrapper { for (Map.Entry> entry : nameToMethod.entrySet()) { comboBoxModel.addElement(entry.getValue()); } - myMethodNameCombo.setEnabled(true); + final boolean isSuitableMethodsFound = comboBoxModel.getSize() != 0; + enable(isSuitableMethodsFound); } } }); - myExamplePanel.setEnabled(false); + setOKActionEnabled(false); init(); } + private void enable(boolean isEnabled) { + myMethodNameCombo.setEnabled(isEnabled); + myTemplatesCombo.setEnabled(isEnabled); + setOKActionEnabled(isEnabled); + myExamplePanel.setEnabled(isEnabled); + if (!isEnabled) { + myBeforeActionPanel.reset("", StdFileTypes.JAVA); + myAfterActionPanel.reset("", StdFileTypes.JAVA); + } + } + private void showTemplateExample(final PseudoLambdaReplaceTemplate template, final PsiMethod method) { final PsiClass aClass = method.getContainingClass(); LOG.assertTrue(aClass != null); diff --git a/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java b/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java index 4c425ed5d9d9..425f1424837e 100644 --- a/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java +++ b/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java @@ -19,17 +19,12 @@ import com.intellij.codeInsight.daemon.impl.quickfix.AddTypeArgumentsFix; import com.intellij.codeInspection.AnonymousCanBeLambdaInspection; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.impl.PsiDiamondTypeUtil; -import com.intellij.psi.impl.PsiSubstitutorImpl; -import com.intellij.psi.impl.source.PsiClassReferenceType; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.hash.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,7 +111,7 @@ class PseudoLambdaReplaceTemplate { } else if (!(returnType instanceof PsiArrayType)) { return null; } - return validate(parameterTypes, returnType, method); + return validate(parameterTypes, returnType, null, method); } @Nullable @@ -136,7 +131,9 @@ class PseudoLambdaReplaceTemplate { if (argumentTypes.length != expectedParameters.length) { return null; } - return validate(argumentTypes, methodReturnType, expression); + final JavaResolveResult result = expression.getMethodExpression().advancedResolve(false); + final PsiSubstitutor methodSubstitutor = result.getSubstitutor(); + return validate(argumentTypes, methodReturnType, methodSubstitutor, expression); } public String getStreamApiMethodName() { @@ -151,7 +148,10 @@ class PseudoLambdaReplaceTemplate { return myAcceptDefaultValue; } - private ValidationInfo validate(final PsiType[] arguments, final PsiType methodReturnType, final PsiElement context) { + private ValidationInfo validate(final PsiType[] arguments, + final PsiType methodReturnType, + final @Nullable PsiSubstitutor methodSubstitutor, + final PsiElement context) { int lambdaPosition = -1; int defaultValuePosition = -1; int iterablePosition = -1; @@ -168,7 +168,7 @@ class PseudoLambdaReplaceTemplate { for (int i = 0; i < arguments.length; i++) { PsiType type = arguments[i]; - if (isFunction(type, methodReturnType, context)) { + if (isFunction(type, methodReturnType, methodSubstitutor, context)) { if (lambdaPosition == -1) { lambdaPosition = i; continue; @@ -207,7 +207,7 @@ class PseudoLambdaReplaceTemplate { return new ValidationInfo(lambdaPosition, iterablePosition, defaultValuePosition); } - private boolean isFunction(PsiType type, PsiType baseMethodReturnType, PsiElement context) { + private boolean isFunction(PsiType type, PsiType baseMethodReturnType, PsiSubstitutor methodSubstitutor, PsiElement context) { if (type instanceof PsiMethodReferenceType) { final PsiMethodReferenceExpression expression = ((PsiMethodReferenceType)type).getExpression(); final PsiMethod resolvedMethod = (PsiMethod)expression.resolve(); @@ -219,20 +219,21 @@ class PseudoLambdaReplaceTemplate { return false; } final PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(expression); - return isSuitableLambdaRole(returnType, baseMethodReturnType, context); + return isSuitableLambdaRole(returnType, baseMethodReturnType, methodSubstitutor, context); } else if (type instanceof PsiLambdaExpressionType) { final PsiLambdaExpression expression = ((PsiLambdaExpressionType)type).getExpression(); final PsiType psiType = LambdaUtil.getFunctionalInterfaceReturnType(expression.getFunctionalInterfaceType()); - return isSuitableLambdaRole(psiType, baseMethodReturnType, context); - } else if (isSuitableFunctionalType(type, baseMethodReturnType, context)) { + return isSuitableLambdaRole(psiType, baseMethodReturnType, methodSubstitutor, context); + } else if (isSuitableFunctionalType(type, baseMethodReturnType, methodSubstitutor, context)) { return true; } return isJavaLangClassType(type) && myLambdaRole == LambdaRole.PREDICATE; } - private boolean isSuitableLambdaRole(final PsiType lambdaReturnType, - final PsiType baseMethodReturnType, - final PsiElement context) { + private boolean isSuitableLambdaRole(PsiType lambdaReturnType, + PsiType baseMethodReturnType, + PsiSubstitutor methodSubstitutor, + PsiElement context) { if (lambdaReturnType == null) { return false; } @@ -244,6 +245,9 @@ class PseudoLambdaReplaceTemplate { } else { LOG.assertTrue(myLambdaRole == LambdaRole.FUNCTION); + if (methodSubstitutor != null) { + lambdaReturnType = methodSubstitutor.substitute(lambdaReturnType); + } if (baseMethodReturnType instanceof PsiClassType) { final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)baseMethodReturnType).resolveGenerics(); final Map substitutionMap = resolveResult.getSubstitutor().getSubstitutionMap(); @@ -274,49 +278,44 @@ class PseudoLambdaReplaceTemplate { return false; } - private boolean isSuitableFunctionalType(final PsiType type, final PsiType baseMethodReturnType, final PsiElement context) { + private boolean isSuitableFunctionalType(final PsiType type, + final PsiType baseMethodReturnType, + final @Nullable PsiSubstitutor methodSubstitutor, + final PsiElement context) { if (type instanceof PsiClassType) { - PsiClass targetClass = ((PsiClassType)type).resolve(); - if (targetClass != null) { - if (targetClass instanceof PsiAnonymousClass) { - targetClass = ((PsiAnonymousClass)targetClass).getBaseClassType().resolve(); - if (targetClass == null) { + final PsiClass resolvedClass = ((PsiClassType)type).resolve(); + if (resolvedClass != null) { + if (resolvedClass instanceof PsiAnonymousClass) { + final PsiClass baseClass = ((PsiAnonymousClass)resolvedClass).getBaseClassType().resolve(); + if (baseClass == null) { return false; } - } - if (!LambdaUtil.isFunctionalClass(targetClass)) { - return false; - } - PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(targetClass); - final PsiMethod[] methods = ((PsiClassType)type).resolve().findMethodsByName(method.getName(), false); - if (methods.length != 1) { - return false; - } - method = methods[0]; - if (method == null) { - return false; - } - final PsiType psiType; - if (type instanceof PsiClassReferenceType) { - final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType)type).getReference(); - final PsiClass resolvedClass = ((PsiClassReferenceType)type).resolve(); - final PsiTypeParameter[] typeParameters = resolvedClass.getTypeParameters(); - final PsiType[] substitutedTypeParameters = reference.getTypeParameters(); - - LOG.assertTrue(typeParameters.length == substitutedTypeParameters.length); - final Map substitutionMap = new HashMap(); - for (int i = 0; i < typeParameters.length; i++) { - PsiTypeParameter parameter = typeParameters[i]; - PsiType t = substitutedTypeParameters[i]; - substitutionMap.put(parameter, t); + if (!LambdaUtil.isFunctionalClass(baseClass)) { + return false; } - PsiSubstitutor substitutor = PsiSubstitutorImpl.createSubstitutor(substitutionMap); - psiType = substitutor.substitute(method.getReturnType()); + PsiMethod superMethod = LambdaUtil.getFunctionalInterfaceMethod(baseClass); + if (superMethod == null) { + return false; + } + final PsiMethod[] methods = resolvedClass.findMethodsByName(superMethod.getName(), false); + PsiMethod method = null; + for (PsiMethod m : methods) { + if (PsiSuperMethodUtil.isSuperMethod(m, superMethod)) { + method = m; + } + } + if (method == null) { + return false; + } + final PsiType psiType = methodSubstitutor == null ? method.getReturnType() : methodSubstitutor.substitute(method.getReturnType()); + return isSuitableLambdaRole(psiType, baseMethodReturnType, methodSubstitutor, context); } else { - psiType = method.getReturnType(); + if (!LambdaUtil.isFunctionalClass(resolvedClass)) { + return false; + } + return isSuitableLambdaRole(LambdaUtil.getFunctionalInterfaceReturnType(type), baseMethodReturnType, methodSubstitutor, context); + } } - return isSuitableLambdaRole(psiType, baseMethodReturnType, context); - } return false; } else { return false; @@ -340,17 +339,19 @@ class PseudoLambdaReplaceTemplate { int lambdaIndex = validationInfo.getLambdaPosition(); final PsiExpression[] expressions = expression.getArgumentList().getExpressions(); + final PsiExpression iterableExpression = expressions[validationInfo.getIterablePosition()]; + final String pipelineHead = createPipelineHeadText(iterableExpression, force); + if (pipelineHead == null) { + return expression; + } + PsiExpression lambdaExpression = expressions[lambdaIndex]; if (!force) { lambdaExpression = convertClassTypeExpression(lambdaExpression); - lambdaExpression = convertToJavaLambda(lambdaExpression, myStreamApiMethodName); + lambdaExpression = convertToJavaLambda(lambdaExpression); } LOG.assertTrue(lambdaExpression != null); - final PsiExpression iterableExpression = expressions[validationInfo.getIterablePosition()]; - final String pipelineHead = createPipelineHeadText(iterableExpression, lambdaExpression, force); - - final String lambdaExpressionText; final String elementText; if (!StreamApiConstants.FAKE_FIND_MATCHED.equals(myStreamApiMethodName)) { @@ -391,38 +392,6 @@ class PseudoLambdaReplaceTemplate { return JavaPsiFacade.getElementFactory(project).createExpressionFromText(sb.toString(), null); } - private static void convertNewExpression(PsiMethod containingMethod, PsiNewExpression newExpression, PsiClass expectedReturnClass) { - final String expectedReturnQName = expectedReturnClass.getQualifiedName(); - LOG.assertTrue(expectedReturnQName != null); - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(newExpression.getProject()); - PsiAnonymousClass anonymousClass = PsiTreeUtil.findChildOfType(newExpression, PsiAnonymousClass.class); - LOG.assertTrue(anonymousClass != null); - PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.findChildOfType(anonymousClass, PsiJavaCodeReferenceElement.class); - LOG.assertTrue(referenceElement != null); - final PsiReferenceParameterList parameterList = PsiTreeUtil.findChildOfType(referenceElement, PsiReferenceParameterList.class); - final PsiJavaCodeReferenceElement newCodeReferenceElement = factory.createReferenceFromText(expectedReturnClass.getQualifiedName() - + - (parameterList == null - ? "" - : parameterList.getText()), null); - referenceElement.replace(newCodeReferenceElement); - final List methods = ContainerUtil.filter(anonymousClass.getMethods(), new Condition() { - @Override - public boolean value(PsiMethod method) { - return !"equals".equals(method.getName()); - } - }); - LOG.assertTrue(methods.size() == 1, methods); - final PsiMethod method = methods.get(0); - method.setName(expectedReturnClass.getMethods()[0].getName()); - final PsiTypeElement element = containingMethod.getReturnTypeElement(); - if (element != null) { - final PsiReferenceParameterList genericParameter = PsiTreeUtil.findChildOfType(element, PsiReferenceParameterList.class); - element.replace( - factory.createTypeElementFromText(expectedReturnQName + (genericParameter == null ? "" : genericParameter.getText()), null)); - } - } - @Nullable private static String findSuitableTailMethodForCollection(PsiMethod lambdaHandler) { final PsiType type = lambdaHandler.getReturnType(); @@ -454,10 +423,7 @@ class PseudoLambdaReplaceTemplate { return null; } - private static PsiExpression convertToJavaLambda(PsiExpression expression, String streamApiMethodName) { - if (streamApiMethodName.equals(StreamApiConstants.FAKE_FIND_MATCHED)) { - streamApiMethodName = StreamApiConstants.FILTER; - } + private static PsiExpression convertToJavaLambda(PsiExpression expression) { if (expression instanceof PsiMethodReferenceExpression) { return expression; } @@ -473,72 +439,25 @@ class PseudoLambdaReplaceTemplate { if (!(type instanceof PsiClassType)) { return null; } - final PsiClass lambdaClass = ((PsiClassType)type).resolve(); + final PsiClassType.ClassResolveResult result = ((PsiClassType)type).resolveGenerics(); + final PsiClass lambdaClass = result.getElement(); if (lambdaClass == null) { return null; } - final String methodName = lambdaClass.getMethods()[0].getName(); - if (tryConvertPseudoLambdaToStreamApi(method, resolveStreamApiLambdaClass(expression.getProject(), streamApiMethodName))) { - return expression; - } - else { - return JavaPsiFacade.getElementFactory(expression.getProject()) - .createExpressionFromText(expression.getText() + "::" + methodName, null); - } + final PsiMethod functionalInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(lambdaClass); + LOG.assertTrue(functionalInterfaceMethod != null); + final String methodName = functionalInterfaceMethod.getName(); + return JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::" + methodName, null); + } + if (expression instanceof PsiReferenceExpression) { + final PsiType expressionType = expression.getType(); + final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(expressionType); + LOG.assertTrue(method != null); + return JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::" + method.getName(), null); } return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, true); } - @NotNull - private static PsiClass resolveStreamApiLambdaClass(Project project, String streamApiMethodName) { - final PsiClass javaUtilStream = JavaPsiFacade.getInstance(project) - .findClass(StreamApiConstants.JAVA_UTIL_STREAM_STREAM, GlobalSearchScope.notScope(GlobalSearchScope.projectScope(project))); - LOG.assertTrue(javaUtilStream != null); - final PsiMethod[] methods = javaUtilStream.findMethodsByName(streamApiMethodName, false); - LOG.assertTrue(methods.length == 1); - final PsiMethod method = methods[0]; - final PsiParameter[] parameters = method.getParameterList().getParameters(); - LOG.assertTrue(parameters.length == 1); - final PsiType type = parameters[0].getType(); - LOG.assertTrue(type instanceof PsiClassType); - final PsiClass resolved = ((PsiClassType)type).resolve(); - LOG.assertTrue(resolved != null); - return resolved; - } - - private static boolean tryConvertPseudoLambdaToStreamApi(final @NotNull PsiMethod method, final @NotNull PsiClass expectedReturnClass) { - final PsiType currentReturnType = method.getReturnType(); - if (!(currentReturnType instanceof PsiClassType)) { - LOG.error("pseudo-lambda return type must be class " + currentReturnType); - return true; - } - final PsiClass resolvedCurrentReturnType = ((PsiClassType)currentReturnType).resolve(); - if (expectedReturnClass.getManager().areElementsEquivalent(expectedReturnClass, resolvedCurrentReturnType)) { - return true; - } - final PsiCodeBlock body = method.getBody(); - Collection returnStatements = PsiTreeUtil.findChildrenOfType(body, PsiReturnStatement.class); - returnStatements = ContainerUtil.filter(returnStatements, new Condition() { - @Override - public boolean value(PsiReturnStatement statement) { - return PsiTreeUtil.getParentOfType(statement, PsiMethod.class) == method; - } - }); - if (returnStatements.size() != 1) { - return false; - } - final PsiReturnStatement returnStatement = ContainerUtil.getFirstItem(returnStatements); - assert returnStatement != null; - final PsiExpression returnValue = returnStatement.getReturnValue(); - if (returnValue instanceof PsiNewExpression) { - convertNewExpression(method, (PsiNewExpression)returnValue, expectedReturnClass); - return true; - } - else { - return false; - } - } - @NotNull private static PsiExpression convertClassTypeExpression(PsiExpression expression) { final PsiType type = expression.getType(); @@ -552,7 +471,7 @@ class PseudoLambdaReplaceTemplate { return expression; } - private static String createPipelineHeadText(PsiExpression collectionExpression, PsiExpression lambdaExpression, boolean force) { + private static String createPipelineHeadText(PsiExpression collectionExpression, boolean force) { if (collectionExpression instanceof PsiNewExpression) { final PsiDiamondType.DiamondInferenceResult diamondResolveResult = PsiDiamondTypeImpl.resolveInferredTypesNoCheck((PsiNewExpression)collectionExpression, collectionExpression); @@ -569,13 +488,20 @@ class PseudoLambdaReplaceTemplate { final PsiType newType = copiedExpression.getType(); if (!currentType.equals(newType)) { collectionExpression = AddTypeArgumentsFix.addTypeArguments(copiedExpression, currentType); + if (collectionExpression == null) { + return null; + } } } final PsiType type = collectionExpression.getType(); if (type instanceof PsiClassType) { final PsiClass resolved = ((PsiClassType)type).resolve(); LOG.assertTrue(resolved != null && resolved.getQualifiedName() != null, type); - return collectionExpression.getText() + ".stream()"; + if (InheritanceUtil.isInheritor(resolved, CommonClassNames.JAVA_UTIL_COLLECTION)) { + return collectionExpression.getText() + ".stream()"; + } else { + return "java.util.stream.StreamSupport.stream(" + collectionExpression.getText() + ".spliterator(), false)"; + } } else if (type instanceof PsiArrayType) { return CommonClassNames.JAVA_UTIL_ARRAYS + ".stream(" + collectionExpression.getText() + ")"; diff --git a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java index 5e3a2d10c36d..a1a22653a60e 100644 --- a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java +++ b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; @@ -34,6 +35,7 @@ import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -41,20 +43,24 @@ public class SuperMethodWarningUtil { private SuperMethodWarningUtil() {} @NotNull - public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString) { - return checkSuperMethods(method, actionString, null); + public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString) { + return checkSuperMethods(method, actionString, Collections.emptyList()); } @NotNull - public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString, Collection ignore) { + public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString, @NotNull Collection ignore) { PsiClass aClass = method.getContainingClass(); if (aClass == null) return new PsiMethod[]{method}; final Collection superMethods = DeepestSuperMethodsSearch.search(method).findAll(); - if (ignore != null) { - superMethods.removeAll(ignore); - } + superMethods.removeAll(ignore); + if (superMethods.isEmpty()) { + PsiMethod siblingSuperMethod = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method); + if (siblingSuperMethod != null) { + superMethods.add(siblingSuperMethod); + } + } if (superMethods.isEmpty()) return new PsiMethod[]{method}; @@ -85,7 +91,7 @@ public class SuperMethodWarningUtil { } - public static PsiMethod checkSuperMethod(final PsiMethod method, String actionString) { + public static PsiMethod checkSuperMethod(@NotNull PsiMethod method, @NotNull String actionString) { PsiClass aClass = method.getContainingClass(); if (aClass == null) return method; @@ -110,10 +116,10 @@ public class SuperMethodWarningUtil { return null; } - public static void checkSuperMethod(final PsiMethod method, - final String actionString, - final PsiElementProcessor processor, - final Editor editor) { + public static void checkSuperMethod(@NotNull PsiMethod method, + @NotNull String actionString, + @NotNull final PsiElementProcessor processor, + @NotNull Editor editor) { PsiClass aClass = method.getContainingClass(); if (aClass == null) { processor.execute(method); @@ -137,7 +143,7 @@ public class SuperMethodWarningUtil { return; } - final PsiMethod[] methods = new PsiMethod[]{superMethod, method}; + final PsiMethod[] methods = {superMethod, method}; final String renameBase = actionString + " base method"; final String renameCurrent = actionString + " only current method"; final JBList list = new JBList(renameBase, renameCurrent); @@ -148,6 +154,7 @@ public class SuperMethodWarningUtil { .setResizable(false) .setRequestFocus(true) .setItemChoosenCallback(new Runnable() { + @Override public void run() { final Object value = list.getSelectedValue(); if (value instanceof String) { diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index fff50d1c41ab..6f74898b9a31 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -816,7 +816,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @Nullable protected Wrap arrangeChildWrap(final ASTNode child, Wrap defaultWrap) { - return myWrapManager.arrangeChildWrap(child, myNode, getSettings(), defaultWrap, this); + return myWrapManager.arrangeChildWrap(child, myNode, mySettings, myJavaSettings, defaultWrap, this); } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java index 54965f9eca1e..c607722df701 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java @@ -20,6 +20,7 @@ import com.intellij.formatting.Block; import com.intellij.formatting.Wrap; import com.intellij.lang.ASTNode; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.codeStyle.JavaCodeStyleSettings; import com.intellij.psi.formatter.java.AbstractJavaBlock; import com.intellij.psi.formatter.java.wrap.impl.JavaChildBlockWrapFactory; import com.intellij.psi.formatter.java.wrap.impl.JavaChildWrapArranger; @@ -78,10 +79,14 @@ public class JavaWrapManager { * null otherwise */ @Nullable - public Wrap arrangeChildWrap(ASTNode child, ASTNode parent, CommonCodeStyleSettings settings, Wrap suggestedWrap, + public Wrap arrangeChildWrap(ASTNode child, + ASTNode parent, + CommonCodeStyleSettings settings, + JavaCodeStyleSettings javaSettings, + Wrap suggestedWrap, AbstractJavaBlock reservedWrapsProvider) { - return myChildArranger.arrange(child, parent, settings, suggestedWrap, reservedWrapsProvider); + return myChildArranger.arrange(child, parent, settings, javaSettings, suggestedWrap, reservedWrapsProvider); } /** diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java index 23914cb5fce8..8516ba04c067 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java @@ -72,9 +72,9 @@ public class JavaChildWrapArranger { public Wrap arrange(ASTNode child, ASTNode parent, CommonCodeStyleSettings settings, + JavaCodeStyleSettings javaSettings, Wrap suggestedWrap, AbstractJavaBlock reservedWrapsProvider) { - final JavaCodeStyleSettings javaSettings = settings.getRootSettings().getCustomSettings(JavaCodeStyleSettings.class); ASTNode directParent = child.getTreeParent(); int role = ((CompositeElement)directParent).getChildRole(child); diff --git a/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java b/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java index e0baa8787526..2d20a2b0441d 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,11 +23,16 @@ import com.intellij.psi.util.FileTypeUtils; public class JavaVetoRenameCondition implements Condition { @Override - public boolean value(final PsiElement element) { + public boolean value(PsiElement element) { if (element instanceof LightMethod) { - final PsiClass containingClass = ((LightMethod)element).getContainingClass(); + PsiClass containingClass = ((LightMethod)element).getContainingClass(); if (containingClass != null && containingClass.isEnum()) return true; } + + if (element instanceof PsiReceiverParameter) { + return true; + } + return element instanceof PsiJavaFile && !FileTypeUtils.isInServerPageFile(element) && !JavaProjectRootsUtil.isOutsideJavaSourceRoot((PsiFile)element) && diff --git a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java index 966a7a3422ea..4be83981446e 100644 --- a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java +++ b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +20,14 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.spi.psi.SPIClassProviderReferenceElement; +import org.jetbrains.annotations.NotNull; /** * User: anna */ public class SPIGotoSuperHandler extends JavaGotoSuperHandler { @Override - protected PsiElement getElement(PsiFile file, int offset) { + protected PsiElement getElement(@NotNull PsiFile file, int offset) { final SPIClassProviderReferenceElement providerElement = PsiTreeUtil.getParentOfType(super.getElement(file, offset), SPIClassProviderReferenceElement.class); if (providerElement != null) { diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java index a614854ba728..797a22e8d68a 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,7 +61,7 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor candidates = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Collection compute() { - return JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, project, scope); - } - }); + Collection candidates = MethodUsagesSearcher.resolveInReadAction(project, + new Computable>() { + @Override + public Collection compute() { + return JavaSuperClassNameOccurenceIndex + .getInstance().get(searchKey, project, scope); + } + }); Map> classes = new HashMap>(); @@ -118,7 +120,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() { @Override @@ -142,16 +144,19 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor anonymousCandidates = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Collection compute() { - return JavaAnonymousClassBaseRefOccurenceIndex.getInstance().get(searchKey, project, scope); - } - }); + Collection anonymousCandidates = MethodUsagesSearcher.resolveInReadAction(project, + new Computable>() { + @Override + public Collection compute() { + return JavaAnonymousClassBaseRefOccurenceIndex + .getInstance() + .get(searchKey, project, scope); + } + }); for (PsiAnonymousClass candidate : anonymousCandidates) { ProgressIndicatorProvider.checkCanceled(); - if (!checkInheritance(p, aClass, candidate)) continue; + if (!checkInheritance(p, aClass, candidate, project)) continue; if (!consumer.process(candidate)) return false; } @@ -190,8 +195,8 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() { + private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate, Project project) { + return MethodUsagesSearcher.resolveInReadAction(project, new Computable() { @Override public Boolean compute() { return !p.isCheckInheritance() || candidate.isInheritor(aClass, false); diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java index c7d9e303aae3..c1a747fb3b03 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.codeInsight; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; +import com.intellij.psi.PsiAnnotation.TargetType; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,28 +29,27 @@ import java.util.Set; * @author peter */ public class AnnotationTargetUtil { - public static final Set DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet( - PsiAnnotation.TargetType.PACKAGE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.ANNOTATION_TYPE, - PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.CONSTRUCTOR, - PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.LOCAL_VARIABLE)); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.AnnotationUtil"); - private static final PsiAnnotation.TargetType[] PACKAGE_TARGETS = {PsiAnnotation.TargetType.PACKAGE}; - private static final PsiAnnotation.TargetType[] TYPE_USE_TARGETS = {PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] ANNOTATION_TARGETS = {PsiAnnotation.TargetType.ANNOTATION_TYPE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] TYPE_TARGETS = {PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] TYPE_PARAMETER_TARGETS = { - PsiAnnotation.TargetType.TYPE_PARAMETER, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] CONSTRUCTOR_TARGETS = {PsiAnnotation.TargetType.CONSTRUCTOR, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] METHOD_TARGETS = {PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] FIELD_TARGETS = {PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] PARAMETER_TARGETS = {PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.TYPE_USE}; - private static final PsiAnnotation.TargetType[] LOCAL_VARIABLE_TARGETS ={ - PsiAnnotation.TargetType.LOCAL_VARIABLE, PsiAnnotation.TargetType.TYPE_USE}; + + public static final Set DEFAULT_TARGETS = ContainerUtil.immutableSet( + TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE, TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR, + TargetType.PARAMETER, TargetType.LOCAL_VARIABLE); + + private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE}; + private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE}; + private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE}; + private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE}; + private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE}; + private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE}; + private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE}; + private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE}; + private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE}; + private static final TargetType[] LOCAL_VARIABLE_TARGETS = {TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE}; @NotNull - public static PsiAnnotation.TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) { + public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) { if (owner == null) { - return PsiAnnotation.TargetType.EMPTY_ARRAY; + return TargetType.EMPTY_ARRAY; } if (owner instanceof PsiType || owner instanceof PsiTypeElement) { @@ -90,24 +90,27 @@ public class AnnotationTargetUtil { if (element instanceof PsiLocalVariable) { return LOCAL_VARIABLE_TARGETS; } + if (element instanceof PsiReceiverParameter) { + return TYPE_USE_TARGETS; + } } - return PsiAnnotation.TargetType.EMPTY_ARRAY; + return TargetType.EMPTY_ARRAY; } @Nullable - public static Set extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) { + public static Set extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) { if (value instanceof PsiReference) { - PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)value); + TargetType targetType = translateTargetRef((PsiReference)value); if (targetType != null) { return Collections.singleton(targetType); } } else if (value instanceof PsiArrayInitializerMemberValue) { - Set targets = ContainerUtil.newHashSet(); + Set targets = ContainerUtil.newHashSet(); for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) { if (initializer instanceof PsiReference) { - PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)initializer); + TargetType targetType = translateTargetRef((PsiReference)initializer); if (targetType != null) { targets.add(targetType); } @@ -120,12 +123,12 @@ public class AnnotationTargetUtil { } @Nullable - private static PsiAnnotation.TargetType translateTargetRef(@NotNull PsiReference reference) { + private static TargetType translateTargetRef(@NotNull PsiReference reference) { PsiElement field = reference.resolve(); if (field instanceof PsiEnumConstant) { String name = ((PsiEnumConstant)field).getName(); try { - return PsiAnnotation.TargetType.valueOf(name); + return TargetType.valueOf(name); } catch (IllegalArgumentException e) { LOG.warn("Unknown target: " + name); diff --git a/java/java-psi-api/src/com/intellij/psi/PsiReceiverParameter.java b/java/java-psi-api/src/com/intellij/psi/PsiReceiverParameter.java index eb93e359f575..abbbb4fbd52c 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiReceiverParameter.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiReceiverParameter.java @@ -15,10 +15,14 @@ */ package com.intellij.psi; +import org.jetbrains.annotations.NotNull; + /** * Represents a receiver parameter of a Java method (Java 8). * * @since 12.1 */ public interface PsiReceiverParameter extends PsiVariable { + @NotNull + PsiThisExpression getIdentifier(); } diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 634eda49bcdc..d916d1d1cf4a 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -608,6 +608,22 @@ public class DeclarationParser { } } + if (typed) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JavaTokenType.THIS_KEYWORD || tokenType == JavaTokenType.IDENTIFIER && builder.lookAhead(1) == JavaTokenType.DOT) { + PsiBuilder.Marker mark = builder.mark(); + + PsiBuilder.Marker expr = myParser.getExpressionParser().parse(builder); + if (expr != null && exprType(expr) == JavaElementType.THIS_EXPRESSION) { + mark.drop(); + done(param, JavaElementType.RECEIVER_PARAMETER); + return param; + } + + mark.rollbackTo(); + } + } + if (expect(builder, JavaTokenType.IDENTIFIER)) { if (!resource) { eatBrackets(builder, typeInfo != null && typeInfo.isVarArg ? "expected.rparen" : null); diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java index 9e088b82b055..d3cf1a559070 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java @@ -56,7 +56,8 @@ public class LocalsControlFlowPolicy implements ControlFlowPolicy { if (codeFragment == null) return null; if (myCodeFragment.getContainingFile() == codeFragment.getContainingFile() && // in order for jsp includes to work !myCodeFragment.equals(codeFragment) && - !(myCodeFragment.getParent() instanceof PsiLambdaExpression && codeFragment.equals(PsiTreeUtil.getParentOfType(myCodeFragment, PsiCodeBlock.class)))) { + !(myCodeFragment.getParent() instanceof PsiLambdaExpression && + PsiTreeUtil.isAncestor(PsiTreeUtil.getParentOfType(myCodeFragment, PsiClass.class), codeFragment, false))) { return null; } return (PsiVariable)refElement; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java deleted file mode 100644 index fa0a470e65f7..000000000000 --- a/java/java-psi-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.psi.impl; - -import com.intellij.psi.CommonClassNames; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.util.PsiSuperMethodUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -public class FindSuperElementsHelper { - @Nullable - public static PsiElement[] findSuperElements(@NotNull PsiElement element) { - if (element instanceof PsiClass) { - PsiClass aClass = (PsiClass) element; - List allSupers = new ArrayList(Arrays.asList(aClass.getSupers())); - for (Iterator iterator = allSupers.iterator(); iterator.hasNext();) { - PsiClass superClass = iterator.next(); - if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) iterator.remove(); - } - return allSupers.toArray(new PsiClass[allSupers.size()]); - } else if (element instanceof PsiMethod) { - PsiMethod method = (PsiMethod) element; - if (method.isConstructor()) { - PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method); - if (constructorInSuper != null) { - return new PsiMethod[]{constructorInSuper}; - } - } else { - return method.findSuperMethods(false); - } - } - return null; - } - -} diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReceiverParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReceiverParameterImpl.java index eb26691f059d..05cbfa82c136 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReceiverParameterImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReceiverParameterImpl.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.impl.source; -import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.impl.source.tree.JavaElementType; @@ -30,6 +29,11 @@ public class PsiReceiverParameterImpl extends CompositePsiElement implements Psi super(JavaElementType.RECEIVER_PARAMETER); } + @NotNull + public PsiThisExpression getIdentifier() { + return PsiTreeUtil.getRequiredChildOfType(this, PsiThisExpression.class); + } + @Nullable @Override public PsiModifierList getModifierList() { @@ -100,13 +104,6 @@ public class PsiReceiverParameterImpl extends CompositePsiElement implements Psi return getIdentifier().getTextOffset(); } - @NotNull - private PsiElement getIdentifier() { - ASTNode node = findChildByType(JavaTokenType.THIS_KEYWORD); - assert node != null : getChildren(); - return node.getPsi(); - } - @Override public String toString() { return "PsiReceiverParameter"; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java index de0aaf4d912f..4609b7844a7c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java @@ -227,6 +227,19 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm psiSubstitutor = TypeConversionUtil.getClassSubstitutor(qContainingClass, paramClass, resolveResult.getSubstitutor()); LOG.assertTrue(psiSubstitutor != null); } + else if (member instanceof PsiMethod && ((PsiMethod)member).isConstructor() || member instanceof PsiClass) { + //15.13.1 + //If ClassType is a raw type, but is not a non-static member type of a raw type, + //the candidate notional member methods are those specified in §15.9.3 for a class instance creation expression that uses <> + //to elide the type arguments to a class. + final PsiResolveHelper helper = JavaPsiFacade.getInstance(myExpression.getProject()).getResolveHelper(); + final PsiType[] paramTypes = + member instanceof PsiMethod ? ((PsiMethod)member).getSignature(PsiSubstitutor.EMPTY).getParameterTypes() : PsiType.EMPTY_ARRAY; + psiSubstitutor = helper.inferTypeArguments(qContainingClass.getTypeParameters(), + paramTypes, + signature.getParameterTypes(), + PsiUtil.getLanguageLevel(myExpression)); + } else { psiSubstitutor = PsiSubstitutor.EMPTY; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java index 20d504d8dbae..cb7fbea9ff4c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.source.Constants; -import com.intellij.psi.impl.source.tree.ChildRole; -import com.intellij.psi.impl.source.tree.CompositeElement; -import com.intellij.psi.impl.source.tree.JavaSourceUtil; -import com.intellij.psi.impl.source.tree.TreeElement; +import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.ChildRoleBase; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; @@ -32,7 +29,8 @@ import org.jetbrains.annotations.Nullable; public class ParameterListElement extends CompositeElement implements Constants { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ParameterListElement"); - private static final TokenSet PARAMETER_SET = TokenSet.create(PARAMETER); + + private static final TokenSet PARAMETER_SET = TokenSet.create(JavaElementType.PARAMETER, JavaElementType.RECEIVER_PARAMETER); public ParameterListElement() { super(PARAMETER_LIST); @@ -50,8 +48,10 @@ public class ParameterListElement extends CompositeElement implements Constants before = Boolean.FALSE; } } + TreeElement firstAdded = super.addInternal(first, last, anchor, before); - if (first == last && first.getElementType() == PARAMETER) { + + if (first == last && PARAMETER_SET.contains(first.getElementType())) { JavaSourceUtil.addSeparatingComma(this, first, PARAMETER_SET); } @@ -69,9 +69,11 @@ public class ParameterListElement extends CompositeElement implements Constants public void deleteChildInternal(@NotNull ASTNode child) { final TreeElement oldLastNodeInsideParens = getLastNodeInsideParens(); final TreeElement oldFirstNodeInsideParens = getFirstNodeInsideParens(); - if (child.getElementType() == PARAMETER) { + + if (PARAMETER_SET.contains(child.getElementType())) { JavaSourceUtil.deleteSeparatingComma(this, child); } + super.deleteChildInternal(child); // We may want to fix trailing white space processing here - there is a following possible case: @@ -79,10 +81,11 @@ public class ParameterListElement extends CompositeElement implements Constants // *) 'arg2' is to be removed; // We don't want to keep trailing white space then TreeElement newLastNodeInsideParens = getLastNodeInsideParens(); - if (newLastNodeInsideParens != null && newLastNodeInsideParens.getElementType() == WHITE_SPACE) { + if (newLastNodeInsideParens != null && oldLastNodeInsideParens != null && newLastNodeInsideParens.getElementType() == WHITE_SPACE) { if (oldLastNodeInsideParens.getElementType() != WHITE_SPACE) { deleteChildInternal(newLastNodeInsideParens); - } else { + } + else { replaceChild(newLastNodeInsideParens, (ASTNode)oldLastNodeInsideParens.clone()); } } @@ -91,7 +94,8 @@ public class ParameterListElement extends CompositeElement implements Constants if (newFirstNodeInsideParens != null && newFirstNodeInsideParens.getElementType() == WHITE_SPACE) { if (oldFirstNodeInsideParens == null || oldFirstNodeInsideParens.getElementType() != WHITE_SPACE) { deleteChildInternal(newFirstNodeInsideParens); - } else { + } + else { replaceChild(newFirstNodeInsideParens, (ASTNode)oldFirstNodeInsideParens.clone()); } } @@ -126,7 +130,7 @@ public class ParameterListElement extends CompositeElement implements Constants public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); IElementType i = child.getElementType(); - if (i == PARAMETER) { + if (PARAMETER_SET.contains((i))) { return ChildRole.PARAMETER; } else if (i == COMMA) { @@ -144,7 +148,7 @@ public class ParameterListElement extends CompositeElement implements Constants } /** - * @return last node before closing right paren if possible; null otherwise + * @return last node before closing right parenthesis if possible; null otherwise */ @Nullable private TreeElement getLastNodeInsideParens() { @@ -152,8 +156,8 @@ public class ParameterListElement extends CompositeElement implements Constants return lastNode.getElementType() == RPARENTH ? lastNode.getTreePrev() : null; } - /** - * @return first node after opening left paren if possible; null otherwise + /** + * @return first node after opening left parenthesis if possible; null otherwise */ @Nullable private TreeElement getFirstNodeInsideParens() { diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index ffee2225b402..eee3b65ce7b1 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -30,6 +30,12 @@ annotation.non.repeatable=The declaration of ''{0}'' does not have a valid java. annotation.container.wrong.place=Container annotation ''{0}'' must not be present at the same time as the element it contains annotation.container.not.applicable=Container annotation ''@{0}'' is not applicable to {1} +receiver.wrong.context=Receivers are not allowed outside of method parameter list +receiver.static.context=The receiver cannot be used in a static context +receiver.wrong.position=The receiver should be the first parameter +receiver.type.mismatch=The receiver type does not match the enclosing class type +receiver.name.mismatch=The receiver name does not match the enclosing class type + # These aren't unused. # suppress inspection "UnusedProperty" annotation.target.ANNOTATION_TYPE=annotation type @@ -388,5 +394,6 @@ feature.extension.methods=Extension methods feature.method.references=Method references feature.lambda.expressions=Lambda expressions feature.type.annotations=Type annotations +feature.type.receivers=Receiver parameters insufficient.language.level={0} are not supported at this language level bad.qualifier.in.super.method.reference=Bad type qualifier in default super call: redundant interface {0} is extended by {1} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java index 168b31bcf55a..19228d9efebc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - import java.io.*; import java.util.*; @@ -47,6 +31,8 @@ class UnsupportedFeatures { } } + void f(Object this) { } + interface I { default void m() { } static void m() { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/invalidPackageAnnotationTarget/package-info.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/package-info.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/invalidPackageAnnotationTarget/package-info.java rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/package-info.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/packageAnnotationNotInPackageInfo/notPackageInfo.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/packageAnnotationNotInPackageInfo.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/packageAnnotationNotInPackageInfo/notPackageInfo.java rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/packageAnnotationNotInPackageInfo.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java new file mode 100644 index 000000000000..8bebd698486f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java @@ -0,0 +1,47 @@ +import java.lang.annotation.*; + +@interface A { } + +@Target(ElementType.TYPE_USE) +@interface TA { } + +class C { + @Override + public String toString(@TA C this) { return ""; } + + @Override + public boolean equals(@TA C this, @TA Object other) { return false; } + + @interface Anno { String f(Anno this); } + + void m0() { + try (Object this) { } + Runnable r = (C C.this) -> { }; + } + + void m1a(final C this) { } + void m1b(@A C this) { } + + void m2(@TA Object other, @TA C this) { } + + void m3a(@TA Object this) { } + void m3b(@TA int this) { } + + void m4a(C C.this) { } + void m4b(C C.X.this) { } + + static void sm1(@TA Object this) { } + + C(C this) { } + + static class X { + X(X this) { } + } + + class B { + B(C C.this) { } + B(B C.this, int p) { } + B(C B.this, long p) { } + B(C this, float p) { } + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java index c1fbcaf07cd6..5c000c2366dc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java @@ -130,19 +130,4 @@ class Outer { IntFunction f = Outer.@TA This.super::getField; } } - - //todo[r.sh] - /*public String toString(@TA C this) { return ""; } - - public boolean equals(@TA C this, @TA C other) { return false; } - - C(@TA C this, boolean b) { } - - class Outer { - class Middle { - class Inner { - void innerMethod(@TA Outer.@TA Middle.@TA Inner this) { } - } - } - }*/ } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RawClassTypeOnConstructorReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RawClassTypeOnConstructorReference.java new file mode 100644 index 000000000000..f72da3d1aaa2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RawClassTypeOnConstructorReference.java @@ -0,0 +1,6 @@ +import java.util.*; +class Test { + public Optional> foo(Optional> args) { + return args.map(HashSet::new).map(Collections::unmodifiableSet); + } +} diff --git a/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java new file mode 100644 index 000000000000..8c4289162396 --- /dev/null +++ b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java @@ -0,0 +1,11 @@ +package z; + +interface I { + void run(); +} +abstract class A { + public void run() {} +} + +class Foo extends A implements I { +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java new file mode 100644 index 000000000000..d8d3e2970a93 --- /dev/null +++ b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java @@ -0,0 +1,11 @@ +package z; + +interface I { + void run(); +} +abstract class A { + public void run() {} +} + +class Foo extends A implements I { +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsVariable/test.java b/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsVariable/test.java new file mode 100644 index 000000000000..45623b513bb0 --- /dev/null +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsVariable/test.java @@ -0,0 +1,24 @@ +import com.google.common.collect.Iterables; +import com.google.common.base.Function; + +import java.lang.String; +import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; + +class c { + void m() { + final Function function = (Function)new Function() { + @Override + public String apply(String input) { + Collectors c; + ArrayList l; + System.out.println(input); + //do something + int i = 1; + return input; + } + }; + Iterables.transform(Collections.emptyList(), function); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsVariable/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsVariable/test_after.java new file mode 100644 index 000000000000..565693317f6a --- /dev/null +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsVariable/test_after.java @@ -0,0 +1,24 @@ +import com.google.common.collect.Iterables; +import com.google.common.base.Function; + +import java.lang.String; +import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; + +class c { + void m() { + final Function function = (Function)new Function() { + @Override + public String apply(String input) { + Collectors c; + ArrayList l; + System.out.println(input); + //do something + int i = 1; + return input; + } + }; + Collections.emptyList().stream().map(function::apply).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsntAnonymous/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsntAnonymous/test_after.java index 82652edb89d4..46d0c8963f26 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsntAnonymous/test_after.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/lambdaIsntAnonymous/test_after.java @@ -6,13 +6,13 @@ import java.util.Collections; class c { void m() { - Collections.emptyList().stream().allMatch(getPredicate(100)); + Collections.emptyList().stream().allMatch(getPredicate(100)::apply); } - public java.util.function.Predicate getPredicate(final int param) { - return new java.util.function.Predicate() { + public Predicate getPredicate(final int param) { + return new Predicate() { @Override - public boolean test(String input) { + public boolean apply(String input) { System.out.println("lambda param " + param); return false; } diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test.java b/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test.java index 659f81f7be23..78cff8625ae8 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test.java @@ -6,9 +6,9 @@ import java.util.Collections; class c { void m() { - Iterables.find(Collections.emptyList(), new Predicate() { + Iterables.find(Collections.emptyList(), new Predicate() { @Override - public boolean apply(Object input) { + public boolean apply(String input) { return true; } }); diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test_after.java index db6dff003227..9e43e688a5c6 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test_after.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/simpleFind/test_after.java @@ -6,6 +6,6 @@ import java.util.Collections; class c { void m() { - Collections.emptyList().stream().filter(input -> true).findFirst().get(); + Collections.emptyList().stream().filter(input -> true).findFirst().get(); } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/simpleTransform/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/simpleTransform/test_after.java index 452f94d0f295..a5a23c03188d 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/simpleTransform/test_after.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/simpleTransform/test_after.java @@ -8,7 +8,7 @@ import java.util.stream.Collectors; class c { void m() { - Collections.emptyList().stream().map(input -> { + Collections.emptyList().stream().map(input -> { Collectors c; ArrayList l; System.out.println(input); diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test.java b/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test.java index cc8ef8ab6ddb..a738f169647d 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test.java @@ -13,7 +13,7 @@ class c { System.out.println(input); //do something int i = 1; - return input; + return input.intern(); } }); } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test_after.java index bf6d86ece3a8..56aa7a1c44a9 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test_after.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/transformLambda/test_after.java @@ -12,6 +12,6 @@ class c { System.out.println(input); //do something int i = 1; - return input; + return input.intern(); }).collect(Collectors.toList()); } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test.java b/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test.java index addd4facbcf6..1f114dcb0fc0 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test.java @@ -1,17 +1,21 @@ import com.google.common.collect.Iterables; import com.google.common.base.Function; +import java.lang.Iterable; import java.lang.String; +import java.util.ArrayList; import java.util.Collections; class c { void m() { - Iterables.transform(new ArrayList<>(), getFunction()) + Iterable trnsfrmd = Iterables.transform(new ArrayList<>(), getFunction()); } Function getFunction() { return new Function() { - + String apply(String s) { + return s.toString().toLowerCase().replace('c', 'h'); + } } } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test_after.java index 452f94d0f295..52ae999287e4 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test_after.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodCalling/test_after.java @@ -1,6 +1,7 @@ import com.google.common.collect.Iterables; import com.google.common.base.Function; +import java.lang.Iterable; import java.lang.String; import java.util.ArrayList; import java.util.Collections; @@ -8,13 +9,14 @@ import java.util.stream.Collectors; class c { void m() { - Collections.emptyList().stream().map(input -> { - Collectors c; - ArrayList l; - System.out.println(input); - //do something - int i = 1; - return input; - }).collect(Collectors.toList()) + Iterable trnsfrmd = new ArrayList().stream().map(getFunction()::apply).collect(Collectors.toList()); + } + + Function getFunction() { + return new Function() { + String apply(String s) { + return s.toString().toLowerCase().replace('c', 'h'); + } + } } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodRef/test_after.java b/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodRef/test_after.java index 452f94d0f295..a5a23c03188d 100644 --- a/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodRef/test_after.java +++ b/java/java-tests/testData/inspection/lambdaLibsStatic/transformMethodRef/test_after.java @@ -8,7 +8,7 @@ import java.util.stream.Collectors; class c { void m() { - Collections.emptyList().stream().map(input -> { + Collections.emptyList().stream().map(input -> { Collectors c; ArrayList l; System.out.println(input); diff --git a/java/java-tests/testData/psi/parser-partial/declarations/Receiver.txt b/java/java-tests/testData/psi/parser-partial/declarations/Receiver.txt new file mode 100644 index 000000000000..aa0e63c9ee3e --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/declarations/Receiver.txt @@ -0,0 +1,178 @@ +PsiJavaFile:Receiver.java + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiMethod:m1 + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:void + PsiKeyword:void('void') + PsiWhiteSpace(' ') + PsiIdentifier:m1('m1') + PsiParameterList:(C this) + PsiJavaToken:LPARENTH('(') + PsiReceiverParameter + PsiModifierList: + + PsiTypeElement:C + PsiJavaCodeReferenceElement:C + PsiIdentifier:C('C') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiThisExpression:this + PsiReferenceParameterList + + PsiKeyword:this('this') + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiMethod:m2 + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:void + PsiKeyword:void('void') + PsiWhiteSpace(' ') + PsiIdentifier:m2('m2') + PsiParameterList:(T T.this) + PsiJavaToken:LPARENTH('(') + PsiReceiverParameter + PsiModifierList: + + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiThisExpression:T.this + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiKeyword:this('this') + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiMethod:m3 + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:void + PsiKeyword:void('void') + PsiWhiteSpace(' ') + PsiIdentifier:m3('m3') + PsiParameterList:(X Y.Z) + PsiJavaToken:LPARENTH('(') + PsiParameter:Y + PsiModifierList: + + PsiTypeElement:X + PsiJavaCodeReferenceElement:X + PsiIdentifier:X('X') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:Y('Y') + PsiErrorElement:',' expected + PsiJavaToken:DOT('.') + PsiJavaCodeReferenceElement:Z + PsiIdentifier:Z('Z') + PsiReferenceParameterList + + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiField:f1 + PsiModifierList: + + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:f1('f1') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLambdaExpression:(T this) -> { } + PsiParameterList:(T this) + PsiJavaToken:LPARENTH('(') + PsiReceiverParameter + PsiModifierList: + + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiThisExpression:this + PsiReferenceParameterList + + PsiKeyword:this('this') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiField:f2 + PsiModifierList: + + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:f2('f2') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLambdaExpression:(T T.this) -> { } + PsiParameterList:(T T.this) + PsiJavaToken:LPARENTH('(') + PsiReceiverParameter + PsiModifierList: + + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiThisExpression:T.this + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiKeyword:this('this') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/FromLambdaBodyToToplevelInsideCodeBlock.java b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBodyToToplevelInsideCodeBlock.java new file mode 100644 index 000000000000..8fd33244505f --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBodyToToplevelInsideCodeBlock.java @@ -0,0 +1,9 @@ +class Test { + void foo(Object o) { + try { + Runnable r = () -> { + System.out.println(o); + }; + } catch (Throwable e) {} + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/FromLambdaBodyToToplevelInsideCodeBlock_after.java b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBodyToToplevelInsideCodeBlock_after.java new file mode 100644 index 000000000000..bd272305fece --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBodyToToplevelInsideCodeBlock_after.java @@ -0,0 +1,13 @@ +class Test { + void foo(Object o) { + try { + Runnable r = () -> { + newMethod(o); + }; + } catch (Throwable e) {} + } + + private void newMethod(Object o) { + System.out.println(o); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java index 3c1ffcd055ef..c0cf9a49f3e0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java @@ -23,40 +23,40 @@ import com.intellij.pom.java.LanguageLevel; public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase { private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/annotations"; - public void testWrongPlace() { doTest(false); } - public void testNotValueNameOmitted() { doTest(false); } - public void testCannotFindMethod() { doTest(false); } - public void testIncompatibleType1() { doTest(false); } - public void testIncompatibleType2() { doTest(false); } - public void testIncompatibleType3() { doTest(false); } - public void testIncompatibleType4() { doTest(false); } - public void testIncompatibleType5() { doTest(false); } - public void testMissingAttribute() { doTest(false); } - public void testDuplicateAnnotation() { doTest(false); } - public void testNonConstantInitializer() { doTest(false); } - public void testInvalidType() { doTest(false); } - public void testInapplicable() { doTest(false); } - public void testDuplicateAttribute() { doTest(false); } - public void testDuplicateTarget() { doTest(false); } - public void testPingPongAnnotationTypesDependencies() { doTest(false); } - public void testClashMethods() { doTest(false); } - public void testDupMethods() { doTest(false); } - public void testPrivateInaccessibleConstant() { doTest(false); } + public void testWrongPlace() { doTest(); } + public void testNotValueNameOmitted() { doTest(); } + public void testCannotFindMethod() { doTest(); } + public void testIncompatibleType1() { doTest(); } + public void testIncompatibleType2() { doTest(); } + public void testIncompatibleType3() { doTest(); } + public void testIncompatibleType4() { doTest(); } + public void testIncompatibleType5() { doTest(); } + public void testMissingAttribute() { doTest(); } + public void testDuplicateAnnotation() { doTest(); } + public void testNonConstantInitializer() { doTest(); } + public void testInvalidType() { doTest(); } + public void testInapplicable() { doTest(); } + public void testDuplicateAttribute() { doTest(); } + public void testDuplicateTarget() { doTest(); } + public void testPingPongAnnotationTypesDependencies() { doTest(); } + public void testClashMethods() { doTest(); } + public void testDupMethods() { doTest(); } + public void testPrivateInaccessibleConstant() { doTest(); } + public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/package-info.java", false, false); } + public void testPackageAnnotationNotInPackageInfo() { doTest(); } - public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/" + getTestName(true) + "/package-info.java", false, false); } - public void testPackageAnnotationNotInPackageInfo() { doTest(BASE_PATH + "/" + getTestName(true) + "/notPackageInfo.java", false, false); } + public void testTypeAnnotations() { doTest8(); } + public void testRepeatable() { doTest8(); } + public void testEnumValues() { doTest8(); } + public void testReceiverParameters() { doTest8(); } - public void testTypeAnnotations() { doTest8(false); } - public void testRepeatable() { doTest8(false); } - public void testEnumValues() { doTest8(false); } - - private void doTest(boolean checkWarnings) { + private void doTest() { setLanguageLevel(LanguageLevel.JDK_1_7); - doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false); + doTest(BASE_PATH + "/" + getTestName(true) + ".java", false, false); } - private void doTest8(boolean checkWarnings) { + private void doTest8() { setLanguageLevel(LanguageLevel.JDK_1_8); - doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false); + doTest(BASE_PATH + "/" + getTestName(true) + ".java", false, false); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java similarity index 51% rename from java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java rename to java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java index e666583564b0..1a04900bc371 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java @@ -13,20 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.navigation; +package com.intellij.codeInsight.daemon.impl; import com.intellij.JavaTestUtil; import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.codeInsight.daemon.LineMarkerInfo; -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; +import com.intellij.ide.DataManager; import com.intellij.lang.CodeInsightActions; import com.intellij.lang.java.JavaLanguage; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.actionSystem.Shortcut; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Document; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -38,7 +39,7 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { return JavaTestUtil.getJavaTestDataPath(); } - protected String getBasePath() { + private static String getBasePath() { return "/codeInsight/gotosuper/"; } @@ -46,6 +47,13 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { doTest(); } + private void doTest() { + configureByFile(getBasePath() + getTestName(false) + ".java"); + final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE); + handler.invoke(getProject(), getEditor(), getFile()); + checkResultByFile(getBasePath() + getTestName(false) + ".after.java"); + } + public void testLambdaMarker() throws Exception { configureByFile(getBasePath() + getTestName(false) + ".java"); int offset = myEditor.getCaretModel().getOffset(); @@ -67,10 +75,52 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { fail("Gutter expected"); } - private void doTest() throws Throwable { - configureByFile(getBasePath() + getTestName(false) + ".java"); - final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE); - handler.invoke(getProject(), getEditor(), getFile()); - checkResultByFile(getBasePath() + getTestName(false) + ".after.java"); + public void testSiblingInheritance() throws Throwable { + doTest(); } + + public void testSiblingInheritanceLineMarkers() throws Throwable { + configureByFile(getBasePath() + "SiblingInheritance.java"); + PsiJavaFile file = (PsiJavaFile)getFile(); + PsiClass i = JavaPsiFacade.getInstance(getProject()).findClass("z.I", GlobalSearchScope.fileScope(file)); + PsiClass a = JavaPsiFacade.getInstance(getProject()).findClass("z.A", GlobalSearchScope.fileScope(file)); + PsiMethod iRun = i.getMethods()[0]; + assertEquals("run", iRun.getName()); + PsiMethod aRun = a.getMethods()[0]; + assertEquals("run", aRun.getName()); + doHighlighting(); + Document document = getEditor().getDocument(); + List markers = DaemonCodeAnalyzerImpl.getLineMarkers(document, getProject()); + assertTrue(markers.size() >= 2); + LineMarkerInfo iMarker = findMarkerWithElement(markers, iRun.getNameIdentifier()); + assertSame(MarkerType.OVERRIDDEN_METHOD.getNavigationHandler(), iMarker.getNavigationHandler()); + + LineMarkerInfo aMarker = findMarkerWithElement(markers, aRun.getNameIdentifier()); + assertSame(MarkerType.OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler()); + } + + private static LineMarkerInfo findMarkerWithElement(List markers, PsiElement psiMethod) { + LineMarkerInfo marker = ContainerUtil.find(markers, info -> { + return info.getElement().equals(psiMethod); + }); + assertNotNull(markers.toString(), marker); + return marker; + } + + public void testSiblingInheritanceGoDown() throws Throwable { + configureByFile(getBasePath() + "SiblingInheritance.after.java"); + AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_GOTO_IMPLEMENTATION); + AnActionEvent event = new AnActionEvent( + null, + DataManager.getInstance().getDataContextFromFocus().getResultSync(), + "", + action.getTemplatePresentation(), + ActionManager.getInstance(), + 0); + action.update(event); + assertTrue(event.getPresentation().isEnabledAndVisible()); + action.actionPerformed(event); + checkResultByFile(getBasePath() + "SiblingInheritance.java"); + } + } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 94d0a6427790..05e475a286a7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -414,6 +414,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testRawClassTypeOnConstructorReference() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/StaticPseudoFunctionalStyleMethodTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/StaticPseudoFunctionalStyleMethodTest.java index 098f85b1561f..c0d143200447 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/StaticPseudoFunctionalStyleMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/StaticPseudoFunctionalStyleMethodTest.java @@ -96,11 +96,11 @@ public class StaticPseudoFunctionalStyleMethodTest extends JavaCodeInsightFixtur doTest(); } - public void _testTransformLambda() { + public void testTransformLambda() { doTest(); } - public void _testTransformMethodCalling() { + public void testTransformMethodCalling() { doTest(); } @@ -108,6 +108,10 @@ public class StaticPseudoFunctionalStyleMethodTest extends JavaCodeInsightFixtur doTest(); } + public void testLambdaIsVariable() { + doTest(); + } + public void _testReplaceWithMethodReference() { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java index 629f102de77d..847dc0f64d64 100644 --- a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java +++ b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java @@ -131,7 +131,7 @@ public class RunConfigurableTest extends LightIdeaTestCase { private void doExpand() { List toExpand = new ArrayList(); RunConfigurable.collectNodesRecursively(myRoot, toExpand, FOLDER); - assertEquals(toExpand.size(), 5); + assertEquals(5, toExpand.size()); List toExpand2 = new ArrayList(); RunConfigurable.collectNodesRecursively(myRoot, toExpand2, CONFIGURATION_TYPE); toExpand.addAll(toExpand2); diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 1fa5ce12b7f9..4cf9e14247f8 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -461,6 +461,10 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { assertEquals(text+"\n", getEditor().getDocument().getText()); } + public void testReplaceWithRegExp() { + doTestRegexpReplace("# Base", "(? { diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java index c51da086ce46..a1a05c6dc9fb 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.lang.java.parser.partial; -import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParsingTestCase; @@ -36,14 +35,7 @@ public class AnnotationParserTest extends JavaParsingTestCase { public void testParameterizedAnnotation () { doParserTest("@Nullable"); } public void testFirstNameMissed() { doParserTest("@Anno(value1, param2=value2)"); } - private void doParserTest(final String text) { - doParserTest(text, new MyTestParser()); + private void doParserTest(String text) { + doParserTest(text, builder -> JavaParser.INSTANCE.getDeclarationParser().parseAnnotations(builder)); } - - private static class MyTestParser implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getDeclarationParser().parseAnnotations(builder); - } - } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java index 960417707dda..f83475c23437 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java @@ -15,7 +15,6 @@ */ package com.intellij.lang.java.parser.partial; -import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParsingTestCase; @@ -34,19 +33,12 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testPines() { doParserTest("{ class A> extends List> { } }"); } public void testIncompleteAnnotation() { doParserTest("{ public class Foo { public void testSomething(); @Null } }"); } public void testClassInit() { doParserTest("{ { /*comment*/ } }"); } - public void testAnnoDeclaration() { doParserTest("{ public @interface Annotation {} }"); } - public void testEnumSmartTypeCompletion() { doParserTest("{ @Preliminary(A.B\n#) public class TimeTravel {}\n" + - " @Preliminary(a=A.B\n#) public class TimeTravel {}\n" + - " @Preliminary(a=A.B\n#, b=c) public class TimeTravel {} }"); } - public void testTypeAnno() { - doParserTest("{ class C<@D T extends @F Object> extends @F Object {\n" + - " @F int @F[] method() throws @F Exception {\n" + - " a = this instanceof @F C;\n" + - " C<@F @G C> c = new @Q C<@F C>();\n" + - " c = (@F Object)c;\n" + - " Class c = @TA String.class;\n" + - " @F C.field++;\n" + - " }\n} }"); + + public void testEnumSmartTypeCompletion() { + doParserTest( + "{ @Preliminary(A.B\n#) public class TimeTravel {}\n" + + " @Preliminary(a=A.B\n#) public class TimeTravel {}\n" + + " @Preliminary(a=A.B\n#, b=c) public class TimeTravel {} }"); } public void testEnumBody0() { doParserTest("{ ; }", false, true); } @@ -59,6 +51,7 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testEnumWithInitializedConstants() { doParserTest("{ A(10) { },\n B { void method() {} } }", false, true); } public void testEnumWithoutConstants() { doParserTest("{ private A }", false, true); } + public void testAnnoDeclaration() { doParserTest("{ public @interface Annotation {} }"); } public void testAnnoSimple() { doParserTest("{ int foo (); }", true, false); } public void testAnnoDefault() { doParserTest("{ Class foo() default String.class; }", true, false); } public void testAnnoNested() { doParserTest("{ @interface Inner { String bar () default \"\"; } }", true, false); } @@ -66,6 +59,27 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testAnnoOtherMembers() { doParserTest("{ int field;\n void m() {}\n class C {}\n interface I {} }", true, false); } public void testAnnoLoop() { doParserTest("{ @@@ int i; }"); } + public void testTypeAnno() { + doParserTest( + "{ class C<@D T extends @F Object> extends @F Object {\n" + + " @F int @F[] method() throws @F Exception {\n" + + " a = this instanceof @F C;\n" + + " C<@F @G C> c = new @Q C<@F C>();\n" + + " c = (@F Object)c;\n" + + " Class c = @TA String.class;\n" + + " @F C.field++;\n" + + " }\n} }"); + } + + public void testReceiver() { + doParserTest( + "{ void m1(C this);" + + " void m2(T T.this);" + + " void m3(X Y.Z);" + + " T f1 = (T this) -> { };" + + " T f2 = (T T.this) -> { }; }"); + } + public void testFieldSimple() { doParserTest("{ int field = 0; }"); } public void testFieldMulti() { doParserTest("{ int field1 = 0, field2; }"); } public void testUnclosedBracket() { doParserTest("{ int field[ }"); } @@ -94,9 +108,13 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testConstructorBrackets() { doParserTest("{ A() [] { } }"); } public void testVarArgBrackets() { doParserTest("{ void foo(int... x[]); }"); } - public void testGenericMethod() { doParserTest("{ public static test();\n" + - " void test1();\n" + - " String test2(); }"); } + public void testGenericMethod() { + doParserTest( + "{ public static test();\n" + + " void test1();\n" + + " String test2(); }"); + } + public void testGenericMethodErrors() { doParserTest("{ test (); }"); } public void testErrors() { doParserTest("{ public static protected int f1 = 0; }"); } public void testCompletionHack0() { doParserTest("{ \n String s = \"\"; }"); } @@ -112,21 +130,6 @@ public class DeclarationParserTest extends JavaParsingTestCase { } private void doParserTest(String text, boolean isAnnotation, boolean isEnum) { - doParserTest(text, new MyTestParser(isAnnotation, isEnum)); + doParserTest(text, builder -> JavaParser.INSTANCE.getDeclarationParser().parseClassBodyWithBraces(builder, isAnnotation, isEnum)); } - - private static class MyTestParser implements TestParser { - private final boolean myAnnotation; - private final boolean myAnEnum; - - public MyTestParser(boolean annotation, boolean anEnum) { - myAnnotation = annotation; - myAnEnum = anEnum; - } - - @Override - public void parse(PsiBuilder builder) { - JavaParser.INSTANCE.getDeclarationParser().parseClassBodyWithBraces(builder, myAnnotation, myAnEnum); - } - } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java index 920894619570..8a3f4ebce29b 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java @@ -15,7 +15,6 @@ */ package com.intellij.lang.java.parser.partial; -import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParsingTestCase; @@ -150,13 +149,6 @@ public class ExpressionParserTest extends JavaParsingTestCase { public void testAmbiguousLambdaExpression() { doParserTest("f( (x) < y , z > (w) -> v )"); } private void doParserTest(String text) { - doParserTest(text, new MyTestParser()); + doParserTest(text, builder -> JavaParser.INSTANCE.getExpressionParser().parse(builder)); } - - private static class MyTestParser implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getExpressionParser().parse(builder); - } - } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java index 8b3969273225..daac0014a2f9 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.lang.java.parser.partial; -import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParsingTestCase; @@ -40,14 +39,20 @@ public class FileParserTest extends JavaParsingTestCase { public void testUnclosedImport2() { doParserTest("import java.awt."); } public void testUnclosedImport3() { doParserTest("import static a"); } - public void testExtraSemicolons() { doParserTest("package p;;\n" + - "import a;;\n" + - "class C{};"); } + public void testExtraSemicolons() { + doParserTest( + "package p;;\n" + + "import a;;\n" + + "class C{};"); + } - public void testFileWithClass() { doParserTest("package a;\n" + - "import b;\n" + - "public class C { }\n" + - "class D { }"); } + public void testFileWithClass() { + doParserTest( + "package a;\n" + + "import b;\n" + + "public class C { }\n" + + "class D { }"); + } public void testBindBefore0() { doParserTest("class A{\n // comment\n int field;\n}"); } public void testBindBefore1() { doParserTest("class A{\n // comment\n\n int field;\n}"); } @@ -61,14 +66,7 @@ public class FileParserTest extends JavaParsingTestCase { public void testBindDocComment3() { doParserTest("class A {\n /** field comment */\n int f;\n}"); } public void testBindDocComment4() { doParserTest("class A {\n /** field comment */\n// field comment\n int f;\n}"); } - private void doParserTest(final String text) { - doParserTest(text, new MyTestParser()); + private void doParserTest(String text) { + doParserTest(text, builder -> JavaParser.INSTANCE.getFileParser().parse(builder)); } - - private static class MyTestParser implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getFileParser().parse(builder); - } - } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java index 555d166e13bf..50b9a634cc33 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.lang.java.parser.partial; -import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParsingTestCase; import com.intellij.lang.java.parser.ReferenceParser; @@ -56,39 +55,16 @@ public class ReferenceParserTest extends JavaParsingTestCase { doTypeParamsParserTest(""); } - private void doRefParserTest(final String text, final boolean incomplete) { - doParserTest(text, new MyTestParser(incomplete)); - } - private static class MyTestParser implements TestParser { - private final boolean myIncomplete; - - public MyTestParser(boolean incomplete) { - myIncomplete = incomplete; - } - - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, myIncomplete, false, false, false); - } + private void doRefParserTest(String text, boolean incomplete) { + doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, incomplete, false, false, false)); } - private void doTypeParserTest(final String text) { - doParserTest(text, new MyTestParser2()); - } - private static class MyTestParser2 implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getReferenceParser().parseType(builder, ReferenceParser.ELLIPSIS | ReferenceParser.DIAMONDS | ReferenceParser.DISJUNCTIONS); - } + private void doTypeParserTest(String text) { + int flags = ReferenceParser.ELLIPSIS | ReferenceParser.DIAMONDS | ReferenceParser.DISJUNCTIONS; + doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseType(builder, flags)); } - private void doTypeParamsParserTest(final String text) { - doParserTest(text, new MyTestParser3()); + private void doTypeParamsParserTest(String text) { + doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseTypeParameters(builder)); } - private static class MyTestParser3 implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getReferenceParser().parseTypeParameters(builder); - } - } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java index e322261fba38..eb70bb346f92 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.lang.java.parser.partial; -import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParsingTestCase; @@ -148,23 +147,11 @@ public class StatementParserTest extends JavaParsingTestCase { public void testWhileIncomplete4() { doParserTest("while(cond)"); } public void testWhileIncomplete5() { doParserTest("while() foo();"); } - private void doBlockParserTest(final String text) { - doParserTest(text, new MyBlockTestParser()); - } - private static class MyBlockTestParser implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true); - } + private void doBlockParserTest(String text) { + doParserTest(text, builder -> JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true)); } - private void doParserTest(final String text) { - doParserTest(text, new MyStatementsTestParser()); + private void doParserTest(String text) { + doParserTest(text, builder -> JavaParser.INSTANCE.getStatementParser().parseStatements(builder)); } - private static class MyStatementsTestParser implements TestParser { - @Override - public void parse(final PsiBuilder builder) { - JavaParser.INSTANCE.getStatementParser().parseStatements(builder); - } - } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java b/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java index f9c585556f24..a11e941d31ec 100644 --- a/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java @@ -371,7 +371,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase { "\n" + "class C<@A T extends @A C> implements @A I<@A T> {\n" + " @TA T<@A T1, @A ? extends @A T2> f;\n" + - " @TA T m(/*@A C this,*/ @TA int p) throws @A E {\n" + + " @TA T m(@A C this, @TA int p) throws @A E {\n" + " o.<@A1 C>m();\n" + " new @A2 C();\n" + " C.@A3 B v = (@A4 C)v.new @A5 C();\n" + diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/IdCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/IdCacheTest.java index 34a66d93c262..a1c4fbba4a23 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/IdCacheTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/IdCacheTest.java @@ -27,13 +27,13 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.cache.CacheManager; import com.intellij.psi.impl.cache.TodoCacheManager; -import com.intellij.psi.impl.cache.impl.id.IdIndex; -import com.intellij.psi.impl.cache.impl.todo.TodoIndex; -import com.intellij.psi.search.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.TodoAttributesUtil; +import com.intellij.psi.search.TodoPattern; +import com.intellij.psi.search.UsageSearchContext; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.indexing.FileBasedIndex; import java.io.File; import java.util.Arrays; @@ -48,9 +48,6 @@ public class IdCacheTest extends CodeInsightTestCase{ protected void setUp() throws Exception { super.setUp(); - FileBasedIndex.getInstance().requestRebuild(IdIndex.NAME); - FileBasedIndex.getInstance().requestRebuild(TodoIndex.NAME); - String root = JavaTestUtil.getJavaTestDataPath()+ "/psi/impl/cache/"; PsiTestUtil.removeAllRoots(myModule, IdeaTestUtil.getMockJdk17()); diff --git a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java index 3a4f928505e7..14830b0a7402 100644 --- a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java @@ -34,7 +34,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.JavaPsiFacadeEx; import com.intellij.psi.impl.PsiManagerImpl; -import com.intellij.psi.impl.cache.impl.id.IdIndex; import com.intellij.psi.impl.cache.impl.todo.TodoIndex; import com.intellij.psi.impl.cache.impl.todo.TodoIndexEntry; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; @@ -52,15 +51,7 @@ import java.io.File; import java.util.*; @PlatformTestCase.WrapInCommand -public class UpdateCacheTest extends PsiTestCase{ - @Override - protected void setUp() throws Exception { - super.setUp(); - - FileBasedIndex.getInstance().requestRebuild(IdIndex.NAME); - FileBasedIndex.getInstance().requestRebuild(TodoIndex.NAME); - } - +public class UpdateCacheTest extends PsiTestCase { @Override protected void setUpProject() throws Exception { myProjectManager = ProjectManagerEx.getInstanceEx(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index 6a232ae4b830..47a038460eb7 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -583,6 +583,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { public void testFromLambdaBodyToAnonymous() throws Exception { doTest(); } + + public void testFromLambdaBodyToToplevelInsideCodeBlock() throws Exception { + doTest(); + } public void testFromLambdaBodyWithReturn() throws Exception { doTest(); diff --git a/lib/org/hamcrest/annotations.xml b/lib/org/hamcrest/annotations.xml new file mode 100644 index 000000000000..36d1cf4640d1 --- /dev/null +++ b/lib/org/hamcrest/annotations.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt b/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt index 0c8c4dc5e13f..dbce08860f58 100644 --- a/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt +++ b/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt @@ -1,5 +1,6 @@ package org.jetbrains.ide +import com.intellij.testFramework.FixtureRule import com.intellij.util.Consumer import com.intellij.util.concurrency.Semaphore import com.intellij.util.net.NetUtils diff --git a/platform/built-in-server/testSrc/RestApiTest.kt b/platform/built-in-server/testSrc/RestApiTest.kt index 2f9586857102..223cc0121693 100644 --- a/platform/built-in-server/testSrc/RestApiTest.kt +++ b/platform/built-in-server/testSrc/RestApiTest.kt @@ -1,19 +1,19 @@ package org.jetbrains.ide +import com.google.gson.stream.JsonWriter +import com.intellij.openapi.vfs.CharsetToolkit +import com.intellij.testFramework.FixtureRule import io.netty.handler.codec.http.HttpResponseStatus -import org.junit.Rule -import org.junit.Test -import org.junit.rules.RuleChain - import org.hamcrest.CoreMatchers.equalTo import org.jetbrains.ide.TestManager.TestDescriptor import org.junit.Assert.assertThat -import java.net.URL -import java.net.HttpURLConnection -import com.google.gson.stream.JsonWriter -import java.io.OutputStreamWriter -import com.intellij.openapi.vfs.CharsetToolkit +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain import java.io.BufferedOutputStream +import java.io.OutputStreamWriter +import java.net.HttpURLConnection +import java.net.URL public class RestApiTest { private val fixtureManager = FixtureRule() diff --git a/platform/built-in-server/testSrc/TestManager.kt b/platform/built-in-server/testSrc/TestManager.kt index 50fa6cd3fe84..be3fc2ef57e3 100644 --- a/platform/built-in-server/testSrc/TestManager.kt +++ b/platform/built-in-server/testSrc/TestManager.kt @@ -1,5 +1,7 @@ package org.jetbrains.ide +import com.intellij.openapi.application.invokeAndWaitIfNeed +import com.intellij.openapi.application.writeAction import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.util.io.FileUtilRt @@ -63,10 +65,10 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() { } invokeAndWaitIfNeed { - val normalizedFilePath = FileUtilRt.toSystemIndependentName(filePath) + val normalizedFilePath = FileUtilRt.toSystemIndependentName(filePath!!) if (annotation!!.relativeToProject) { val root = projectFixture.getProject().getBaseDir() - runWriteAction { + writeAction { fileToDelete = root.findOrCreateChildData(this@TestManager, normalizedFilePath) } } @@ -75,7 +77,7 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() { ModuleRootModificationUtil.updateModel(projectFixture.getModule()) { model -> val contentEntry = model.getContentEntries()[0] val contentRoot = contentEntry.getFile()!! - runWriteAction { + writeAction { contentRoot.findChild(EXCLUDED_DIR_NAME)?.delete(this@TestManager) fileToDelete = contentRoot.createChildDirectory(this@TestManager, EXCLUDED_DIR_NAME) fileToDelete!!.createChildData(this@TestManager, normalizedFilePath) @@ -87,7 +89,7 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() { } else { val root = ModuleRootManager.getInstance(projectFixture.getModule()).getSourceRoots()[0] - runWriteAction { + writeAction { fileToDelete = root.findOrCreateChildData(this@TestManager, normalizedFilePath) } } @@ -101,11 +103,11 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() { } if (fileToDelete != null) { - invokeAndWaitIfNeed { runWriteAction { fileToDelete?.delete(this@TestManager) } } + invokeAndWaitIfNeed { writeAction { fileToDelete?.delete(this@TestManager) } } fileToDelete = null } - if (ioFileToDelete != null && !FileUtilRt.delete(ioFileToDelete)) { + if (ioFileToDelete != null && !FileUtilRt.delete(ioFileToDelete!!)) { ioFileToDelete!!.deleteOnExit() } diff --git a/platform/core-api/src/com/intellij/lang/PsiBuilder.java b/platform/core-api/src/com/intellij/lang/PsiBuilder.java index bc6d2eca1c4b..66b4abd44afd 100644 --- a/platform/core-api/src/com/intellij/lang/PsiBuilder.java +++ b/platform/core-api/src/com/intellij/lang/PsiBuilder.java @@ -140,6 +140,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @return the new marker instance. */ + @NotNull Marker precede(); /** @@ -160,7 +161,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @param type the type of the node in the AST tree. */ - void done(IElementType type); + void done(@NotNull IElementType type); /** * Like {@linkplain #done(IElementType)}, but collapses all tokens between start and end markers @@ -168,7 +169,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @param type the type of the node in the AST tree. */ - void collapse(IElementType type); + void collapse(@NotNull IElementType type); /** * Like {@linkplain #done(IElementType)}, but the marker is completed (end marker inserted) @@ -178,7 +179,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * @param type the type of the node in the AST tree. * @param before marker to complete this one before. */ - void doneBefore(IElementType type, Marker before); + void doneBefore(@NotNull IElementType type, @NotNull Marker before); /** * Like {@linkplain #doneBefore(IElementType, Marker)}, but in addition an error element with given text @@ -188,7 +189,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * @param before marker to complete this one before. * @param errorMessage for error element. */ - void doneBefore(IElementType type, Marker before, String errorMessage); + void doneBefore(@NotNull IElementType type, @NotNull Marker before, String errorMessage); /** * Completes this marker and labels it as error element with specified message. Before calling this method, @@ -204,7 +205,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * @param message for error element. * @param before marker to complete this one before. */ - void errorBefore(String message, Marker before); + void errorBefore(String message, @NotNull Marker before); /** * Allows to define custom edge token binders instead of default ones. If any of parameters is null @@ -222,6 +223,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @return the new marker instance. */ + @NotNull Marker mark(); /** diff --git a/platform/core-api/src/com/intellij/lang/PsiParser.java b/platform/core-api/src/com/intellij/lang/PsiParser.java index 0d241bcb50f1..0962ed977ed4 100644 --- a/platform/core-api/src/com/intellij/lang/PsiParser.java +++ b/platform/core-api/src/com/intellij/lang/PsiParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,5 +38,5 @@ public interface PsiParser { * @return the root of the resulting AST tree. */ @NotNull - ASTNode parse(IElementType root, PsiBuilder builder); + ASTNode parse(@NotNull IElementType root, @NotNull PsiBuilder builder); } diff --git a/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java b/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java index 2c24103f954b..7c3eb4070d63 100644 --- a/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java +++ b/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.lang; import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -31,6 +32,7 @@ public interface WhitespacesAndCommentsBinder { * Provides an ability for the processor to get a text of any of given tokens. */ interface TokenTextGetter { + @NotNull CharSequence get(int i); } diff --git a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java index 88f6e37ce838..28844ab00844 100644 --- a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java +++ b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java @@ -46,8 +46,6 @@ public abstract class SchemesManager convertor) { } @@ -69,4 +70,11 @@ public abstract class SchemesManager schemes, @Nullable Condition removeCondition) { } + + /** + * Bundled / read-only (or overriding) scheme cannot be renamed or deleted. + */ + public boolean isMetadataEditable(@NotNull E scheme) { + return true; + } } diff --git a/platform/core-impl/core-impl.iml b/platform/core-impl/core-impl.iml index 6d93fd99a32c..e57a2b6e112a 100644 --- a/platform/core-impl/core-impl.iml +++ b/platform/core-impl/core-impl.iml @@ -11,5 +11,6 @@ + \ No newline at end of file diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index 41d7551234d9..73a0bbb993d8 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -196,15 +196,18 @@ public class PluginManagerCore { if (!plugins.isFile()) { FileUtil.ensureCanCreateFile(plugins); } - PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(plugins, append))); + writePluginsList(ids, new BufferedWriter(new FileWriter(plugins, append))); + } + + public static void writePluginsList(@NotNull Collection ids, @NotNull Writer writer) throws IOException { try { for (String id : ids) { - printWriter.println(id); + writer.write(id); + writer.write(LineSeparator.getSystemLineSeparator().getSeparatorString()); } - printWriter.flush(); } finally { - printWriter.close(); + writer.close(); } } diff --git a/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java b/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java index c28af8b4860b..10b6ae5f9d7d 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java +++ b/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ public abstract class DelegateMarker implements PsiBuilder.Marker { return myDelegate; } + @NotNull @Override public PsiBuilder.Marker precede() { return myDelegate.precede(); @@ -51,22 +52,22 @@ public abstract class DelegateMarker implements PsiBuilder.Marker { } @Override - public void done(IElementType type) { + public void done(@NotNull IElementType type) { myDelegate.done(type); } @Override - public void collapse(IElementType type) { + public void collapse(@NotNull IElementType type) { myDelegate.collapse(type); } @Override - public void doneBefore(IElementType type, PsiBuilder.Marker before) { + public void doneBefore(@NotNull IElementType type, @NotNull PsiBuilder.Marker before) { myDelegate.doneBefore(type, before); } @Override - public void doneBefore(IElementType type, PsiBuilder.Marker before, String errorMessage) { + public void doneBefore(@NotNull IElementType type, @NotNull PsiBuilder.Marker before, String errorMessage) { myDelegate.doneBefore(type, before, errorMessage); } @@ -76,7 +77,7 @@ public abstract class DelegateMarker implements PsiBuilder.Marker { } @Override - public void errorBefore(String message, PsiBuilder.Marker before) { + public void errorBefore(String message, @NotNull PsiBuilder.Marker before) { myDelegate.errorBefore(message, before); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java index b66f8062d42e..9cd3540180b0 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java @@ -101,6 +101,7 @@ public class PsiBuilderAdapter implements PsiBuilder { return myDelegate.getCurrentOffset(); } + @NotNull @Override public Marker mark() { return myDelegate.mark(); diff --git a/platform/core-impl/src/com/intellij/openapi/application/actions.kt b/platform/core-impl/src/com/intellij/openapi/application/actions.kt new file mode 100644 index 000000000000..4be236085b50 --- /dev/null +++ b/platform/core-impl/src/com/intellij/openapi/application/actions.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.application + +import javax.swing.SwingUtilities + +public inline fun writeAction(runnable: () -> Unit) { + val token = WriteAction.start() + try { + runnable() + } + finally { + token.finish() + } +} + +public fun invokeAndWaitIfNeed(runnable: () -> Unit) { + val app = ApplicationManager.getApplication() + if (app == null) { + if (SwingUtilities.isEventDispatchThread()) runnable() else SwingUtilities.invokeAndWait(runnable) + } + else { + if (app.isDispatchThread()) runnable() else app.invokeAndWait(runnable, ModalityState.any()) + } +} diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java deleted file mode 100644 index 2fcd086a2924..000000000000 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java +++ /dev/null @@ -1,705 +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.openapi.editor.impl; - -import com.intellij.diagnostic.Dumpable; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.impl.ApplicationInfoImpl; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.LocalTimeCounter; -import com.intellij.util.text.CharArrayCharSequence; -import com.intellij.util.text.CharArrayUtil; -import com.intellij.util.text.CharSequenceBackedByArray; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * @author cdr - */ -abstract class CharArray implements CharSequenceBackedByArray, Dumpable { - private static final boolean CHECK_DOCUMENT_CONSISTENCY = ApplicationManager.getApplication() != null && ApplicationManager.getApplication().isUnitTestMode(); - private static final Logger LOG = Logger.getInstance("#" + CharArray.class.getName()); - - @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") - private static final boolean DISABLE_DEFERRED_PROCESSING = Boolean.getBoolean("idea.document.deny.deferred.changes"); - - @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") - private static final boolean DEBUG_DEFERRED_PROCESSING = LOG.isDebugEnabled() || Boolean.getBoolean("idea.document.debug.bulk.processing"); - /** - * We can't exclude possibility of situation when 'defer changes' state is {@link #setDeferredChangeMode(boolean) entered} - * but not exited, hence, we want to perform automatic flushing if necessary in order to avoid memory leaks. This constant holds - * a value that defines that 'automatic flushing' criteria, i.e. every time number of stored deferred changes exceeds this value, - * they are automatically flushed. - */ - private static final int MAX_DEFERRED_CHANGES_NUMBER = 10000; - - private final TextChangesStorage myDeferredChangesStorage; - - private volatile int myStart; // start offset in myArray (used as an optimization when call substring()) - private volatile int myCount; - - private volatile CharSequence myOriginalSequence; - private volatile char[] myArray; - private volatile Reference myStringRef; // buffers String value - for not to generate it every time - private volatile int myBufferSize; - private volatile int myDeferredShift; - private volatile boolean myDeferredChangeMode; - private volatile boolean myHasDeferredChanges; - // this lock is for mutual exclusion during read action access - // (some fields are changed in read action too) - private final Object lock = new String("myOriginalSequence"); - - // We had a problems with bulk document text processing, hence, debug facilities were introduced. The fields group below work with them. - // The main idea is to hold all history of bulk processing iteration in order to be able to retrieve it from client and reproduce the - // problem. - - private final boolean myDebug = isDebug(); - - boolean isDebug() { - return DEBUG_DEFERRED_PROCESSING || CHECK_DOCUMENT_CONSISTENCY && !ApplicationInfoImpl.isInPerformanceTest(); - } - - /** - * Duplicate instance of the current char array that is used during debug processing as follows - apply every text change - * from the bulk changes group to this instance immediately in order to be able to check if the current 'deferred change-aware' - * instance functionally behaves at the same way as 'straightforward' one. - */ - private CharArray myDebugArray; - - /** - * Holds deferred changes create during the current bulk processing iteration. - */ - private List myDebugDeferredChanges; - - /** - * Document text on bulk processing start. - */ - private String myDebugTextOnBatchUpdateStart; - - // bufferSize == 0 means unbounded - CharArray(final int bufferSize, @NotNull char[] data, int length) { - myBufferSize = bufferSize; - myDeferredChangesStorage = new TextChangesStorage(); - myArray = Arrays.copyOf(data, length); - myCount = length; - - if (myDebug) { - myDebugArray = new CharArray(bufferSize, data, length) { - @NotNull - @Override - protected DocumentEvent beforeChangedUpdate(int offset, - CharSequence oldString, - CharSequence newString, - boolean wholeTextReplaced) { - return CharArray.this.beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced); - } - - @Override - protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) { - } - - @Override - protected void assertWriteAccess() { - } - - @Override - protected void assertReadAccess() { - } - - @Override - boolean isDebug() { - return false; - } - }; - myDebugDeferredChanges = new ArrayList(); - } - assertConsistency(); - } - - public void setBufferSize(int bufferSize) { - assert bufferSize >= 0 : bufferSize; - myBufferSize = bufferSize; - assertConsistency(); - } - - private DocumentEvent startChange(int offset, - @Nullable CharSequence oldString, - @Nullable CharSequence newString, - boolean wholeTextReplaced) { - assert myStart == 0; // can't change substring - assertWriteAccess(); - assertConsistency(); - - return beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced); - } - - @NotNull - protected abstract DocumentEvent beforeChangedUpdate(int offset, - @Nullable CharSequence oldString, - @Nullable CharSequence newString, - boolean wholeTextReplaced); - protected abstract void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp); - - protected abstract void assertWriteAccess(); - protected abstract void assertReadAccess(); - - private void setText(@NotNull CharSequence chars) { - assertConsistency(); - myOriginalSequence = chars.toString(); - myArray = null; - myStringRef = null; - myCount = chars.length(); - assert myStart == 0; // can't change substring - myDeferredChangesStorage.clear(); - myHasDeferredChanges = false; - trimToSize(); - - if (myDebug) { - myDebugArray.setText(chars); - myDebugDeferredChanges.clear(); - } - assertConsistency(); - } - - private void assertConsistency() { - if (isDeferredChangeMode()) { - assert myOriginalSequence == null; - } - CharSequence originalSequence = myOriginalSequence; - int origLen = originalSequence == null ? -1 : originalSequence.length(); - String string = com.intellij.reference.SoftReference.dereference(myStringRef); - int stringLen = string == null ? -1 : string.length(); - assert origLen == stringLen || origLen==-1 || stringLen==-1; - - int count = myCount + myDeferredShift; - assert count == origLen || origLen==-1; - assert count == stringLen || stringLen==-1; - - if (!myDebug) return; - final CharSequence seqFromCharArray; - - if (myArray != null) { - assert myCount <= myArray.length; - seqFromCharArray = new CharArrayCharSequence(myArray, myStart, myCount); - } - else { - seqFromCharArray = null; - } - - if (seqFromCharArray != null && originalSequence != null) { - assert StringUtil.equals(seqFromCharArray, originalSequence); - } - if (!isDeferredChangeMode() && seqFromCharArray != null && string != null) { - assert StringUtil.equals(seqFromCharArray, string); - } - if (originalSequence != null && string != null) { - assert string.equals(originalSequence.toString()); - } - - myDebugArray.assertConsistency(); - - CharSequence str = com.intellij.reference.SoftReference.dereference(myStringRef); - if (str == null) { - if (myHasDeferredChanges) { - str = doSubString(0, myCount + myDeferredShift).toString(); - } - else if (myOriginalSequence != null) { - str = myOriginalSequence.toString(); - } - else { - str = seqFromCharArray; - } - } - assert count == str.length(); - if (isDeferredChangeMode()) { - String expected = myDebugArray.toString(); - checkStrings("toString()", expected, str); - } - } - - public void replace(int startOffset, - int endOffset, - @NotNull CharSequence toDelete, - @NotNull CharSequence newString, - long newModificationStamp, - boolean wholeTextReplaced) { - final DocumentEvent event = startChange(startOffset, toDelete, newString, wholeTextReplaced); - - startOffset += myStart; - endOffset += myStart; - doReplace(startOffset, endOffset, newString); - afterChangedUpdate(event, newModificationStamp); - assertConsistency(); - } - - private void doReplace(int startOffset, int endOffset, @NotNull CharSequence newString) { - prepareForModification(); - - if (isDeferredChangeMode()) { - storeChange(new TextChangeImpl(newString, startOffset, endOffset)); - if (myDebug) { - myDebugArray.doReplace(startOffset, endOffset, newString); - } - } - else { - int newLength = newString.length(); - int oldLength = endOffset - startOffset; - - CharArrayUtil.getChars(newString, myArray, startOffset, Math.min(newLength, oldLength)); - myStringRef = null; - - if (newLength > oldLength) { - doInsert(newString.subSequence(oldLength, newLength), endOffset); - } - else if (newLength < oldLength) { - doRemove(startOffset + newLength, startOffset + oldLength); - } - } - } - - public void remove(int startIndex, int endIndex, @NotNull CharSequence toDelete) { - DocumentEvent event = startChange(startIndex, toDelete, null, false); - startIndex += myStart; - endIndex += myStart; - doRemove(startIndex, endIndex); - afterChangedUpdate(event, LocalTimeCounter.currentTime()); - assertConsistency(); - } - - private void doRemove(int startIndex, int endIndex) { - if (startIndex == endIndex) { - return; - } - prepareForModification(); - - if (isDeferredChangeMode()) { - storeChange(new TextChangeImpl("", startIndex, endIndex)); - if (myDebug) { - myDebugArray.doRemove(startIndex, endIndex); - } - } - else { - if (endIndex < myCount) { - System.arraycopy(myArray, endIndex, myArray, startIndex, myCount - endIndex); - myStringRef = null; - } - myCount -= endIndex - startIndex; - } - } - - public void insert(@NotNull CharSequence s, int startIndex) { - DocumentEvent event = startChange(startIndex, null, s, false); - startIndex += myStart; - doInsert(s, startIndex); - - afterChangedUpdate(event, LocalTimeCounter.currentTime()); - trimToSize(); - assertConsistency(); - } - - private void doInsert(@NotNull CharSequence s, final int startIndex) { - prepareForModification(); - - if (isDeferredChangeMode()) { - storeChange(new TextChangeImpl(s, startIndex)); - if (myDebug) { - myDebugArray.doInsert(s, startIndex); - } - } - else { - int insertLength = s.length(); - myArray = resizeArray(myArray, myCount + insertLength); - if (startIndex < myCount) { - System.arraycopy(myArray, startIndex, myArray, startIndex + insertLength, myCount - startIndex); - } - - CharArrayUtil.getChars(s, myArray, startIndex); - myCount += insertLength; - myStringRef = null; - } - } - - /** - * Stores given change at collection of deferred changes (merging it with others if necessary) and updates current object - * state ({@link #length() length} etc). - * - * @param change new change to store - */ - private void storeChange(@NotNull TextChangeImpl change) { - if (!change.isWithinBounds(length())) { - LOG.error( - "Invalid change attempt detected - given change bounds are not within the current char array. Change: " + - change.getText().length()+":" + change.getStart()+"-" + change.getEnd(), dumpState()); - return; - } - if (myDeferredChangesStorage.size() >= MAX_DEFERRED_CHANGES_NUMBER) { - flushDeferredChanged(); - } - myDeferredChangesStorage.store(change); - myHasDeferredChanges = true; - myDeferredShift += change.getDiff(); - - if (myDebug) { - myDebugDeferredChanges.add(change); - } - } - - private void prepareForModification() { - if (myOriginalSequence != null) { - myArray = new char[myOriginalSequence.length()]; - CharArrayUtil.getChars(myOriginalSequence, myArray, 0); - myCount = myArray.length; - myOriginalSequence = null; - myStart = 0; - } - myStringRef = null; - - assertConsistency(); - } - - @NotNull - public CharSequence getCharArray() { - assertConsistency(); - CharSequence originalSequence = myOriginalSequence; - return originalSequence == null ? this : originalSequence; - } - - @Override - @NotNull - public String toString() { - assertConsistency(); - String str = com.intellij.reference.SoftReference.dereference(myStringRef); - if (str == null) { - if (myHasDeferredChanges) { - str = substring(0, length()).toString(); - } - else { - str = myOriginalSequence == null ? new String(myArray, myStart, myCount) : myOriginalSequence.toString(); - } - myStringRef = new SoftReference(str); - } - return str; - } - - @Override - public final int length() { - final int result = myCount + myDeferredShift; - if (myDebug && isDeferredChangeMode()) { - int expected = myDebugArray.length(); - if (expected != result) { - dumpDebugInfo("Incorrect length() processing. Expected: '" + expected + "', actual: '" + result + "'"); - } - } - return result; - } - - @Override - public final char charAt(int i) { - if (i < 0 || i >= length()) { - throw new IndexOutOfBoundsException("Wrong offset: " + i + "; count:" + length()); - } - i += myStart; - final char result; - if (!myHasDeferredChanges) { - if (myOriginalSequence != null) { - result = myOriginalSequence.charAt(i); - } - else { - result = myArray[i]; - } - } - else { - result = myDeferredChangesStorage.charAt(myArray, i); - } - - if (myDebug && isDeferredChangeMode()) { - char expected = myDebugArray.charAt(i); - if (expected != result) { - dumpDebugInfo("Incorrect charAt() processing for index " + i + ". Expected: '" + expected + "', actual: '" + result + "'"); - } - } - return result; - } - - @Override - @NotNull - public CharSequence subSequence(final int start, final int end) { - assertReadAccess(); - assertConsistency(); - if (start == 0 && end == length()) return this; - if (myOriginalSequence != null) { - return myOriginalSequence.subSequence(start, end); - } - flushDeferredChanged(); - return new CharArrayCharSequence(myArray, start, end); - } - - @Override - @NotNull - public char[] getChars() { - assertReadAccess(); - assertConsistency(); - char[] array = myArray; - CharSequence originalSequence = myOriginalSequence; - if (myHasDeferredChanges || originalSequence != null && array == null) { - // slow track - synchronized (lock) { - flushDeferredChanged(); - array = myArray; - originalSequence = myOriginalSequence; - if (originalSequence != null && array == null) { - myArray = array = CharArrayUtil.fromSequence(originalSequence); - myStringRef = null; - } - } - assertConsistency(); - } - return array; - } - - @Override - public void getChars(@NotNull final char[] dst, final int dstOffset) { - assertReadAccess(); - assertConsistency(); - flushDeferredChanged(); - if (myOriginalSequence == null) { - System.arraycopy(myArray, myStart, dst, dstOffset, length()); - } - else { - CharArrayUtil.getChars(myOriginalSequence, dst, dstOffset); - } - - if (myDebug && isDeferredChangeMode()) { - char[] expected = new char[dst.length]; - myDebugArray.getChars(expected, dstOffset); - for (int i = dstOffset, j = myStart; i < dst.length && j < myArray.length; i++, j++) { - if (expected[i] != myArray[j]) { - dumpDebugInfo("getChars(char[], int). Given array of length " + dst.length + ", offset " + dstOffset + ". Found char '" + myArray[j] + - "' at index " + i + ", expected to find '" + expected[i] + "'"); - break; - } - } - } - } - - @NotNull - public CharSequence substring(final int start, final int end) { - assertReadAccess(); - final CharSequence result = doSubString(start, end); - - assertConsistency(); - return result; - } - - private CharSequence doSubString(int start, int end) { - if (start == end) return ""; - final CharSequence result; - if (myOriginalSequence == null) { - result = myDeferredChangesStorage.substring(myArray, start + myStart, end + myStart); - } - else { - result = myOriginalSequence.subSequence(start, end); - } - return result; - } - - @NotNull - private static char[] resizeArray(@NotNull char[] array, int newSize) { - if (newSize < array.length) { - return array; - } - - int newArraySize = array.length; - if (newArraySize == 0) { - newArraySize = 16; - } - while (newArraySize <= newSize) { - newArraySize = newArraySize * 12 / 10 + 1; - } - char[] newArray = new char[newArraySize]; - System.arraycopy(array, 0, newArray, 0, array.length); - return newArray; - } - - private void trimToSize() { - if (myBufferSize != 0 && length() > myBufferSize) { - flushDeferredChanged(); - - // make a copy - int endIndex = myCount - myBufferSize; - String toDelete = getCharArray().subSequence(0, endIndex).toString(); - remove(0, endIndex, toDelete); - } - } - - /** - * @return true if this object is in the defer changes mode, see {@link #setDeferredChangeMode(boolean)}; - */ - public boolean isDeferredChangeMode() { - return myDeferredChangeMode; - } - - public boolean hasDeferredChanges() { - return myHasDeferredChanges; - } - - /** - * There is a possible case that client of this class wants to perform great number of modifications in a short amount of time - * (e.g. end-user performs formatting of the document backed by the object of the current class). It may result in significant - * performance degradation is the changes are performed one by one (every time the change is applied tail content is shifted to - * the left or right). So, we may want to optimize that by avoiding actual array modification until information about - * all target changes is provided and perform array data moves only after that. - *

- * This method allows to define that 'defer changes' mode usages, i.e. expected usage pattern is as follows: - *

-   * 
    - *
  1. - * Client of this class enters 'defer changes' mode (calls this method with 'true' argument). - * That means that all subsequent changes will not actually modify backed array data and will be stored separately; - *
  2. - *
  3. - * Number of target changes are applied to the current object via standard API - * ({@link #insert(CharSequence, int) insert}, - * {@link #remove(int, int, CharSequence) remove} and - * {@link #replace(int, int, java.lang.CharSequence, java.lang.CharSequence, long, boolean)}); - *
  4. - *
  5. - * Client of this class indicates that 'massive change time' is over by calling this method with 'false' - * argument. That flushes all deferred changes (if any) to the backed data array and makes every subsequent change to - * be immediate flushed to the backed array; - *
  6. - *
- *
- *

- * Note: we can't exclude possibility that 'defer changes' mode is started but inadvertently not ended - * (due to programming error, unexpected exception etc). Hence, this class is free to automatically end - * 'defer changes' mode when necessary in order to avoid memory leak with infinite deferred changes storing. - * - * @param deferredChangeMode flag that defines if 'defer changes' mode should be used by the current object - */ - public void setDeferredChangeMode(boolean deferredChangeMode) { - if (!DISABLE_DEFERRED_PROCESSING) { - if (deferredChangeMode) { - if (myDebug) { - myDebugArray.setText(myDebugTextOnBatchUpdateStart = toString()); - myDebugDeferredChanges.clear(); - } - prepareForModification(); - } - else { - flushDeferredChanged(); - } - myDeferredChangeMode = deferredChangeMode; - } - assertConsistency(); - } - - private void flushDeferredChanged() { - List changes = myDeferredChangesStorage.getChanges(); - if (changes.isEmpty()) { - return; - } - - synchronized (lock) { - char[] beforeMerge = null; - if (myDebug) { - beforeMerge = new char[myArray.length]; - System.arraycopy(myArray, 0, beforeMerge, 0, myArray.length); - } - - BulkChangesMerger changesMerger = BulkChangesMerger.INSTANCE; - final boolean inPlace; - if (myArray.length < length()) { - myArray = changesMerger.mergeToCharArray(myArray, myCount, changes); - inPlace = false; - } - else { - changesMerger.mergeInPlace(myArray, myCount, changes); - inPlace = true; - } - - myCount += myDeferredShift; - myDeferredShift = 0; - myDeferredChangesStorage.clear(); - myHasDeferredChanges = false; - myDeferredChangeMode = false; - myStringRef = null; - - if (myDebug) { - for (int i = 0, max = length(); i < max; i++) { - if (myArray[i] != myDebugArray.myArray[i]) { - dumpDebugInfo("flushDeferredChanged(). Index " + i + ", expected: '" + myDebugArray.myArray[i]+"', actual '" + - myArray[i]+"'. Text before merge: '" + Arrays.toString(beforeMerge)+"', merge inplace: "+inPlace); - break; - } - } - } - } - assertConsistency(); - } - - @Override - @NonNls - @NotNull - public String dumpState() { - return "deferred changes mode: " + isDeferredChangeMode()+", length: " + length()+" (data array length: " + myCount+ - ", deferred shift: " + myDeferredShift+"); view offsets: [" + myStart+"; "+myCount+"]; deferred changes: "+myDeferredChangesStorage; - } - - private void checkStrings(@NonNls @NotNull String operation, @NotNull String expected, @NotNull CharSequence actual) { - if (StringUtil.equals(expected, actual)) { - return; - } - for (int i = 0, max = Math.min(expected.length(), actual.length()); i < max; i++) { - if (actual.charAt(i) != expected.charAt(i)) { - dumpDebugInfo( - "Incorrect " + - operation+" processing. Expected length: " + - expected.length()+", actual length: " + - actual.length()+". Unmatched symbol at " + - i+" - expected: '" + - expected.charAt(i)+"', " + - "actual: '" + - actual.charAt(i)+"', expected document: '" + - expected+"', actual document: '" + - actual+"'" - ); - return; - } - } - dumpDebugInfo("Incorrect " + operation+" processing. Expected length: " + expected.length()+", actual length: " + - actual.length()+", expected: '" + expected+"', actual: '" + actual+"'"); - } - - private void dumpDebugInfo(@NonNls @NotNull String problem) { - LOG.error( - "Incorrect CharArray processing detected: " + problem + - ". Start: " + myStart - + ", count: " + myCount + ", text on batch update start: " + - myDebugTextOnBatchUpdateStart + ", deferred changes history: " + - myDebugDeferredChanges + ", current deferred changes: " + myDeferredChangesStorage - ); - } -} diff --git a/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java b/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java index 55a74d08ebd1..f5bc6cee0c35 100644 --- a/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java +++ b/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java @@ -48,10 +48,6 @@ public class EmptySchemesManager extends SchemesManager { return null; } - @Override - public void save() { - } - @Override public void setCurrentSchemeName(String schemeName) { } diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 9741110e23cf..c2ef19131a90 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -178,14 +178,15 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi psiFile = PsiUtilCore.NULL_PSI_FILE; } boolean set = myPsiFile.compareAndSet(null, psiFile); - if (!set) { + if (!set && psiFile != PsiUtilCore.NULL_PSI_FILE) { + PsiFile alreadyCreated = myPsiFile.get(); + if (alreadyCreated == psiFile) { + LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile); + } if (psiFile instanceof PsiFileImpl) { - if (myPsiFile.get() == psiFile) { - LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile); - } ((PsiFileImpl)psiFile).markInvalidated(); } - psiFile = myPsiFile.get(); + psiFile = alreadyCreated; } } return psiFile == PsiUtilCore.NULL_PSI_FILE ? null : psiFile; diff --git a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java index 0bbc064b3cab..9e2f84f0b1ca 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.diff.DiffBundle; import com.intellij.openapi.project.DefaultProjectFactory; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,8 +58,7 @@ public class DiffApplication extends ApplicationStarterBase { if (file1 == null) throw new Exception("Can't find file " + path1); if (file2 == null) throw new Exception("Can't find file " + path2); - file1.refresh(false, true); - file2.refresh(false, true); + VfsUtil.markDirtyAndRefresh(false, false, false, file1, file2); DiffRequest request = DiffRequestFactory.getInstance().createFromFiles(null, file1, file2); Project project = DefaultProjectFactory.getInstance().getDefaultProject(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java index f0cf5497bf83..21ba91b76207 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java @@ -346,8 +346,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase { EditorHighlighter highlighter2 = DiffUtil.initEditorHighlighter(project, content2, text2); if (highlighter1 == null && highlighter2 == null) return null; - if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(project, text1); - if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(project, text2); + if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(text1); + if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(text2); return new UnifiedEditorHighlighter(myDocument, highlighter1, highlighter2, ranges, textLength); } diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index d5fedbcf2c95..1d14498c31bd 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -107,7 +107,7 @@ public class DiffUtil { } @NotNull - public static EditorHighlighter initEmptyEditorHighlighter(@Nullable Project project, @NotNull CharSequence text) { + public static EditorHighlighter initEmptyEditorHighlighter(@NotNull CharSequence text) { EditorHighlighter highlighter = createEmptyEditorHighlighter(); highlighter.setText(text); return highlighter; @@ -216,10 +216,6 @@ public class DiffUtil { scrollToCaret(editor, animated); } - public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point) { - scrollToPoint(editor, point, false); - } - public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point, boolean animated) { if (editor == null) return; if (!animated) editor.getScrollingModel().disableAnimation(); @@ -876,14 +872,6 @@ public class DiffUtil { return holder; } - public static UserDataHolderBase createUserDataHolder(@NotNull Key key1, @Nullable T value1, - @NotNull Key key2, @Nullable T value2) { - UserDataHolderBase holder = new UserDataHolderBase(); - holder.putUserData(key1, value1); - holder.putUserData(key2, value2); - return holder; - } - public static boolean isUserDataFlagSet(@NotNull Key key, UserDataHolder... holders) { for (UserDataHolder holder : holders) { if (holder == null) continue; @@ -1039,9 +1027,5 @@ public class DiffUtil { this(ignorePolicy.getComparisonPolicy(), highlightPolicy.isFineFragments(), highlightPolicy.isShouldSquash(), ignorePolicy.isShouldTrimChunks()); } - - public DiffConfig() { - this(IgnorePolicy.DEFAULT, HighlightPolicy.BY_LINE); - } } } diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java index b4f3dcbc30e8..ad865eae4bed 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java @@ -26,10 +26,13 @@ import javax.swing.*; /** * Interface which should be implemented in order to draw icons in the gutter area and handle events * for them. Gutter icons are drawn to the left of the folding area and can be used, for example, - * to mark implemented or overridden methods. + * to mark implemented or overridden methods.

* * Daemon code analyzer checks newly arrived gutter icon renderer against the old one and if they are equal, does not redraw the icon. - * So it is highly advisable to override hashCode()/equals() methods to avoid icon flickering when old gutter renderer gets replaced with the new. + * So it is highly advisable to override hashCode()/equals() methods to avoid icon flickering when old gutter renderer gets replaced with the new.

+ * + * During indexing, click handlers are only invoked for renderers implementing {@link com.intellij.openapi.project.DumbAware}. + * * @author max * @see RangeHighlighter#setGutterIconRenderer(GutterIconRenderer) */ diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 704aae2194bb..0969093acc78 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -312,7 +312,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } // we failed to run read action in job launcher thread // run read action in our thread instead to wait for a write action to complete and resume parallel processing - ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance()); + DumbService.getInstance(myManager.getProject()).runReadActionInSmartMode(EmptyRunnable.getInstance()); files = failedList; } return completed; @@ -347,7 +347,10 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { ApplicationUtil.tryRunReadAction(new Computable() { @Override public Void compute() { - if (myManager.getProject().isDisposed()) throw new ProcessCanceledException(); + final Project project = myManager.getProject(); + if (project.isDisposed()) throw new ProcessCanceledException(); + if (DumbService.isDumb(project)) throw new ApplicationUtil.CannotRunReadActionException(); + List psiRoots = file.getViewProvider().getAllFiles(); Set processed = new THashSet(psiRoots.size() * 2, (float)0.5); for (final PsiFile psiRoot : psiRoots) { diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java index 90ccfbffbf8b..bc3bb1de1bd5 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.ShortcutSet; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.event.MouseEvent; @@ -28,10 +29,10 @@ import java.awt.event.MouseEvent; * @author Dmitry Avdeev */ public class NavigateAction extends AnAction { - private LineMarkerInfo myInfo; + private final LineMarkerInfo myInfo; - public NavigateAction(String text, - LineMarkerInfo info, + public NavigateAction(@NotNull String text, + @NotNull LineMarkerInfo info, @Nullable String originalActionId) { super(text); myInfo = info; @@ -41,7 +42,7 @@ public class NavigateAction extends AnAction { } } - public NavigateAction(LineMarkerInfo info) { + public NavigateAction(@NotNull LineMarkerInfo info) { myInfo = info; } @@ -56,7 +57,8 @@ public class NavigateAction extends AnAction { } } - public static LineMarkerInfo setNavigateAction(LineMarkerInfo info, String text, @Nullable String originalActionId) { + @NotNull + public static LineMarkerInfo setNavigateAction(@NotNull LineMarkerInfo info, @NotNull String text, @Nullable String originalActionId) { NavigateAction action = new NavigateAction(text, info, originalActionId); info.setNavigateAction(action); return info; diff --git a/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java b/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java index 8e1ec4e47a21..2740cd0254aa 100644 --- a/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java +++ b/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java @@ -161,6 +161,20 @@ public interface RunnerAndConfigurationSettings { */ boolean isEditBeforeRun(); + /** + * Sets the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.) + * + * @param b if true, the tool window will be activated before launching this configuration. + */ + void setActivateToolWindowBeforeRun(boolean activate); + + /** + * Returns the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.) + * + * @return if true (it's default value), the tool window will be activated before launching this configuration. + */ + boolean isActivateToolWindowBeforeRun(); + /** * Sets the "Single instance only" flag (meaning that only one instance of this run configuration can be run at the same time). * diff --git a/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java index a2028185089b..637729d795cc 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java +++ b/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java @@ -16,10 +16,7 @@ package com.intellij.execution.runners; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.ExecutionResult; -import com.intellij.execution.Executor; -import com.intellij.execution.RunManager; +import com.intellij.execution.*; import com.intellij.execution.configurations.*; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.options.SettingsEditor; @@ -72,6 +69,10 @@ abstract class BaseProgramRunner implements Pro static RunContentDescriptor postProcess(@NotNull ExecutionEnvironment environment, @Nullable RunContentDescriptor descriptor, @Nullable Callback callback) { if (descriptor != null) { descriptor.setExecutionId(environment.getExecutionId()); + RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings(); + if (settings != null) { + descriptor.setActivateToolWindowWhenAdded(settings.isActivateToolWindowBeforeRun()); + } } if (callback != null) { callback.processStarted(descriptor); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index 57f65283fd2f..4eeca2b71704 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.usages.UsageView; import com.intellij.util.Consumer; import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -88,12 +89,12 @@ public class PsiElementListNavigator { } @Nullable - public static JBPopup navigateOrCreatePopup(final NavigatablePsiElement[] targets, + public static JBPopup navigateOrCreatePopup(@NotNull final NavigatablePsiElement[] targets, final String title, final String findUsagesTitle, final ListCellRenderer listRenderer, @Nullable final ListBackgroundUpdaterTask listUpdaterTask, - final Consumer consumer) { + @NotNull final Consumer consumer) { if (targets.length == 0) return null; if (targets.length == 1) { consumer.consume(targets); 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 995110c7d172..0a1d25315b42 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -33,7 +33,6 @@ import com.intellij.lang.Language; import com.intellij.lang.LanguageDocumentation; import com.intellij.lang.documentation.*; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.ex.AnActionListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -96,7 +95,7 @@ public class DocumentationManager extends DockablePopupManager ORIGINAL_ELEMENT_KEY = Key.create("Original element"); - private final ActionManagerEx myActionManagerEx; + private final ActionManager myActionManager; private final TargetElementUtil myTargetElementUtil; @@ -161,9 +160,9 @@ public class DocumentationManager extends DockablePopupManager> actions = ContainerUtil.newSmartList(); - AnAction quickDocAction = ActionManagerEx.getInstanceEx().getAction(IdeActions.ACTION_QUICK_JAVADOC); + AnAction quickDocAction = ActionManager.getInstance().getAction(IdeActions.ACTION_QUICK_JAVADOC); for (Shortcut shortcut : quickDocAction.getShortcutSet().getShortcuts()) { if (!(shortcut instanceof KeyboardShortcut)) continue; actions.add(Pair.create(actionListener, ((KeyboardShortcut)shortcut).getFirstKeyStroke())); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java index 7c3a0ced14d7..c48ae61e93c6 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -105,7 +105,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } - protected Editor getEditor(DataContext dataContext) { + protected static Editor getEditor(@NotNull DataContext dataContext) { Editor editor = CommonDataKeys.EDITOR.getData(dataContext); if (editor == null) { @@ -123,7 +123,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { return editor; } - public void performForContext(DataContext dataContext, boolean invokedByShortcut) { + public void performForContext(@NotNull DataContext dataContext, boolean invokedByShortcut) { final Project project = CommonDataKeys.PROJECT.getData(dataContext); if (project == null) return; PsiDocumentManager.getInstance(project).commitAllDocuments(); @@ -185,7 +185,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { showImplementations(impls, project, text, editor, file, element, isInvokedFromEditor, invokedByShortcut); } - protected static PsiElement getElement(Project project, PsiFile file, Editor editor, PsiElement element) { + protected static PsiElement getElement(@NotNull Project project, PsiFile file, Editor editor, PsiElement element) { if (element == null && editor != null) { element = TargetElementUtil.findTargetElement(editor, TargetElementUtil.getInstance().getAllAccepted()); final PsiElement adjustedElement = @@ -200,6 +200,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { return element; } + @NotNull protected static ImplementationSearcher createImplementationsSearcher() { if (ApplicationManager.getApplication().isUnitTestMode()) { return new ImplementationSearcher() { @@ -209,18 +210,16 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } }; } - else { - return new ImplementationSearcher.FirstImplementationsSearcher() { - @Override - protected PsiElement[] filterElements(PsiElement element, PsiElement[] targetElements, final int offset) { - return ShowImplementationsAction.filterElements(targetElements); - } - }; - } + return new ImplementationSearcher.FirstImplementationsSearcher() { + @Override + protected PsiElement[] filterElements(PsiElement element, PsiElement[] targetElements, final int offset) { + return ShowImplementationsAction.filterElements(targetElements); + } + }; } - protected void updateElementImplementations(final PsiElement element, final Editor editor, final Project project, final PsiFile file) { - PsiElement[] impls = null; + private void updateElementImplementations(final PsiElement element, final Editor editor, @NotNull Project project, final PsiFile file) { + PsiElement[] impls = {}; String text = ""; if (element != null) { // if (element instanceof PsiPackage) return; @@ -234,10 +233,15 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { showImplementations(impls, project, text, editor, file, element, false, false); } - protected void showImplementations(final PsiElement[] impls, final Project project, final String text, final Editor editor, final PsiFile file, + protected void showImplementations(@NotNull PsiElement[] impls, + @NotNull final Project project, + final String text, + final Editor editor, + final PsiFile file, final PsiElement element, - boolean invokedFromEditor, boolean invokedByShortcut) { - if (impls == null || impls.length == 0) return; + boolean invokedFromEditor, + boolean invokedByShortcut) { + if (impls.length == 0) return; FeatureUsageTracker.getInstance().triggerFeatureUsed(CODEASSISTS_QUICKDEFINITION_FEATURE); if (LookupManager.getInstance(project).getActiveLookup() != null) { @@ -317,7 +321,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } } - private static boolean cancelTask(ImplementationsUpdaterTask task) { + private static boolean cancelTask(@Nullable ImplementationsUpdaterTask task) { if (task != null) { ProgressIndicator indicator = task.myIndicator; if (indicator != null) { @@ -330,9 +334,10 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { private void updateInBackground(Editor editor, @Nullable PsiElement element, - ImplementationViewComponent component, + @NotNull ImplementationViewComponent component, String title, - AbstractPopup popup, Ref usageView) { + @NotNull AbstractPopup popup, + @NotNull Ref usageView) { final ImplementationsUpdaterTask updaterTask = SoftReference.dereference(myTaskRef); cancelTask(updaterTask); @@ -348,15 +353,17 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { return true; } + @NotNull private static PsiElement[] getSelfAndImplementations(Editor editor, - PsiElement element, - final ImplementationSearcher handler) { + @NotNull PsiElement element, + @NotNull ImplementationSearcher handler) { return getSelfAndImplementations(editor, element, handler, !(element instanceof PomTargetPsiElement)); } + @NotNull protected static PsiElement[] getSelfAndImplementations(Editor editor, - PsiElement element, - final ImplementationSearcher handler, + @NotNull PsiElement element, + @NotNull ImplementationSearcher handler, final boolean includeSelfAlways) { int offset = editor == null ? 0 : editor.getCaretModel().getOffset(); final PsiElement[] handlerImplementations = handler.searchImplementations(element, editor, offset, includeSelfAlways, true); @@ -367,17 +374,18 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { // Magically, it's null for ant property declarations. element = element.getNavigationElement(); psiFile = element.getContainingFile(); - if (psiFile == null) return PsiElement.EMPTY_ARRAY; + if (psiFile == null) { + return PsiElement.EMPTY_ARRAY; + } } if (psiFile.getVirtualFile() != null && (element.getTextRange() != null || element instanceof PsiFile)) { return new PsiElement[]{element}; } - else { - return PsiElement.EMPTY_ARRAY; - } + return PsiElement.EMPTY_ARRAY; } - private static PsiElement[] filterElements(final PsiElement[] targetElements) { + @NotNull + private static PsiElement[] filterElements(@NotNull final PsiElement[] targetElements) { final Set unique = new LinkedHashSet(Arrays.asList(targetElements)); for (final PsiElement elt : targetElements) { ApplicationManager.getApplication().runReadAction(new Runnable() { @@ -410,12 +418,13 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { private static class ImplementationsUpdaterTask extends BackgroundUpdaterTask { private final String myCaption; private final Editor myEditor; + @NotNull private final PsiElement myElement; private final boolean myIncludeSelf; private PsiElement[] myElements; private volatile ProgressIndicator myIndicator; - public ImplementationsUpdaterTask(final PsiElement element, final Editor editor, final String caption, boolean includeSelf) { + private ImplementationsUpdaterTask(@NotNull PsiElement element, final Editor editor, final String caption, boolean includeSelf) { super(element.getProject(), ImplementationSearcher.SEARCHING_FOR_IMPLEMENTATIONS); myCaption = caption; myEditor = editor; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java index 397889c8e1cf..85cd0952c0ad 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,6 @@ import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopupAdapter; -import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.ui.popup.AbstractPopup; @@ -69,7 +67,7 @@ public abstract class BackgroundUpdaterTask extends Task.Backgroundable { super(project, title, canBeCancelled, backgroundOption); } - public void init(@NotNull AbstractPopup popup, T component, Ref usageView) { + public void init(@NotNull AbstractPopup popup, @NotNull T component, @NotNull Ref usageView) { myPopup = popup; myComponent = component; myUsageView = usageView; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateTree.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateTree.java new file mode 100644 index 000000000000..29f835193636 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateTree.java @@ -0,0 +1,159 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.impl; + +import com.intellij.codeInsight.template.TemplateContextType; +import com.intellij.ide.CopyProvider; +import com.intellij.ide.PasteProvider; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.CheckboxTree; +import com.intellij.ui.CheckedTreeNode; +import com.intellij.ui.TreeSpeedSearch; +import com.intellij.util.Function; +import com.intellij.util.SystemProperties; +import com.intellij.util.containers.Convertor; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.io.StringReader; +import java.util.Set; + +/** + * @author peter + */ +class LiveTemplateTree extends CheckboxTree implements DataProvider, CopyProvider, PasteProvider { + private final TemplateListPanel myConfigurable; + + LiveTemplateTree(final CheckboxTreeCellRenderer renderer, final CheckedTreeNode root, TemplateListPanel configurable) { + super(renderer, root); + myConfigurable = configurable; + } + + @Override + protected void onNodeStateChanged(final CheckedTreeNode node) { + Object obj = node.getUserObject(); + if (obj instanceof TemplateImpl) { + ((TemplateImpl)obj).setDeactivated(!node.isChecked()); + } + } + + @Override + protected void installSpeedSearch() { + new TreeSpeedSearch(this, new Convertor() { + @Override + public String convert(TreePath o) { + Object object = ((DefaultMutableTreeNode)o.getLastPathComponent()).getUserObject(); + if (object instanceof TemplateGroup) { + return ((TemplateGroup)object).getName(); + } + if (object instanceof TemplateImpl) { + TemplateImpl template = (TemplateImpl)object; + return StringUtil.notNullize(template.getKey()) + + " " + + StringUtil.notNullize(template.getDescription()) + + " " + + template.getTemplateText(); + } + return ""; + } + }, true); + } + + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (PlatformDataKeys.COPY_PROVIDER.is(dataId) || PlatformDataKeys.PASTE_PROVIDER.is(dataId)) { + return this; + } + return null; + } + + @Override + public void performCopy(@NotNull DataContext dataContext) { + final Set templates = myConfigurable.getSelectedTemplates().keySet(); + + + CopyPasteManager.getInstance().setContents(new StringSelection(StringUtil.join(templates, new Function() { + @Override + public String fun(TemplateImpl template) { + TemplateContext zeroContext = new TemplateContext(); + for (TemplateContextType type : TemplateContextType.EP_NAME.getExtensions()) { + zeroContext.setEnabled(type, false); + } + return JDOMUtil.writeElement(TemplateSettings.serializeTemplate(template, zeroContext)); + } + }, SystemProperties.getLineSeparator()))); + + } + + @Override + public boolean isCopyEnabled(@NotNull DataContext dataContext) { + return !myConfigurable.getSelectedTemplates().isEmpty(); + } + + @Override + public boolean isCopyVisible(@NotNull DataContext dataContext) { + return isCopyEnabled(dataContext); + } + + @Override + public boolean isPastePossible(@NotNull DataContext dataContext) { + if (myConfigurable.getSingleSelectedGroup() == null) return false; + + String s = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor); + return s != null && s.startsWith("