Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2014-04-23 20:07:07 +02:00
294 changed files with 3551 additions and 1713 deletions
-4
View File
@@ -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);
@@ -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,
@@ -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();
@@ -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"),
@@ -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;
@@ -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) {
@@ -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"));
}
}
}
}
@@ -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();
@@ -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;
}
@@ -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);
}
@@ -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());
@@ -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;
@@ -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
@@ -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 ? "→" : "->";
}
}
@@ -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(
@@ -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());
}
}
@@ -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);
@@ -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);
@@ -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;
@@ -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();
@@ -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());
}
@@ -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) {
@@ -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 ||
@@ -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
@@ -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() {
@@ -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());
}
}
@@ -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));
@@ -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
@@ -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();
@@ -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();
}
}
@@ -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);
@@ -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);
}
@@ -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();
@@ -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;
@@ -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);
}
@@ -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);
}
@@ -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());
}
@@ -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();
@@ -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();
}
@@ -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;
}
}
@@ -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);
}
@@ -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;
@@ -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;
}
@@ -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.
@@ -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
@@ -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();
@@ -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) {
@@ -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);
@@ -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;
}
@@ -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);
}
}
@@ -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:
@@ -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));
@@ -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;
}
@@ -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
@@ -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);
}
@@ -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;
@@ -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;
}
@@ -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 = "";
@@ -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) {}
}
@@ -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> {}
}
@@ -0,0 +1,3 @@
class Test {
void <warning descr="Use of '_' as an identifier might not be supported in releases after Java 8">_</warning>(){}
}
@@ -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> { }
@@ -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() {}
}
@@ -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);
}
}
@@ -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) ()->{};
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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(_));
@@ -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;
}
}
@@ -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;
}
}
@@ -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>;
}
}
@@ -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) -> {});
}
}
@@ -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>;
}
}
@@ -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);
}
}
@@ -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(); });
}
}
@@ -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) {}
}
@@ -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(() -> {});
}
}
@@ -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>) {
@@ -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));
}
}
@@ -0,0 +1,13 @@
interface I {
static void a() {}
}
interface J {
void foo();
}
class Test {
{
J j = I::a;
}
}
@@ -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);
}
}
@@ -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