mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java: type annotations
This commit is contained in:
+20
-19
@@ -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.
|
||||
@@ -33,10 +33,11 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
|
||||
public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
private final PsiType myType;
|
||||
|
||||
@@ -75,28 +76,26 @@ public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement
|
||||
addTypeCast(project, (PsiExpression)startElement, myType);
|
||||
}
|
||||
|
||||
private static void addTypeCast(Project project, PsiExpression originalExpression, PsiType type) throws IncorrectOperationException {
|
||||
private static void addTypeCast(Project project, PsiExpression originalExpression, PsiType type) {
|
||||
PsiExpression typeCast = createCastExpression(originalExpression, project, type);
|
||||
originalExpression.replace(typeCast);
|
||||
}
|
||||
|
||||
static PsiExpression createCastExpression(PsiExpression originalExpression, Project project, PsiType type) throws IncorrectOperationException {
|
||||
static PsiExpression createCastExpression(PsiExpression originalExpression, Project project, PsiType type) {
|
||||
// remove nested casts
|
||||
PsiElement element = PsiUtil.deparenthesizeExpression(originalExpression);
|
||||
if (element == null){
|
||||
return null;
|
||||
}
|
||||
PsiElement expression = PsiUtil.deparenthesizeExpression(originalExpression);
|
||||
if (expression == null) return null;
|
||||
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory();
|
||||
|
||||
PsiTypeCastExpression typeCast = (PsiTypeCastExpression)factory.createExpressionFromText("(Type)value", null);
|
||||
assertNotNull(typeCast.getCastType()).replace(factory.createTypeElement(type));
|
||||
typeCast = (PsiTypeCastExpression)CodeStyleManager.getInstance(project).reformat(typeCast);
|
||||
typeCast.getCastType().replace(factory.createTypeElement(type));
|
||||
|
||||
if (element instanceof PsiConditionalExpression) {
|
||||
// we'd better cast one branch of ternary expression if we could
|
||||
PsiConditionalExpression expression = (PsiConditionalExpression)element.copy();
|
||||
PsiExpression thenE = expression.getThenExpression();
|
||||
PsiExpression elseE = expression.getElseExpression();
|
||||
if (expression instanceof PsiConditionalExpression) {
|
||||
// we'd better cast one branch of ternary expression if we can
|
||||
PsiConditionalExpression conditional = (PsiConditionalExpression)expression.copy();
|
||||
PsiExpression thenE = conditional.getThenExpression();
|
||||
PsiExpression elseE = conditional.getElseExpression();
|
||||
PsiType thenType = thenE == null ? null : thenE.getType();
|
||||
PsiType elseType = elseE == null ? null : elseE.getType();
|
||||
if (elseType != null && thenType != null) {
|
||||
@@ -104,18 +103,20 @@ public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement
|
||||
boolean replaceElse = !TypeConversionUtil.isAssignable(type, elseType);
|
||||
if (replaceThen != replaceElse) {
|
||||
if (replaceThen) {
|
||||
typeCast.getOperand().replace(thenE);
|
||||
assertNotNull(typeCast.getOperand()).replace(thenE);
|
||||
thenE.replace(typeCast);
|
||||
}
|
||||
else {
|
||||
typeCast.getOperand().replace(elseE);
|
||||
assertNotNull(typeCast.getOperand()).replace(elseE);
|
||||
elseE.replace(typeCast);
|
||||
}
|
||||
return expression;
|
||||
return conditional;
|
||||
}
|
||||
}
|
||||
}
|
||||
typeCast.getOperand().replace(element);
|
||||
|
||||
assertNotNull(typeCast.getOperand()).replace(expression);
|
||||
|
||||
return typeCast;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,12 @@ public class JavaReferenceAdjuster implements ReferenceAdjuster {
|
||||
}
|
||||
|
||||
if (rightKind) {
|
||||
// annotations may jump out of reference (see PsiJavaCodeReferenceImpl#setAnnotations()) so they should be processed first
|
||||
List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(ref, PsiAnnotation.class);
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
process(annotation.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode);
|
||||
}
|
||||
|
||||
boolean isInsideDocComment = TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null;
|
||||
boolean isShort = !ref.isQualified();
|
||||
if (isInsideDocComment ? !useFqInJavadoc : !useFqInCode) {
|
||||
|
||||
@@ -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.
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -24,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
*
|
||||
* @author max
|
||||
*/
|
||||
public class PsiArrayType extends PsiType {
|
||||
public class PsiArrayType extends PsiType.Stub {
|
||||
private final PsiType myComponentType;
|
||||
|
||||
/**
|
||||
@@ -44,19 +43,33 @@ public class PsiArrayType extends PsiType {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return StringUtil.join(myComponentType.getPresentableText(), getAnnotationsTextPrefix(false, true, true), "[]");
|
||||
return getText(myComponentType.getPresentableText(), "[]", false, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return StringUtil.join(myComponentType.getCanonicalText(), "[]");
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return getText(myComponentType.getCanonicalText(annotated), "[]", true, annotated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return StringUtil.join(myComponentType.getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "[]");
|
||||
return getText(myComponentType.getInternalCanonicalText(), "[]", true, true);
|
||||
}
|
||||
|
||||
protected String getText(@NotNull String prefix, @NotNull String suffix, boolean qualified, boolean annotated) {
|
||||
StringBuilder sb = new StringBuilder(prefix.length() + suffix.length());
|
||||
sb.append(prefix);
|
||||
if (annotated) {
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if (annotations.length != 0) {
|
||||
sb.append(' ');
|
||||
PsiNameHelper.appendAnnotations(sb, annotations, qualified);
|
||||
}
|
||||
}
|
||||
sb.append(suffix);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class PsiCapturedWildcardType extends PsiType {
|
||||
public class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
@NotNull private final PsiWildcardType myExistential;
|
||||
@NotNull private final PsiElement myContext;
|
||||
@Nullable private final PsiTypeParameter myParameter;
|
||||
@@ -78,8 +78,8 @@ public class PsiCapturedWildcardType extends PsiType {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return myExistential.getCanonicalText();
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return myExistential.getCanonicalText(annotated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -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.
|
||||
@@ -280,4 +280,23 @@ public abstract class PsiClassType extends PsiType {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary class to facilitate transition to {@link #getCanonicalText(boolean)}.
|
||||
*/
|
||||
public static abstract class Stub extends PsiClassType {
|
||||
protected Stub(LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations) {
|
||||
super(languageLevel, annotations);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public final String getCanonicalText() {
|
||||
return getCanonicalText(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract String getCanonicalText(boolean annotated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -33,7 +33,7 @@ import java.util.List;
|
||||
* Composite type resulting from Project Coin's multi-catch statements, i.e. <code>FileNotFoundException | EOFException</code>.
|
||||
* In most cases should be threatened via its least upper bound (<code>IOException</code> in the example above).
|
||||
*/
|
||||
public class PsiDisjunctionType extends PsiType {
|
||||
public class PsiDisjunctionType extends PsiType.Stub {
|
||||
private final PsiManager myManager;
|
||||
private final List<PsiType> myTypes;
|
||||
private final CachedValue<PsiType> myLubCache;
|
||||
@@ -85,15 +85,21 @@ public class PsiDisjunctionType extends PsiType {
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return StringUtil.join(myTypes, new Function<PsiType, String>() {
|
||||
@Override public String fun(PsiType psiType) { return psiType.getPresentableText(); }
|
||||
@Override
|
||||
public String fun(PsiType psiType) {
|
||||
return psiType.getPresentableText();
|
||||
}
|
||||
}, " | ");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
public String getCanonicalText(final boolean annotated) {
|
||||
return StringUtil.join(myTypes, new Function<PsiType, String>() {
|
||||
@Override public String fun(PsiType psiType) { return psiType.getCanonicalText(); }
|
||||
@Override
|
||||
public String fun(PsiType psiType) {
|
||||
return psiType.getCanonicalText(annotated);
|
||||
}
|
||||
}, " | ");
|
||||
}
|
||||
|
||||
@@ -101,7 +107,10 @@ public class PsiDisjunctionType extends PsiType {
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return StringUtil.join(myTypes, new Function<PsiType, String>() {
|
||||
@Override public String fun(PsiType psiType) { return psiType.getInternalCanonicalText(); }
|
||||
@Override
|
||||
public String fun(PsiType psiType) {
|
||||
return psiType.getInternalCanonicalText();
|
||||
}
|
||||
}, " | ");
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -45,19 +44,19 @@ public class PsiEllipsisType extends PsiArrayType {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return StringUtil.join(getComponentType().getPresentableText(), getAnnotationsTextPrefix(false, true, true), "...");
|
||||
return getText(getComponentType().getPresentableText(), "...", false, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return StringUtil.join(getComponentType().getCanonicalText(), "...");
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return getText(getComponentType().getCanonicalText(annotated), "...", true, annotated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return StringUtil.join(getComponentType().getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "...");
|
||||
return getText(getComponentType().getInternalCanonicalText(), "...", true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -29,7 +29,7 @@ import java.util.*;
|
||||
*
|
||||
* @author ven
|
||||
*/
|
||||
public class PsiIntersectionType extends PsiType {
|
||||
public class PsiIntersectionType extends PsiType.Stub {
|
||||
private final PsiType[] myConjuncts;
|
||||
|
||||
private PsiIntersectionType(@NotNull PsiType[] conjuncts) {
|
||||
@@ -111,19 +111,19 @@ public class PsiIntersectionType extends PsiType {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return myConjuncts[0].getCanonicalText();
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return myConjuncts[0].getCanonicalText(annotated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (int i = 0; i < myConjuncts.length; i++) {
|
||||
buffer.append(myConjuncts[i].getInternalCanonicalText());
|
||||
if (i < myConjuncts.length - 1) buffer.append(" & ");
|
||||
}
|
||||
return buffer.toString();
|
||||
return StringUtil.join(myConjuncts, new Function<PsiType, String>() {
|
||||
@Override
|
||||
public String fun(PsiType psiType) {
|
||||
return psiType.getInternalCanonicalText();
|
||||
}
|
||||
}, " & ");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -23,8 +23,11 @@ import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
import static com.intellij.util.ObjectUtils.notNull;
|
||||
|
||||
/**
|
||||
@@ -37,7 +40,7 @@ public abstract class PsiNameHelper {
|
||||
public static PsiNameHelper getInstance(Project project) {
|
||||
return ServiceManager.getService(project, PsiNameHelper.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the specified text is a Java identifier, using the language level of the project
|
||||
* with which the name helper is associated to filter out keywords.
|
||||
@@ -121,30 +124,15 @@ public abstract class PsiNameHelper {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPresentableText(@Nullable String refName, @NotNull PsiAnnotation[] annotations, @NotNull PsiType[] typeParameters) {
|
||||
if (typeParameters.length == 0 && annotations.length == 0) {
|
||||
public static String getPresentableText(@Nullable String refName, @NotNull PsiAnnotation[] annotations, @NotNull PsiType[] types) {
|
||||
if (types.length == 0 && annotations.length == 0) {
|
||||
return refName != null ? refName : "";
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
if (annotations.length > 0) {
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
buffer.append(annotation.getText()).append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
appendAnnotations(buffer, annotations, false);
|
||||
buffer.append(refName);
|
||||
|
||||
if (typeParameters.length > 0) {
|
||||
buffer.append("<");
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
buffer.append(typeParameters[i].getPresentableText());
|
||||
if (i < typeParameters.length - 1) buffer.append(", ");
|
||||
}
|
||||
buffer.append(">");
|
||||
}
|
||||
|
||||
appendTypeArgs(buffer, types, false, true);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@@ -262,4 +250,43 @@ public abstract class PsiNameHelper {
|
||||
return subpackageName.equals(packageName) ||
|
||||
subpackageName.startsWith(packageName) && subpackageName.charAt(packageName.length()) == '.';
|
||||
}
|
||||
|
||||
public static void appendTypeArgs(@NotNull StringBuilder sb, @NotNull PsiType[] types, boolean canonical, boolean annotated) {
|
||||
if (types.length == 0) return;
|
||||
|
||||
sb.append('<');
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(canonical ? "," : ", ");
|
||||
}
|
||||
|
||||
PsiType type = types[i];
|
||||
if (canonical) {
|
||||
sb.append(type.getCanonicalText(annotated));
|
||||
}
|
||||
else {
|
||||
sb.append(type.getPresentableText());
|
||||
}
|
||||
}
|
||||
sb.append('>');
|
||||
}
|
||||
|
||||
public static boolean appendAnnotations(@NotNull StringBuilder sb, @NotNull PsiAnnotation[] annotations, boolean canonical) {
|
||||
return appendAnnotations(sb, Arrays.asList(annotations), canonical);
|
||||
}
|
||||
|
||||
public static boolean appendAnnotations(@NotNull StringBuilder sb, @NotNull List<PsiAnnotation> annotations, boolean canonical) {
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
sb.append('@');
|
||||
if (canonical) {
|
||||
sb.append(annotation.getQualifiedName());
|
||||
sb.append(annotation.getParameterList().getText());
|
||||
}
|
||||
else {
|
||||
sb.append(assertNotNull(annotation.getNameReferenceElement()).getText());
|
||||
}
|
||||
sb.append(' ');
|
||||
}
|
||||
return annotations.size() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Represents primitive types of Java language.
|
||||
*/
|
||||
public class PsiPrimitiveType extends PsiType {
|
||||
public class PsiPrimitiveType extends PsiType.Stub {
|
||||
private static final Map<String, PsiPrimitiveType> ourQNameToUnboxed = new THashMap<String, PsiPrimitiveType>();
|
||||
private static final Map<PsiPrimitiveType, String> ourUnboxedToQName = new THashMap<PsiPrimitiveType, String>();
|
||||
|
||||
@@ -52,19 +52,29 @@ public class PsiPrimitiveType extends PsiType {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return getAnnotationsTextPrefix(false, false, true) + myName;
|
||||
return getText(false, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return myName;
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return getText(true, annotated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return getAnnotationsTextPrefix(true, false, true) + myName;
|
||||
return getText(true, true);
|
||||
}
|
||||
|
||||
private String getText(boolean qualified, boolean annotated) {
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if (!annotated || annotations.length == 0) return myName;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
PsiNameHelper.appendAnnotations(sb, annotations, qualified);
|
||||
sb.append(myName);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -84,6 +84,15 @@ public abstract class PsiType implements PsiAnnotationOwner {
|
||||
*/
|
||||
@NonNls
|
||||
@NotNull
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return getCanonicalText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@code getCanonicalText(false)}.
|
||||
*/
|
||||
@NonNls
|
||||
@NotNull
|
||||
public abstract String getCanonicalText();
|
||||
|
||||
/**
|
||||
@@ -284,24 +293,15 @@ public abstract class PsiType implements PsiAnnotationOwner {
|
||||
return getAnnotations();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/** @deprecated use {@link PsiNameHelper#appendAnnotations(StringBuilder, PsiAnnotation[], boolean)} (to remove in IDEA 14) */
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
protected String getAnnotationsTextPrefix(boolean qualified, boolean leadingSpace, boolean trailingSpace) {
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if (annotations.length == 0) return "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (leadingSpace) sb.append(' ');
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
if (i > 0) sb.append(' ');
|
||||
PsiAnnotation annotation = annotations[i];
|
||||
if (qualified) {
|
||||
sb.append('@').append(annotation.getQualifiedName()).append(annotation.getParameterList().getText());
|
||||
}
|
||||
else {
|
||||
sb.append(annotation.getText());
|
||||
}
|
||||
}
|
||||
if (trailingSpace) sb.append(' ');
|
||||
if (PsiNameHelper.appendAnnotations(sb, annotations, qualified) &&!trailingSpace) sb.setLength(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -310,4 +310,23 @@ public abstract class PsiType implements PsiAnnotationOwner {
|
||||
//noinspection HardCodedStringLiteral
|
||||
return "PsiType:" + getPresentableText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary class to facilitate transition to {@link #getCanonicalText(boolean)}.
|
||||
*/
|
||||
protected static abstract class Stub extends PsiType {
|
||||
protected Stub(@NotNull PsiAnnotation[] annotations) {
|
||||
super(annotations);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public final String getCanonicalText() {
|
||||
return getCanonicalText(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract String getCanonicalText(boolean annotated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
*
|
||||
* @author dsl
|
||||
*/
|
||||
public class PsiWildcardType extends PsiType {
|
||||
public class PsiWildcardType extends PsiType.Stub {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiWildcardType");
|
||||
|
||||
private static final Key<PsiWildcardType> UNBOUNDED_WILDCARD = new Key<PsiWildcardType>("UNBOUNDED_WILDCARD");
|
||||
@@ -83,21 +83,37 @@ public class PsiWildcardType extends PsiType {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return getAnnotationsTextPrefix(false, false, true) +
|
||||
(myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getPresentableText());
|
||||
return getText(false, true, myBound == null ? null : myBound.getPresentableText());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getCanonicalText() {
|
||||
return myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getCanonicalText();
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return getText(true, annotated, myBound == null ? null : myBound.getCanonicalText(annotated));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return getAnnotationsTextPrefix(true, false, true) +
|
||||
(myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getInternalCanonicalText());
|
||||
return getText(true, true, myBound == null ? null : myBound.getInternalCanonicalText());
|
||||
}
|
||||
|
||||
private String getText(boolean qualified, boolean annotated, @Nullable String suffix) {
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if ((!annotated || annotations.length == 0) && suffix == null) return "?";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (annotated) {
|
||||
PsiNameHelper.appendAnnotations(sb, annotations, qualified);
|
||||
}
|
||||
if (suffix == null) {
|
||||
sb.append('?');
|
||||
}
|
||||
else {
|
||||
sb.append(myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX);
|
||||
sb.append(suffix);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -30,16 +30,16 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class PsiClassReferenceType extends PsiClassType {
|
||||
public class PsiClassReferenceType extends PsiClassType.Stub {
|
||||
@NotNull
|
||||
private final PsiJavaCodeReferenceElement myReference;
|
||||
|
||||
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) {
|
||||
this(reference, langLevel, collectAnnotations(reference));
|
||||
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level) {
|
||||
this(reference, level, collectAnnotations(reference));
|
||||
}
|
||||
|
||||
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel, @NotNull PsiAnnotation[] annotations) {
|
||||
super(langLevel, annotations);
|
||||
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level, @NotNull PsiAnnotation[] annotations) {
|
||||
super(level, annotations);
|
||||
myReference = reference;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public class PsiClassReferenceType extends PsiClassType {
|
||||
return resolveGenerics().getElement();
|
||||
}
|
||||
|
||||
private static class DelegatingClassResolveResult implements ClassResolveResult {
|
||||
private static class DelegatingClassResolveResult implements PsiClassType.ClassResolveResult {
|
||||
private final JavaResolveResult myDelegate;
|
||||
|
||||
private DelegatingClassResolveResult(@NotNull JavaResolveResult delegate) {
|
||||
@@ -182,19 +182,37 @@ public class PsiClassReferenceType extends PsiClassType {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return getAnnotationsTextPrefix(false, false, true) + PsiNameHelper.getPresentableText(myReference);
|
||||
String presentableText = PsiNameHelper.getPresentableText(myReference);
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if (annotations.length == 0) return presentableText;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
PsiNameHelper.appendAnnotations(sb, annotations, false);
|
||||
sb.append(presentableText);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return myReference.getCanonicalText();
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
return getText(annotated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return getAnnotationsTextPrefix(true, false, true) + getCanonicalText();
|
||||
return getText(true);
|
||||
}
|
||||
|
||||
private String getText(boolean annotated) {
|
||||
if (myReference instanceof PsiJavaCodeReferenceElementImpl) {
|
||||
PsiAnnotation[] annotations = getAnnotations();
|
||||
if (!annotated || annotations.length == 0) annotations = null;
|
||||
return ((PsiJavaCodeReferenceElementImpl)myReference).getCanonicalText(annotated, annotations);
|
||||
}
|
||||
else {
|
||||
return myReference.getCanonicalText();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -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.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.source;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -30,11 +31,12 @@ import java.util.List;
|
||||
/**
|
||||
* @author dsl
|
||||
*/
|
||||
public class PsiImmediateClassType extends PsiClassType {
|
||||
public class PsiImmediateClassType extends PsiClassType.Stub {
|
||||
private final PsiClass myClass;
|
||||
private final PsiSubstitutor mySubstitutor;
|
||||
private final PsiManager myManager;
|
||||
private String myCanonicalText;
|
||||
private String myCanonicalTextAnnotated;
|
||||
private String myPresentableText;
|
||||
private String myInternalCanonicalText;
|
||||
|
||||
@@ -80,15 +82,15 @@ public class PsiImmediateClassType extends PsiClassType {
|
||||
this(aClass, substitutor, null, PsiAnnotation.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) {
|
||||
this(aClass, substitutor, languageLevel, PsiAnnotation.EMPTY_ARRAY);
|
||||
public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel level) {
|
||||
this(aClass, substitutor, level, PsiAnnotation.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
public PsiImmediateClassType(@NotNull PsiClass aClass,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
@Nullable LanguageLevel languageLevel,
|
||||
@NotNull PsiAnnotation[] annotations) {
|
||||
super(languageLevel, annotations);
|
||||
@Nullable LanguageLevel level,
|
||||
@NotNull PsiAnnotation... annotations) {
|
||||
super(level, annotations);
|
||||
myClass = aClass;
|
||||
myManager = aClass.getManager();
|
||||
mySubstitutor = substitutor;
|
||||
@@ -138,112 +140,119 @@ public class PsiImmediateClassType extends PsiClassType {
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
if (myPresentableText == null) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buildText(myClass, mySubstitutor, buffer, false, false);
|
||||
myPresentableText = buffer.toString();
|
||||
myPresentableText = getText(TextType.PRESENTABLE, true);
|
||||
}
|
||||
return myPresentableText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
if (myCanonicalText == null) {
|
||||
assert mySubstitutor.isValid();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buildText(myClass, mySubstitutor, buffer, true, false);
|
||||
myCanonicalText = buffer.toString();
|
||||
public String getCanonicalText(boolean annotated) {
|
||||
String cached = annotated ? myCanonicalTextAnnotated : myCanonicalText;
|
||||
if (cached == null) {
|
||||
cached = getText(TextType.CANONICAL, annotated);
|
||||
if (annotated) myCanonicalTextAnnotated = cached;
|
||||
else myCanonicalText = cached;
|
||||
}
|
||||
return myCanonicalText;
|
||||
return cached;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
if (myInternalCanonicalText == null) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buildText(myClass, mySubstitutor, buffer, true, true);
|
||||
myInternalCanonicalText = buffer.toString();
|
||||
myInternalCanonicalText = getText(TextType.INT_CANONICAL, true);
|
||||
}
|
||||
return myInternalCanonicalText;
|
||||
}
|
||||
|
||||
private enum TextType { PRESENTABLE, CANONICAL, INT_CANONICAL }
|
||||
|
||||
private String getText(@NotNull TextType textType, boolean annotated) {
|
||||
assert mySubstitutor.isValid();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buildText(myClass, mySubstitutor, buffer, textType, annotated);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void buildText(@NotNull PsiClass aClass,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
@NotNull StringBuilder buffer,
|
||||
boolean canonical,
|
||||
boolean internal) {
|
||||
@NotNull TextType textType,
|
||||
boolean annotated) {
|
||||
if (aClass instanceof PsiAnonymousClass) {
|
||||
ClassResolveResult baseResolveResult = ((PsiAnonymousClass) aClass).getBaseClassType().resolveGenerics();
|
||||
ClassResolveResult baseResolveResult = ((PsiAnonymousClass)aClass).getBaseClassType().resolveGenerics();
|
||||
PsiClass baseClass = baseResolveResult.getElement();
|
||||
PsiSubstitutor baseSub = baseResolveResult.getSubstitutor();
|
||||
if (baseClass != null) {
|
||||
buildText(baseClass, baseSub, buffer, canonical, internal);
|
||||
buildText(baseClass, baseResolveResult.getSubstitutor(), buffer, textType, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (canonical == internal) {
|
||||
buffer.append(getAnnotationsTextPrefix(internal, false, true));
|
||||
}
|
||||
boolean qualified = textType != TextType.PRESENTABLE;
|
||||
|
||||
PsiClass enclosingClass = null;
|
||||
if (!aClass.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
final PsiElement parent = aClass.getParent();
|
||||
PsiElement parent = aClass.getParent();
|
||||
if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) {
|
||||
enclosingClass = (PsiClass)parent;
|
||||
}
|
||||
}
|
||||
if (enclosingClass != null) {
|
||||
buildText(enclosingClass, substitutor, buffer, canonical, false);
|
||||
buildText(enclosingClass, substitutor, buffer, textType, false);
|
||||
buffer.append('.');
|
||||
buffer.append(aClass.getName());
|
||||
}
|
||||
else {
|
||||
final String name;
|
||||
if (!canonical) {
|
||||
name = aClass.getName();
|
||||
}
|
||||
else {
|
||||
final String qualifiedName = aClass.getQualifiedName();
|
||||
if (qualifiedName == null) {
|
||||
name = aClass.getName();
|
||||
}
|
||||
else {
|
||||
name = qualifiedName;
|
||||
else if (qualified) {
|
||||
String fqn = aClass.getQualifiedName();
|
||||
if (fqn != null) {
|
||||
String prefix = StringUtil.getPackageName(fqn);
|
||||
if (!StringUtil.isEmpty(prefix)) {
|
||||
buffer.append(prefix);
|
||||
buffer.append('.');
|
||||
}
|
||||
}
|
||||
buffer.append(name);
|
||||
}
|
||||
|
||||
if (annotated) {
|
||||
PsiNameHelper.appendAnnotations(buffer, getAnnotations(), qualified);
|
||||
}
|
||||
|
||||
buffer.append(aClass.getName());
|
||||
|
||||
PsiTypeParameter[] typeParameters = aClass.getTypeParameters();
|
||||
if (typeParameters.length > 0) {
|
||||
StringBuilder pineBuffer = new StringBuilder();
|
||||
pineBuffer.append('<');
|
||||
int pos = buffer.length();
|
||||
buffer.append('<');
|
||||
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
PsiTypeParameter typeParameter = typeParameters[i];
|
||||
PsiUtilCore.ensureValid(typeParameter);
|
||||
if (i > 0) pineBuffer.append(',');
|
||||
final PsiType substitutionResult = substitutor.substitute(typeParameter);
|
||||
|
||||
if (i > 0) {
|
||||
buffer.append(',');
|
||||
if (textType == TextType.PRESENTABLE) buffer.append(' ');
|
||||
}
|
||||
|
||||
PsiType substitutionResult = substitutor.substitute(typeParameter);
|
||||
if (substitutionResult == null) {
|
||||
pineBuffer = null;
|
||||
buffer.setLength(pos);
|
||||
pos = -1;
|
||||
break;
|
||||
}
|
||||
PsiUtil.ensureValidType(substitutionResult);
|
||||
if (canonical) {
|
||||
if (internal) {
|
||||
pineBuffer.append(substitutionResult.getInternalCanonicalText());
|
||||
}
|
||||
else {
|
||||
pineBuffer.append(substitutionResult.getCanonicalText());
|
||||
}
|
||||
|
||||
if (textType == TextType.PRESENTABLE) {
|
||||
buffer.append(substitutionResult.getPresentableText());
|
||||
}
|
||||
else if (textType == TextType.CANONICAL) {
|
||||
buffer.append(substitutionResult.getCanonicalText(annotated));
|
||||
}
|
||||
else {
|
||||
pineBuffer.append(substitutionResult.getPresentableText());
|
||||
buffer.append(substitutionResult.getInternalCanonicalText());
|
||||
}
|
||||
}
|
||||
if (pineBuffer != null) {
|
||||
buffer.append(pineBuffer);
|
||||
|
||||
if (pos >= 0) {
|
||||
buffer.append('>');
|
||||
}
|
||||
}
|
||||
@@ -265,7 +274,6 @@ public class PsiImmediateClassType extends PsiClassType {
|
||||
return false;
|
||||
}
|
||||
return equals(patternType);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,14 +285,12 @@ public class PsiImmediateClassType extends PsiClassType {
|
||||
@Override
|
||||
@NotNull
|
||||
public LanguageLevel getLanguageLevel() {
|
||||
if (myLanguageLevel != null) return myLanguageLevel;
|
||||
return PsiUtil.getLanguageLevel(myClass);
|
||||
return myLanguageLevel != null ? myLanguageLevel : PsiUtil.getLanguageLevel(myClass);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
|
||||
if (languageLevel.equals(myLanguageLevel)) return this;
|
||||
return new PsiImmediateClassType(myClass, mySubstitutor, languageLevel,getAnnotations());
|
||||
public PsiClassType setLanguageLevel(@NotNull LanguageLevel level) {
|
||||
return level.equals(myLanguageLevel) ? this : new PsiImmediateClassType(myClass, mySubstitutor, level, getAnnotations());
|
||||
}
|
||||
}
|
||||
|
||||
+42
-25
@@ -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.
|
||||
@@ -49,6 +49,7 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement implements PsiJavaCodeReferenceElement, SourceJavaCodeReference {
|
||||
@@ -255,36 +256,47 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
@Override
|
||||
@NotNull
|
||||
public String getCanonicalText() {
|
||||
return getCanonicalText(false, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations) {
|
||||
switch (getKind()) {
|
||||
case CLASS_NAME_KIND:
|
||||
case CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
final PsiElement target = resolve();
|
||||
if (target instanceof PsiClass) {
|
||||
final PsiClass aClass = (PsiClass)target;
|
||||
String name = aClass.getQualifiedName();
|
||||
if (name == null) {
|
||||
name = aClass.getName(); //?
|
||||
PsiClass aClass = (PsiClass)target;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
PsiElement qualifier = getQualifier();
|
||||
String prefix = null;
|
||||
if (qualifier instanceof PsiJavaCodeReferenceElementImpl) {
|
||||
prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null);
|
||||
}
|
||||
final PsiType[] types = getTypeParameters();
|
||||
if (types.length == 0) {
|
||||
final PsiElement qualifier = getQualifier();
|
||||
if (qualifier instanceof PsiJavaCodeReferenceElement) {
|
||||
return StringUtil.getQualifiedName(((PsiJavaCodeReferenceElement)qualifier).getCanonicalText(), aClass.getName());
|
||||
else {
|
||||
String fqn = aClass.getQualifiedName();
|
||||
if (fqn != null) {
|
||||
prefix = StringUtil.getPackageName(fqn);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
buf.append(name);
|
||||
buf.append('<');
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (i > 0) buf.append(',');
|
||||
buf.append(types[i].getCanonicalText());
|
||||
if (!StringUtil.isEmpty(prefix)) {
|
||||
buffer.append(prefix);
|
||||
buffer.append('.');
|
||||
}
|
||||
buf.append('>');
|
||||
|
||||
return buf.toString();
|
||||
if (annotated) {
|
||||
List<PsiAnnotation> list = annotations != null ? Arrays.asList(annotations) : getAnnotations();
|
||||
PsiNameHelper.appendAnnotations(buffer, list, true);
|
||||
}
|
||||
|
||||
buffer.append(aClass.getName());
|
||||
|
||||
PsiNameHelper.appendTypeArgs(buffer, getTypeParameters(), true, annotated);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
else if (target instanceof PsiPackage) {
|
||||
return ((PsiPackage)target).getQualifiedName();
|
||||
@@ -293,6 +305,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
LOG.assertTrue(target == null, target);
|
||||
return getNormalizedText();
|
||||
}
|
||||
|
||||
case PACKAGE_NAME_KIND:
|
||||
case CLASS_FQ_NAME_KIND:
|
||||
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
|
||||
@@ -327,7 +340,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
if (incompleteCode && result.length == 0 && kind != CLASS_FQ_NAME_KIND && kind != CLASS_FQ_OR_PACKAGE_NAME_KIND) {
|
||||
VariableResolverProcessor processor = new VariableResolverProcessor(referenceElement, containingFile);
|
||||
PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, incompleteCode);
|
||||
PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, true);
|
||||
result = processor.getResult();
|
||||
if (result.length == 0 && kind == CLASS_NAME_KIND) {
|
||||
result = referenceElement.resolve(PACKAGE_NAME_KIND, containingFile);
|
||||
@@ -457,16 +470,16 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
|
||||
case CLASS_OR_PACKAGE_NAME_KIND: {
|
||||
int classKind = kind == CLASS_OR_PACKAGE_NAME_KIND ? CLASS_NAME_KIND : CLASS_FQ_NAME_KIND;
|
||||
JavaResolveResult[] result = resolve(classKind,containingFile);
|
||||
JavaResolveResult[] result = resolve(classKind, containingFile);
|
||||
|
||||
if (result.length == 1 && !result[0].isAccessible()) {
|
||||
JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND,containingFile);
|
||||
JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND, containingFile);
|
||||
if (packageResult.length != 0) {
|
||||
result = packageResult;
|
||||
}
|
||||
}
|
||||
else if (result.length == 0) {
|
||||
result = resolve(PACKAGE_NAME_KIND,containingFile);
|
||||
result = resolve(PACKAGE_NAME_KIND, containingFile);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -607,7 +620,12 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
if (annotation.getParent() != newParent) {
|
||||
newParent.addAfter(annotation, anchor);
|
||||
if (anchor != null) {
|
||||
newParent.addAfter(annotation, anchor);
|
||||
}
|
||||
else {
|
||||
newParent.add(annotation);
|
||||
}
|
||||
annotation.delete();
|
||||
}
|
||||
}
|
||||
@@ -935,7 +953,6 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
final PsiReferenceParameterList parameterList = getParameterList();
|
||||
if (parameterList == null) return PsiType.EMPTY_ARRAY;
|
||||
return parameterList.getTypeArguments();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -131,7 +131,7 @@ public class JavaTreeGenerator implements TreeGenerator {
|
||||
type = PsiType.getJavaLangObject(manager, GlobalSearchScope.projectScope(manager.getProject()));
|
||||
}
|
||||
|
||||
String text = type.getPresentableText();
|
||||
String text = type.getCanonicalText(true);
|
||||
PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(original.getProject()).getParserFacade();
|
||||
PsiTypeElement element = parserFacade.createTypeElementFromText(text, original);
|
||||
|
||||
|
||||
+5
-5
@@ -157,14 +157,14 @@ class ParenthTest<T extends TZ> {
|
||||
class TestWildcardInference {
|
||||
interface A<T> {
|
||||
}
|
||||
|
||||
|
||||
class B<V> implements A<V> {
|
||||
B(C<V> v) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class C<E> {}
|
||||
|
||||
|
||||
class U {
|
||||
void foo() {
|
||||
C<? extends Number> x = null;
|
||||
@@ -202,13 +202,13 @@ class Another {
|
||||
|
||||
System.out.println(i);
|
||||
|
||||
<error descr="Incompatible types. Found: 'Outer2.Inner2<java.lang.String>', required: 'Outer2.Inner2<java.lang.String>'">Outer2<Integer>.Inner2<String> i5 = new Outer2<>().new Inner2<>();</error>
|
||||
<error descr="Incompatible types. Found: 'Outer2.Inner2<java.lang.String>', required: 'Outer2<java.lang.Integer>.Inner2<java.lang.String>'">Outer2<Integer>.Inner2<String> i5 = new Outer2<>().new Inner2<>();</error>
|
||||
}
|
||||
|
||||
static Outer m() {return null;}
|
||||
static <T extends Outer> T m1() {return null;}
|
||||
static <T> T m2() {return null;}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TypeParamsExtendsList {
|
||||
|
||||
+1
-1
@@ -40,6 +40,6 @@ class AAmbiguous {
|
||||
}
|
||||
|
||||
public static void main(Promise<String> helloWorld) {
|
||||
helloWorld.then<error descr="Ambiguous method call: both 'Promise.then(Function<? super String,Promise<Integer>>)' and 'Promise.then(AsyncFunction<? super String,Promise<Integer>>)' match">(AAmbiguous::calculateLength)</error>;
|
||||
helloWorld.then<error descr="Ambiguous method call: both 'Promise.then(Function<? super String, Promise<Integer>>)' and 'Promise.then(AsyncFunction<? super String, Promise<Integer>>)' match">(AAmbiguous::calculateLength)</error>;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@ class Test {
|
||||
}
|
||||
|
||||
void foo(Foo<String> as, final Foo<Character> ac) {
|
||||
boolean b1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> false)</error>);
|
||||
String s1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> "")</error>);
|
||||
boolean b2 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> "")</error>);
|
||||
boolean b1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character, Boolean>)' and 'Foo.forAll(II<Character, String>)' match">(c -> false)</error>);
|
||||
String s1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character, Boolean>)' and 'Foo.forAll(II<Character, String>)' match">(c -> "")</error>);
|
||||
boolean b2 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character, Boolean>)' and 'Foo.forAll(II<Character, String>)' match">(c -> "")</error>);
|
||||
String s2 = as.forAll2(s -> ac.forAll2(<error descr="Incompatible return type boolean in lambda expression">c -> false</error>));
|
||||
boolean b3 = as.forAll((I<String, Boolean>)s -> ac.forAll((I<Character, Boolean>)<error descr="Incompatible return type String in lambda expression">c -> ""</error>));
|
||||
String s3 = as.forAll((II<String, String>)s -> ac.forAll((II<Character, String>)<error descr="Incompatible return type boolean in lambda expression">c -> false</error>));
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ class Test {
|
||||
Test s1 = staticCall(Test::n0);
|
||||
Test s2 = staticCall(Test::n1);
|
||||
Test s3 = staticCall<error descr="Cannot resolve method 'staticCall(<method reference>)'">(Test::n2)</error>;
|
||||
Test s4 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test,String>)' match">(Test::n01)</error>;
|
||||
Test s5 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test,String>)' match">(Test::n012)</error>;
|
||||
Test s4 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test, String>)' match">(Test::n01)</error>;
|
||||
Test s5 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test, String>)' match">(Test::n012)</error>;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
@Target({TYPE_USE}) @interface TA { }
|
||||
import pkg.TA;
|
||||
|
||||
class Outer {
|
||||
class Middle {
|
||||
class Inner {
|
||||
void m1(Outer.Middle.Inner p) { }
|
||||
void m2(@TA Outer.Middle.Inner p) { }
|
||||
void m3(Outer.@TA Middle.Inner p) { }
|
||||
void m4(Outer.Middle.@TA @TA Inner p) { }
|
||||
void m2(@pkg.TA Outer.Middle.Inner p) { }
|
||||
void m3(Outer.@pkg.TA Middle.Inner p) { }
|
||||
void m4(Outer.Middle.@pkg.TA @pkg.TA Inner p) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
@Target({TYPE_USE}) @interface TA { }
|
||||
import pkg.TA;
|
||||
|
||||
class Outer {
|
||||
class Middle {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package pkg;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.TYPE_USE})
|
||||
@interface TA { }
|
||||
+1
-1
@@ -2,6 +2,6 @@ import util.Pair;
|
||||
|
||||
class Client {
|
||||
void method() {
|
||||
Pair<String, Pair<Integer,Boolean>> p = PairProvider.getPair();
|
||||
Pair<String, Pair<Integer, Boolean>> p = PairProvider.getPair();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
@@ -15,15 +15,22 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.psi
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType
|
||||
import com.intellij.testFramework.LightIdeaTestCase
|
||||
|
||||
@SuppressWarnings(["GrUnresolvedAccess", "GroovyAssignabilityCheck"])
|
||||
@SuppressWarnings("GroovyAssignabilityCheck")
|
||||
class AnnotatedTypeTest extends LightIdeaTestCase {
|
||||
private PsiFile context
|
||||
private PsiElementFactory factory
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp()
|
||||
factory = javaFacade.elementFactory
|
||||
context = createFile("typeCompositionTest.java", """
|
||||
package pkg;
|
||||
|
||||
public void testTypeComposition() {
|
||||
PsiFile context = createFile("typeCompositionTest.java", """
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
@@ -33,31 +40,55 @@ import static java.lang.annotation.ElementType.*;
|
||||
class E1 extends Exception { }
|
||||
class E2 extends Exception { }
|
||||
""")
|
||||
PsiElement psi
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) int @TA(2) [] a", context)
|
||||
assertEquals("@TA(1) int @TA(2) []", psi.declaredElements[0].type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context)
|
||||
assertEquals("@TA(1) E1 | @TA(2) E2", psi.catchBlockParameters[0].type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) String @TA(2) [] f @TA(3) []", context)
|
||||
assertEquals("@TA(1) String @TA(2) [] @TA(3) []", psi.declaredElements[0].type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("Class<@TA(1) ?> c", context)
|
||||
assertEquals("Class<@TA(1) ?>", psi.declaredElements[0].type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("Class<@TA String> cs = new Class<>()", context)
|
||||
assertEquals("Class<@TA String>", psi.declaredElements[0].initializer.type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) String s", context)
|
||||
assertEquals("@TA(1) String", psi.declaredElements[0].type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("@A java.lang.@TA(1) String s", context)
|
||||
assertEquals("@TA(1) String", psi.declaredElements[0].type.presentableText)
|
||||
|
||||
psi = javaFacade.elementFactory.createStatementFromText("Collection<? extends> s", context)
|
||||
assertEquals("Collection<?>", psi.declaredElements[0].type.presentableText)
|
||||
}
|
||||
|
||||
public void testPrimitiveArrayType() {
|
||||
doTest("@A @TA(1) int @TA(2) [] a", "@pkg.TA(1) int @pkg.TA(2) []", "int[]")
|
||||
}
|
||||
|
||||
public void testEllipsisType() {
|
||||
def psi = factory.createParameterFromText("@TA int @TA ... p", context)
|
||||
assertTypeText(psi.type, "@pkg.TA int @pkg.TA ...", "int...")
|
||||
}
|
||||
|
||||
public void testClassReferenceType() {
|
||||
doTest("@A @TA(1) String s", "java.lang.@pkg.TA(1) String", "java.lang.String")
|
||||
doTest("@A java.lang.@TA(1) String s", "java.lang.@pkg.TA(1) String", "java.lang.String")
|
||||
}
|
||||
|
||||
public void testCStyleArrayType() {
|
||||
doTest("@A @TA(1) String @TA(2) [] f @TA(3) []", "java.lang.@pkg.TA(1) String @pkg.TA(2) [] @pkg.TA(3) []", "java.lang.String[][]")
|
||||
}
|
||||
|
||||
public void testWildcardType() {
|
||||
doTest("Class<@TA(1) ?> c", "java.lang.Class<@pkg.TA(1) ?>", "java.lang.Class<?>")
|
||||
}
|
||||
|
||||
public void testDisjunctionType() {
|
||||
def psi = factory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context)
|
||||
assertTypeText(psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2")
|
||||
}
|
||||
|
||||
public void testDiamondType() {
|
||||
def psi = factory.createStatementFromText("Class<@TA String> cs = new Class<>()", context)
|
||||
assertTypeText(psi.declaredElements[0].initializer.type, "java.lang.Class<java.lang.@pkg.TA String>", "java.lang.Class<java.lang.String>")
|
||||
}
|
||||
|
||||
public void testImmediateClassType() {
|
||||
def aClass = javaFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT)
|
||||
def statement = factory.createStatementFromText("@TA int x", context)
|
||||
def annotations = statement.declaredElements[0].modifierList.annotations
|
||||
def type = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY, LanguageLevel.JDK_1_8, annotations)
|
||||
assertTypeText(type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT)
|
||||
}
|
||||
|
||||
private void doTest(String text, String annotated, String canonical) {
|
||||
def psi = factory.createStatementFromText(text, context)
|
||||
assertTypeText(psi.declaredElements[0].type, annotated, canonical)
|
||||
}
|
||||
|
||||
private static void assertTypeText(PsiType type, String annotated, String canonical) {
|
||||
assert type.getCanonicalText(true) == annotated
|
||||
assert type.getCanonicalText(false) == canonical
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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.
|
||||
@@ -61,6 +61,7 @@ public class ShortenClassReferencesTest extends LightCodeInsightFixtureTestCase
|
||||
public void testSCR37254() { doTest(); }
|
||||
|
||||
public void testTypeAnnotatedRef() {
|
||||
myFixture.configureByFile("pkg/TA.java");
|
||||
doTest();
|
||||
for (PsiParameter parameter : PsiTreeUtil.findChildrenOfType(myFixture.getFile(), PsiParameter.class)) {
|
||||
PsiTypeElement typeElement = parameter.getTypeElement();
|
||||
|
||||
+24
-18
@@ -17,12 +17,15 @@ package com.siyeh.ipp.exceptions;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ipp.base.Intention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.psi.PsiAnnotation.TargetType;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
|
||||
public class SplitMultiCatchIntention extends Intention {
|
||||
|
||||
@@ -52,27 +55,30 @@ public class SplitMultiCatchIntention extends Intention {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiModifierList modifierList = parameter.getModifierList();
|
||||
if (modifierList != null) {
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
if (PsiImplUtil.findApplicableTarget(annotation, TargetType.TYPE_USE) == TargetType.TYPE_USE) {
|
||||
annotation.delete();
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
|
||||
final List<PsiTypeElement> disjunctions = PsiTreeUtil.getChildrenOfTypeAsList(parameter.getTypeElement(), PsiTypeElement.class);
|
||||
for (int i = 0; i < disjunctions.size(); i++) {
|
||||
final PsiCatchSection copy = (PsiCatchSection)catchSection.copy();
|
||||
|
||||
final PsiTypeElement typeElement = assertNotNull(assertNotNull(copy.getParameter()).getTypeElement());
|
||||
final PsiTypeElement newTypeElement = factory.createTypeElementFromText(disjunctions.get(i).getText(), catchSection);
|
||||
typeElement.replace(newTypeElement);
|
||||
|
||||
grandParent.addBefore(copy, catchSection);
|
||||
|
||||
if (i == 0) {
|
||||
// clear the original from type annotations: they belong to the first disjunction and should not appear in others
|
||||
final PsiModifierList modifierList = parameter.getModifierList();
|
||||
if (modifierList != null) {
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
if (PsiImplUtil.findApplicableTarget(annotation, PsiAnnotation.TargetType.TYPE_USE) == PsiAnnotation.TargetType.TYPE_USE) {
|
||||
annotation.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
|
||||
for (PsiType disjunction : ((PsiDisjunctionType)type).getDisjunctions()) {
|
||||
final PsiCatchSection copy = (PsiCatchSection)catchSection.copy();
|
||||
final PsiParameter copyParameter = copy.getParameter();
|
||||
assert copyParameter != null : copy.getText();
|
||||
final PsiTypeElement typeElement = copyParameter.getTypeElement();
|
||||
assert typeElement != null : copyParameter.getText();
|
||||
final PsiTypeElement newTypeElement = factory.createTypeElement(disjunction);
|
||||
typeElement.replace(newTypeElement);
|
||||
grandParent.addBefore(copy, catchSection);
|
||||
}
|
||||
|
||||
catchSection.delete();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user