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:
@@ -344,10 +344,6 @@ public def layoutCommunityPlugins(String home) {
|
||||
jar("gradle-tooling-extension-impl.jar") {
|
||||
module("gradle-tooling-extension-impl")
|
||||
}
|
||||
|
||||
jar("gradle-tooling-extension.jar") {
|
||||
module("gradle-tooling-extension")
|
||||
}
|
||||
fileset(dir: "$home/plugins/gradle/lib") { include(name: "*.jar") }
|
||||
}
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ public abstract class QuickFixFactory {
|
||||
|
||||
@NotNull public abstract IntentionAction createDeferFinalAssignmentFix(@NotNull PsiVariable variable, @NotNull PsiReferenceExpression expression);
|
||||
|
||||
@NotNull public abstract IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass);
|
||||
@NotNull public abstract IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement scope);
|
||||
|
||||
@NotNull public abstract IntentionAction createCreateConstructorParameterFromFieldFix(@NotNull PsiField field);
|
||||
|
||||
|
||||
+14
-6
@@ -42,6 +42,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -326,7 +327,8 @@ public class GenericsHighlightUtil {
|
||||
if (errorResult == null && languageLevel.isAtLeast(LanguageLevel.JDK_1_7) &&
|
||||
referenceElements.length > 1) {
|
||||
//todo suppress erased methods which come from the same class
|
||||
return checkOverrideEquivalentMethods(languageLevel, aClass);
|
||||
final Collection<HighlightInfo> result = checkOverrideEquivalentMethods(languageLevel, aClass);
|
||||
return result != null && result.size() > 0 ? result.iterator().next() : null;
|
||||
}
|
||||
return errorResult;
|
||||
}
|
||||
@@ -380,23 +382,29 @@ public class GenericsHighlightUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HighlightInfo checkOverrideEquivalentMethods(@NotNull LanguageLevel languageLevel,
|
||||
@NotNull PsiClass aClass) {
|
||||
public static Collection<HighlightInfo> checkOverrideEquivalentMethods(@NotNull LanguageLevel languageLevel,
|
||||
@NotNull PsiClass aClass) {
|
||||
List<HighlightInfo> result = new ArrayList<HighlightInfo>();
|
||||
final Collection<HierarchicalMethodSignature> signaturesWithSupers = aClass.getVisibleSignatures();
|
||||
PsiManager manager = aClass.getManager();
|
||||
Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods =
|
||||
new THashMap<MethodSignature, MethodSignatureBackedByPsiMethod>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
|
||||
|
||||
final Set<MethodSignature> foundProblems = new THashSet<MethodSignature>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
|
||||
for (HierarchicalMethodSignature signature : signaturesWithSupers) {
|
||||
HighlightInfo info = checkSameErasureNotSubSignatureInner(signature, manager, aClass, sameErasureMethods);
|
||||
if (info != null) return info;
|
||||
if (info != null && foundProblems.add(signature)) {
|
||||
result.add(info);
|
||||
}
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
info = HighlightMethodUtil.checkMethodIncompatibleReturnType(signature, signature.getSuperSignatures(), true, HighlightNamesUtil.getClassDeclarationTextRange(aClass));
|
||||
if (info != null) return info;
|
||||
if (info != null) {
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return result.isEmpty() ? null : result;
|
||||
}
|
||||
|
||||
static HighlightInfo checkDefaultMethodOverrideEquivalentToObjectNonPrivate(@NotNull LanguageLevel languageLevel,
|
||||
|
||||
+15
-8
@@ -590,7 +590,7 @@ public class HighlightControlFlowUtil {
|
||||
JavaErrorMessages.message("assignment.to.final.variable", name);
|
||||
final HighlightInfo highlightInfo =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(reference.getTextRange()).descriptionAndTooltip(description).create();
|
||||
final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression);
|
||||
final PsiElement innerClass = getInnerClassVariableReferencedFrom(variable, expression);
|
||||
if (innerClass == null || variable instanceof PsiField) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo,
|
||||
QUICK_FIX_FACTORY.createModifierListFix(variable, PsiModifier.FINAL, false, false));
|
||||
@@ -607,7 +607,7 @@ public class HighlightControlFlowUtil {
|
||||
private static boolean canWriteToFinal(PsiVariable variable, PsiExpression expression, final PsiReferenceExpression reference, @NotNull PsiFile containingFile) {
|
||||
if (variable.hasInitializer()) return false;
|
||||
if (variable instanceof PsiParameter) return false;
|
||||
PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression);
|
||||
PsiElement innerClass = getInnerClassVariableReferencedFrom(variable, expression);
|
||||
if (variable instanceof PsiField) {
|
||||
// if inside some field initializer
|
||||
if (HighlightUtil.findEnclosingFieldInitializer(expression) != null) return true;
|
||||
@@ -642,8 +642,8 @@ public class HighlightControlFlowUtil {
|
||||
@NotNull PsiJavaCodeReferenceElement context,
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
if (variable.hasModifierProperty(PsiModifier.FINAL)) return null;
|
||||
final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context);
|
||||
if (innerClass != null) {
|
||||
final PsiElement innerClass = getInnerClassVariableReferencedFrom(variable, context);
|
||||
if (innerClass instanceof PsiClass) {
|
||||
if (variable instanceof PsiParameter) {
|
||||
final PsiElement parent = variable.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression &&
|
||||
@@ -672,8 +672,12 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
if (!isEffectivelyFinal(variable, lambdaExpression, context)) {
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip(
|
||||
"Variable used in lambda expression should be effectively final").create();
|
||||
final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(context)
|
||||
.descriptionAndTooltip("Variable used in lambda expression should be effectively final")
|
||||
.create();
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createVariableAccessFromInnerClassFix(variable, lambdaExpression));
|
||||
return highlightInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -716,7 +720,7 @@ public class HighlightControlFlowUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getInnerClassVariableReferencedFrom(@NotNull PsiVariable variable, @NotNull PsiElement context) {
|
||||
public static PsiElement getInnerClassVariableReferencedFrom(@NotNull PsiVariable variable, @NotNull PsiElement context) {
|
||||
final PsiElement[] scope;
|
||||
if (variable instanceof PsiResourceVariable) {
|
||||
scope = ((PsiResourceVariable)variable).getDeclarationScope();
|
||||
@@ -741,7 +745,10 @@ public class HighlightControlFlowUtil {
|
||||
if (parent.equals(scopeElement)) break outer;
|
||||
}
|
||||
if (parent instanceof PsiClass && !(prevParent instanceof PsiExpressionList && parent instanceof PsiAnonymousClass)) {
|
||||
return (PsiClass)parent;
|
||||
return parent;
|
||||
}
|
||||
if (parent instanceof PsiLambdaExpression) {
|
||||
return parent;
|
||||
}
|
||||
prevParent = parent;
|
||||
parent = parent.getParent();
|
||||
|
||||
+1
-1
@@ -1181,7 +1181,7 @@ public class HighlightMethodUtil {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (JavaGenericsUtil.isRawToGeneric(currentType, otherSuperReturnType)) continue;
|
||||
if (currentMethod.getTypeParameters().length > 0 && JavaGenericsUtil.isRawToGeneric(currentType, otherSuperReturnType)) continue;
|
||||
}
|
||||
return createIncompatibleReturnTypeMessage(currentMethod, otherSuperMethod, otherSuperReturnType,
|
||||
currentType, JavaErrorMessages.message("unrelated.overriding.methods.return.types"),
|
||||
|
||||
-4
@@ -684,10 +684,6 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
String message = JavaErrorMessages.message("underscore.lambda.identifier");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create();
|
||||
}
|
||||
else {
|
||||
String message = JavaErrorMessages.message("underscore.identifier");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(identifier).descriptionAndTooltip(message).create();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+2
-3
@@ -888,8 +888,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper));
|
||||
}
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass, myFile));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass
|
||||
));
|
||||
if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass));
|
||||
}
|
||||
catch (IndexNotReadyException ignored) {
|
||||
@@ -1045,7 +1044,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
|
||||
if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
|
||||
PsiClass aClass = (PsiClass)parent;
|
||||
myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass));
|
||||
myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass));
|
||||
}
|
||||
|
||||
if (resolved instanceof PsiVariable) {
|
||||
|
||||
+12
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.compiler;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -63,4 +65,14 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIdentifier(PsiIdentifier identifier) {
|
||||
super.visitIdentifier(identifier);
|
||||
if (PsiUtil.getLanguageLevel(identifier).isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
if ("_".equals(identifier.getText())) {
|
||||
myHolder.registerProblem(identifier, JavaErrorMessages.message("underscore.identifier"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -198,6 +198,18 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
|
||||
super.visitMethodReferenceExpression(expression);
|
||||
if (IGNORE_UNCHECKED_CALL) return;
|
||||
final JavaResolveResult result = expression.advancedResolve(false);
|
||||
final String description = getUncheckedCallDescription(result);
|
||||
if (description != null) {
|
||||
final PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
registerProblem(description, referenceNameElement != null ? referenceNameElement : expression, myGenerifyFixes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallExpression(PsiCallExpression callExpression) {
|
||||
super.visitCallExpression(callExpression);
|
||||
@@ -383,8 +395,9 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
|
||||
|
||||
@Nullable
|
||||
private String getUncheckedCallDescription(JavaResolveResult resolveResult) {
|
||||
final PsiMethod method = (PsiMethod)resolveResult.getElement();
|
||||
if (method == null) return null;
|
||||
final PsiElement element = resolveResult.getElement();
|
||||
if (!(element instanceof PsiMethod)) return null;
|
||||
final PsiMethod method = (PsiMethod)element;
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
if (!PsiUtil.isRawSubstitutor(method, substitutor)) return null;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -400,7 +400,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return isSecondCompletion;
|
||||
|
||||
if (parent instanceof PsiJavaCodeReferenceElementImpl &&
|
||||
((PsiJavaCodeReferenceElementImpl)parent).getKind() == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) {
|
||||
((PsiJavaCodeReferenceElementImpl)parent).getKind(parent.getContainingFile()) == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -124,15 +124,16 @@ public class CreateMethodFromMethodReferenceFix extends CreateFromUsageBaseFix {
|
||||
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
|
||||
LOG.assertTrue(interfaceReturnType != null);
|
||||
|
||||
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult);
|
||||
final ExpectedTypeInfo[] expectedTypes = {new ExpectedTypeInfoImpl(interfaceReturnType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, interfaceReturnType, TailType.NONE, null, ExpectedTypeInfoImpl.NULL)};
|
||||
CreateMethodFromUsageFix.doCreate(targetClass, method, false,
|
||||
ContainerUtil.map2List(interfaceMethod.getParameterList().getParameters(), new Function<PsiParameter, Pair<PsiExpression, PsiType>>() {
|
||||
@Override
|
||||
public Pair<PsiExpression, PsiType> fun(PsiParameter parameter) {
|
||||
return Pair.create(null, parameter.getType());
|
||||
return Pair.create(null, substitutor.substitute(parameter.getType()));
|
||||
}
|
||||
}),
|
||||
LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult),
|
||||
PsiSubstitutor.EMPTY,
|
||||
expectedTypes, context);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -17,14 +17,14 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilCore;
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.template.Template;
|
||||
import com.intellij.codeInsight.template.TemplateBuilderImpl;
|
||||
import com.intellij.codeInsight.template.TemplateEditingAdapter;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -259,7 +259,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
|
||||
startTemplate(newEditor, template, project, new TemplateEditingAdapter() {
|
||||
@Override
|
||||
public void templateFinished(Template template, boolean brokenOff) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument());
|
||||
|
||||
+19
-19
@@ -42,16 +42,16 @@ import java.util.*;
|
||||
public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix");
|
||||
private final PsiVariable myVariable;
|
||||
private final PsiClass myClass;
|
||||
private final PsiElement myContext;
|
||||
private final int myFixType;
|
||||
private static final int MAKE_FINAL = 0;
|
||||
private static final int MAKE_ARRAY = 1;
|
||||
private static final int COPY_TO_FINAL = 2;
|
||||
private static final Key<Map<PsiVariable,Boolean>>[] VARS = new Key[] {Key.create("VARS_TO_MAKE_FINAL"), Key.create("VARS_TO_TRANSFORM"), Key.create("???")};
|
||||
|
||||
public VariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass) {
|
||||
public VariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement element) {
|
||||
myVariable = variable;
|
||||
myClass = aClass;
|
||||
myContext = element;
|
||||
myFixType = getQuickFixType(variable);
|
||||
if (myFixType == -1) return;
|
||||
|
||||
@@ -87,21 +87,21 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return myClass.isValid() &&
|
||||
myClass.getManager().isInProject(myClass) &&
|
||||
return myContext.isValid() &&
|
||||
myContext.getManager().isInProject(myContext) &&
|
||||
myVariable.isValid() &&
|
||||
myFixType != -1 &&
|
||||
!getVariablesToFix().isEmpty() &&
|
||||
!inOwnInitializer(myVariable, myClass);
|
||||
!inOwnInitializer(myVariable, myContext);
|
||||
}
|
||||
|
||||
private static boolean inOwnInitializer(PsiVariable variable, PsiClass aClass) {
|
||||
return PsiTreeUtil.isAncestor(variable, aClass, false);
|
||||
private static boolean inOwnInitializer(PsiVariable variable, PsiElement context) {
|
||||
return PsiTreeUtil.isAncestor(variable, context, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(myClass, myVariable)) return;
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(myContext, myVariable)) return;
|
||||
try {
|
||||
switch (myFixType) {
|
||||
case MAKE_FINAL:
|
||||
@@ -131,8 +131,8 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
|
||||
@NotNull
|
||||
private Collection<PsiVariable> getVariablesToFix() {
|
||||
Map<PsiVariable, Boolean> vars = myClass.getUserData(VARS[myFixType]);
|
||||
if (vars == null) myClass.putUserData(VARS[myFixType], vars = new ConcurrentWeakHashMap<PsiVariable, Boolean>(1));
|
||||
Map<PsiVariable, Boolean> vars = myContext.getUserData(VARS[myFixType]);
|
||||
if (vars == null) myContext.putUserData(VARS[myFixType], vars = new ConcurrentWeakHashMap<PsiVariable, Boolean>(1));
|
||||
final Map<PsiVariable, Boolean> finalVars = vars;
|
||||
return new AbstractCollection<PsiVariable>() {
|
||||
@Override
|
||||
@@ -164,7 +164,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
private void makeArray(PsiVariable variable) throws IncorrectOperationException {
|
||||
PsiType type = variable.getType();
|
||||
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(myContext.getProject()).getElementFactory();
|
||||
PsiType newType = type.createArrayType();
|
||||
|
||||
PsiDeclarationStatement variableDeclarationStatement;
|
||||
@@ -195,9 +195,9 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
}
|
||||
|
||||
private void copyToFinal() throws IncorrectOperationException {
|
||||
PsiManager psiManager = myClass.getManager();
|
||||
PsiManager psiManager = myContext.getManager();
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
|
||||
PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myClass);
|
||||
PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myContext);
|
||||
String newName = suggestNewName(psiManager.getProject(), myVariable);
|
||||
PsiType type = myVariable.getType();
|
||||
PsiDeclarationStatement copyDecl = factory.createVariableDeclarationStatement(newName, type, initializer);
|
||||
@@ -206,7 +206,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
PsiElement statement = getStatementToInsertBefore();
|
||||
if (statement == null) return;
|
||||
PsiExpression newExpression = factory.createExpressionFromText(newName, myVariable);
|
||||
replaceReferences(myClass, myVariable, newExpression);
|
||||
replaceReferences(myContext, myVariable, newExpression);
|
||||
if (RefactoringUtil.isLoopOrIf(statement.getParent())) {
|
||||
RefactoringUtil.putStatementInLoopBody(copyDecl, statement.getParent(), statement);
|
||||
} else {
|
||||
@@ -219,7 +219,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
? ((PsiParameter)myVariable).getDeclarationScope() : PsiUtil.getVariableCodeBlock(myVariable, null);
|
||||
if (declarationScope == null) return null;
|
||||
|
||||
PsiElement statement = myClass;
|
||||
PsiElement statement = myContext;
|
||||
nextInnerClass:
|
||||
do {
|
||||
statement = RefactoringUtil.getParentStatement(statement, false);
|
||||
@@ -291,11 +291,11 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
|
||||
int type = MAKE_FINAL;
|
||||
for (PsiReferenceExpression expression : outerReferences) {
|
||||
// if it happens that variable referenced from another inner class, make sure it can be make final from there
|
||||
PsiClass innerClass = HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression);
|
||||
PsiElement innerScope = HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression);
|
||||
|
||||
if (innerClass != null) {
|
||||
if (innerScope != null) {
|
||||
int thisType = MAKE_FINAL;
|
||||
if (writtenInside(variable, innerClass)) {
|
||||
if (writtenInside(variable, innerScope)) {
|
||||
// cannot make parameter array
|
||||
if (variable instanceof PsiParameter) return -1;
|
||||
thisType = MAKE_ARRAY;
|
||||
|
||||
+2
-2
@@ -547,8 +547,8 @@ public class QuickFixFactoryImpl extends QuickFixFactory {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass) {
|
||||
return new VariableAccessFromInnerClassFix(variable, aClass);
|
||||
public IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement scope) {
|
||||
return new VariableAccessFromInnerClassFix(variable, scope);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-6
@@ -19,8 +19,8 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElement {
|
||||
@@ -44,15 +44,11 @@ public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElemen
|
||||
public void renderElement(LookupElementPresentation presentation) {
|
||||
super.renderElement(presentation);
|
||||
if (sudden) {
|
||||
presentation.setTailText(" " + arrow() + " " + myTemplate.getExample());
|
||||
presentation.setTailText(" " + UIUtil.rightArrow() + " " + myTemplate.getExample());
|
||||
}
|
||||
else {
|
||||
presentation.setTypeText(myTemplate.getExample());
|
||||
presentation.setTypeGrayed(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static String arrow() {
|
||||
return SystemInfo.isMac ? "→" : "->";
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.codeInsight.completion.PrefixMatcher;
|
||||
import com.intellij.codeInsight.template.CustomTemplateCallback;
|
||||
import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor;
|
||||
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
|
||||
@@ -42,8 +43,8 @@ class PostfixTemplatesCompletionProvider extends CompletionProvider<CompletionPa
|
||||
PostfixLiveTemplate postfixLiveTemplate = getPostfixLiveTemplate(parameters.getOriginalFile(), parameters.getEditor());
|
||||
if (postfixLiveTemplate != null) {
|
||||
postfixLiveTemplate.addCompletions(parameters, result.withPrefixMatcher(new MyPrefixMatcher(result.getPrefixMatcher().getPrefix())));
|
||||
String possibleKey = postfixLiveTemplate
|
||||
.computeTemplateKeyWithoutContextChecking(parameters.getOriginalFile(), parameters.getEditor(), parameters.getOffset());
|
||||
String possibleKey = postfixLiveTemplate.computeTemplateKeyWithoutContextChecking(
|
||||
new CustomTemplateCallback(parameters.getEditor(), parameters.getOriginalFile(), false));
|
||||
if (possibleKey != null) {
|
||||
result = result.withPrefixMatcher(possibleKey);
|
||||
result.restartCompletionOnPrefixChange(
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ abstract public class BooleanPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression topmostExpression = getTopmostExpression(context);
|
||||
PsiExpression topmostExpression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
return topmostExpression != null && PostfixTemplatesUtils.isBoolean(topmostExpression.getType());
|
||||
}
|
||||
}
|
||||
|
||||
+16
-1
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightServicesUtil;
|
||||
@@ -15,7 +30,7 @@ public class ElseStatementPostfixTemplate extends BooleanPostfixTemplate {
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
assert expression != null;
|
||||
PsiExpression invertedExpression = (PsiExpression)expression.replace(CodeInsightServicesUtil.invertCondition(expression));
|
||||
TextRange range = PostfixTemplatesUtils.ifStatement(invertedExpression.getProject(), editor, invertedExpression);
|
||||
|
||||
+14
-5
@@ -42,6 +42,13 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
|
||||
super(name, description, example);
|
||||
}
|
||||
|
||||
protected ExpressionPostfixTemplateWithChooser(@NotNull String name,
|
||||
@NotNull String key,
|
||||
@NotNull String description,
|
||||
@NotNull String example) {
|
||||
super(name, key, description, example);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
return !getExpressions(context, copyDocument, newOffset).isEmpty();
|
||||
@@ -75,20 +82,22 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
|
||||
}
|
||||
},
|
||||
new PsiExpressionTrimRenderer.RenderFunction(),
|
||||
"Expressions", 0, ScopeHighlighter.NATURAL_RANGER);
|
||||
"Expressions", 0, ScopeHighlighter.NATURAL_RANGER
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected List<PsiExpression> getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) {
|
||||
List<PsiExpression> expressions = ContainerUtil.filter(IntroduceVariableBase.collectExpressions(context.getContainingFile(), document,
|
||||
Math.max(offset - 1, 0), false),
|
||||
List<PsiExpression> expressions = ContainerUtil.filter(IntroduceVariableBase.collectExpressions(context.getContainingFile(), document,
|
||||
Math.max(offset - 1, 0), false),
|
||||
new Condition<PsiExpression>() {
|
||||
@Override
|
||||
public boolean value(PsiExpression expression) {
|
||||
return expression.getTextRange().getEndOffset() == offset;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition());
|
||||
}
|
||||
|
||||
@@ -100,7 +109,7 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
|
||||
|
||||
@NotNull
|
||||
private static List<PsiExpression> maybeTopmostExpression(@NotNull PsiElement context) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
PsiType type = expression != null ? expression.getType() : null;
|
||||
if (type == null || PsiType.VOID.equals(type)) return ContainerUtil.emptyList();
|
||||
return ContainerUtil.createMaybeSingletonList(expression);
|
||||
|
||||
+2
-2
@@ -37,7 +37,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
return expr != null && (PostfixTemplatesUtils.isNumber(expr.getType()) ||
|
||||
PostfixTemplatesUtils.isArray(expr.getType()) ||
|
||||
PostfixTemplatesUtils.isIterable(expr.getType()));
|
||||
@@ -45,7 +45,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
if (expr == null) {
|
||||
PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
|
||||
return;
|
||||
|
||||
+2
-2
@@ -37,13 +37,13 @@ public class ForeachPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
return expr != null && (PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
if (expr == null) return;
|
||||
Project project = context.getProject();
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class FormatPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
PsiType type = expr != null ? expr.getType() : null;
|
||||
return expr != null && type != null && CommonClassNames.JAVA_LANG_STRING.equals(type.getCanonicalText());
|
||||
}
|
||||
|
||||
+16
-1
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
@@ -14,7 +29,7 @@ public class IfStatementPostfixTemplate extends BooleanPostfixTemplate {
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
assert expression != null;
|
||||
TextRange range = PostfixTemplatesUtils.ifStatement(expression.getProject(), editor, expression);
|
||||
if (range != null) {
|
||||
|
||||
+10
-6
@@ -19,7 +19,6 @@ import com.intellij.codeInsight.guess.GuessManager;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.codeInsight.template.*;
|
||||
import com.intellij.codeInsight.template.postfix.util.Aliases;
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -35,25 +34,30 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Aliases(".inst")
|
||||
public class InstanceofExpressionPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
public InstanceofExpressionPostfixTemplate() {
|
||||
super("instanceof", "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null");
|
||||
this("instanceof");
|
||||
}
|
||||
|
||||
public InstanceofExpressionPostfixTemplate(String alias) {
|
||||
super(alias, "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(getTopmostExpression(context));
|
||||
return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expression)) return;
|
||||
surroundExpression(context.getProject(), editor, expression);
|
||||
}
|
||||
|
||||
private static void surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) throws IncorrectOperationException {
|
||||
private static void surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr)
|
||||
throws IncorrectOperationException {
|
||||
assert expr.isValid();
|
||||
PsiType[] types = GuessManager.getInstance(project).guessTypeToCast(expr);
|
||||
final boolean parenthesesNeeded = expr instanceof PsiPolyadicExpression ||
|
||||
|
||||
+33
-70
@@ -18,10 +18,8 @@ package com.intellij.codeInsight.template.postfix.templates;
|
||||
import com.intellij.codeInsight.completion.CompletionInitializationContext;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionContributor;
|
||||
import com.intellij.codeInsight.template.CustomTemplateCallback;
|
||||
import com.intellij.codeInsight.template.postfix.util.Aliases;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
@@ -30,75 +28,47 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
|
||||
private final Set<PostfixTemplate> templates;
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(JavaPostfixTemplateProvider.class);
|
||||
|
||||
private final Map<String, PostfixTemplate> myMapTemplates;
|
||||
|
||||
public JavaPostfixTemplateProvider() {
|
||||
myMapTemplates = ContainerUtil.newHashMap();
|
||||
for (PostfixTemplate template : getInitializeTemplateSet()) {
|
||||
register(template.getKey(), template);
|
||||
Aliases aliases = template.getClass().getAnnotation(Aliases.class);
|
||||
if (aliases != null) {
|
||||
for (String key : aliases.value()) {
|
||||
register(key, template);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Set<PostfixTemplate> getInitializeTemplateSet() {
|
||||
return ContainerUtil.newHashSet(new AssertStatementPostfixTemplate(),
|
||||
new CastExpressionPostfixTemplate(),
|
||||
new ElseStatementPostfixTemplate(),
|
||||
new ForAscendingPostfixTemplate(),
|
||||
new ForDescendingPostfixTemplate(),
|
||||
new ForeachPostfixTemplate(),
|
||||
new FormatPostfixTemplate(),
|
||||
new IfStatementPostfixTemplate(),
|
||||
new InstanceofExpressionPostfixTemplate(),
|
||||
new IntroduceFieldPostfixTemplate(),
|
||||
new IntroduceVariablePostfixTemplate(),
|
||||
new IsNullCheckPostfixTemplate(),
|
||||
new NotExpressionPostfixTemplate(),
|
||||
new NotNullCheckPostfixTemplate(),
|
||||
new ParenthesizedExpressionPostfixTemplate(),
|
||||
new ReturnStatementPostfixTemplate(),
|
||||
new SoutPostfixTemplate(),
|
||||
new SwitchStatementPostfixTemplate(),
|
||||
new SynchronizedStatementPostfixTemplate(),
|
||||
new ThrowExceptionPostfixTemplate(),
|
||||
new TryStatementPostfixTemplate(),
|
||||
new TryWithResourcesPostfixTemplate(),
|
||||
new WhileStatementPostfixTemplate());
|
||||
templates = ContainerUtil.newHashSet(new AssertStatementPostfixTemplate(),
|
||||
new CastExpressionPostfixTemplate(),
|
||||
new ElseStatementPostfixTemplate(),
|
||||
new ForAscendingPostfixTemplate(),
|
||||
new ForDescendingPostfixTemplate(),
|
||||
new ForeachPostfixTemplate(),
|
||||
new FormatPostfixTemplate(),
|
||||
new IfStatementPostfixTemplate(),
|
||||
new InstanceofExpressionPostfixTemplate(),
|
||||
new InstanceofExpressionPostfixTemplate("inst"),
|
||||
new IntroduceFieldPostfixTemplate(),
|
||||
new IntroduceVariablePostfixTemplate(),
|
||||
new IsNullCheckPostfixTemplate(),
|
||||
new NotExpressionPostfixTemplate(),
|
||||
new NotExpressionPostfixTemplate("!"),
|
||||
new NotNullCheckPostfixTemplate(),
|
||||
new NotNullCheckPostfixTemplate("nn"),
|
||||
new ParenthesizedExpressionPostfixTemplate(),
|
||||
new ReturnStatementPostfixTemplate(),
|
||||
new SoutPostfixTemplate(),
|
||||
new SwitchStatementPostfixTemplate(),
|
||||
new SynchronizedStatementPostfixTemplate(),
|
||||
new ThrowExceptionPostfixTemplate(),
|
||||
new TryStatementPostfixTemplate(),
|
||||
new TryWithResourcesPostfixTemplate(),
|
||||
new WhileStatementPostfixTemplate());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<PostfixTemplate> getTemplates() {
|
||||
return ContainerUtil.newHashSet(myMapTemplates.values());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
return myMapTemplates.keySet();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PostfixTemplate get(@Nullable String key) {
|
||||
return myMapTemplates.get(key);
|
||||
return templates;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,24 +85,17 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile file, int currentOffset) {
|
||||
Document document = file.getViewProvider().getDocument();
|
||||
public PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile copyFile, int currentOffset) {
|
||||
Document document = copyFile.getViewProvider().getDocument();
|
||||
assert document != null;
|
||||
CharSequence sequence = document.getCharsSequence();
|
||||
StringBuilder fileContentWithoutKey = new StringBuilder(sequence);
|
||||
if (isSemicolonNeeded(file, editor)) {
|
||||
if (isSemicolonNeeded(copyFile, editor)) {
|
||||
fileContentWithoutKey.insert(currentOffset, ';');
|
||||
file = PostfixLiveTemplate.copyFile(file, fileContentWithoutKey);
|
||||
copyFile = PostfixLiveTemplate.copyFile(copyFile, fileContentWithoutKey);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private void register(@NotNull String key, @NotNull PostfixTemplate template) {
|
||||
PostfixTemplate registered = myMapTemplates.put(key, template);
|
||||
if (registered != null) {
|
||||
LOG.error("Can't register postfix template. Duplicated key: " + template.getKey());
|
||||
}
|
||||
return copyFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ package com.intellij.codeInsight.template.postfix.templates;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
|
||||
public class LanguagePostfixTemplate extends LanguageExtension<PostfixTemplateProvider> {
|
||||
public static final LanguagePostfixTemplate INSTANCE = new LanguagePostfixTemplate();
|
||||
public static final LanguagePostfixTemplate LANG_EP = new LanguagePostfixTemplate();
|
||||
public static final String EP_NAME = "com.intellij.codeInsight.template.postfixTemplateProvider";
|
||||
|
||||
private LanguagePostfixTemplate() {
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ abstract public class NonVoidPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
return expr != null && PostfixTemplatesUtils.isNonVoid(expr.getType());
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -16,14 +16,12 @@
|
||||
package com.intellij.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightServicesUtil;
|
||||
import com.intellij.codeInsight.template.postfix.util.Aliases;
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Aliases("!")
|
||||
public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
|
||||
private static final Condition<PsiExpression> BOOLEAN_TYPE_CONDITION = new Condition<PsiExpression>() {
|
||||
@Override
|
||||
@@ -36,6 +34,10 @@ public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithC
|
||||
super("not", "Negates boolean expression", "!expr");
|
||||
}
|
||||
|
||||
public NotExpressionPostfixTemplate(String alias) {
|
||||
super(alias, alias, "Negates boolean expression", "!expr");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) {
|
||||
expression.replace(CodeInsightServicesUtil.invertCondition(expression));
|
||||
|
||||
+21
-3
@@ -1,12 +1,30 @@
|
||||
/*
|
||||
* 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.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.template.postfix.util.Aliases;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Aliases(".nn")
|
||||
public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate {
|
||||
|
||||
public NotNullCheckPostfixTemplate() {
|
||||
super("notnull", "Checks expression to be not-null", "if (expr != null)");
|
||||
this("notnull");
|
||||
}
|
||||
|
||||
public NotNullCheckPostfixTemplate(String alias) {
|
||||
super(alias, "Checks expression to be not-null", "if (expr != null)");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-2
@@ -39,12 +39,12 @@ public abstract class NullCheckPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(getTopmostExpression(context));
|
||||
return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expr)) return;
|
||||
|
||||
Project project = expr.getProject();
|
||||
|
||||
+82
-104
@@ -43,40 +43,28 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.codeInsight.template.postfix.templates.LanguagePostfixTemplate.LANG_EP;
|
||||
|
||||
public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
public static final String POSTFIX_TEMPLATE_ID = "POSTFIX_TEMPLATE_ID";
|
||||
private static final Logger LOG = Logger.getInstance(PostfixLiveTemplate.class);
|
||||
private static final LanguagePostfixTemplate templates = LanguagePostfixTemplate.INSTANCE;
|
||||
|
||||
@NotNull
|
||||
public Set<String> getAllTemplateKeys(PsiFile file, int offset) {
|
||||
Set<String> keys = Sets.newHashSet();
|
||||
Language language = PsiUtilCore.getLanguageAtOffset(file, offset);
|
||||
|
||||
for (PostfixTemplateProvider provider : templates.allForLanguage(language)) {
|
||||
keys.addAll(provider.getKeys());
|
||||
for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(language)) {
|
||||
keys.addAll(getKeys(provider));
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
public boolean hasNotEmptyKey(PsiFile file, int offset) {
|
||||
Language language = PsiUtilCore.getLanguageAtOffset(file, offset);
|
||||
for (PostfixTemplateProvider provider : templates.allForLanguage(language)) {
|
||||
if (StringUtil
|
||||
.isNotEmpty(computeTemplateKeyWithoutContextChecking(provider, file.getText(), offset + 1))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String computeTemplateKeyWithoutContextChecking(PostfixTemplateProvider provider,
|
||||
@NotNull CharSequence documentContent,
|
||||
int currentOffset) {
|
||||
private static String computeTemplateKeyWithoutContextChecking(@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull CharSequence documentContent,
|
||||
int currentOffset) {
|
||||
int startOffset = currentOffset;
|
||||
if (documentContent.length() < startOffset) {
|
||||
return null;
|
||||
@@ -102,14 +90,12 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
Editor editor = callback.getEditor();
|
||||
CharSequence charsSequence = editor.getDocument().getCharsSequence();
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
Language language = getLanguage(callback);
|
||||
for (PostfixTemplateProvider provider : templates.allForLanguage(language)) {
|
||||
for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) {
|
||||
String key = computeTemplateKeyWithoutContextChecking(provider, charsSequence, offset);
|
||||
if (key != null && isApplicableTemplate(provider, key, callback.getFile(), editor)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -117,7 +103,12 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
@Override
|
||||
public String computeTemplateKeyWithoutContextChecking(@NotNull CustomTemplateCallback callback) {
|
||||
Editor editor = callback.getEditor();
|
||||
return computeTemplateKeyWithoutContextChecking(callback.getFile(), editor, editor.getCaretModel().getOffset());
|
||||
int currentOffset = editor.getCaretModel().getOffset();
|
||||
for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) {
|
||||
String key = computeTemplateKeyWithoutContextChecking(provider, editor.getDocument().getCharsSequence(), currentOffset);
|
||||
if (key != null) return key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,27 +116,26 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String computeTemplateKeyWithoutContextChecking(PsiFile file, Editor editor, int currentOffset) {
|
||||
Language language = PsiUtilCore.getLanguageAtOffset(file, currentOffset);
|
||||
for (PostfixTemplateProvider provider : templates.allForLanguage(language)) {
|
||||
String key = computeTemplateKeyWithoutContextChecking(provider, editor.getDocument().getCharsSequence(), currentOffset);
|
||||
if (key != null) return key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull final String key, @NotNull final CustomTemplateCallback callback) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.postfix");
|
||||
|
||||
Editor editor = callback.getEditor();
|
||||
Language language = getLanguage(callback);
|
||||
for (PostfixTemplateProvider provider : templates.allForLanguage(language)) {
|
||||
PostfixTemplate postfixTemplate = provider.get(key);
|
||||
for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) {
|
||||
PostfixTemplate postfixTemplate = getTemplate(provider, key);
|
||||
if (postfixTemplate != null) {
|
||||
expandForProvider(provider, key, callback);
|
||||
final PsiFile file = callback.getContext().getContainingFile();
|
||||
if (isApplicableTemplate(provider, key, file, editor)) {
|
||||
int currentOffset = editor.getCaretModel().getOffset();
|
||||
PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key);
|
||||
newContext = provider.preExpand(editor, newContext, currentOffset, key);
|
||||
expandTemplate(postfixTemplate, editor, newContext);
|
||||
}
|
||||
// don't care about errors in multiCaret mode
|
||||
else if (editor.getCaretModel().getAllCarets().size() == 1) {
|
||||
LOG.error("Template not found by key: " + key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -156,37 +146,19 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static Language getLanguage(CustomTemplateCallback callback) {
|
||||
return PsiUtilCore.getLanguageAtOffset(callback.getFile(), callback.getEditor().getCaretModel().getOffset());
|
||||
}
|
||||
|
||||
public void expandForProvider(
|
||||
@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull final String key,
|
||||
@NotNull final CustomTemplateCallback callback) {
|
||||
final Editor editor = callback.getEditor();
|
||||
final PsiFile file = callback.getContext().getContainingFile();
|
||||
if (isApplicableTemplate(provider, key, file, editor)) {
|
||||
int currentOffset = editor.getCaretModel().getOffset();
|
||||
PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key);
|
||||
newContext = provider.preExpand(editor, newContext, currentOffset, key);
|
||||
PostfixTemplate template = provider.get(key);
|
||||
assert template != null;
|
||||
expandTemplate(template, editor, newContext);
|
||||
}
|
||||
// don't care about errors in multiCaret mode
|
||||
else if (editor.getCaretModel().getAllCarets().size() == 1) {
|
||||
LOG.error("Template not found by key: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(PsiFile file, int offset, boolean wrapping) {
|
||||
PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
|
||||
if (wrapping || file == null || settings == null || !settings.isPostfixTemplatesEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return hasNotEmptyKey(file, offset);
|
||||
Language language = PsiUtilCore.getLanguageAtOffset(file, offset);
|
||||
for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(language)) {
|
||||
if (StringUtil.isNotEmpty(computeTemplateKeyWithoutContextChecking(provider, file.getText(), offset + 1))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,42 +194,25 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
@NotNull Editor editor,
|
||||
int offset) {
|
||||
Collection<CustomLiveTemplateLookupElement> result = ContainerUtil.newHashSet();
|
||||
Language language = PsiUtilCore.getLanguageAtOffset(file, editor.getCaretModel().getOffset());
|
||||
for (PostfixTemplateProvider provider : templates.allForLanguage(language)) {
|
||||
result.addAll(getLookupElementsForProvider(provider, file, editor, offset));
|
||||
CustomTemplateCallback callback = new CustomTemplateCallback(editor, file, false);
|
||||
for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) {
|
||||
String key = computeTemplateKeyWithoutContextChecking(callback);
|
||||
if (key != null && editor.getCaretModel().getCaretCount() == 1) {
|
||||
Condition<PostfixTemplate> isApplicationTemplateFunction = createIsApplicationTemplateFunction(provider, key, file, editor);
|
||||
for (PostfixTemplate postfixTemplate : provider.getTemplates()) {
|
||||
if (isApplicationTemplateFunction.value(postfixTemplate)) {
|
||||
result.add(new PostfixTemplateLookupElement(this, postfixTemplate, postfixTemplate.getKey(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<? extends CustomLiveTemplateLookupElement> getLookupElementsForProvider(
|
||||
@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Editor editor,
|
||||
int offset) {
|
||||
String key = computeTemplateKeyWithoutContextChecking(file, editor, offset);
|
||||
if (key != null && editor.getCaretModel().getCaretCount() == 1) {
|
||||
Collection<CustomLiveTemplateLookupElement> result = ContainerUtil.newHashSet();
|
||||
|
||||
Condition<PostfixTemplate> isApplicationTemplateFunction = createIsApplicationTemplateFunction(provider, key, file, editor);
|
||||
for (String postfixKey : provider.getKeys()) {
|
||||
PostfixTemplate postfixTemplate = provider.get(postfixKey);
|
||||
assert postfixTemplate != null;
|
||||
if (isApplicationTemplateFunction.value(postfixTemplate)) {
|
||||
result.add(new PostfixTemplateLookupElement(this, postfixTemplate, postfixKey, false));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
private static void expandTemplate(
|
||||
@NotNull final PostfixTemplate template,
|
||||
@NotNull final Editor editor,
|
||||
@NotNull final PsiElement context) {
|
||||
private static void expandTemplate(@NotNull final PostfixTemplate template,
|
||||
@NotNull final Editor editor,
|
||||
@NotNull final PsiElement context) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -293,11 +248,10 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
return CustomTemplateCallback.getContext(file, startOffset > 0 ? startOffset - 1 : startOffset);
|
||||
}
|
||||
|
||||
private static Condition<PostfixTemplate> createIsApplicationTemplateFunction(
|
||||
@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull String key,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Editor editor) {
|
||||
private static Condition<PostfixTemplate> createIsApplicationTemplateFunction(@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull String key,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Editor editor) {
|
||||
int currentOffset = editor.getCaretModel().getOffset();
|
||||
final int newOffset = currentOffset - key.length();
|
||||
CharSequence fileContent = editor.getDocument().getCharsSequence();
|
||||
@@ -340,11 +294,35 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase {
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static boolean isApplicableTemplate(
|
||||
@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull String key,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Editor editor) {
|
||||
return createIsApplicationTemplateFunction(provider, key, file, editor).value(provider.get(key));
|
||||
public static boolean isApplicableTemplate(@NotNull PostfixTemplateProvider provider,
|
||||
@NotNull String key,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Editor editor) {
|
||||
return createIsApplicationTemplateFunction(provider, key, file, editor).value(getTemplate(provider, key));
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static Set<String> getKeys(@NotNull PostfixTemplateProvider provider) {
|
||||
Set<String> result = ContainerUtil.newHashSet();
|
||||
for (PostfixTemplate template : provider.getTemplates()) {
|
||||
result.add(template.getKey());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PostfixTemplate getTemplate(@NotNull PostfixTemplateProvider provider, @Nullable String key) {
|
||||
for (PostfixTemplate template : provider.getTemplates()) {
|
||||
if (template.getKey().equals(key)) {
|
||||
return template;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Language getLanguage(@NotNull CustomTemplateCallback callback) {
|
||||
return callback.getContext().getLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
-10
@@ -19,11 +19,7 @@ import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettin
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiExpressionStatement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class PostfixTemplate {
|
||||
@NotNull private final String myPresentableName;
|
||||
@@ -67,12 +63,6 @@ public abstract class PostfixTemplate {
|
||||
return settings != null && settings.isPostfixTemplatesEnabled() && settings.isTemplateEnabled(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiExpression getTopmostExpression(PsiElement context) {
|
||||
PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class);
|
||||
return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null;
|
||||
}
|
||||
|
||||
public abstract boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset);
|
||||
|
||||
public abstract void expand(@NotNull PsiElement context, @NotNull Editor editor);
|
||||
|
||||
+4
-16
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -32,18 +31,6 @@ public interface PostfixTemplateProvider {
|
||||
@NotNull
|
||||
Set<PostfixTemplate> getTemplates();
|
||||
|
||||
/**
|
||||
* Return all keys registered in the provider
|
||||
*/
|
||||
@NotNull
|
||||
Set<String> getKeys();
|
||||
|
||||
/**
|
||||
* Return postfix template for key
|
||||
*/
|
||||
@Nullable
|
||||
PostfixTemplate get(@Nullable String key);
|
||||
|
||||
/**
|
||||
* Check symbol can separate template keys
|
||||
*/
|
||||
@@ -51,14 +38,15 @@ public interface PostfixTemplateProvider {
|
||||
|
||||
/**
|
||||
* Prepare original file content for template expanding
|
||||
* Return context after transformation
|
||||
*/
|
||||
@NotNull
|
||||
PsiElement preExpand(@NotNull Editor editor, @NotNull PsiElement context, int currentOffset, @NotNull String key);
|
||||
PsiElement preExpand(@NotNull Editor editor, @NotNull PsiElement context, int offset, @NotNull String key);
|
||||
|
||||
/**
|
||||
* Do some actions with the file content before check applicable.
|
||||
* Return new copy of file because we should not change original file
|
||||
* Return copyFile or another copy of file after processing
|
||||
*/
|
||||
@NotNull
|
||||
PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile file, int currentOffset);
|
||||
PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile copyFile, int currentOffset);
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -26,7 +27,7 @@ public class ReturnStatementPostfixTemplate extends NonVoidPostfixTemplate {
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
PsiElement parent = expr != null ? expr.getParent() : null;
|
||||
if (!(parent instanceof PsiExpressionStatement)) return;
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory();
|
||||
|
||||
+17
-1
@@ -1,6 +1,22 @@
|
||||
/*
|
||||
* 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.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilCore;
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -17,7 +33,7 @@ public abstract class StatementPostfixTemplateBase extends PostfixTemplate {
|
||||
}
|
||||
|
||||
protected void surroundWith(PsiElement context, Editor editor, String text) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
PsiElement parent = expr != null ? expr.getParent() : null;
|
||||
if (!(parent instanceof PsiExpressionStatement)) return;
|
||||
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -51,7 +52,7 @@ public class SwitchStatementPostfixTemplate extends StatementPostfixTemplateBase
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
return expr != null && isSwitchCompatibleType(expr.getType(), context);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -30,7 +31,7 @@ public class SynchronizedStatementPostfixTemplate extends StatementPostfixTempla
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
PsiType type = expression != null ? expression.getType() : null;
|
||||
return type != null && !(type instanceof PsiPrimitiveType);
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class ThrowExceptionPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
return expression != null && PostfixTemplatesUtils.isThrowable(expression.getType());
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.TemplateManager;
|
||||
import com.intellij.codeInsight.template.impl.MacroCallNode;
|
||||
import com.intellij.codeInsight.template.impl.TextExpression;
|
||||
import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -44,7 +45,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
|
||||
public boolean isApplicable(@NotNull PsiElement element, @NotNull Document copyDocument, int newOffset) {
|
||||
if (!PsiUtil.isLanguageLevel7OrHigher(element)) return false;
|
||||
|
||||
PsiExpression initializer = getTopmostExpression(element);
|
||||
PsiExpression initializer = PostfixTemplatesUtils.getTopmostExpression(element);
|
||||
|
||||
if (initializer == null) return false;
|
||||
|
||||
@@ -61,7 +62,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
assert expression != null;
|
||||
|
||||
Project project = context.getProject();
|
||||
|
||||
+17
-1
@@ -1,5 +1,21 @@
|
||||
/*
|
||||
* 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.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -11,7 +27,7 @@ public class WhileStatementPostfixTemplate extends BooleanPostfixTemplate {
|
||||
|
||||
@Override
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expression = getTopmostExpression(context);
|
||||
PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context);
|
||||
assert expression != null;
|
||||
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject());
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.intellij.codeInsight.template.postfix.util;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author ignatov
|
||||
*/
|
||||
@Target(value = ElementType.TYPE)
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
public @interface Aliases {
|
||||
String[] value();
|
||||
}
|
||||
+8
-2
@@ -17,12 +17,12 @@ package com.intellij.codeInsight.template.postfix.util;
|
||||
|
||||
import com.intellij.codeInsight.generation.surroundWith.JavaExpressionSurrounder;
|
||||
import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder;
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -45,7 +45,7 @@ public abstract class PostfixTemplatesUtils {
|
||||
}
|
||||
|
||||
public static void createStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String prefix, @NotNull String suffix, int offset) {
|
||||
PsiExpression expr = PostfixTemplate.getTopmostExpression(context);
|
||||
PsiExpression expr = getTopmostExpression(context);
|
||||
PsiElement parent = expr != null ? expr.getParent() : null;
|
||||
assert parent instanceof PsiStatement;
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory();
|
||||
@@ -121,5 +121,11 @@ public abstract class PostfixTemplatesUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiExpression getTopmostExpression(PsiElement context) {
|
||||
PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class);
|
||||
return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public final class MethodHierarchyNodeDescriptor extends HierarchyNodeDescriptor
|
||||
myTreeStructure = treeStructure;
|
||||
}
|
||||
|
||||
private PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) {
|
||||
PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) {
|
||||
return MethodHierarchyUtil.findBaseMethodInClass(myTreeStructure.getBaseMethod(), aClass, checkBases);
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -172,13 +172,16 @@ public final class MethodHierarchyTreeStructure extends HierarchyTreeStructure {
|
||||
descriptors.add(d);
|
||||
}
|
||||
|
||||
FunctionalExpressionSearch.search(getBaseMethod()).forEach(new Processor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean process(PsiFunctionalExpression expression) {
|
||||
descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false);
|
||||
if (existingMethod != null) {
|
||||
FunctionalExpressionSearch.search(existingMethod).forEach(new Processor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean process(PsiFunctionalExpression expression) {
|
||||
descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -415,19 +415,6 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
return versionString;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() { }
|
||||
|
||||
@Override
|
||||
public void disposeComponent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull String versionString, @NotNull String versionNumber) {
|
||||
return getVersionNumber(versionString).compareTo(versionNumber);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -766,7 +766,7 @@ public class ImportHelper{
|
||||
continue;
|
||||
}
|
||||
if (reference instanceof PsiJavaCodeReferenceElementImpl
|
||||
&& ((PsiJavaCodeReferenceElementImpl)reference).getKind() == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) {
|
||||
&& ((PsiJavaCodeReferenceElementImpl)reference).getKind(((PsiJavaCodeReferenceElementImpl)reference).getContainingFile()) == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -774,7 +774,7 @@ public class ImportHelper{
|
||||
final JavaResolveResult resolveResult = javaReference.advancedResolve(true);
|
||||
PsiElement refElement = resolveResult.getElement();
|
||||
if (refElement == null && referenceElement != null) {
|
||||
refElement = ResolveClassUtil.resolveClass(referenceElement); // might be uncomplete code
|
||||
refElement = ResolveClassUtil.resolveClass(referenceElement, referenceElement.getContainingFile()); // might be uncomplete code
|
||||
}
|
||||
if (refElement == null) continue;
|
||||
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@ public class JavaReferenceAdjuster implements ReferenceAdjuster {
|
||||
|
||||
boolean rightKind = true;
|
||||
if (elementType == JavaElementType.JAVA_CODE_REFERENCE) {
|
||||
int kind = ((PsiJavaCodeReferenceElementImpl)element).getKind();
|
||||
PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl)element;
|
||||
int kind = impl.getKind(impl.getContainingFile());
|
||||
rightKind = kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND;
|
||||
}
|
||||
|
||||
|
||||
+22
-20
@@ -268,10 +268,11 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
return JavaClassReferenceProvider.EXTEND_CLASS_NAMES.getValue(getOptions());
|
||||
}
|
||||
|
||||
private LookupElement[] processPackage(final PsiPackage aPackage) {
|
||||
@NotNull
|
||||
private LookupElement[] processPackage(@NotNull PsiPackage aPackage) {
|
||||
final ArrayList<LookupElement> list = ContainerUtil.newArrayList();
|
||||
final int startOffset = StringUtil.isEmpty(aPackage.getName()) ? 0 : aPackage.getQualifiedName().length() + 1;
|
||||
final GlobalSearchScope scope = getScope();
|
||||
final GlobalSearchScope scope = getScope(getElement().getContainingFile());
|
||||
for (final PsiPackage subPackage : aPackage.getSubPackages(scope)) {
|
||||
final String shortName = subPackage.getQualifiedName().substring(startOffset);
|
||||
if (JavaPsiFacade.getInstance(subPackage.getProject()).getNameHelper().isIdentifier(shortName)) {
|
||||
@@ -355,7 +356,8 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
return (JavaResolveResult) resolveCache.resolveWithCaching(this, MyResolver.INSTANCE, false, false,file)[0];
|
||||
}
|
||||
|
||||
private JavaResolveResult doAdvancedResolve() {
|
||||
@NotNull
|
||||
private JavaResolveResult doAdvancedResolve(@NotNull PsiFile containingFile) {
|
||||
final PsiElement psiElement = getElement();
|
||||
|
||||
if (!psiElement.isValid()) return JavaResolveResult.EMPTY;
|
||||
@@ -366,7 +368,9 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
if (context instanceof PsiClass) {
|
||||
if (isStaticClassReference(elementText, false)) {
|
||||
final PsiClass psiClass = ((PsiClass)context).findInnerClassByName(getCanonicalText(), false);
|
||||
if (psiClass != null) return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement);
|
||||
if (psiClass != null) {
|
||||
return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement);
|
||||
}
|
||||
PsiElement member = doResolveMember((PsiClass)context, myText);
|
||||
return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement);
|
||||
}
|
||||
@@ -382,18 +386,18 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
if (!qName.contains(".")) {
|
||||
final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions());
|
||||
if (StringUtil.isNotEmpty(defaultPackage)) {
|
||||
final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName);
|
||||
final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName, containingFile);
|
||||
if (resolveResult != JavaResolveResult.EMPTY) {
|
||||
return resolveResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
return advancedResolveInner(psiElement, qName);
|
||||
return advancedResolveInner(psiElement, qName, containingFile);
|
||||
}
|
||||
|
||||
private JavaResolveResult advancedResolveInner(final PsiElement psiElement, final String qName) {
|
||||
final PsiManager manager = psiElement.getManager();
|
||||
final GlobalSearchScope scope = getScope();
|
||||
private JavaResolveResult advancedResolveInner(@NotNull PsiElement psiElement, @NotNull String qName, @NotNull PsiFile containingFile) {
|
||||
final PsiManager manager = containingFile.getManager();
|
||||
final GlobalSearchScope scope = getScope(containingFile);
|
||||
if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) {
|
||||
final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope);
|
||||
if (aClass != null) {
|
||||
@@ -413,8 +417,6 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
resolveResult = resolveMember(qName, manager, getElement().getResolveScope());
|
||||
}
|
||||
if (resolveResult == null) {
|
||||
PsiFile containingFile = psiElement.getContainingFile();
|
||||
|
||||
if (containingFile instanceof PsiJavaFile) {
|
||||
if (containingFile instanceof ServerPageFile) {
|
||||
containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE);
|
||||
@@ -448,12 +450,12 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
: JavaResolveResult.EMPTY;
|
||||
}
|
||||
|
||||
private GlobalSearchScope getScope() {
|
||||
Project project = getElement().getProject();
|
||||
private GlobalSearchScope getScope(@NotNull PsiFile containingFile) {
|
||||
Project project = containingFile.getProject();
|
||||
GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope(project);
|
||||
if (scope == null) {
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(getElement());
|
||||
return module != null ? module.getModuleWithDependenciesAndLibrariesScope(true) : GlobalSearchScope.allScope(project);
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(containingFile);
|
||||
return module == null ? GlobalSearchScope.allScope(project) : module.getModuleWithDependenciesAndLibrariesScope(true);
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@@ -472,7 +474,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<? extends LocalQuickFix> registerFixes(final HighlightInfo info) {
|
||||
private List<? extends LocalQuickFix> registerFixes(HighlightInfo info) {
|
||||
|
||||
final List<LocalQuickFix> list = OrderEntryFix.registerFixes(new QuickFixActionRegistrarImpl(info), this);
|
||||
|
||||
@@ -498,7 +500,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
final TextRange range = new TextRange(references[0].getRangeInElement().getStartOffset(),
|
||||
getRangeInElement().getEndOffset());
|
||||
final String qualifiedName = range.substring(getElement().getText());
|
||||
final CreateClassOrPackageFix action = CreateClassOrPackageFix.createFix(qualifiedName, getScope(), getElement(), contextPackage,
|
||||
final CreateClassOrPackageFix action = CreateClassOrPackageFix.createFix(qualifiedName, getScope(getElement().getContainingFile()), getElement(), contextPackage,
|
||||
kind, extendClass, templateName);
|
||||
if (action != null) {
|
||||
QuickFixAction.registerQuickFixAction(info, action);
|
||||
@@ -591,13 +593,13 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
|
||||
return myJavaClassReferenceSet.getUnresolvedMessagePattern(myIndex);
|
||||
}
|
||||
|
||||
private static class MyResolver implements ResolveCache.PolyVariantResolver<JavaClassReference> {
|
||||
private static class MyResolver implements ResolveCache.PolyVariantContextResolver<JavaClassReference> {
|
||||
private static final MyResolver INSTANCE = new MyResolver();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JavaResolveResult[] resolve(@NotNull JavaClassReference javaClassReference, boolean incompleteCode) {
|
||||
return new JavaResolveResult[]{javaClassReference.doAdvancedResolve()};
|
||||
public ResolveResult[] resolve(@NotNull JavaClassReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) {
|
||||
return new JavaResolveResult[]{ref.doAdvancedResolve(containingFile)};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -200,7 +200,7 @@ public class JavaTreeCopyHandler implements TreeCopyHandler {
|
||||
}
|
||||
}
|
||||
else if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE) {
|
||||
switch (((PsiJavaCodeReferenceElementImpl)original).getKind()) {
|
||||
switch (((PsiJavaCodeReferenceElementImpl)original).getKind(((PsiJavaCodeReferenceElementImpl)original).getContainingFile())) {
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND:
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
|
||||
@@ -31,7 +31,9 @@ public enum JavaSdkVersion {
|
||||
JDK_1_5(LanguageLevel.JDK_1_5, "1.5"),
|
||||
JDK_1_6(LanguageLevel.JDK_1_6, "1.6"),
|
||||
JDK_1_7(LanguageLevel.JDK_1_7, "1.7"),
|
||||
JDK_1_8(LanguageLevel.JDK_1_8, "1.8");
|
||||
JDK_1_8(LanguageLevel.JDK_1_8, "1.8"),
|
||||
JDK_1_9(LanguageLevel.JDK_1_9, "1.9");
|
||||
|
||||
private final LanguageLevel myMaxLanguageLevel;
|
||||
private final String myDescription;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ public class JdkVersionUtil {
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_6, new String[]{"1.6", "6.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_7, new String[]{"1.7", "7.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_8, new String[]{"1.8", "8.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_9, new String[]{"1.9", "9.0"});
|
||||
}
|
||||
|
||||
public static JavaSdkVersion getVersion(@NotNull String versionString) {
|
||||
|
||||
@@ -30,9 +30,10 @@ public enum LanguageLevel {
|
||||
JDK_1_5(JavaCoreBundle.message("jdk.1.5.language.level.description")),
|
||||
JDK_1_6(JavaCoreBundle.message("jdk.1.6.language.level.description")),
|
||||
JDK_1_7(JavaCoreBundle.message("jdk.1.7.language.level.description")),
|
||||
JDK_1_8(JavaCoreBundle.message("jdk.1.8.language.level.description"));
|
||||
JDK_1_8(JavaCoreBundle.message("jdk.1.8.language.level.description")),
|
||||
JDK_1_9(JavaCoreBundle.message("jdk.1.9.language.level.description"));
|
||||
|
||||
public static final LanguageLevel HIGHEST = JDK_1_8;
|
||||
public static final LanguageLevel HIGHEST = JDK_1_8; // TODO! when language level 9 is really supported, update this field
|
||||
public static final Key<LanguageLevel> KEY = Key.create("LANGUAGE_LEVEL");
|
||||
|
||||
private final String myPresentableText;
|
||||
@@ -59,6 +60,7 @@ public enum LanguageLevel {
|
||||
if ("1.6".equals(value)) return JDK_1_6;
|
||||
if ("1.7".equals(value)) return JDK_1_7;
|
||||
if ("1.8".equals(value)) return JDK_1_8;
|
||||
if ("1.9".equals(value)) return JDK_1_9;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class LambdaHighlightingUtil {
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(@NotNull PsiClass psiClass, String interfaceNonFunctionalMessage) {
|
||||
if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(psiClass);
|
||||
final List<HierarchicalMethodSignature> signatures = LambdaUtil.findFunctionCandidates(psiClass);
|
||||
if (signatures == null) return interfaceNonFunctionalMessage;
|
||||
if (signatures.isEmpty()) return "No target method found";
|
||||
if (signatures.size() == 1) {
|
||||
@@ -97,15 +97,23 @@ public class LambdaHighlightingUtil {
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
|
||||
if (functionalInterfaceType instanceof PsiIntersectionType) {
|
||||
int count = 0;
|
||||
for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) {
|
||||
if (checkInterfaceFunctional(type) == null) return null;
|
||||
if (checkInterfaceFunctional(type) == null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
return "Multiple non-overriding abstract methods found in " + functionalInterfaceType.getPresentableText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
final PsiClass aClass = resolveResult.getElement();
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(aClass);
|
||||
final List<HierarchicalMethodSignature> signatures = LambdaUtil.findFunctionCandidates(aClass);
|
||||
if (signatures != null && signatures.size() == 1) {
|
||||
final MethodSignature functionalMethod = signatures.get(0);
|
||||
if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic";
|
||||
|
||||
@@ -103,9 +103,7 @@ public class LambdaUtil {
|
||||
|
||||
public static boolean isFunctionalType(PsiType type) {
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
for (PsiType type1 : ((PsiIntersectionType)type).getConjuncts()) {
|
||||
if (isFunctionalType(type1)) return true;
|
||||
}
|
||||
return extractFunctionalConjunct((PsiIntersectionType)type) != null;
|
||||
}
|
||||
return isFunctionalClass(PsiUtil.resolveGenericsClassInType(type).getElement());
|
||||
}
|
||||
@@ -114,7 +112,7 @@ public class LambdaUtil {
|
||||
public static boolean isFunctionalClass(PsiClass aClass) {
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return false;
|
||||
final List<MethodSignature> signatures = findFunctionCandidates(aClass);
|
||||
final List<HierarchicalMethodSignature> signatures = findFunctionCandidates(aClass);
|
||||
return signatures != null && signatures.size() == 1;
|
||||
}
|
||||
return false;
|
||||
@@ -144,7 +142,7 @@ public class LambdaUtil {
|
||||
@Nullable
|
||||
static MethodSignature getFunction(PsiClass psiClass) {
|
||||
if (psiClass == null) return null;
|
||||
final List<MethodSignature> functions = findFunctionCandidates(psiClass);
|
||||
final List<HierarchicalMethodSignature> functions = findFunctionCandidates(psiClass);
|
||||
if (functions != null && functions.size() == 1) {
|
||||
return functions.get(0);
|
||||
}
|
||||
@@ -178,12 +176,13 @@ public class LambdaUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<MethodSignature> hasSubsignature(List<MethodSignature> signatures) {
|
||||
for (MethodSignature signature : signatures) {
|
||||
private static List<HierarchicalMethodSignature> hasSubsignature(List<HierarchicalMethodSignature> signatures) {
|
||||
for (HierarchicalMethodSignature signature : signatures) {
|
||||
boolean subsignature = true;
|
||||
for (MethodSignature methodSignature : signatures) {
|
||||
for (HierarchicalMethodSignature methodSignature : signatures) {
|
||||
if (!signature.equals(methodSignature)) {
|
||||
if (!MethodSignatureUtil.isSubsignature(signature, methodSignature)) {
|
||||
if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) &&
|
||||
!skipMethod(signature, methodSignature)) {
|
||||
subsignature = false;
|
||||
break;
|
||||
}
|
||||
@@ -194,10 +193,20 @@ public class LambdaUtil {
|
||||
return signatures;
|
||||
}
|
||||
|
||||
private static boolean skipMethod(HierarchicalMethodSignature signature,
|
||||
HierarchicalMethodSignature methodSignature) {
|
||||
//not generic
|
||||
if (methodSignature.getTypeParameters().length == 0) {
|
||||
return false;
|
||||
}
|
||||
//foreign class
|
||||
return signature.getMethod().getContainingClass() != methodSignature.getMethod().getContainingClass();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static List<MethodSignature> findFunctionCandidates(PsiClass psiClass) {
|
||||
public static List<HierarchicalMethodSignature> findFunctionCandidates(PsiClass psiClass) {
|
||||
if (psiClass != null && psiClass.isInterface() && !psiClass.isAnnotationType()) {
|
||||
final List<MethodSignature> methods = new ArrayList<MethodSignature>();
|
||||
final List<HierarchicalMethodSignature> methods = new ArrayList<HierarchicalMethodSignature>();
|
||||
final Collection<HierarchicalMethodSignature> visibleSignatures = psiClass.getVisibleSignatures();
|
||||
for (HierarchicalMethodSignature signature : visibleSignatures) {
|
||||
final PsiMethod psiMethod = signature.getMethod();
|
||||
@@ -286,9 +295,8 @@ public class LambdaUtil {
|
||||
} else if (parent instanceof PsiTypeCastExpression) {
|
||||
final PsiType castType = ((PsiTypeCastExpression)parent).getType();
|
||||
if (castType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunctType : ((PsiIntersectionType)castType).getConjuncts()) {
|
||||
if (getFunctionalInterfaceMethod(conjunctType) != null) return conjunctType;
|
||||
}
|
||||
final PsiType conjunct = extractFunctionalConjunct((PsiIntersectionType)castType);
|
||||
if (conjunct != null) return conjunct;
|
||||
}
|
||||
return castType;
|
||||
}
|
||||
@@ -363,6 +371,19 @@ public class LambdaUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType extractFunctionalConjunct(PsiIntersectionType type) {
|
||||
PsiType conjunct = null;
|
||||
for (PsiType conjunctType : type.getConjuncts()) {
|
||||
final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(conjunctType);
|
||||
if (interfaceMethod != null) {
|
||||
if (conjunct != null && !conjunct.equals(conjunctType)) return null;
|
||||
conjunct = conjunctType;
|
||||
}
|
||||
}
|
||||
return conjunct;
|
||||
}
|
||||
|
||||
private static PsiType getFunctionalInterfaceTypeByContainingLambda(@NotNull PsiLambdaExpression parentLambda) {
|
||||
final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType();
|
||||
return parentInterfaceType != null ? getFunctionalInterfaceReturnType(parentInterfaceType) : null;
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.intellij.psi;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PsiFunctionalExpression extends PsiExpression, Iconable {
|
||||
public interface PsiFunctionalExpression extends PsiExpression, Iconable, NavigatablePsiElement {
|
||||
/**
|
||||
* @return SAM type the lambda expression corresponds to
|
||||
* null when no SAM type could be found
|
||||
|
||||
@@ -6,3 +6,4 @@ jdk.1.5.language.level.description=5.0 - 'enum' keyword, autoboxing etc.
|
||||
jdk.1.6.language.level.description=6.0 - @Override in interfaces
|
||||
jdk.1.7.language.level.description=7.0 - Diamonds, ARM, multi-catch etc.
|
||||
jdk.1.8.language.level.description=8.0 - Lambdas, type annotations etc.
|
||||
jdk.1.9.language.level.description=9.0 - Jigsaw project etc.
|
||||
|
||||
+17
-12
@@ -15,18 +15,21 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.psi.impl.ResolveScopeManager;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
@@ -44,7 +47,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
private final String myQualifiedName;
|
||||
private final PsiReferenceParameterList myRefParameterList;
|
||||
|
||||
public ClsJavaCodeReferenceElementImpl(PsiElement parent, String canonicalText) {
|
||||
public ClsJavaCodeReferenceElementImpl(PsiElement parent, @NotNull String canonicalText) {
|
||||
myParent = parent;
|
||||
|
||||
String canonical = TypeInfo.internFrequentType(canonicalText);
|
||||
@@ -88,20 +91,20 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
return myCanonicalText;
|
||||
}
|
||||
|
||||
private static class Resolver implements ResolveCache.PolyVariantResolver<ClsJavaCodeReferenceElementImpl> {
|
||||
private static class Resolver implements ResolveCache.PolyVariantContextResolver<ClsJavaCodeReferenceElementImpl> {
|
||||
public static final Resolver INSTANCE = new Resolver();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JavaResolveResult[] resolve(@NotNull ClsJavaCodeReferenceElementImpl ref, boolean incompleteCode) {
|
||||
final JavaResolveResult resolveResult = ref.advancedResolveImpl();
|
||||
public JavaResolveResult[] resolve(@NotNull ClsJavaCodeReferenceElementImpl ref, @NotNull PsiFile containingFile, boolean incompleteCode) {
|
||||
final JavaResolveResult resolveResult = ref.advancedResolveImpl(containingFile);
|
||||
return resolveResult == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[] {resolveResult};
|
||||
}
|
||||
}
|
||||
|
||||
private JavaResolveResult advancedResolveImpl() {
|
||||
private JavaResolveResult advancedResolveImpl(@NotNull PsiFile containingFile) {
|
||||
PsiTypeElement[] typeElements = myRefParameterList == null ? PsiTypeElement.EMPTY_ARRAY : myRefParameterList.getTypeParameterElements();
|
||||
PsiElement resolve = resolveElement();
|
||||
PsiElement resolve = resolveElement(containingFile);
|
||||
if (resolve == null) return null;
|
||||
if (resolve instanceof PsiClass) {
|
||||
Map<PsiTypeParameter, PsiType> substitutionMap = new HashMap<PsiTypeParameter, PsiType>();
|
||||
@@ -137,7 +140,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
}
|
||||
}
|
||||
|
||||
private void collectOuterClassTypeArgs(final PsiClass psiClass,
|
||||
private void collectOuterClassTypeArgs(@NotNull PsiClass psiClass,
|
||||
final String canonicalText,
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap) {
|
||||
final PsiClass containingClass = psiClass.getContainingClass();
|
||||
@@ -179,7 +182,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiElement resolveElement() {
|
||||
private PsiElement resolveElement(@NotNull PsiFile containingFile) {
|
||||
PsiElement element = getParent();
|
||||
while(element != null && (!(element instanceof PsiClass) || element instanceof PsiTypeParameter)) {
|
||||
if(element instanceof PsiMethod){
|
||||
@@ -199,16 +202,18 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable((PsiTypeParameterListOwner)element)) {
|
||||
if (myQualifiedName.equals(parameter.getName())) return parameter;
|
||||
}
|
||||
return resolveClassPreferringMyJar();
|
||||
return resolveClassPreferringMyJar(containingFile);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiClass resolveClassPreferringMyJar() {
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(getProject()).findClasses(myQualifiedName, getResolveScope());
|
||||
private PsiClass resolveClassPreferringMyJar(@NotNull PsiFile containingFile) {
|
||||
Project project = containingFile.getProject();
|
||||
GlobalSearchScope scope = ResolveScopeManager.getInstance(project).getResolveScope(this);
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(project).findClasses(myQualifiedName, scope);
|
||||
if (classes.length == 0) return null;
|
||||
|
||||
if (classes.length > 1) {
|
||||
VirtualFile jarFile = PsiUtil.getJarFile(this);
|
||||
VirtualFile jarFile = PsiUtil.getJarFile(containingFile);
|
||||
if (jarFile != null) {
|
||||
for (PsiClass aClass : classes) {
|
||||
if (Comparing.equal(PsiUtil.getJarFile(aClass), jarFile)) return aClass;
|
||||
|
||||
@@ -208,11 +208,10 @@ public class PsiClassReferenceType extends PsiClassType.Stub {
|
||||
if (myReference instanceof PsiJavaCodeReferenceElementImpl) {
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if (!annotated || annotations.length == 0) annotations = null;
|
||||
return ((PsiJavaCodeReferenceElementImpl)myReference).getCanonicalText(annotated, annotations);
|
||||
}
|
||||
else {
|
||||
return myReference.getCanonicalText();
|
||||
PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl)myReference;
|
||||
return impl.getCanonicalText(annotated, annotations, impl.getContainingFile());
|
||||
}
|
||||
return myReference.getCanonicalText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+86
-78
@@ -57,7 +57,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
private volatile String myCachedQName = null;
|
||||
private volatile String myCachedNormalizedText;
|
||||
private int myKindWhenDummy = CLASS_NAME_KIND;
|
||||
private volatile int myKindWhenDummy = CLASS_NAME_KIND;
|
||||
|
||||
public static final int CLASS_NAME_KIND = 1;
|
||||
public static final int PACKAGE_NAME_KIND = 2;
|
||||
@@ -92,8 +92,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
return type == TokenType.DUMMY_HOLDER || type == JavaElementType.DUMMY_ELEMENT;
|
||||
}
|
||||
|
||||
public int getKind() {
|
||||
PsiUtilCore.ensureValid(this);
|
||||
public int getKind(@NotNull PsiFile containingFile) {
|
||||
PsiUtilCore.ensureValid(containingFile);
|
||||
CompositeElement treeParent = getTreeParent();
|
||||
IElementType i = treeParent.getElementType();
|
||||
if (isDummy(i)) {
|
||||
@@ -142,7 +142,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
return CLASS_FQ_OR_PACKAGE_NAME_KIND;
|
||||
}
|
||||
if (i == JavaElementType.JAVA_CODE_REFERENCE) {
|
||||
int parentKind = ((PsiJavaCodeReferenceElementImpl)treeParent).getKind();
|
||||
int parentKind = ((PsiJavaCodeReferenceElementImpl)treeParent).getKind(containingFile);
|
||||
if (parentKind == CLASS_NAME_KIND) {
|
||||
return CLASS_OR_PACKAGE_NAME_KIND;
|
||||
}
|
||||
@@ -256,16 +256,17 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
@Override
|
||||
@NotNull
|
||||
public String getCanonicalText() {
|
||||
return getCanonicalText(false, null);
|
||||
return getCanonicalText(false, null, getContainingFile());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations) {
|
||||
switch (getKind()) {
|
||||
public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations, @NotNull PsiFile containingFile) {
|
||||
switch (getKind(containingFile)) {
|
||||
case CLASS_NAME_KIND:
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
final PsiElement target = resolve();
|
||||
JavaResolveResult[] results = multiResolve(false, containingFile, containingFile.getProject());
|
||||
final PsiElement target = results.length == 1 ? results[0].getElement() : null;
|
||||
if (target instanceof PsiClass) {
|
||||
PsiClass aClass = (PsiClass)target;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
@@ -273,7 +274,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
PsiElement qualifier = getQualifier();
|
||||
String prefix = null;
|
||||
if (qualifier instanceof PsiJavaCodeReferenceElementImpl) {
|
||||
prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null);
|
||||
prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null, containingFile);
|
||||
}
|
||||
else {
|
||||
String fqn = aClass.getQualifiedName();
|
||||
@@ -327,15 +328,14 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
return advancedResolve(false).getElement();
|
||||
}
|
||||
|
||||
private static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver<PsiJavaReference> {
|
||||
private static final class OurGenericsResolver implements ResolveCache.PolyVariantContextResolver<PsiJavaReference> {
|
||||
private static final OurGenericsResolver INSTANCE = new OurGenericsResolver();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) {
|
||||
public ResolveResult[] resolve(@NotNull PsiJavaReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) {
|
||||
PsiJavaCodeReferenceElementImpl referenceElement = (PsiJavaCodeReferenceElementImpl)ref;
|
||||
int kind = referenceElement.getKind();
|
||||
PsiFile containingFile = referenceElement.getContainingFile();
|
||||
int kind = referenceElement.getKind(containingFile);
|
||||
JavaResolveResult[] result = referenceElement.resolve(kind, containingFile);
|
||||
|
||||
if (incompleteCode && result.length == 0 && kind != CLASS_FQ_NAME_KIND && kind != CLASS_FQ_OR_PACKAGE_NAME_KIND) {
|
||||
@@ -347,7 +347,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
}
|
||||
}
|
||||
|
||||
JavaResolveUtil.substituteResults((PsiJavaCodeReferenceElement)ref, result);
|
||||
JavaResolveUtil.substituteResults(referenceElement, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -373,16 +373,21 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
LOG.error("getManager() == null!");
|
||||
return JavaResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
PsiFile file = SharedImplUtil.getContainingFile(fileElement);
|
||||
boolean valid = file != null && file.isValid();
|
||||
PsiFile containingFile = SharedImplUtil.getContainingFile(fileElement);
|
||||
boolean valid = containingFile != null && containingFile.isValid();
|
||||
if (!valid) {
|
||||
LOG.error("invalid!");
|
||||
return JavaResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
Project project = manager.getProject();
|
||||
|
||||
return multiResolve(incompleteCode, containingFile, project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaResolveResult[] multiResolve(boolean incompleteCode, @NotNull PsiFile containingFile, @NotNull Project project) {
|
||||
final ResolveCache resolveCache = ResolveCache.getInstance(project);
|
||||
final ResolveResult[] results = resolveCache.resolveWithCaching(this, OurGenericsResolver.INSTANCE, true, incompleteCode, file);
|
||||
final ResolveResult[] results = resolveCache.resolveWithCaching(this, OurGenericsResolver.INSTANCE, true, incompleteCode, containingFile);
|
||||
return results.length == 0 ? JavaResolveResult.EMPTY_ARRAY : (JavaResolveResult[])results;
|
||||
}
|
||||
|
||||
@@ -394,14 +399,15 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
return subst;
|
||||
}
|
||||
|
||||
private JavaResolveResult[] resolve(final int kind, PsiFile containingFile) {
|
||||
@NotNull
|
||||
private JavaResolveResult[] resolve(final int kind, @NotNull PsiFile containingFile) {
|
||||
switch (kind) {
|
||||
case CLASS_FQ_NAME_KIND: {
|
||||
// TODO: support type parameters in FQ names
|
||||
String text = getNormalizedText();
|
||||
if (StringUtil.isEmptyOrSpaces(text)) return JavaResolveResult.EMPTY_ARRAY;
|
||||
|
||||
PsiClass aClass = JavaPsiFacade.getInstance(getProject()).findClass(text, getResolveScope());
|
||||
PsiClass aClass = JavaPsiFacade.getInstance(containingFile.getProject()).findClass(text, getResolveScope());
|
||||
if (aClass == null) return JavaResolveResult.EMPTY_ARRAY;
|
||||
|
||||
if (!isQualified() && text.equals(aClass.getQualifiedName())) {
|
||||
@@ -503,16 +509,17 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
@Override
|
||||
public PsiElement bindToElement(@NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
CheckUtil.checkWritable(this);
|
||||
PsiFile containingFile = getContainingFile();
|
||||
CheckUtil.checkWritable(containingFile);
|
||||
if (isReferenceTo(element)) return this;
|
||||
|
||||
switch (getKind()) {
|
||||
switch (getKind(containingFile)) {
|
||||
case CLASS_NAME_KIND:
|
||||
case CLASS_FQ_NAME_KIND:
|
||||
if (!(element instanceof PsiClass)) {
|
||||
throw cannotBindError(element);
|
||||
}
|
||||
return bindToClass((PsiClass)element);
|
||||
return bindToClass((PsiClass)element, containingFile);
|
||||
|
||||
case PACKAGE_NAME_KIND:
|
||||
if (!(element instanceof PsiPackage)) {
|
||||
@@ -523,7 +530,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
|
||||
if (element instanceof PsiClass) {
|
||||
return bindToClass((PsiClass)element);
|
||||
return bindToClass((PsiClass)element, containingFile);
|
||||
}
|
||||
else if (element instanceof PsiPackage) {
|
||||
return bindToPackage((PsiPackage)element);
|
||||
@@ -538,7 +545,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
if (name == null) {
|
||||
throw new IncorrectOperationException(aClass.toString());
|
||||
}
|
||||
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
|
||||
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(containingFile.getProject()).getParserFacade();
|
||||
final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(name, getParent());
|
||||
getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode());
|
||||
return ref;
|
||||
@@ -557,10 +564,11 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
return new IncorrectOperationException("Cannot bind to " + element);
|
||||
}
|
||||
|
||||
private PsiElement bindToClass(PsiClass aClass) throws IncorrectOperationException {
|
||||
private PsiElement bindToClass(@NotNull PsiClass aClass, @NotNull PsiFile containingFile) throws IncorrectOperationException {
|
||||
String qName = aClass.getQualifiedName();
|
||||
boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(getProject()).useFQClassNames() && isFullyQualified();
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
|
||||
Project project = containingFile.getProject();
|
||||
boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(project).useFQClassNames() && isFullyQualified(containingFile);
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
if (qName == null) {
|
||||
qName = aClass.getName();
|
||||
PsiClass psiClass = facade.getResolveHelper().resolveReferencedClass(qName, this);
|
||||
@@ -583,7 +591,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
((PsiJavaCodeReferenceElementImpl)ref).setAnnotations(annotations);
|
||||
|
||||
if (!preserveQualification) {
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(aClass.getProject());
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
|
||||
ref = (PsiJavaCodeReferenceElement)codeStyleManager.shortenClassReferences(ref, JavaCodeStyleManager.UNCOMPLETE_CODE);
|
||||
}
|
||||
|
||||
@@ -631,8 +639,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFullyQualified() {
|
||||
switch (getKind()) {
|
||||
private boolean isFullyQualified(@NotNull PsiFile containingFile) {
|
||||
switch (getKind(containingFile)) {
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
if (resolve() instanceof PsiPackage) return true;
|
||||
//noinspection fallthrough
|
||||
@@ -656,10 +664,10 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
final PsiElement refElement = SourceTreeToPsiMap.<PsiJavaCodeReferenceElement>treeToPsiNotNull(qualifier).resolve();
|
||||
if (refElement instanceof PsiPackage) return true;
|
||||
|
||||
return SourceTreeToPsiMap.<PsiJavaCodeReferenceElementImpl>treeToPsiNotNull(qualifier).isFullyQualified();
|
||||
return SourceTreeToPsiMap.<PsiJavaCodeReferenceElementImpl>treeToPsiNotNull(qualifier).isFullyQualified(containingFile);
|
||||
}
|
||||
|
||||
private PsiElement bindToPackage(final PsiPackage aPackage) throws IncorrectOperationException {
|
||||
private PsiElement bindToPackage(@NotNull PsiPackage aPackage) throws IncorrectOperationException {
|
||||
final String qName = aPackage.getQualifiedName();
|
||||
if (qName.isEmpty()) {
|
||||
throw new IncorrectOperationException("Cannot bind to default package: "+aPackage);
|
||||
@@ -672,7 +680,12 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
@Override
|
||||
public boolean isReferenceTo(final PsiElement element) {
|
||||
switch (getKind()) {
|
||||
PsiFile containingFile = getContainingFile();
|
||||
return isReferenceTo(element, containingFile);
|
||||
}
|
||||
|
||||
private boolean isReferenceTo(PsiElement element, @NotNull PsiFile containingFile) {
|
||||
switch (getKind(containingFile)) {
|
||||
case CLASS_NAME_KIND:
|
||||
case CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
if (!(element instanceof PsiClass)) return false;
|
||||
@@ -681,44 +694,40 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
case CLASS_FQ_NAME_KIND: {
|
||||
if (!(element instanceof PsiClass)) return false;
|
||||
final String qName = ((PsiClass)element).getQualifiedName();
|
||||
return qName != null && qName.equals(getCanonicalText());
|
||||
return qName != null && qName.equals(getCanonicalText(false, null, containingFile));
|
||||
}
|
||||
|
||||
case PACKAGE_NAME_KIND: {
|
||||
if (!(element instanceof PsiPackage)) return false;
|
||||
final String qName = ((PsiPackage)element).getQualifiedName();
|
||||
return qName.equals(getCanonicalText());
|
||||
return qName.equals(getCanonicalText(false, null, containingFile));
|
||||
}
|
||||
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
// if (lastChild.type != IDENTIFIER) return false;
|
||||
if (element instanceof PsiPackage) {
|
||||
final String qName = ((PsiPackage)element).getQualifiedName();
|
||||
return qName.equals(getCanonicalText());
|
||||
return qName.equals(getCanonicalText(false, null, containingFile));
|
||||
}
|
||||
else if (element instanceof PsiClass) {
|
||||
if (element instanceof PsiClass) {
|
||||
final PsiIdentifier nameIdentifier = ((PsiClass)element).getNameIdentifier();
|
||||
if (nameIdentifier == null) return false;
|
||||
PsiElement nameElement = getReferenceNameElement();
|
||||
return nameElement != null && nameElement.textMatches(nameIdentifier) &&
|
||||
element.getManager().areElementsEquivalent(resolve(), element);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
containingFile.getManager().areElementsEquivalent(resolve(), element);
|
||||
}
|
||||
return false;
|
||||
|
||||
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
|
||||
if (element instanceof PsiClass) {
|
||||
final String qName = ((PsiClass)element).getQualifiedName();
|
||||
return qName != null && qName.equals(getCanonicalText());
|
||||
return qName != null && qName.equals(getCanonicalText(false, null, containingFile));
|
||||
}
|
||||
else if (element instanceof PsiPackage) {
|
||||
if (element instanceof PsiPackage) {
|
||||
final String qName = ((PsiPackage)element).getQualifiedName();
|
||||
return qName.equals(getCanonicalText());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
return qName.equals(getCanonicalText(false, null, containingFile));
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
LOG.assertTrue(false);
|
||||
return true;
|
||||
@@ -727,7 +736,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
final ASTNode referenceNameElement = getReferenceNameNode();
|
||||
if (referenceNameElement == null || referenceNameElement.getElementType() != JavaTokenType.IDENTIFIER) return false;
|
||||
final String name = ((PsiClass)element).getName();
|
||||
return name != null && referenceNameElement.getText().equals(name) && element.getManager().areElementsEquivalent(resolve(), element);
|
||||
return name != null && referenceNameElement.getText().equals(name) && containingFile.getManager().areElementsEquivalent(resolve(), element);
|
||||
}
|
||||
|
||||
private String getNormalizedText() {
|
||||
@@ -748,8 +757,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fullyQualify(final PsiClass targetClass) {
|
||||
final int kind = getKind();
|
||||
public void fullyQualify(@NotNull final PsiClass targetClass) {
|
||||
final int kind = getKind(getContainingFile());
|
||||
if (kind != CLASS_NAME_KIND && kind != CLASS_OR_PACKAGE_NAME_KIND && kind != CLASS_IN_QUALIFIED_NEW_KIND) {
|
||||
LOG.error("Wrong kind " + kind);
|
||||
return;
|
||||
@@ -778,32 +787,31 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
@NotNull
|
||||
public Object[] getVariants() {
|
||||
final ElementFilter filter;
|
||||
switch (getKind()) {
|
||||
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
filter = new OrFilter();
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.CLASS);
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
break;
|
||||
case CLASS_NAME_KIND:
|
||||
filter = ElementClassFilter.CLASS;
|
||||
break;
|
||||
case PACKAGE_NAME_KIND:
|
||||
filter = ElementClassFilter.PACKAGE_FILTER;
|
||||
break;
|
||||
case CLASS_FQ_NAME_KIND:
|
||||
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
|
||||
filter = new OrFilter();
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
if (isQualified()) {
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.CLASS);
|
||||
}
|
||||
break;
|
||||
case CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
filter = ElementClassFilter.CLASS;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown reference type");
|
||||
switch (getKind(getContainingFile())) {
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
filter = new OrFilter();
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.CLASS);
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
break;
|
||||
case CLASS_NAME_KIND:
|
||||
filter = ElementClassFilter.CLASS;
|
||||
break;
|
||||
case PACKAGE_NAME_KIND:
|
||||
filter = ElementClassFilter.PACKAGE_FILTER;
|
||||
break;
|
||||
case CLASS_FQ_NAME_KIND:
|
||||
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
|
||||
filter = new OrFilter();
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
if (isQualified()) {
|
||||
((OrFilter)filter).addFilter(ElementClassFilter.CLASS);
|
||||
}
|
||||
break;
|
||||
case CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
filter = ElementClassFilter.CLASS;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown reference type");
|
||||
}
|
||||
|
||||
return PsiImplUtil.getReferenceVariantsByFilter(this, filter);
|
||||
@@ -821,7 +829,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter())));
|
||||
filter.addFilter(ElementClassFilter.VARIABLE);
|
||||
}
|
||||
switch (getKind()) {
|
||||
switch (getKind(getContainingFile())) {
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
filter.addFilter(ElementClassFilter.CLASS);
|
||||
filter.addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
@@ -899,7 +907,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
@Override
|
||||
public String getQualifiedName() {
|
||||
switch (getKind()) {
|
||||
switch (getKind(getContainingFile())) {
|
||||
case CLASS_NAME_KIND:
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi.impl.source;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This interface should be implemented by all PsiJavaCodeReference implementations
|
||||
@@ -35,9 +36,8 @@ public interface SourceJavaCodeReference {
|
||||
* Helper method for ReferenceAdjuster. Tries to qualify this reference as if
|
||||
* it references <code>targetClass</code>. Does not check that it indeed references
|
||||
* targetClass
|
||||
* @param targetClass
|
||||
*/
|
||||
void fullyQualify(PsiClass targetClass);
|
||||
void fullyQualify(@NotNull PsiClass targetClass);
|
||||
|
||||
boolean isQualified();
|
||||
|
||||
|
||||
+6
-4
@@ -35,6 +35,8 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi
|
||||
private static final String[] DEFAULT_PACKAGES = {CommonClassNames.DEFAULT_PACKAGE};
|
||||
|
||||
private final String myClassName;
|
||||
@NotNull
|
||||
private final PsiFile myContainingFile;
|
||||
private final PsiElement myPlace;
|
||||
private PsiClass myAccessClass = null;
|
||||
private List<ClassCandidateInfo> myCandidates = null;
|
||||
@@ -43,8 +45,9 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi
|
||||
private JavaResolveResult[] myResult = JavaResolveResult.EMPTY_ARRAY;
|
||||
private PsiElement myCurrentFileContext;
|
||||
|
||||
public ClassResolverProcessor(String className, @NotNull PsiElement startPlace, PsiFile containingFile) {
|
||||
public ClassResolverProcessor(@NotNull String className, @NotNull PsiElement startPlace, @NotNull PsiFile containingFile) {
|
||||
myClassName = className;
|
||||
myContainingFile = containingFile;
|
||||
PsiElement place = containingFile instanceof JavaCodeFragment && ((JavaCodeFragment)containingFile).getVisibilityChecker() != null ? null : startPlace;
|
||||
myPlace = place;
|
||||
if (place instanceof PsiJavaCodeReferenceElement) {
|
||||
@@ -111,7 +114,7 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi
|
||||
String fqn = psiClass.getQualifiedName();
|
||||
if (fqn == null) return false;
|
||||
|
||||
PsiFile file = myPlace == null ? null : FileContextUtil.getContextFile(myPlace);
|
||||
PsiFile file = myPlace == null ? null : FileContextUtil.getContextFile(myContainingFile);
|
||||
|
||||
String[] defaultPackages = file instanceof PsiJavaFile ? ((PsiJavaFile)file).getImplicitlyImportedPackages() : DEFAULT_PACKAGES;
|
||||
String packageName = StringUtil.getPackageName(fqn);
|
||||
@@ -123,9 +126,8 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi
|
||||
return file instanceof PsiJavaFile && ((PsiJavaFile)file).getPackageName().equals(packageName);
|
||||
}
|
||||
|
||||
private Domination dominates(PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) {
|
||||
private Domination dominates(@NotNull PsiClass aClass, boolean accessible, @NotNull String fqName, @NotNull ClassCandidateInfo info) {
|
||||
final PsiClass otherClass = info.getElement();
|
||||
assert otherClass != null;
|
||||
String otherQName = otherClass.getQualifiedName();
|
||||
if (fqName.equals(otherQName)) {
|
||||
return Domination.DOMINATED_BY;
|
||||
|
||||
@@ -225,7 +225,7 @@ public class JavaResolveUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void substituteResults(final @NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
|
||||
public static void substituteResults(@NotNull final PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
|
||||
if (result.length > 0 && result[0].getElement() instanceof PsiClass) {
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
final CandidateInfo resolveResult = (CandidateInfo)result[i];
|
||||
@@ -247,7 +247,7 @@ public class JavaResolveUtil {
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiPolyVariantReference> JavaResolveResult[] resolveWithContainingFile(@NotNull T ref,
|
||||
@NotNull ResolveCache.PolyVariantResolver<T> resolver,
|
||||
@NotNull ResolveCache.PolyVariantContextResolver<T> resolver,
|
||||
boolean needToPreventRecursion,
|
||||
boolean incompleteCode,
|
||||
@NotNull PsiFile containingFile) {
|
||||
|
||||
+3
-2
@@ -80,8 +80,9 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(myManager.getProject()).getParserFacade();
|
||||
try {
|
||||
final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(referenceText, context);
|
||||
LOG.assertTrue(ref.isValid(), referenceText);
|
||||
return ResolveClassUtil.resolveClass(ref);
|
||||
PsiFile containingFile = ref.getContainingFile();
|
||||
LOG.assertTrue(containingFile.isValid(), referenceText);
|
||||
return ResolveClassUtil.resolveClass(ref, containingFile);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -20,15 +20,16 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
|
||||
import com.intellij.psi.scope.util.PsiScopesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ResolveClassUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.ResolveClassUtil");
|
||||
|
||||
@Nullable
|
||||
public static PsiClass resolveClass(PsiJavaCodeReferenceElement ref) {
|
||||
public static PsiClass resolveClass(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiFile containingFile) {
|
||||
if (ref instanceof PsiJavaCodeReferenceElementImpl &&
|
||||
((PsiJavaCodeReferenceElementImpl)ref).getKind() == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) {
|
||||
((PsiJavaCodeReferenceElementImpl)ref).getKind(containingFile) == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) {
|
||||
PsiElement parent = ref.getParent();
|
||||
if (parent instanceof PsiAnonymousClass){
|
||||
parent = parent.getParent();
|
||||
@@ -63,7 +64,7 @@ public class ResolveClassUtil {
|
||||
long time1 = System.currentTimeMillis();
|
||||
*/
|
||||
|
||||
ClassResolverProcessor processor = new ClassResolverProcessor(className, ref, ref.getContainingFile());
|
||||
ClassResolverProcessor processor = new ClassResolverProcessor(className, ref, containingFile);
|
||||
PsiScopesUtil.resolveAndWalk(processor, ref, null);
|
||||
|
||||
|
||||
|
||||
+9
-5
@@ -41,7 +41,7 @@ public class VariableResolverProcessor extends ConflictFilterProcessor implement
|
||||
private final PsiClass myAccessClass;
|
||||
private PsiElement myCurrentFileContext = null;
|
||||
|
||||
public VariableResolverProcessor(@NotNull PsiJavaCodeReferenceElement place, PsiFile placeFile) {
|
||||
public VariableResolverProcessor(@NotNull PsiJavaCodeReferenceElement place, @NotNull PsiFile placeFile) {
|
||||
super(place.getText(), ourFilter, new PsiConflictResolver[]{new JavaVariableConflictResolver()}, new SmartList<CandidateInfo>(), place, placeFile);
|
||||
|
||||
PsiElement referenceName = place.getReferenceNameElement();
|
||||
@@ -54,16 +54,20 @@ public class VariableResolverProcessor extends ConflictFilterProcessor implement
|
||||
final JavaResolveResult accessClass = PsiUtil.getAccessObjectClass((PsiExpression)qualifier);
|
||||
final PsiElement element = accessClass.getElement();
|
||||
if (element instanceof PsiTypeParameter) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(element.getProject()).getElementFactory();
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(placeFile.getProject()).getElementFactory();
|
||||
final PsiClassType type = factory.createType((PsiTypeParameter)element);
|
||||
final PsiType accessType = accessClass.getSubstitutor().substitute(type);
|
||||
if (accessType instanceof PsiArrayType) {
|
||||
LanguageLevel languageLevel = PsiUtil.getLanguageLevel(qualifier);
|
||||
LanguageLevel languageLevel = PsiUtil.getLanguageLevel(placeFile);
|
||||
access = factory.getArrayClass(languageLevel);
|
||||
}
|
||||
else if (accessType instanceof PsiClassType) access = ((PsiClassType)accessType).resolve();
|
||||
else if (accessType instanceof PsiClassType) {
|
||||
access = ((PsiClassType)accessType).resolve();
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiClass) {
|
||||
access = (PsiClass)element;
|
||||
}
|
||||
else if (element instanceof PsiClass) access = (PsiClass)element;
|
||||
}
|
||||
myAccessClass = access;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1070,7 +1070,7 @@ public class InferenceSession {
|
||||
session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType));
|
||||
return true;
|
||||
} else {
|
||||
return TypeConversionUtil.isAssignable(sReturnType, tReturnType);
|
||||
return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(tReturnType, sReturnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,7 +1115,7 @@ public class InferenceSession {
|
||||
session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType));
|
||||
return true;
|
||||
} else {
|
||||
return TypeConversionUtil.isAssignable(sReturnType, tReturnType);
|
||||
return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(tReturnType, sReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -65,7 +65,10 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula
|
||||
}
|
||||
}
|
||||
|
||||
collectReturnTypeVariables(session, psiExpression, substitutor.substitute(interfaceMethod.getReturnType()), result);
|
||||
final PsiType returnType = interfaceMethod.getReturnType();
|
||||
if (returnType != null) {
|
||||
collectReturnTypeVariables(session, psiExpression, substitutor.substitute(returnType), result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -19,11 +19,12 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.SourceJavaCodeReference;
|
||||
import com.intellij.util.CharTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JavaSourceUtil {
|
||||
private JavaSourceUtil() { }
|
||||
|
||||
public static void fullyQualifyReference(final CompositeElement reference, final PsiClass targetClass) {
|
||||
public static void fullyQualifyReference(@NotNull CompositeElement reference, @NotNull PsiClass targetClass) {
|
||||
if (((SourceJavaCodeReference)reference).isQualified()) { // qualified reference
|
||||
final PsiClass parentClass = targetClass.getContainingClass();
|
||||
if (parentClass == null) return;
|
||||
|
||||
@@ -85,7 +85,7 @@ public class JavaTreeGenerator implements TreeGenerator {
|
||||
|
||||
boolean isFQ = false;
|
||||
if (original instanceof PsiJavaCodeReferenceElementImpl) {
|
||||
int kind = ((PsiJavaCodeReferenceElementImpl)original).getKind();
|
||||
int kind = ((PsiJavaCodeReferenceElementImpl)original).getKind(original.getContainingFile());
|
||||
switch (kind) {
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND:
|
||||
|
||||
+13
-10
@@ -41,14 +41,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMethodReferenceExpression> {
|
||||
class MethodReferenceResolver implements ResolveCache.PolyVariantContextResolver<PsiMethodReferenceExpressionImpl> {
|
||||
private static final Logger LOG = Logger.getInstance("#" + MethodReferenceResolver.class.getName());
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ResolveResult[] resolve(@NotNull final PsiMethodReferenceExpression reference, boolean incompleteCode) {
|
||||
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(
|
||||
reference);
|
||||
public JavaResolveResult[] resolve(@NotNull final PsiMethodReferenceExpressionImpl reference, @NotNull final PsiFile containingFile, boolean incompleteCode) {
|
||||
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(reference);
|
||||
|
||||
final PsiClass containingClass = qualifierResolveResult.getContainingClass();
|
||||
PsiSubstitutor substitutor = qualifierResolveResult.getSubstitutor();
|
||||
@@ -87,7 +86,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
|
||||
final PsiConflictResolver conflictResolver = createResolver(reference, qualifierResolveResult, interfaceMethod, signature);
|
||||
final MethodCandidatesProcessor processor =
|
||||
new MethodCandidatesProcessor(reference, reference.getContainingFile(), new PsiConflictResolver[] {conflictResolver}, new SmartList<CandidateInfo>()) {
|
||||
new MethodCandidatesProcessor(reference, containingFile, new PsiConflictResolver[] {conflictResolver}, new SmartList<CandidateInfo>()) {
|
||||
@Override
|
||||
protected boolean acceptVarargs() {
|
||||
return true;
|
||||
@@ -156,7 +155,11 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil
|
||||
.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
|
||||
if (receiverSubstitutor != null) {
|
||||
if (!method.hasTypeParameters() && signature.getParameterTypes().length == 1) return receiverSubstitutor;
|
||||
if (!method.hasTypeParameters()) {
|
||||
if (signature.getParameterTypes().length == 1 || PsiUtil.isRawSubstitutor(containingClass, receiverSubstitutor)) {
|
||||
return receiverSubstitutor;
|
||||
}
|
||||
}
|
||||
psiSubstitutor = receiverSubstitutor;
|
||||
}
|
||||
}
|
||||
@@ -175,7 +178,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
if (interfaceMethodReturnType != PsiType.VOID) {
|
||||
if (interfaceMethodReturnType != PsiType.VOID && interfaceMethodReturnType != null) {
|
||||
final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType();
|
||||
if (returnType != null) {
|
||||
session.registerConstraints(returnType, interfaceMethodReturnType);
|
||||
@@ -241,7 +244,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
return functionalInterfaceType;
|
||||
}
|
||||
|
||||
protected PsiConflictResolver createResolver(PsiMethodReferenceExpression referenceExpression,
|
||||
protected PsiConflictResolver createResolver(PsiMethodReferenceExpressionImpl referenceExpression,
|
||||
PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult,
|
||||
PsiMethod interfaceMethod,
|
||||
MethodSignature signature) {
|
||||
@@ -257,11 +260,11 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
|
||||
private static class MethodReferenceConflictResolver extends JavaMethodsConflictResolver {
|
||||
private final MethodSignature mySignature;
|
||||
private PsiMethodReferenceExpression myReferenceExpression;
|
||||
private final PsiMethodReferenceExpressionImpl myReferenceExpression;
|
||||
private final PsiMethodReferenceUtil.QualifierResolveResult myQualifierResolveResult;
|
||||
private final boolean myFunctionalMethodVarArgs;
|
||||
|
||||
private MethodReferenceConflictResolver(PsiMethodReferenceExpression referenceExpression,
|
||||
private MethodReferenceConflictResolver(PsiMethodReferenceExpressionImpl referenceExpression,
|
||||
PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult,
|
||||
@Nullable MethodSignature signature, boolean varArgs) {
|
||||
super(referenceExpression, signature != null ? signature.getParameterTypes() : PsiType.EMPTY_ARRAY, PsiUtil.getLanguageLevel(referenceExpression));
|
||||
|
||||
+6
-8
@@ -47,6 +47,7 @@ import java.util.Map;
|
||||
|
||||
public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiMethodReferenceExpression {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl");
|
||||
private static final MethodReferenceResolver RESOLVER = new MethodReferenceResolver();
|
||||
|
||||
public PsiMethodReferenceExpressionImpl() {
|
||||
super(JavaElementType.METHOD_REF_EXPRESSION);
|
||||
@@ -77,7 +78,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
|
||||
final MethodReferenceResolver resolver = new MethodReferenceResolver() {
|
||||
@Override
|
||||
protected PsiConflictResolver createResolver(PsiMethodReferenceExpression referenceExpression,
|
||||
protected PsiConflictResolver createResolver(PsiMethodReferenceExpressionImpl referenceExpression,
|
||||
PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult,
|
||||
PsiMethod interfaceMethod,
|
||||
MethodSignature signature) {
|
||||
@@ -90,7 +91,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
}
|
||||
};
|
||||
|
||||
final ResolveResult[] result = resolver.resolve(this, false);
|
||||
final ResolveResult[] result = resolver.resolve(this, getContainingFile(), false);
|
||||
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(this);
|
||||
final int interfaceArity = interfaceMethod.getParameterList().getParametersCount();
|
||||
for (ResolveResult resolveResult : result) {
|
||||
@@ -262,12 +263,11 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
LOG.error("invalid!");
|
||||
return JavaResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
final MethodReferenceResolver resolver = new MethodReferenceResolver();
|
||||
final Map<PsiMethodReferenceExpression, PsiType> map = PsiMethodReferenceUtil.ourRefs.get();
|
||||
if (map != null && map.containsKey(this)) {
|
||||
return (JavaResolveResult[])resolver.resolve(this, incompleteCode);
|
||||
return RESOLVER.resolve(this, file, incompleteCode);
|
||||
}
|
||||
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, resolver, true, incompleteCode,file);
|
||||
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, true, incompleteCode, file);
|
||||
return results.length == 0 ? JavaResolveResult.EMPTY_ARRAY : (JavaResolveResult[])results;
|
||||
}
|
||||
|
||||
@@ -421,9 +421,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
if (interfaceMethod != null) {
|
||||
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(left);
|
||||
|
||||
LOG.assertTrue(interfaceReturnType != null);
|
||||
|
||||
if (interfaceReturnType == PsiType.VOID) {
|
||||
if (interfaceReturnType == PsiType.VOID || interfaceReturnType == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -136,12 +136,12 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew
|
||||
return new PsiPolyVariantCachingReference() {
|
||||
@Override
|
||||
@NotNull
|
||||
public JavaResolveResult[] resolveInner(boolean incompleteCode) {
|
||||
public JavaResolveResult[] resolveInner(boolean incompleteCode, @NotNull PsiFile containingFile) {
|
||||
ASTNode classRef = findChildByRole(ChildRole.TYPE_REFERENCE);
|
||||
if (classRef != null) {
|
||||
ASTNode argumentList = PsiImplUtil.skipWhitespaceAndComments(classRef.getTreeNext());
|
||||
if (argumentList != null && argumentList.getElementType() == JavaElementType.EXPRESSION_LIST) {
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(containingFile.getProject());
|
||||
PsiType aClass = facade.getElementFactory().createType((PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(classRef));
|
||||
return facade.getResolveHelper().multiResolveConstructor((PsiClassType)aClass,
|
||||
(PsiExpressionList)SourceTreeToPsiMap.treeElementToPsi(argumentList),
|
||||
@@ -151,7 +151,7 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew
|
||||
else{
|
||||
ASTNode anonymousClassElement = findChildByType(JavaElementType.ANONYMOUS_CLASS);
|
||||
if (anonymousClassElement != null) {
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(containingFile.getProject());
|
||||
final PsiAnonymousClass anonymousClass = (PsiAnonymousClass)SourceTreeToPsiMap.treeElementToPsi(anonymousClassElement);
|
||||
PsiType aClass = anonymousClass.getBaseClassType();
|
||||
ASTNode argumentList = anonymousClassElement.findChildByType(JavaElementType.EXPRESSION_LIST);
|
||||
@@ -176,7 +176,7 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew
|
||||
@Override
|
||||
@NotNull
|
||||
public String getCanonicalText() {
|
||||
return null;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-15
@@ -181,23 +181,22 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
super.clearCaches();
|
||||
}
|
||||
|
||||
public static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver<PsiJavaReference> {
|
||||
public static final class OurGenericsResolver implements ResolveCache.PolyVariantContextResolver<PsiJavaReference> {
|
||||
public static final OurGenericsResolver INSTANCE = new OurGenericsResolver();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) {
|
||||
@Override
|
||||
public ResolveResult[] resolve(@NotNull PsiJavaReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) {
|
||||
PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)ref;
|
||||
CompositeElement treeParent = expression.getTreeParent();
|
||||
IElementType parentType = treeParent == null ? null : treeParent.getElementType();
|
||||
PsiFile file = expression.getContainingFile();
|
||||
|
||||
List<PsiElement> qualifiers = resolveAllQualifiers(expression, file);
|
||||
List<PsiElement> qualifiers = resolveAllQualifiers(expression, containingFile);
|
||||
try {
|
||||
JavaResolveResult[] result = expression.resolve(parentType, file);
|
||||
JavaResolveResult[] result = expression.resolve(parentType, containingFile);
|
||||
|
||||
if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) {
|
||||
result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, file);
|
||||
result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, containingFile);
|
||||
}
|
||||
|
||||
JavaResolveUtil.substituteResults(expression, result);
|
||||
@@ -213,6 +212,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PsiElement> resolveAllQualifiers(@NotNull PsiReferenceExpressionImpl expression, @NotNull final PsiFile containingFile) {
|
||||
// to avoid SOE, resolve all qualifiers starting from the innermost
|
||||
PsiElement qualifier = expression.getQualifier();
|
||||
@@ -246,9 +246,9 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaResolveResult[] resolve(IElementType parentType, PsiFile containingFile) {
|
||||
private JavaResolveResult[] resolve(IElementType parentType, @NotNull PsiFile containingFile) {
|
||||
if (parentType == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
JavaResolveResult[] result = resolveToVariable();
|
||||
JavaResolveResult[] result = resolveToVariable(containingFile);
|
||||
if (result.length > 0) {
|
||||
return result;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
return resolve(JavaElementType.REFERENCE_EXPRESSION, containingFile);
|
||||
}
|
||||
|
||||
return resolveToVariable();
|
||||
return resolveToVariable(containingFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -297,7 +297,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaResolveResult[] resolveToPackage(PsiFile containingFile) {
|
||||
private JavaResolveResult[] resolveToPackage(@NotNull PsiFile containingFile) {
|
||||
final String packageName = getCachedNormalizedText();
|
||||
Project project = containingFile.getProject();
|
||||
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
@@ -316,7 +316,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaResolveResult[] resolveToClass(@NotNull PsiElement classNameElement, PsiFile containingFile) {
|
||||
private JavaResolveResult[] resolveToClass(@NotNull PsiElement classNameElement, @NotNull PsiFile containingFile) {
|
||||
final String className = classNameElement.getText();
|
||||
|
||||
final ClassResolverProcessor processor = new ClassResolverProcessor(className, this, containingFile);
|
||||
@@ -325,8 +325,8 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaResolveResult[] resolveToVariable() {
|
||||
final VariableResolverProcessor processor = new VariableResolverProcessor(this, getContainingFile());
|
||||
private JavaResolveResult[] resolveToVariable(@NotNull PsiFile containingFile) {
|
||||
final VariableResolverProcessor processor = new VariableResolverProcessor(this, containingFile);
|
||||
PsiScopesUtil.resolveAndWalk(processor, this, null);
|
||||
return processor.getResult();
|
||||
}
|
||||
@@ -730,7 +730,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fullyQualify(PsiClass targetClass) {
|
||||
public void fullyQualify(@NotNull PsiClass targetClass) {
|
||||
JavaSourceUtil.fullyQualifyReference(this, targetClass);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -624,11 +624,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
}
|
||||
|
||||
if (!applicable12ignoreFunctionalType && applicable21ignoreFunctionalType) {
|
||||
return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER;
|
||||
return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER;
|
||||
}
|
||||
|
||||
if (!applicable21ignoreFunctionalType && applicable12ignoreFunctionalType) {
|
||||
return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER;
|
||||
return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER;
|
||||
}
|
||||
|
||||
return specifics;
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
|
||||
};
|
||||
}
|
||||
|
||||
protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
|
||||
protected static PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
|
||||
return argumentList != null ? argumentList.getExpressionTypes() : null;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -72,8 +72,7 @@ public abstract class JavaClassTreeElementBase<Value extends PsiElement> extends
|
||||
myLocation = "";
|
||||
} else {
|
||||
myLocation = cls.getName();
|
||||
char rightArrow = '\u2192';
|
||||
myLocation = UIUtil.getLabelFont().canDisplay(rightArrow) ? rightArrow + myLocation : "->" + myLocation;
|
||||
myLocation = UIUtil.rightArrow() + myLocation;
|
||||
}
|
||||
} else {
|
||||
myLocation = "";
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.List;
|
||||
|
||||
class MyClass {
|
||||
<error descr="'method1(Comparable<Integer>)' clashes with 'method1(Comparable<Boolean>)'; both methods have same erasure">void method1 (Comparable<Integer> c)</error> {}
|
||||
void method1(Comparable<Boolean> c) {}
|
||||
|
||||
<error descr="'method2(List<Integer>)' clashes with 'method2(List<Boolean>)'; both methods have same erasure">void method2(List<Integer> l)</error> {}
|
||||
void method2(List<Boolean> l) {}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
interface A {
|
||||
Iterable<Integer> m(List ls);
|
||||
}
|
||||
|
||||
interface B {
|
||||
Iterable<String> m(List l);
|
||||
}
|
||||
|
||||
<error descr="'m(List)' in 'Test.B' clashes with 'm(List)' in 'Test.A'; methods have unrelated return types">interface AB extends A, B</error> {}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class Test {
|
||||
void <warning descr="Use of '_' as an identifier might not be supported in releases after Java 8">_</warning>(){}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface I<T, K extends Integer> {
|
||||
void m(T t);
|
||||
void m(K k);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface IEx extends I<Integer, Integer> { }
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
<X> void m();
|
||||
}
|
||||
|
||||
interface B {
|
||||
void m();
|
||||
}
|
||||
|
||||
interface C extends A, B { }
|
||||
|
||||
{
|
||||
C c = ()-> {};
|
||||
}
|
||||
}
|
||||
|
||||
class Test1 {
|
||||
|
||||
interface F {
|
||||
<X> void m();
|
||||
}
|
||||
|
||||
{
|
||||
F f = this::g;
|
||||
}
|
||||
|
||||
void g() {}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
|
||||
interface F {
|
||||
<X> void m();
|
||||
void a();
|
||||
}
|
||||
|
||||
{
|
||||
F f = <error descr="Multiple non-overriding abstract methods found">() -> g()</error>;
|
||||
}
|
||||
|
||||
void g() {}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
int m();
|
||||
}
|
||||
|
||||
interface B {
|
||||
int m(int i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
A a = ()-> ((B)i -> i).m(3);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import java.io.Serializable;
|
||||
|
||||
class Test {
|
||||
|
||||
interface I {
|
||||
void foo();
|
||||
}
|
||||
|
||||
interface A {
|
||||
void bar(int i);
|
||||
}
|
||||
|
||||
{
|
||||
Object o1 = (Serializable & I) () -> {};
|
||||
Object o2 = (I & Serializable) () -> {};
|
||||
Object o3 = (I & Runnable) <error descr="Multiple non-overriding abstract methods found in Runnable & I">() -> {}</error>;
|
||||
Object o4 = (A & Runnable) <error descr="Multiple non-overriding abstract methods found in Runnable & A">() -> {}</error>;
|
||||
Object o5 = (Runnable & A) <error descr="Multiple non-overriding abstract methods found in Runnable & A">() -> {}</error>;
|
||||
}
|
||||
}
|
||||
|
||||
class Test1 {
|
||||
|
||||
interface A {
|
||||
<X> void foo();
|
||||
}
|
||||
|
||||
interface B {
|
||||
void foo();
|
||||
}
|
||||
|
||||
{
|
||||
Object c0 = (A & B) ()->{};
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class LambdaConv10 {
|
||||
|
||||
interface I<T, R> { public R call( T t); }
|
||||
|
||||
{
|
||||
I<Integer,Integer> in = (<error descr="Incompatible parameter types in lambda expression">int i</error>) -> 2 * i;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class Test {
|
||||
|
||||
Runnable r;
|
||||
{ r = r::run; }
|
||||
Runnable r1;
|
||||
{ r1 = () -> r1.run(); }
|
||||
|
||||
|
||||
{
|
||||
Runnable r = () -> <error descr="Variable 'r' might not have been initialized">r</error>.run();
|
||||
Runnable r1 = <error descr="Variable 'r1' might not have been initialized">r1</error>::run;
|
||||
}
|
||||
}
|
||||
-5
@@ -1,10 +1,5 @@
|
||||
class C {
|
||||
void test() {
|
||||
{
|
||||
I <warning descr="Use of '_' as an identifier might not be supported in releases after Java 8">_</warning> = new I() { public void f(int i) { } };
|
||||
accept(_);
|
||||
}
|
||||
|
||||
{
|
||||
accept(<error descr="Use of '_' as a lambda parameter name is not allowed">_</error> -> System.out.println(_));
|
||||
accept((int <error descr="Use of '_' as a lambda parameter name is not allowed">_</error>) -> System.out.println(_));
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
A f();
|
||||
}
|
||||
interface B {}
|
||||
|
||||
static abstract class C implements A, B {}
|
||||
static abstract class D implements A, B {}
|
||||
|
||||
interface I<T> {
|
||||
<error descr="Invalid method declaration; return type required">m</error>(T arg);
|
||||
}
|
||||
|
||||
void bar(C c) {
|
||||
foo(c, x -> x.f());
|
||||
foo(c, x -> x);
|
||||
}
|
||||
|
||||
<T> void foo(T t1, I<T> t3) {}
|
||||
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
|
||||
interface F {
|
||||
<X> <error descr="Invalid method declaration; return type required">m</error>();
|
||||
}
|
||||
|
||||
void g() {}
|
||||
|
||||
{
|
||||
F f = this::g;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Test {
|
||||
interface I {
|
||||
void foo();
|
||||
}
|
||||
|
||||
private Object o;
|
||||
|
||||
public static void main(String[] args){
|
||||
I i = <error descr="Non-static field 'o' cannot be referenced from a static context">o</error>::wait;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
class Test {
|
||||
private static void m(int i) {System.out.println(i);}
|
||||
private static void <warning descr="Private method 'm(java.lang.Integer)' is never used">m</warning>(Integer i) {System.out.println(i);}
|
||||
|
||||
interface I {
|
||||
void foo(int p);
|
||||
}
|
||||
|
||||
static {
|
||||
I s = Test::m;
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
|
||||
static void m(Integer i) { }
|
||||
|
||||
interface I1 {
|
||||
void m(int x);
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
void m(Integer x);
|
||||
}
|
||||
|
||||
static void call(I1 i1) { System.out.println(i1); }
|
||||
static void call(I2 i2) { System.out.println(i2); }
|
||||
|
||||
static {
|
||||
call<error descr="Ambiguous method call: both 'Test2.call(I1)' and 'Test2.call(I2)' match">(Test2::m)</error>;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
class Test {
|
||||
|
||||
interface I0 {
|
||||
void m();
|
||||
}
|
||||
|
||||
interface I1 {
|
||||
void m(Object a);
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
void m(Object a1, Object a2);
|
||||
}
|
||||
|
||||
interface IVarargs {
|
||||
void m(Object... as);
|
||||
}
|
||||
|
||||
void call(I0 p) { }
|
||||
void call(I1 p) { }
|
||||
void call(I2 p) { }
|
||||
void call(IVarargs p) { }
|
||||
|
||||
void test() {
|
||||
call(() -> { });
|
||||
call<error descr="Ambiguous method call: both 'Test.call(I1)' and 'Test.call(IVarargs)' match">(p1 -> { })</error>;
|
||||
call((p1, p2) -> {});
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class Test {
|
||||
interface I { Object in<EOLError descr="';' expected"></EOLError>
|
||||
<error descr="Invalid method declaration; return type required">voke</error>(); }
|
||||
interface IStr { String foo(); }
|
||||
|
||||
public static void call(IStr str) {}
|
||||
public static void call(I i) { }
|
||||
|
||||
public static void main(String[] args) {
|
||||
call<error descr="Ambiguous method call: both 'Test.call(IStr)' and 'Test.call(I)' match">(()-> null)</error>;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class Test {
|
||||
interface I { Object invoke(); }
|
||||
interface IStr { String foo(); }
|
||||
|
||||
private static void call(IStr str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'call(Test.I)' is never used">call</warning>(I i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
call(()-> null);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
class Test {
|
||||
|
||||
interface I1 {String m();}
|
||||
interface I2 {void m();}
|
||||
|
||||
void call(I1 p) { }
|
||||
void call(I2 p) { }
|
||||
|
||||
void test() {
|
||||
call<error descr="Ambiguous method call: both 'Test.call(I1)' and 'Test.call(I2)' match">(() -> { throw new RuntimeException(); })</error>;
|
||||
call(() -> { if (true) return ""; throw new RuntimeException(); });
|
||||
call(() -> { if (true) return; throw new RuntimeException(); });
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
A f();
|
||||
}
|
||||
interface B {}
|
||||
|
||||
static abstract class C implements A, B {}
|
||||
static abstract class D implements A, B {}
|
||||
|
||||
interface I<T> {
|
||||
T m(T arg);
|
||||
}
|
||||
|
||||
void bar(C c) {
|
||||
foo(c, <error descr="Incompatible return type A in lambda expression">x -> x.f()</error>);
|
||||
foo(c, x -> x);
|
||||
}
|
||||
|
||||
<T> void foo(T t1, I<T> t3) {}
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class Test {
|
||||
interface I {
|
||||
void m();
|
||||
}
|
||||
|
||||
<T> void call(T t) {}
|
||||
<T extends Runnable> void call1(T t) {}
|
||||
|
||||
{
|
||||
call<error descr="'call(T)' in 'Test' cannot be applied to '(<lambda expression>)'">(() -> {})</error>;
|
||||
call1(() -> {});
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
class BBB {
|
||||
|
||||
static <T> void f() {
|
||||
TerminalOp<T, LinkedHashSet<T>> <warning descr="Variable 'reduceOp' is never used">reduceOp</warning> = BBB.<T, LinkedHashSet<T>>makeRef(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll);
|
||||
TerminalOp<T, LinkedHashSet<T>> <warning descr="Variable 'reduceOp' is never used">reduceOp</warning> = BBB.<T, LinkedHashSet<T>>makeRef(LinkedHashSet::new, LinkedHashSet::<warning descr="Unchecked call to 'add(E)' as a member of raw type 'HashSet'">add</warning>, LinkedHashSet::<warning descr="Unchecked call to 'addAll(Collection<? extends E>)' as a member of raw type 'AbstractCollection'">addAll</warning>);
|
||||
}
|
||||
|
||||
public static <T, U> TerminalOp<T, U> makeRef(U <warning descr="Parameter 'seed' is never used">seed</warning>, BiFunction<U, ? super T, U> <warning descr="Parameter 'reducer' is never used">reducer</warning>, BinaryOperator<U> <warning descr="Parameter 'combiner' is never used">combiner</warning>) {
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import java.util.*;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class A<T>
|
||||
{
|
||||
public <S> S foldRight(Supplier<S> value, BiFunction<T, Supplier<S>, Supplier<S>> f)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <S> Optional<S> h(A<S> flow)
|
||||
{
|
||||
return flow.foldRight(() -> Optional.empty(), (element, lazyResult) -> () -> Optional.of(element));
|
||||
|
||||
}
|
||||
|
||||
public static <S> Optional<S> hR(A<S> flow)
|
||||
{
|
||||
return flow.foldRight(Optional::empty, (element, lazyResult) -> () -> Optional.of(element));
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface I {
|
||||
static void a() {}
|
||||
}
|
||||
|
||||
interface J {
|
||||
void foo();
|
||||
}
|
||||
|
||||
class Test {
|
||||
{
|
||||
J j = I::a;
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
|
||||
interface I<T> {
|
||||
void m(List<T> l, T el);
|
||||
}
|
||||
|
||||
{
|
||||
I<String> i1 = List::add;
|
||||
System.out.println(i1);
|
||||
I i2 = List::<warning descr="Unchecked call to 'add(E)' as a member of raw type 'java.util.List'">add</warning>;
|
||||
System.out.println(i2);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Create Method 'fooBar'" "true"
|
||||
class FooBar {
|
||||
{
|
||||
Comparator<String> c = this::fooBar;
|
||||
}
|
||||
|
||||
private int fooBar(String s, String s1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface Comparator<T> {
|
||||
int compare(T o1, T o2);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user