mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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" \
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<SuspendContextImpl> suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), myThread);
|
||||
for (SuspendContextImpl suspendContext : suspendingContexts) {
|
||||
if (suspendContext.getThread() == myThread) {
|
||||
getSession().getXDebugSession().sessionResumed();
|
||||
getManagerThread().invoke(createResumeCommand(suspendContext));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -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<PsiElement>() {
|
||||
@Override
|
||||
public Iterator<PsiElement> iterator() {
|
||||
return new Iterator<PsiElement>() {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
+9
-9
@@ -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<UsageInfo> 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);
|
||||
}
|
||||
|
||||
+60
-2
@@ -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();
|
||||
|
||||
+5
-1
@@ -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;
|
||||
|
||||
+12
-6
@@ -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);
|
||||
|
||||
@@ -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<PsiClass> allSupers = new ArrayList<PsiClass>(Arrays.asList(aClass.getSupers()));
|
||||
for (Iterator<PsiClass> 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<PsiClass, PsiClass> 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<PsiClass> checkedInterfaces = new THashSet<PsiClass>();
|
||||
final PsiMethod[] result = new PsiMethod[1];
|
||||
ClassInheritorsSearch.search(containingClass, true).forEach(new Processor<PsiClass>() {
|
||||
@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<PsiClass, PsiClass> createSubClassCache() {
|
||||
return new FactoryMap<PsiClass, PsiClass>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiClass create(PsiClass aClass) {
|
||||
return ClassInheritorsSearch.search(aClass, false).findFirst();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+78
-39
@@ -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<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
Map<PsiClass, PsiClass> subClassCache = FindSuperElementsHelper.createSubClassCache();
|
||||
|
||||
Set<PsiMethod> methods = new HashSet<PsiMethod>();
|
||||
Collection<PsiMethod> methods = new THashSet<PsiMethod>();
|
||||
//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<LineMarkerInfo> result) {
|
||||
private static void collectSiblingInheritedMethods(@NotNull final Collection<PsiMethod> methods,
|
||||
@NotNull Collection<LineMarkerInfo> result,
|
||||
@NotNull Map<PsiClass, PsiClass> 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<LineMarkerInfo> result,
|
||||
@NotNull Map<PsiClass, PsiClass> 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<PsiElement>(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<PsiMethod> methods, Collection<LineMarkerInfo> result) {
|
||||
private static void collectOverridingMethods(@NotNull final Collection<PsiMethod> methods, @NotNull Collection<LineMarkerInfo> result) {
|
||||
final Set<PsiMethod> overridden = new HashSet<PsiMethod>();
|
||||
Set<PsiClass> classes = new THashSet<PsiClass>();
|
||||
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<PsiElement> info = new LineMarkerInfo<PsiElement>(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<PsiElement> {
|
||||
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<? super PsiElement, String> getCommonTooltip(@NotNull List<MergeableLineMarkerInfo> infos) {
|
||||
return new Function<PsiElement, String>() {
|
||||
|
||||
@@ -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 = "<br><div style='margin-top: 5px'><font size='2'>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<PsiElement, PsiMethod>() {
|
||||
@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<PsiMethod> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5);
|
||||
OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(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<PsiClass> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(5, new THashSet<PsiClass>());
|
||||
ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(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;
|
||||
|
||||
+4
@@ -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);
|
||||
}
|
||||
|
||||
+15
-4
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -50,7 +50,7 @@ public class FormatPostfixTemplate extends StringBasedPostfixTemplate {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldRemoveParent() {
|
||||
return false;
|
||||
protected PsiElement getElementToRemove(PsiElement expr) {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-4
@@ -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<PseudoLambdaReplaceTemplate> possibleTemplates = PseudoLambdaReplaceTemplate.getAllTemplates();
|
||||
final MultiMap<String, PsiMethod> nameToMethod = new MultiMap<String, PsiMethod>();
|
||||
final LinkedMultiMap<String, PsiMethod> nameToMethod = new LinkedMultiMap<String, PsiMethod>();
|
||||
for (PsiMethod m : ContainerUtil.filter(aClass.getMethods(), new Condition<PsiMethod>() {
|
||||
@Override
|
||||
public boolean value(PsiMethod method) {
|
||||
@@ -181,15 +182,27 @@ public class AddMethodsDialog extends DialogWrapper {
|
||||
for (Map.Entry<String, Collection<PsiMethod>> 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);
|
||||
|
||||
+81
-155
@@ -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<PsiTypeParameter, PsiType> 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<PsiTypeParameter, PsiType> substitutionMap = new HashMap<PsiTypeParameter, PsiType>();
|
||||
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<PsiMethod> methods = ContainerUtil.filter(anonymousClass.getMethods(), new Condition<PsiMethod>() {
|
||||
@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<PsiReturnStatement> returnStatements = PsiTreeUtil.findChildrenOfType(body, PsiReturnStatement.class);
|
||||
returnStatements = ContainerUtil.filter(returnStatements, new Condition<PsiReturnStatement>() {
|
||||
@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() + ")";
|
||||
|
||||
@@ -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.<PsiElement>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString, Collection<PsiElement> ignore) {
|
||||
public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString, @NotNull Collection<PsiElement> ignore) {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return new PsiMethod[]{method};
|
||||
|
||||
final Collection<PsiMethod> 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<PsiMethod> processor,
|
||||
final Editor editor) {
|
||||
public static void checkSuperMethod(@NotNull PsiMethod method,
|
||||
@NotNull String actionString,
|
||||
@NotNull final PsiElementProcessor<PsiMethod> 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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
* <code>null</code> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
|
||||
@@ -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<PsiElement> {
|
||||
@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) &&
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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<Pair<PsiM
|
||||
PsiSubstitutor substitutor = null;
|
||||
|
||||
for (String name : methods.keySet()) {
|
||||
if (inheritor.findMethodsByName(name, false).length == 0) continue;
|
||||
if (inheritor.findMethodsByName(name, true).length == 0) continue;
|
||||
|
||||
for (PsiMethod method : methods.get(name)) {
|
||||
if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
|
||||
|
||||
+21
-16
@@ -101,12 +101,14 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
return true;
|
||||
}
|
||||
|
||||
Collection<PsiReferenceList> candidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiReferenceList>>() {
|
||||
@Override
|
||||
public Collection<PsiReferenceList> compute() {
|
||||
return JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, project, scope);
|
||||
}
|
||||
});
|
||||
Collection<PsiReferenceList> candidates = MethodUsagesSearcher.resolveInReadAction(project,
|
||||
new Computable<Collection<PsiReferenceList>>() {
|
||||
@Override
|
||||
public Collection<PsiReferenceList> compute() {
|
||||
return JavaSuperClassNameOccurenceIndex
|
||||
.getInstance().get(searchKey, project, scope);
|
||||
}
|
||||
});
|
||||
|
||||
Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
|
||||
|
||||
@@ -118,7 +120,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
return referenceList.getParent();
|
||||
}
|
||||
});
|
||||
if (!checkInheritance(p, aClass, candidate)) continue;
|
||||
if (!checkInheritance(p, aClass, candidate, project)) continue;
|
||||
|
||||
String fqn = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Override
|
||||
@@ -142,16 +144,19 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
}
|
||||
|
||||
if (p.includeAnonymous()) {
|
||||
Collection<PsiAnonymousClass> anonymousCandidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiAnonymousClass>>() {
|
||||
@Override
|
||||
public Collection<PsiAnonymousClass> compute() {
|
||||
return JavaAnonymousClassBaseRefOccurenceIndex.getInstance().get(searchKey, project, scope);
|
||||
}
|
||||
});
|
||||
Collection<PsiAnonymousClass> anonymousCandidates = MethodUsagesSearcher.resolveInReadAction(project,
|
||||
new Computable<Collection<PsiAnonymousClass>>() {
|
||||
@Override
|
||||
public Collection<PsiAnonymousClass> 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<PsiClass, Dir
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate, Project project) {
|
||||
return MethodUsagesSearcher.resolveInReadAction(project, new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return !p.isCheckInheritance() || candidate.isInheritor(aClass, false);
|
||||
|
||||
@@ -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<PsiAnnotation.TargetType> 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<TargetType> 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<PsiAnnotation.TargetType> extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) {
|
||||
public static Set<TargetType> 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 <PsiAnnotation.TargetType> targets = ContainerUtil.newHashSet();
|
||||
Set <TargetType> 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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<PsiClass> allSupers = new ArrayList<PsiClass>(Arrays.asList(aClass.getSupers()));
|
||||
for (Iterator<PsiClass> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
+13
@@ -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;
|
||||
}
|
||||
|
||||
+19
-15
@@ -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; <code>null</code> otherwise
|
||||
* @return last node before closing right parenthesis if possible; <code>null</code> 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; <code>null</code> otherwise
|
||||
/**
|
||||
* @return first node after opening left parenthesis if possible; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
private TreeElement getFirstNodeInsideParens() {
|
||||
|
||||
@@ -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}
|
||||
|
||||
+2
-16
@@ -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(<error descr="Receiver parameters are not supported at this language level">Object this</error>) { }
|
||||
|
||||
interface I {
|
||||
<error descr="Extension methods are not supported at this language level">default void m() { }</error>
|
||||
<error descr="Extension methods are not supported at this language level">static void m() { }</error>
|
||||
|
||||
+47
@@ -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 <error descr="Receivers are not allowed outside of method parameter list">this</error>) { }
|
||||
Runnable r = (C <error descr="Receivers are not allowed outside of method parameter list">C.this</error>) -> { };
|
||||
}
|
||||
|
||||
void m1a(<error descr="Modifier 'final' not allowed here">final</error> C this) { }
|
||||
void m1b(<error descr="'@A' not applicable to type use">@A</error> C this) { }
|
||||
|
||||
void m2(@TA Object other, @TA C <error descr="The receiver should be the first parameter">this</error>) { }
|
||||
|
||||
void m3a(@TA <error descr="The receiver type does not match the enclosing class type">Object</error> this) { }
|
||||
void m3b(@TA <error descr="The receiver type does not match the enclosing class type">int</error> this) { }
|
||||
|
||||
void m4a(C C.this) { }
|
||||
void m4b(C <error descr="The receiver name does not match the enclosing class type">C.X.this</error>) { }
|
||||
|
||||
static void sm1(@TA Object <error descr="The receiver cannot be used in a static context">this</error>) { }
|
||||
|
||||
C(C <error descr="The receiver cannot be used in a static context">this</error>) { }
|
||||
|
||||
static class X {
|
||||
X(X <error descr="The receiver cannot be used in a static context">this</error>) { }
|
||||
}
|
||||
|
||||
class B {
|
||||
B(C C.this) { }
|
||||
B(<error descr="The receiver type does not match the enclosing class type">B</error> C.this, int p) { }
|
||||
B(C <error descr="The receiver name does not match the enclosing class type">B.this</error>, long p) { }
|
||||
B(C <error descr="The receiver name does not match the enclosing class type">this</error>, float p) { }
|
||||
}
|
||||
}
|
||||
-15
@@ -130,19 +130,4 @@ class Outer {
|
||||
IntFunction<Super> f = Outer.<error descr="Annotations are not allowed here">@TA</error> 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) { }
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import java.util.*;
|
||||
class Test {
|
||||
public Optional<Set<String>> foo(Optional<Set<String>> args) {
|
||||
return args.map(HashSet::new).map(Collections::unmodifiableSet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package z;
|
||||
|
||||
interface I {
|
||||
void <caret>run();
|
||||
}
|
||||
abstract class A {
|
||||
public void run() {}
|
||||
}
|
||||
|
||||
class Foo extends A implements I {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package z;
|
||||
|
||||
interface I {
|
||||
void run();
|
||||
}
|
||||
abstract class A {
|
||||
public void <caret>run() {}
|
||||
}
|
||||
|
||||
class Foo extends A implements I {
|
||||
}
|
||||
@@ -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<String, String> function = (Function<String, String>)new Function<String, String>() {
|
||||
@Override
|
||||
public String apply(String input) {
|
||||
Collectors c;
|
||||
ArrayList l;
|
||||
System.out.println(input);
|
||||
//do something
|
||||
int i = 1;
|
||||
return input;
|
||||
}
|
||||
};
|
||||
Iterables.transfo<caret>rm(Collections.emptyList(), function);
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> function = (Function<String, String>)new Function<String, String>() {
|
||||
@Override
|
||||
public String apply(String input) {
|
||||
Collectors c;
|
||||
ArrayList l;
|
||||
System.out.println(input);
|
||||
//do something
|
||||
int i = 1;
|
||||
return input;
|
||||
}
|
||||
};
|
||||
Collections.<String>emptyList().stream().map(function::apply).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -6,13 +6,13 @@ import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().allMatch(getPredicate(100));
|
||||
Collections.<String>emptyList().stream().allMatch(getPredicate(100)::apply);
|
||||
}
|
||||
|
||||
public java.util.function.Predicate<String> getPredicate(final int param) {
|
||||
return new java.util.function.Predicate<String>() {
|
||||
public Predicate<String> getPredicate(final int param) {
|
||||
return new Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String input) {
|
||||
public boolean apply(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.f<caret>ind(Collections.emptyList(), new Predicate<Object>() {
|
||||
Iterables.f<caret>ind(Collections.emptyList(), new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(Object input) {
|
||||
public boolean apply(String input) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,6 +6,6 @@ import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().filter(input -> true).findFirst().get();
|
||||
Collections.<String>emptyList().stream().filter(input -> true).findFirst().get();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().map(input -> {
|
||||
Collections.<String>emptyList().stream().map(input -> {
|
||||
Collectors c;
|
||||
ArrayList l;
|
||||
System.out.println(input);
|
||||
|
||||
@@ -13,7 +13,7 @@ class c {
|
||||
System.out.println(input);
|
||||
//do something
|
||||
int i = 1;
|
||||
return input;
|
||||
return input.intern();
|
||||
}
|
||||
});
|
||||
}
|
||||
+1
-1
@@ -12,6 +12,6 @@ class c {
|
||||
System.out.println(input);
|
||||
//do something
|
||||
int i = 1;
|
||||
return input;
|
||||
return input.intern();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
+6
-2
@@ -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.transf<caret>orm(new ArrayList<>(), getFunction())
|
||||
Iterable<String> trnsfrmd = Iterables.transf<caret>orm(new ArrayList<>(), getFunction());
|
||||
}
|
||||
|
||||
Function<String, String> getFunction() {
|
||||
return new Function<String, String>() {
|
||||
|
||||
String apply(String s) {
|
||||
return s.toString().toLowerCase().replace('c', 'h');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-8
@@ -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<String> trnsfrmd = new ArrayList<String>().stream().map(getFunction()::apply).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
Function<String, String> getFunction() {
|
||||
return new Function<String, String>() {
|
||||
String apply(String s) {
|
||||
return s.toString().toLowerCase().replace('c', 'h');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().map(input -> {
|
||||
Collections.<String>emptyList().stream().map(input -> {
|
||||
Collectors c;
|
||||
ArrayList l;
|
||||
System.out.println(input);
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
PsiJavaFile:Receiver.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:m1
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:m1('m1')
|
||||
PsiParameterList:(C this)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiReceiverParameter
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:C
|
||||
PsiJavaCodeReferenceElement:C
|
||||
PsiIdentifier:C('C')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiThisExpression:this
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:m2
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:m2('m2')
|
||||
PsiParameterList:(T T.this)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiReceiverParameter
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:T
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiThisExpression:T.this
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:m3
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:m3('m3')
|
||||
PsiParameterList:(X Y.Z)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:Y
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:X
|
||||
PsiJavaCodeReferenceElement:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:Y('Y')
|
||||
PsiErrorElement:',' expected
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiJavaCodeReferenceElement:Z
|
||||
PsiIdentifier:Z('Z')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:f1
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:T
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f1('f1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLambdaExpression:(T this) -> { }
|
||||
PsiParameterList:(T this)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiReceiverParameter
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:T
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiThisExpression:this
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:f2
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:T
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f2('f2')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLambdaExpression:(T T.this) -> { }
|
||||
PsiParameterList:(T T.this)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiReceiverParameter
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:T
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiThisExpression:T.this
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class Test {
|
||||
void foo(Object o) {
|
||||
try {
|
||||
Runnable r = () -> {
|
||||
<selection>System.out.println(o);</selection>
|
||||
};
|
||||
} catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
+13
@@ -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);
|
||||
}
|
||||
}
|
||||
+29
-29
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+61
-11
@@ -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<LineMarkerInfo> 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<LineMarkerInfo> 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");
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -414,6 +414,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRawClassTypeOnConstructorReference() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
+6
-2
@@ -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();
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ public class RunConfigurableTest extends LightIdeaTestCase {
|
||||
private void doExpand() {
|
||||
List<DefaultMutableTreeNode> toExpand = new ArrayList<DefaultMutableTreeNode>();
|
||||
RunConfigurable.collectNodesRecursively(myRoot, toExpand, FOLDER);
|
||||
assertEquals(toExpand.size(), 5);
|
||||
assertEquals(5, toExpand.size());
|
||||
List<DefaultMutableTreeNode> toExpand2 = new ArrayList<DefaultMutableTreeNode>();
|
||||
RunConfigurable.collectNodesRecursively(myRoot, toExpand2, CONFIGURATION_TYPE);
|
||||
toExpand.addAll(toExpand2);
|
||||
|
||||
@@ -461,6 +461,10 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
|
||||
assertEquals(text+"\n", getEditor().getDocument().getText());
|
||||
}
|
||||
|
||||
public void testReplaceWithRegExp() {
|
||||
doTestRegexpReplace("# Base", "(?<!^) ", " ", "# Base");
|
||||
}
|
||||
|
||||
private void initProject(String folderName, final String... sourceDirs) {
|
||||
final String testDir = JavaTestUtil.getJavaTestDataPath() + "/find/" + folderName;
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
|
||||
+4
-12
@@ -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<T>"); }
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
-34
@@ -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<T extends List<String>> extends List<List<Integer>> { } }"); }
|
||||
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 \"<unspecified>\"; } }", 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 <E> test();\n" +
|
||||
" <E> void test1();\n" +
|
||||
" <E1 extends Integer, E2 extends Runnable> String test2(); }"); }
|
||||
public void testGenericMethod() {
|
||||
doParserTest(
|
||||
"{ public static <E> test();\n" +
|
||||
" <E> void test1();\n" +
|
||||
" <E1 extends Integer, E2 extends Runnable> String test2(); }");
|
||||
}
|
||||
|
||||
public void testGenericMethodErrors() { doParserTest("{ <Error sss /> test <error>(); }"); }
|
||||
public void testErrors() { doParserTest("{ public static <error descr=\"2\">protected int f1 = 0; }"); }
|
||||
public void testCompletionHack0() { doParserTest("{ <X IntelliJIdeaRulezz>\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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-10
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-33
@@ -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("<any T>");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-19
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <T> @A2 C();\n" +
|
||||
" C.@A3 B v = (@A4 C)v.new @A5 C();\n" +
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<root>
|
||||
<item name='org.hamcrest.SelfDescribing void describeTo(org.hamcrest.Description) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='org.hamcrest.TypeSafeDiagnosingMatcher boolean matchesSafely(T, org.hamcrest.Description) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='org.hamcrest.TypeSafeDiagnosingMatcher boolean matchesSafely(T, org.hamcrest.Description) 1'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ public abstract class SchemesManager<T extends Scheme, E extends ExternalizableS
|
||||
@Nullable
|
||||
public abstract T findSchemeByName(@NotNull String schemeName);
|
||||
|
||||
public abstract void save();
|
||||
|
||||
public abstract void setCurrentSchemeName(@Nullable String schemeName);
|
||||
|
||||
@Nullable
|
||||
@@ -60,6 +58,9 @@ public abstract class SchemesManager<T extends Scheme, E extends ExternalizableS
|
||||
|
||||
public abstract File getRootDirectory();
|
||||
|
||||
/**
|
||||
* Must be called before {@link #loadSchemes}
|
||||
*/
|
||||
public void loadBundledScheme(@NotNull String resourceName, @NotNull Object requestor, @NotNull ThrowableConvertor<Element, T, Throwable> convertor) {
|
||||
}
|
||||
|
||||
@@ -69,4 +70,11 @@ public abstract class SchemesManager<T extends Scheme, E extends ExternalizableS
|
||||
|
||||
public void setSchemes(@NotNull List<T> schemes, @Nullable Condition<T> removeCondition) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Bundled / read-only (or overriding) scheme cannot be renamed or deleted.
|
||||
*/
|
||||
public boolean isMetadataEditable(@NotNull E scheme) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
<orderEntry type="library" name="picocontainer" level="project" />
|
||||
<orderEntry type="module" module-name="boot" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -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<String> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ public class PsiBuilderAdapter implements PsiBuilder {
|
||||
return myDelegate.getCurrentOffset();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Marker mark() {
|
||||
return myDelegate.mark();
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -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 <code>'defer changes'</code> 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<String> 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<TextChangeImpl> 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<TextChangeImpl>();
|
||||
}
|
||||
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<String>(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 <code>true</code> 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.
|
||||
* <p/>
|
||||
* This method allows to define that <code>'defer changes'</code> mode usages, i.e. expected usage pattern is as follows:
|
||||
* <pre>
|
||||
* <ol>
|
||||
* <li>
|
||||
* Client of this class enters <code>'defer changes'</code> mode (calls this method with <code>'true'</code> argument).
|
||||
* That means that all subsequent changes will not actually modify backed array data and will be stored separately;
|
||||
* </li>
|
||||
* <li>
|
||||
* 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)});
|
||||
* </li>
|
||||
* <li>
|
||||
* Client of this class indicates that <code>'massive change time'</code> is over by calling this method with <code>'false'</code>
|
||||
* 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;
|
||||
* </li>
|
||||
* </ol>
|
||||
* </pre>
|
||||
* <p/>
|
||||
* <b>Note:</b> we can't exclude possibility that <code>'defer changes'</code> mode is started but inadvertently not ended
|
||||
* (due to programming error, unexpected exception etc). Hence, this class is free to automatically end
|
||||
* <code>'defer changes'</code> mode when necessary in order to avoid memory leak with infinite deferred changes storing.
|
||||
*
|
||||
* @param deferredChangeMode flag that defines if <code>'defer changes'</code> 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<TextChangeImpl> 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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -48,10 +48,6 @@ public class EmptySchemesManager extends SchemesManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentSchemeName(String schemeName) {
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 <T> UserDataHolderBase createUserDataHolder(@NotNull Key<T> key1, @Nullable T value1,
|
||||
@NotNull Key<T> key2, @Nullable T value2) {
|
||||
UserDataHolderBase holder = new UserDataHolderBase();
|
||||
holder.putUserData(key1, value1);
|
||||
holder.putUserData(key2, value2);
|
||||
return holder;
|
||||
}
|
||||
|
||||
public static boolean isUserDataFlagSet(@NotNull Key<Boolean> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -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.<p/>
|
||||
*
|
||||
* 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.<p/>
|
||||
*
|
||||
* During indexing, click handlers are only invoked for renderers implementing {@link com.intellij.openapi.project.DumbAware}.
|
||||
*
|
||||
* @author max
|
||||
* @see RangeHighlighter#setGutterIconRenderer(GutterIconRenderer)
|
||||
*/
|
||||
|
||||
@@ -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<Void>() {
|
||||
@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<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
|
||||
Set<PsiFile> processed = new THashSet<PsiFile>(psiRoots.size() * 2, (float)0.5);
|
||||
for (final PsiFile psiRoot : psiRoots) {
|
||||
|
||||
@@ -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<T extends PsiElement> extends AnAction {
|
||||
private LineMarkerInfo<T> myInfo;
|
||||
private final LineMarkerInfo<T> myInfo;
|
||||
|
||||
public NavigateAction(String text,
|
||||
LineMarkerInfo<T> info,
|
||||
public NavigateAction(@NotNull String text,
|
||||
@NotNull LineMarkerInfo<T> info,
|
||||
@Nullable String originalActionId) {
|
||||
super(text);
|
||||
myInfo = info;
|
||||
@@ -41,7 +42,7 @@ public class NavigateAction<T extends PsiElement> extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
public NavigateAction(LineMarkerInfo<T> info) {
|
||||
public NavigateAction(@NotNull LineMarkerInfo<T> info) {
|
||||
myInfo = info;
|
||||
}
|
||||
|
||||
@@ -56,7 +57,8 @@ public class NavigateAction<T extends PsiElement> extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends PsiElement> LineMarkerInfo<T> setNavigateAction(LineMarkerInfo<T> info, String text, @Nullable String originalActionId) {
|
||||
@NotNull
|
||||
public static <T extends PsiElement> LineMarkerInfo<T> setNavigateAction(@NotNull LineMarkerInfo<T> info, @NotNull String text, @Nullable String originalActionId) {
|
||||
NavigateAction<T> action = new NavigateAction<T>(text, info, originalActionId);
|
||||
info.setNavigateAction(action);
|
||||
return info;
|
||||
|
||||
@@ -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).
|
||||
*
|
||||
|
||||
@@ -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<Settings extends RunnerSettings> 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);
|
||||
|
||||
+4
-3
@@ -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<Object[]> consumer) {
|
||||
@NotNull final Consumer<Object[]> consumer) {
|
||||
if (targets.length == 0) return null;
|
||||
if (targets.length == 1) {
|
||||
consumer.consume(targets);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user