Type annotations on C-style arrays are recognized now even better

This commit is contained in:
Roman Shevchenko
2013-04-05 22:28:42 +02:00
parent 41d93bf6e8
commit 52c17b2657
4 changed files with 36 additions and 33 deletions
@@ -208,13 +208,6 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
@Override
public PsiAnnotationOwner getOwner(@NotNull PsiAnnotation annotation) {
assert annotation.getParent() == this : annotation.getParent();
PsiElement next = PsiTreeUtil.skipSiblingsForward(annotation, PsiComment.class, PsiWhiteSpace.class, PsiAnnotation.class);
if (PsiUtil.isJavaToken(next, JavaTokenType.LBRACKET)) {
return JavaSharedImplUtil.findAnnotatedSubtype(getType(), annotation);
}
return this;
}
@@ -21,8 +21,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.GeneratedMarkerVisitor;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
@@ -40,9 +40,14 @@ public class JavaSharedImplUtil {
private JavaSharedImplUtil() { }
public static PsiType getType(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor) {
return getType(typeElement, anchor, null);
}
public static PsiType getType(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @Nullable PsiAnnotation stopAt) {
PsiType type = typeElement.getType();
List<PsiAnnotation[]> allAnnotations = collectAnnotations(anchor);
List<PsiAnnotation[]> allAnnotations = collectAnnotations(anchor, stopAt);
if (allAnnotations == null) return null;
for (PsiAnnotation[] annotations : allAnnotations) {
type = type.createArrayType(annotations);
}
@@ -50,41 +55,33 @@ public class JavaSharedImplUtil {
return type;
}
private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor) {
private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor, PsiAnnotation stopAt) {
List<PsiAnnotation[]> annotations = new SmartList<PsiAnnotation[]>();
List<PsiAnnotation> current = null;
boolean stop = false;
for (PsiElement child = anchor.getNextSibling(); child != null; child = child.getNextSibling()) {
if (child instanceof PsiComment || child instanceof PsiWhiteSpace) continue;
if (child instanceof PsiAnnotation) {
if (current == null) current = new SmartList<PsiAnnotation>();
current.add((PsiAnnotation)child);
if (child == stopAt) stop = true;
continue;
}
IElementType i = child.getNode().getElementType();
if (i == JavaTokenType.LBRACKET) {
if (PsiUtil.isJavaToken(child, JavaTokenType.LBRACKET)) {
annotations.add(ContainerUtil.toArray(current, PsiAnnotation.ARRAY_FACTORY));
current = null;
if (stop) return annotations;
}
else if (i != JavaTokenType.RBRACKET && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(i)) {
else if (!PsiUtil.isJavaToken(child, JavaTokenType.RBRACKET)) {
break;
}
}
return annotations;
}
@Nullable
public static PsiType findAnnotatedSubtype(@Nullable PsiType type, @NotNull PsiAnnotation annotation) {
while (type instanceof PsiArrayType) {
for (PsiAnnotation a : type.getAnnotations()) {
if (a == annotation) {
return type;
}
}
type = ((PsiArrayType)type).getComponentType();
}
return null;
// stop == true means annotation is misplaced
return stop ? null : annotations;
}
public static void normalizeBrackets(@NotNull PsiVariable variable) {
@@ -124,11 +124,6 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp
return ((PsiNewExpression)parent).getOwner(this);
}
if (parent instanceof PsiMethod) {
PsiType type = ((PsiMethod)parent).getReturnType();
return JavaSharedImplUtil.findAnnotatedSubtype(type, this);
}
if (parent instanceof PsiReferenceExpression) {
PsiElement ctx = parent.getParent();
if (ctx instanceof PsiMethodReferenceExpression) {
@@ -142,6 +137,20 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp
}
}
PsiTypeElement typeElement = null;
PsiElement anchor = null;
if (parent instanceof PsiMethod) {
typeElement = ((PsiMethod)parent).getReturnTypeElement();
anchor = ((PsiMethod)parent).getParameterList();
}
else if (parent instanceof PsiField || parent instanceof PsiParameter || parent instanceof PsiLocalVariable) {
typeElement = ((PsiVariable)parent).getTypeElement();
anchor = ((PsiVariable)parent).getNameIdentifier();
}
if (typeElement != null && anchor != null) {
return JavaSharedImplUtil.getType(typeElement, anchor, this);
}
return null;
}
}
@@ -107,7 +107,11 @@ class Outer {
new Boolean @TA [2] <error descr="Annotations are not allowed here">@TA</error>;
}
int @TA [] mixedArrays() @TA [] <error descr="Annotations are not allowed here">@TA</error> { return new int[0][0]; }
int @TA [] mixedArrays @TA [] <error descr="Annotations are not allowed here">@TA</error> = new int[0][0];
int @TA [] mixedArrays(int @TA [] p @TA [] <error descr="Annotations are not allowed here">@TA</error>) @TA [] <error descr="Annotations are not allowed here">@TA</error> {
int @TA [] a @TA [] <error descr="Annotations are not allowed here">@TA</error> = (p != null ? p : mixedArrays);
return a;
}
@TA Outer() { }