mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Type annotations on C-style arrays are recognized now
This commit is contained in:
@@ -405,7 +405,7 @@ public class DeclarationParser {
|
||||
private PsiBuilder.Marker parseMethodFromLeftParenth(PsiBuilder builder, PsiBuilder.Marker declaration, boolean anno, boolean constructor) {
|
||||
parseParameterList(builder);
|
||||
|
||||
eatBrackets(builder, constructor, "expected.semicolon");
|
||||
eatBrackets(builder, constructor ? "expected.semicolon" : null);
|
||||
|
||||
myParser.getReferenceParser().parseReferenceList(builder, JavaTokenType.THROWS_KEYWORD, JavaElementType.THROWS_LIST, JavaTokenType.COMMA);
|
||||
|
||||
@@ -600,7 +600,7 @@ public class DeclarationParser {
|
||||
|
||||
if (expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
if (!resource) {
|
||||
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, "expected.rparen");
|
||||
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg ? "expected.rparen" : null);
|
||||
done(param, JavaElementType.PARAMETER);
|
||||
return param;
|
||||
}
|
||||
@@ -644,7 +644,7 @@ public class DeclarationParser {
|
||||
while (true) {
|
||||
shouldRollback = true;
|
||||
|
||||
if (!eatBrackets(builder, false, null)) {
|
||||
if (!eatBrackets(builder, null)) {
|
||||
unclosed = true;
|
||||
}
|
||||
|
||||
@@ -706,26 +706,33 @@ public class DeclarationParser {
|
||||
return declaration;
|
||||
}
|
||||
|
||||
private static boolean eatBrackets(final PsiBuilder builder, final boolean isError,
|
||||
@Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACKET) return true;
|
||||
private boolean eatBrackets(PsiBuilder builder, @Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) {
|
||||
IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType != JavaTokenType.LBRACKET && tokenType != JavaTokenType.AT) return true;
|
||||
|
||||
final PsiBuilder.Marker marker = isError ? builder.mark() : null;
|
||||
PsiBuilder.Marker marker = errorKey != null ? builder.mark() : null;
|
||||
|
||||
boolean result = true;
|
||||
while (expect(builder, JavaTokenType.LBRACKET)) {
|
||||
if (!expect(builder, JavaTokenType.RBRACKET)) {
|
||||
if (!isError) error(builder, JavaErrorMessages.message("expected.rbracket"));
|
||||
result = false;
|
||||
int count = 0;
|
||||
while (true) {
|
||||
parseAnnotations(builder);
|
||||
if (!expect(builder, JavaTokenType.LBRACKET)) {
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
if (!expect(builder, JavaTokenType.RBRACKET)) {
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
|
||||
if (marker != null && errorKey != null) {
|
||||
boolean paired = count % 2 == 0;
|
||||
if (marker != null) {
|
||||
marker.error(JavaErrorMessages.message(errorKey));
|
||||
}
|
||||
|
||||
return result;
|
||||
else if (!paired) {
|
||||
error(builder, JavaErrorMessages.message("expected.rbracket"));
|
||||
}
|
||||
return paired;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -27,7 +27,12 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.CharTable;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class JavaSharedImplUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaSharedImplUtil");
|
||||
@@ -35,7 +40,6 @@ public class JavaSharedImplUtil {
|
||||
private JavaSharedImplUtil() { }
|
||||
|
||||
public static PsiType getType(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @NotNull PsiElement context) {
|
||||
int cStyleArrayCount = countBrackets(anchor);
|
||||
PsiType type;
|
||||
if (typeElement instanceof PsiTypeElementImpl) {
|
||||
type = ((PsiTypeElementImpl)typeElement).getDetachedType(context);
|
||||
@@ -43,34 +47,61 @@ public class JavaSharedImplUtil {
|
||||
else {
|
||||
type = typeElement.getType();
|
||||
}
|
||||
for (int i = 0; i < cStyleArrayCount; i++) {
|
||||
type = type.createArrayType();
|
||||
|
||||
List<PsiAnnotation[]> allAnnotations = collectAnnotations(anchor);
|
||||
for (PsiAnnotation[] annotations : allAnnotations) {
|
||||
type = type.createArrayType(annotations);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public static PsiType getTypeNoResolve(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @NotNull PsiElement context) {
|
||||
int cStyleArrayCount = countBrackets(anchor);
|
||||
PsiType type = typeElement.getTypeNoResolve(context);
|
||||
for (int i = 0; i < cStyleArrayCount; i++) {
|
||||
type = type.createArrayType();
|
||||
|
||||
List<PsiAnnotation[]> allAnnotations = collectAnnotations(anchor);
|
||||
for (PsiAnnotation[] annotations : allAnnotations) {
|
||||
type = type.createArrayType(annotations);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private static int countBrackets(PsiElement anchor) {
|
||||
int cStyleArrayCount = 0;
|
||||
ASTNode name = SourceTreeToPsiMap.psiToTreeNotNull(anchor);
|
||||
for (ASTNode child = name.getTreeNext(); child != null; child = child.getTreeNext()) {
|
||||
IElementType i = child.getElementType();
|
||||
private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor) {
|
||||
List<PsiAnnotation[]> annotations = new SmartList<PsiAnnotation[]>();
|
||||
|
||||
List<PsiAnnotation> current = null;
|
||||
for (PsiElement child = anchor.getNextSibling(); child != null; child = child.getNextSibling()) {
|
||||
if (child instanceof PsiAnnotation) {
|
||||
if (current == null) current = new SmartList<PsiAnnotation>();
|
||||
current.add((PsiAnnotation)child);
|
||||
continue;
|
||||
}
|
||||
|
||||
IElementType i = child.getNode().getElementType();
|
||||
if (i == JavaTokenType.LBRACKET) {
|
||||
cStyleArrayCount++;
|
||||
annotations.add(ContainerUtil.toArray(current, PsiAnnotation.ARRAY_FACTORY));
|
||||
current = null;
|
||||
}
|
||||
else if (i != JavaTokenType.RBRACKET && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cStyleArrayCount;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static void normalizeBrackets(PsiVariable variable) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.impl.java.stubs.PsiAnnotationStub;
|
||||
import com.intellij.psi.impl.meta.MetaRegistry;
|
||||
import com.intellij.psi.impl.source.JavaStubPsiElement;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import com.intellij.psi.impl.source.tree.JavaSharedImplUtil;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.PairFunction;
|
||||
@@ -123,6 +124,11 @@ 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) {
|
||||
|
||||
+2
@@ -108,6 +108,8 @@ class Outer {
|
||||
new Boolean @<error descr="Duplicate annotation">TA</error> @<error descr="Duplicate annotation">TA</error> [42];
|
||||
}
|
||||
|
||||
int @TA [] mixedArrays() @TA [] <error descr="Annotations are not allowed here">@TA</error> { return new int[0][0]; }
|
||||
|
||||
@TA Outer() { }
|
||||
|
||||
class MyClass<@TA @TPA T> { }
|
||||
|
||||
+2
@@ -65,6 +65,8 @@ class SpecSamples {
|
||||
@NonNegative int @NonEmpty [] ints = new @NonNegative int @MinSize(2) [2];
|
||||
}
|
||||
|
||||
int m() @Slowpoke [] @Slowbro [] { return null; }
|
||||
|
||||
//
|
||||
// 4. A type annotation is permitted in front of a constructor declaration ...
|
||||
//
|
||||
|
||||
+51
@@ -1404,6 +1404,57 @@ PsiJavaFile:TypeAnnotations.java
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiWhiteSpace('\n\n ')
|
||||
PsiMethod:m
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:m('m')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Slowpoke
|
||||
PsiIdentifier:Slowpoke('Slowpoke')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Slowbro
|
||||
PsiIdentifier:Slowbro('Slowbro')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReturnStatement
|
||||
PsiKeyword:return('return')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiWhiteSpace('\n\n ')
|
||||
PsiComment(END_OF_LINE_COMMENT)('//')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiComment(END_OF_LINE_COMMENT)('// 4. A type annotation is permitted in front of a constructor declaration ...')
|
||||
|
||||
@@ -380,6 +380,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
|
||||
" m(@A6 C::m);\n" +
|
||||
" @A7 T @A8[] @A9[] a = new @A7 T @A8[0] @A9[0];\n" +
|
||||
" }\n" +
|
||||
" int @A [] v() @A [] { }\n" +
|
||||
"}",
|
||||
|
||||
"PsiJavaFileStub []\n" +
|
||||
@@ -447,7 +448,16 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
|
||||
" ANNOTATION:PsiAnnotationStub[@A8]\n" +
|
||||
" ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" +
|
||||
" ANNOTATION:PsiAnnotationStub[@A9]\n" +
|
||||
" ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n");
|
||||
" ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" +
|
||||
" METHOD:PsiMethodStub[v:int[][]]\n" +
|
||||
" MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" +
|
||||
" TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" +
|
||||
" ANNOTATION:PsiAnnotationStub[@A]\n" +
|
||||
" ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" +
|
||||
" PARAMETER_LIST:PsiParameterListStub\n" +
|
||||
" ANNOTATION:PsiAnnotationStub[@A]\n" +
|
||||
" ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" +
|
||||
" THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n");
|
||||
}
|
||||
|
||||
public void testSOEProof() {
|
||||
|
||||
Reference in New Issue
Block a user