Support @field: annotations
This commit is contained in:
@@ -81,17 +81,30 @@ public abstract class AnnotationCodegen {
|
|||||||
* @param returnType can be null if not applicable (e.g. {@code annotated} is a class)
|
* @param returnType can be null if not applicable (e.g. {@code annotated} is a class)
|
||||||
*/
|
*/
|
||||||
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) {
|
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) {
|
||||||
if (annotated == null) {
|
genAnnotations(annotated, returnType, null);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!(annotated instanceof DeclarationDescriptor)) {
|
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType, @Nullable AnnotationUseSiteTarget target) {
|
||||||
|
if (annotated == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> annotationDescriptorsAlreadyPresent = new HashSet<String>();
|
Set<String> annotationDescriptorsAlreadyPresent = new HashSet<String>();
|
||||||
|
|
||||||
for (AnnotationDescriptor annotation : annotated.getAnnotations()) {
|
Annotations annotations = annotated.getAnnotations();
|
||||||
|
|
||||||
|
if (target != null) {
|
||||||
|
for (AnnotationWithTarget annotationWithTarget : annotations.getUseSiteTargetedAnnotations()) {
|
||||||
|
if (target != annotationWithTarget.getTarget()) continue;
|
||||||
|
|
||||||
|
String descriptor = genAnnotation(annotationWithTarget.getAnnotation());
|
||||||
|
if (descriptor != null) {
|
||||||
|
annotationDescriptorsAlreadyPresent.add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AnnotationDescriptor annotation : annotations) {
|
||||||
String descriptor = genAnnotation(annotation);
|
String descriptor = genAnnotation(annotation);
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
annotationDescriptorsAlreadyPresent.add(descriptor);
|
annotationDescriptorsAlreadyPresent.add(descriptor);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.context.*;
|
|||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||||
@@ -293,7 +294,7 @@ public class PropertyCodegen {
|
|||||||
|
|
||||||
FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||||
typeMapper.mapFieldSignature(jetType), defaultValue);
|
typeMapper.mapFieldSignature(jetType), defaultValue);
|
||||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type);
|
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type, AnnotationUseSiteTarget.FIELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public interface JetNodeTypes {
|
|||||||
IElementType MODIFIER_LIST = JetStubElementTypes.MODIFIER_LIST;
|
IElementType MODIFIER_LIST = JetStubElementTypes.MODIFIER_LIST;
|
||||||
IElementType ANNOTATION = JetStubElementTypes.ANNOTATION;
|
IElementType ANNOTATION = JetStubElementTypes.ANNOTATION;
|
||||||
IElementType ANNOTATION_ENTRY = JetStubElementTypes.ANNOTATION_ENTRY;
|
IElementType ANNOTATION_ENTRY = JetStubElementTypes.ANNOTATION_ENTRY;
|
||||||
|
IElementType ANNOTATION_TARGET = JetStubElementTypes.ANNOTATION_TARGET;
|
||||||
|
|
||||||
IElementType TYPE_ARGUMENT_LIST = JetStubElementTypes.TYPE_ARGUMENT_LIST;
|
IElementType TYPE_ARGUMENT_LIST = JetStubElementTypes.TYPE_ARGUMENT_LIST;
|
||||||
JetNodeType VALUE_ARGUMENT_LIST = new JetNodeType("VALUE_ARGUMENT_LIST", JetValueArgumentList.class);
|
JetNodeType VALUE_ARGUMENT_LIST = new JetNodeType("VALUE_ARGUMENT_LIST", JetValueArgumentList.class);
|
||||||
|
|||||||
@@ -131,6 +131,9 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<JetExpression> ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<JetExpression> ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<JetExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<JetExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
|
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
// Classes and traits
|
// Classes and traits
|
||||||
|
|
||||||
DiagnosticFactory0<JetTypeProjection> PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE =
|
DiagnosticFactory0<JetTypeProjection> PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE =
|
||||||
|
|||||||
+3
@@ -124,6 +124,9 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
||||||
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||||
|
|
||||||
|
MAP.put(INAPPLICABLE_FIELD_TARGET, "''@field:'' annotations could be applied only to property declarations");
|
||||||
|
MAP.put(INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD, "Property has neither a backing field nor a delegate");
|
||||||
|
|
||||||
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
||||||
MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in interface");
|
MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in interface");
|
||||||
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ public interface JetTokens {
|
|||||||
|
|
||||||
JetToken EOL_OR_SEMICOLON = new JetToken("EOL_OR_SEMICOLON");
|
JetToken EOL_OR_SEMICOLON = new JetToken("EOL_OR_SEMICOLON");
|
||||||
JetKeywordToken FILE_KEYWORD = JetKeywordToken.softKeyword("file");
|
JetKeywordToken FILE_KEYWORD = JetKeywordToken.softKeyword("file");
|
||||||
|
JetKeywordToken FIELD_KEYWORD = JetKeywordToken.softKeyword("field");
|
||||||
JetKeywordToken IMPORT_KEYWORD = JetKeywordToken.softKeyword("import");
|
JetKeywordToken IMPORT_KEYWORD = JetKeywordToken.softKeyword("import");
|
||||||
JetKeywordToken WHERE_KEYWORD = JetKeywordToken.softKeyword("where");
|
JetKeywordToken WHERE_KEYWORD = JetKeywordToken.softKeyword("where");
|
||||||
JetKeywordToken BY_KEYWORD = JetKeywordToken.softKeyword("by");
|
JetKeywordToken BY_KEYWORD = JetKeywordToken.softKeyword("by");
|
||||||
@@ -174,7 +175,8 @@ public interface JetTokens {
|
|||||||
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD,
|
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD,
|
||||||
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
|
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
|
||||||
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD,
|
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD,
|
||||||
DYNAMIC_KEYWORD, COMPANION_KEYWORD, CONSTRUCTOR_KEYWORD, INIT_KEYWORD, SEALED_KEYWORD
|
DYNAMIC_KEYWORD, COMPANION_KEYWORD, CONSTRUCTOR_KEYWORD, INIT_KEYWORD, SEALED_KEYWORD,
|
||||||
|
FIELD_KEYWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
private static final TokenSet LAMBDA_VALUE_PARAMETER_FIRST =
|
private static final TokenSet LAMBDA_VALUE_PARAMETER_FIRST =
|
||||||
TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS);
|
TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS);
|
||||||
private static final TokenSet SOFT_KEYWORDS_AT_MEMBER_START = TokenSet.create(CONSTRUCTOR_KEYWORD, INIT_KEYWORD);
|
private static final TokenSet SOFT_KEYWORDS_AT_MEMBER_START = TokenSet.create(CONSTRUCTOR_KEYWORD, INIT_KEYWORD);
|
||||||
|
private static final TokenSet ANNOTATION_TARGETS = TokenSet.create(FILE_KEYWORD, FIELD_KEYWORD);
|
||||||
|
|
||||||
static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
|
static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||||
JetParsing jetParsing = new JetParsing(builder);
|
JetParsing jetParsing = new JetParsing(builder);
|
||||||
@@ -544,7 +545,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
* ;
|
* ;
|
||||||
*
|
*
|
||||||
* annotationPrefix:
|
* annotationPrefix:
|
||||||
* : ("@" (":" "file")?)
|
* : ("@" (":" ("file" | "field"))?)
|
||||||
* ;
|
* ;
|
||||||
*/
|
*/
|
||||||
private boolean parseAnnotationOrList(AnnotationParsingMode mode) {
|
private boolean parseAnnotationOrList(AnnotationParsingMode mode) {
|
||||||
@@ -556,7 +557,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
IElementType tokenToMatch = nextRawToken;
|
IElementType tokenToMatch = nextRawToken;
|
||||||
boolean isTargetedAnnotation = false;
|
boolean isTargetedAnnotation = false;
|
||||||
|
|
||||||
if ((nextRawToken == IDENTIFIER || nextRawToken == FILE_KEYWORD) && lookahead(2) == COLON) {
|
if ((nextRawToken == IDENTIFIER || ANNOTATION_TARGETS.contains(nextRawToken)) && lookahead(2) == COLON) {
|
||||||
tokenToMatch = lookahead(3);
|
tokenToMatch = lookahead(3);
|
||||||
isTargetedAnnotation = true;
|
isTargetedAnnotation = true;
|
||||||
}
|
}
|
||||||
@@ -578,7 +579,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
errorAndAdvance("Expected annotation identifier after ':'", 2); // AT, COLON
|
errorAndAdvance("Expected annotation identifier after ':'", 2); // AT, COLON
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errorAndAdvance("Expected annotation identifier after '@file:'", 3); // AT, FILE_KEYWORD, COLON
|
errorAndAdvance("Expected annotation identifier after ':'", 3); // AT, (ANNOTATION TARGET KEYWORD), COLON
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -634,7 +635,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
// Returns true if we should continue parse annotation
|
// Returns true if we should continue parse annotation
|
||||||
private boolean parseAnnotationTargetIfNeeded(AnnotationParsingMode mode) {
|
private boolean parseAnnotationTargetIfNeeded(AnnotationParsingMode mode) {
|
||||||
String expectedAnnotationTargetBeforeColon = "Expected 'file' keyword before ':'";
|
String expectedAnnotationTargetBeforeColon = "Expected annotation target before ':'";
|
||||||
|
|
||||||
if (at(COLON)) {
|
if (at(COLON)) {
|
||||||
// recovery for "@:ann"
|
// recovery for "@:ann"
|
||||||
@@ -666,19 +667,29 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
private void parseAnnotationTarget(AnnotationParsingMode mode, JetKeywordToken keyword) {
|
private void parseAnnotationTarget(AnnotationParsingMode mode, JetKeywordToken keyword) {
|
||||||
if (keyword == FILE_KEYWORD && !mode.isFileAnnotationParsingMode && at(keyword) && lookahead(1) == COLON) {
|
if (keyword == FILE_KEYWORD && !mode.isFileAnnotationParsingMode && at(keyword) && lookahead(1) == COLON) {
|
||||||
errorAndAdvance("File annotations are only allowed before package declaration", 2);
|
errorAndAdvance(AT.getValue() + keyword.getValue() + " annotations are only allowed before package declaration", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = "Expecting \"" + keyword.getValue() + COLON.getValue() + "\" prefix for " + keyword.getValue() + " annotations";
|
String message = "Expecting \"" + keyword.getValue() + COLON.getValue() + "\" prefix for " + keyword.getValue() + " annotations";
|
||||||
|
|
||||||
expect(keyword, message);
|
PsiBuilder.Marker marker = mark();
|
||||||
|
|
||||||
|
if (!expect(keyword, message)) {
|
||||||
|
marker.drop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
marker.done(ANNOTATION_TARGET);
|
||||||
|
}
|
||||||
|
|
||||||
expect(COLON, message, TokenSet.create(IDENTIFIER, RBRACKET, LBRACKET));
|
expect(COLON, message, TokenSet.create(IDENTIFIER, RBRACKET, LBRACKET));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JetKeywordToken atTargetKeyword() {
|
private JetKeywordToken atTargetKeyword() {
|
||||||
if (at(FILE_KEYWORD)) return (JetKeywordToken) FILE_KEYWORD;
|
for (IElementType target : ANNOTATION_TARGETS.getTypes()) {
|
||||||
|
if (at(target)) return (JetKeywordToken) target;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi;
|
|||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
|
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
|
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
|
||||||
|
|
||||||
@@ -41,4 +42,9 @@ public class JetAnnotation extends JetElementImplStub<KotlinPlaceHolderStub<JetA
|
|||||||
public List<JetAnnotationEntry> getEntries() {
|
public List<JetAnnotationEntry> getEntries() {
|
||||||
return getStubOrPsiChildrenAsList(JetStubElementTypes.ANNOTATION_ENTRY);
|
return getStubOrPsiChildrenAsList(JetStubElementTypes.ANNOTATION_ENTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JetAnnotationUseSiteTarget getUseSiteTarget() {
|
||||||
|
return getStubOrPsiChild(JetStubElementTypes.ANNOTATION_TARGET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,4 +107,18 @@ public class JetAnnotationEntry extends JetElementImplStub<KotlinAnnotationEntry
|
|||||||
public PsiElement getAtSymbol() {
|
public PsiElement getAtSymbol() {
|
||||||
return findChildByType(JetTokens.AT);
|
return findChildByType(JetTokens.AT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JetAnnotationUseSiteTarget getUseSiteTarget() {
|
||||||
|
JetAnnotationUseSiteTarget target = getStubOrPsiChild(JetStubElementTypes.ANNOTATION_TARGET);
|
||||||
|
|
||||||
|
if (target == null) {
|
||||||
|
PsiElement parent = getStubOrPsiParent();
|
||||||
|
if (parent instanceof JetAnnotation) {
|
||||||
|
return ((JetAnnotation) parent).getUseSiteTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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 org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.psi.impl.source.tree.TreeElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
|
import org.jetbrains.kotlin.lexer.JetKeywordToken
|
||||||
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.KotlinAnnotationEntryStub
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
|
||||||
|
|
||||||
|
public class JetAnnotationUseSiteTarget : JetElementImplStub<KotlinPlaceHolderStub<JetAnnotationUseSiteTarget>> {
|
||||||
|
|
||||||
|
constructor(node: ASTNode) : super(node)
|
||||||
|
|
||||||
|
constructor(stub: KotlinPlaceHolderStub<JetAnnotationUseSiteTarget>) : super(stub, JetStubElementTypes.ANNOTATION_TARGET)
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D) = visitor.visitAnnotationUseSiteTarget(this, data)
|
||||||
|
|
||||||
|
public fun getAnnotationUseSiteTarget(): AnnotationUseSiteTarget {
|
||||||
|
val node = getFirstChild().getNode()
|
||||||
|
return when (node.getElementType()) {
|
||||||
|
JetTokens.FIELD_KEYWORD -> AnnotationUseSiteTarget.FIELD
|
||||||
|
JetTokens.FILE_KEYWORD -> AnnotationUseSiteTarget.FILE
|
||||||
|
else -> throw IllegalStateException("Unknown annotation target " + node.getText())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -106,6 +106,10 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
|
|||||||
return visitJetElement(annotationEntry, data);
|
return visitJetElement(annotationEntry, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public R visitAnnotationUseSiteTarget(@NotNull JetAnnotationUseSiteTarget annotationTarget, D data) {
|
||||||
|
return visitJetElement(annotationTarget, data);
|
||||||
|
}
|
||||||
|
|
||||||
public R visitConstructorCalleeExpression(@NotNull JetConstructorCalleeExpression constructorCalleeExpression, D data) {
|
public R visitConstructorCalleeExpression(@NotNull JetConstructorCalleeExpression constructorCalleeExpression, D data) {
|
||||||
return visitJetElement(constructorCalleeExpression, data);
|
return visitJetElement(constructorCalleeExpression, data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ public interface JetStubElementTypes {
|
|||||||
JetPlaceHolderStubElementType<JetAnnotation> ANNOTATION =
|
JetPlaceHolderStubElementType<JetAnnotation> ANNOTATION =
|
||||||
new JetPlaceHolderStubElementType<JetAnnotation>("ANNOTATION", JetAnnotation.class);
|
new JetPlaceHolderStubElementType<JetAnnotation>("ANNOTATION", JetAnnotation.class);
|
||||||
|
|
||||||
|
JetPlaceHolderStubElementType<JetAnnotationUseSiteTarget> ANNOTATION_TARGET =
|
||||||
|
new JetPlaceHolderStubElementType<JetAnnotationUseSiteTarget>("ANNOTATION_TARGET", JetAnnotationUseSiteTarget.class);
|
||||||
|
|
||||||
JetPlaceHolderStubElementType<JetClassBody> CLASS_BODY =
|
JetPlaceHolderStubElementType<JetClassBody> CLASS_BODY =
|
||||||
new JetPlaceHolderStubElementType<JetClassBody>("CLASS_BODY", JetClassBody.class);
|
new JetPlaceHolderStubElementType<JetClassBody>("CLASS_BODY", JetClassBody.class);
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.JetAnnotationEntry;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.JetModifierList;
|
|
||||||
import org.jetbrains.kotlin.psi.JetTypeParameter;
|
|
||||||
import org.jetbrains.kotlin.psi.JetTypeReference;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver;
|
import org.jetbrains.kotlin.resolve.calls.CallResolver;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||||
@@ -45,6 +43,8 @@ import org.jetbrains.kotlin.types.ErrorUtils;
|
|||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS;
|
import static org.jetbrains.kotlin.diagnostics.Errors.NOT_AN_ANNOTATION_CLASS;
|
||||||
@@ -130,7 +130,8 @@ public class AnnotationResolver {
|
|||||||
boolean shouldResolveArguments
|
boolean shouldResolveArguments
|
||||||
) {
|
) {
|
||||||
if (annotationEntryElements.isEmpty()) return Annotations.EMPTY;
|
if (annotationEntryElements.isEmpty()) return Annotations.EMPTY;
|
||||||
List<AnnotationDescriptor> result = Lists.newArrayList();
|
List<AnnotationWithTarget> result = new ArrayList<AnnotationWithTarget>(0);
|
||||||
|
|
||||||
for (JetAnnotationEntry entryElement : annotationEntryElements) {
|
for (JetAnnotationEntry entryElement : annotationEntryElements) {
|
||||||
AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
|
AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
|
||||||
if (descriptor == null) {
|
if (descriptor == null) {
|
||||||
@@ -140,9 +141,15 @@ public class AnnotationResolver {
|
|||||||
ForceResolveUtil.forceResolveAllContents(descriptor);
|
ForceResolveUtil.forceResolveAllContents(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(descriptor);
|
JetAnnotationUseSiteTarget target = entryElement.getUseSiteTarget();
|
||||||
|
if (target != null) {
|
||||||
|
result.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.add(new AnnotationWithTarget(descriptor, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new AnnotationsImpl(result);
|
return AnnotationsImpl.create(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ import com.intellij.psi.PsiElement;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
||||||
import org.jetbrains.kotlin.lexer.JetKeywordToken;
|
import org.jetbrains.kotlin.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||||
@@ -34,6 +38,9 @@ import java.util.*;
|
|||||||
import static org.jetbrains.kotlin.diagnostics.Errors.NESTED_CLASS_NOT_ALLOWED;
|
import static org.jetbrains.kotlin.diagnostics.Errors.NESTED_CLASS_NOT_ALLOWED;
|
||||||
import static org.jetbrains.kotlin.lexer.JetTokens.*;
|
import static org.jetbrains.kotlin.lexer.JetTokens.*;
|
||||||
import static org.jetbrains.kotlin.psi.JetStubbedPsiUtil.getContainingDeclaration;
|
import static org.jetbrains.kotlin.psi.JetStubbedPsiUtil.getContainingDeclaration;
|
||||||
|
import static org.jetbrains.kotlin.resolve.BindingContext.BACKING_FIELD_REQUIRED;
|
||||||
|
import static org.jetbrains.kotlin.diagnostics.Errors.INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD;
|
||||||
|
import static org.jetbrains.kotlin.diagnostics.Errors.INAPPLICABLE_FIELD_TARGET;
|
||||||
|
|
||||||
public class ModifiersChecker {
|
public class ModifiersChecker {
|
||||||
private static final Collection<JetModifierKeywordToken> MODALITY_MODIFIERS =
|
private static final Collection<JetModifierKeywordToken> MODALITY_MODIFIERS =
|
||||||
@@ -183,6 +190,7 @@ public class ModifiersChecker {
|
|||||||
checkNestedClassAllowed(modifierListOwner, descriptor);
|
checkNestedClassAllowed(modifierListOwner, descriptor);
|
||||||
ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor);
|
ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor);
|
||||||
checkTypeParametersModifiers(modifierListOwner);
|
checkTypeParametersModifiers(modifierListOwner);
|
||||||
|
checkAnnotationUseSiteTargetApplicability(modifierListOwner, descriptor);
|
||||||
runDeclarationCheckers(modifierListOwner, descriptor);
|
runDeclarationCheckers(modifierListOwner, descriptor);
|
||||||
ClassDescriptor classDescriptor = descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
|
ClassDescriptor classDescriptor = descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
|
||||||
annotationChecker.check(modifierListOwner, trace, classDescriptor);
|
annotationChecker.check(modifierListOwner, trace, classDescriptor);
|
||||||
@@ -192,6 +200,7 @@ public class ModifiersChecker {
|
|||||||
@NotNull JetDeclaration modifierListOwner,
|
@NotNull JetDeclaration modifierListOwner,
|
||||||
@NotNull DeclarationDescriptor descriptor
|
@NotNull DeclarationDescriptor descriptor
|
||||||
) {
|
) {
|
||||||
|
checkAnnotationUseSiteTargetApplicability(modifierListOwner, descriptor);
|
||||||
runDeclarationCheckers(modifierListOwner, descriptor);
|
runDeclarationCheckers(modifierListOwner, descriptor);
|
||||||
annotationChecker.check(modifierListOwner, trace,
|
annotationChecker.check(modifierListOwner, trace,
|
||||||
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
|
descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null);
|
||||||
@@ -209,6 +218,59 @@ public class ModifiersChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void checkAnnotationUseSiteTargetApplicability(
|
||||||
|
@NotNull JetDeclaration modifierListOwner,
|
||||||
|
@NotNull DeclarationDescriptor descriptor
|
||||||
|
) {
|
||||||
|
for (AnnotationWithTarget annotationWithTarget : descriptor.getAnnotations().getUseSiteTargetedAnnotations()) {
|
||||||
|
AnnotationDescriptor annotation = annotationWithTarget.getAnnotation();
|
||||||
|
AnnotationUseSiteTarget target = annotationWithTarget.getTarget();
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case FIELD:
|
||||||
|
checkFieldTargetApplicability(modifierListOwner, descriptor, annotation);
|
||||||
|
break;
|
||||||
|
case FILE:
|
||||||
|
throw new IllegalArgumentException("@file annotations are not allowed here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkFieldTargetApplicability(
|
||||||
|
JetDeclaration modifierListOwner,
|
||||||
|
DeclarationDescriptor descriptor,
|
||||||
|
AnnotationDescriptor annotation
|
||||||
|
) {
|
||||||
|
if (reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_FIELD_TARGET)) return;
|
||||||
|
|
||||||
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
|
boolean hasDelegate = modifierListOwner instanceof JetProperty && ((JetProperty) modifierListOwner).hasDelegate();
|
||||||
|
|
||||||
|
if (!hasDelegate && Boolean.FALSE.equals(trace.getBindingContext().get(BACKING_FIELD_REQUIRED, propertyDescriptor))) {
|
||||||
|
reportAnnotationTargetNotApplicable(annotation, INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean reportIfNotPropertyDescriptor(
|
||||||
|
DeclarationDescriptor descriptor,
|
||||||
|
AnnotationDescriptor annotation,
|
||||||
|
DiagnosticFactory0<PsiElement> diagnosticFactory
|
||||||
|
) {
|
||||||
|
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||||
|
reportAnnotationTargetNotApplicable(annotation, diagnosticFactory);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reportAnnotationTargetNotApplicable(AnnotationDescriptor annotation, DiagnosticFactory0<PsiElement> diagnosticFactory) {
|
||||||
|
JetAnnotationEntry annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation);
|
||||||
|
if (annotationEntry == null) return;
|
||||||
|
trace.report(diagnosticFactory.on(annotationEntry));
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Map<JetModifierKeywordToken, PsiElement> getTokensCorrespondingToModifiers(
|
public Map<JetModifierKeywordToken, PsiElement> getTokensCorrespondingToModifiers(
|
||||||
@NotNull JetModifierList modifierList,
|
@NotNull JetModifierList modifierList,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
@@ -62,8 +63,8 @@ public class ForceResolveUtil {
|
|||||||
|
|
||||||
public static void forceResolveAllContents(@NotNull Annotations annotations) {
|
public static void forceResolveAllContents(@NotNull Annotations annotations) {
|
||||||
doForceResolveAllContents(annotations);
|
doForceResolveAllContents(annotations);
|
||||||
for (AnnotationDescriptor annotation : annotations) {
|
for (AnnotationWithTarget annotationWithTarget : annotations.getAllAnnotations()) {
|
||||||
doForceResolveAllContents(annotation);
|
doForceResolveAllContents(annotationWithTarget.getAnnotation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+32
-8
@@ -18,9 +18,13 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.JetAnnotationEntry
|
import org.jetbrains.kotlin.psi.JetAnnotationEntry
|
||||||
|
import org.jetbrains.kotlin.psi.JetAnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.resolve.AnnotationResolver
|
import org.jetbrains.kotlin.resolve.AnnotationResolver
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
@@ -33,9 +37,9 @@ import org.jetbrains.kotlin.resolve.source.toSourceElement
|
|||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
abstract class LazyAnnotationsContext(
|
abstract class LazyAnnotationsContext(
|
||||||
val annotationResolver: AnnotationResolver,
|
val annotationResolver: AnnotationResolver,
|
||||||
val storageManager: StorageManager,
|
val storageManager: StorageManager,
|
||||||
val trace: BindingTrace
|
val trace: BindingTrace
|
||||||
) {
|
) {
|
||||||
abstract val scope: LexicalScope
|
abstract val scope: LexicalScope
|
||||||
}
|
}
|
||||||
@@ -55,7 +59,10 @@ public class LazyAnnotations(
|
|||||||
|
|
||||||
private val annotation = c.storageManager.createMemoizedFunction {
|
private val annotation = c.storageManager.createMemoizedFunction {
|
||||||
entry: JetAnnotationEntry ->
|
entry: JetAnnotationEntry ->
|
||||||
LazyAnnotationDescriptor(c, entry)
|
|
||||||
|
val descriptor = LazyAnnotationDescriptor(c, entry)
|
||||||
|
val target = entry.getUseSiteTarget()?.getAnnotationUseSiteTarget()
|
||||||
|
AnnotationWithTarget(descriptor, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
|
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
|
||||||
@@ -65,8 +72,7 @@ public class LazyAnnotations(
|
|||||||
val annotationType = annotationDescriptor.getType()
|
val annotationType = annotationDescriptor.getType()
|
||||||
if (annotationType.isError()) continue
|
if (annotationType.isError()) continue
|
||||||
|
|
||||||
val descriptor = annotationType.getConstructor().getDeclarationDescriptor()
|
val descriptor = annotationType.getConstructor().getDeclarationDescriptor() ?: continue
|
||||||
if (descriptor == null) continue
|
|
||||||
|
|
||||||
if (DescriptorUtils.getFqNameSafe(descriptor) == fqName) {
|
if (DescriptorUtils.getFqNameSafe(descriptor) == fqName) {
|
||||||
return annotationDescriptor
|
return annotationDescriptor
|
||||||
@@ -78,11 +84,29 @@ public class LazyAnnotations(
|
|||||||
|
|
||||||
override fun findExternalAnnotation(fqName: FqName) = null
|
override fun findExternalAnnotation(fqName: FqName) = null
|
||||||
|
|
||||||
override fun iterator(): Iterator<AnnotationDescriptor> = annotationEntries.asSequence().map(annotation).iterator()
|
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
|
||||||
|
return annotationEntries
|
||||||
|
.asSequence()
|
||||||
|
.map {
|
||||||
|
val (descriptor, target) = annotation(it)
|
||||||
|
if (target == null) null else AnnotationWithTarget(descriptor, target)
|
||||||
|
}.filterNotNull().toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = annotationEntries.map(annotation)
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<AnnotationDescriptor> {
|
||||||
|
return annotationEntries
|
||||||
|
.asSequence()
|
||||||
|
.map {
|
||||||
|
val (descriptor, target) = annotation(it)
|
||||||
|
if (target == null) descriptor else null // Filter out annotations with target
|
||||||
|
}.filterNotNull().iterator()
|
||||||
|
}
|
||||||
|
|
||||||
override fun forceResolveAllContents() {
|
override fun forceResolveAllContents() {
|
||||||
// To resolve all entries
|
// To resolve all entries
|
||||||
this.toList()
|
getAllAnnotations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ JetFile: DocCommentAfterFileAnnotations.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ JetFile: LineCommentAfterFileAnnotations.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ JetFile: fileAnnotationInWrongPlace.kt
|
|||||||
MODIFIER_LIST
|
MODIFIER_LIST
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:File annotations are only allowed before package declaration
|
PsiErrorElement:@file annotations are only allowed before package declaration
|
||||||
PsiElement(file)('file')
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
@@ -28,7 +28,7 @@ JetFile: fileAnnotationInWrongPlace.kt
|
|||||||
MODIFIER_LIST
|
MODIFIER_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:File annotations are only allowed before package declaration
|
PsiErrorElement:@file annotations are only allowed before package declaration
|
||||||
PsiElement(file)('file')
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
@@ -62,7 +62,7 @@ JetFile: fileAnnotationInWrongPlace.kt
|
|||||||
MODIFIER_LIST
|
MODIFIER_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:File annotations are only allowed before package declaration
|
PsiErrorElement:@file annotations are only allowed before package declaration
|
||||||
PsiElement(file)('file')
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
@@ -80,7 +80,7 @@ JetFile: fileAnnotationInWrongPlace.kt
|
|||||||
PsiWhiteSpace('\n\n')
|
PsiWhiteSpace('\n\n')
|
||||||
CLASS
|
CLASS
|
||||||
MODIFIER_LIST
|
MODIFIER_LIST
|
||||||
PsiErrorElement:Expected annotation identifier after '@file:'
|
PsiErrorElement:Expected annotation identifier after ':'
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(IDENTIFIER)('file')
|
PsiElement(IDENTIFIER)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
@@ -93,7 +93,7 @@ JetFile: fileAnnotationInWrongPlace.kt
|
|||||||
MODIFIER_LIST
|
MODIFIER_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:File annotations are only allowed before package declaration
|
PsiErrorElement:@file annotations are only allowed before package declaration
|
||||||
PsiElement(file)('file')
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ JetFile: manyAnnotationBlocks.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
TYPE_REFERENCE
|
TYPE_REFERENCE
|
||||||
@@ -12,7 +13,8 @@ JetFile: manyAnnotationBlocks.kt
|
|||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ JetFile: manyInOneAnnotationBlock.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ JetFile: nonFIleAnnotationBeforePackage.kt
|
|||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiErrorElement:Expecting "file:" prefix for file annotations
|
PsiErrorElement:Expecting "file:" prefix for file annotations
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
@@ -22,14 +23,14 @@ JetFile: nonFIleAnnotationBeforePackage.kt
|
|||||||
REFERENCE_EXPRESSION
|
REFERENCE_EXPRESSION
|
||||||
PsiElement(IDENTIFIER)('bar')
|
PsiElement(IDENTIFIER)('bar')
|
||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
PsiErrorElement:Expected annotation identifier after '@file:'
|
PsiErrorElement:Expected annotation identifier after ':'
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(IDENTIFIER)('file')
|
PsiElement(IDENTIFIER)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:Expected 'file' keyword before ':'
|
PsiErrorElement:Expected annotation target before ':'
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
TYPE_REFERENCE
|
TYPE_REFERENCE
|
||||||
@@ -39,7 +40,7 @@ JetFile: nonFIleAnnotationBeforePackage.kt
|
|||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:Expected 'file' keyword before ':'
|
PsiErrorElement:Expected annotation target before ':'
|
||||||
PsiElement(IDENTIFIER)('fil')
|
PsiElement(IDENTIFIER)('fil')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
|
|||||||
+2
-1
@@ -2,7 +2,8 @@ JetFile: single.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
TYPE_REFERENCE
|
TYPE_REFERENCE
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ JetFile: withoutPackage.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
TYPE_REFERENCE
|
TYPE_REFERENCE
|
||||||
@@ -34,7 +35,7 @@ JetFile: withoutPackage.kt
|
|||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:File annotations are only allowed before package declaration
|
PsiErrorElement:@file annotations are only allowed before package declaration
|
||||||
PsiElement(file)('file')
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
|
|||||||
+3
-2
@@ -2,7 +2,8 @@ JetFile: withoutPackageWithSimpleAnnotation.kt
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
TYPE_REFERENCE
|
TYPE_REFERENCE
|
||||||
@@ -32,7 +33,7 @@ JetFile: withoutPackageWithSimpleAnnotation.kt
|
|||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiErrorElement:File annotations are only allowed before package declaration
|
PsiErrorElement:@file annotations are only allowed before package declaration
|
||||||
PsiElement(file)('file')
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
+4
-2
@@ -2,7 +2,8 @@ JetFile: manyAnnotationsOnFile.kts
|
|||||||
FILE_ANNOTATION_LIST
|
FILE_ANNOTATION_LIST
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -16,7 +17,8 @@ JetFile: manyAnnotationsOnFile.kts
|
|||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
PsiElement(AT)('@')
|
PsiElement(AT)('@')
|
||||||
PsiElement(file)('file')
|
ANNOTATION_TARGET
|
||||||
|
PsiElement(file)('file')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiElement(LBRACKET)('[')
|
PsiElement(LBRACKET)('[')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
|
|||||||
+5
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.load.java.lazy
|
package org.jetbrains.kotlin.load.java.lazy
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.load.java.components.JavaAnnotationMapper
|
import org.jetbrains.kotlin.load.java.components.JavaAnnotationMapper
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||||
@@ -38,6 +39,10 @@ class LazyJavaAnnotations(
|
|||||||
override fun findExternalAnnotation(fqName: FqName) =
|
override fun findExternalAnnotation(fqName: FqName) =
|
||||||
c.components.externalAnnotationResolver.findExternalAnnotation(annotationOwner, fqName)?.let(annotationDescriptors)
|
c.components.externalAnnotationResolver.findExternalAnnotation(annotationOwner, fqName)?.let(annotationDescriptors)
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations() = emptyList<AnnotationWithTarget>()
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = this.map { AnnotationWithTarget(it, null) }
|
||||||
|
|
||||||
override fun iterator() =
|
override fun iterator() =
|
||||||
(annotationOwner.annotations.asSequence().map(annotationDescriptors)
|
(annotationOwner.annotations.asSequence().map(annotationDescriptors)
|
||||||
+ JavaAnnotationMapper.findMappedJavaAnnotation(KotlinBuiltIns.FQ_NAMES.annotation, annotationOwner, c)
|
+ JavaAnnotationMapper.findMappedJavaAnnotation(KotlinBuiltIns.FQ_NAMES.annotation, annotationOwner, c)
|
||||||
|
|||||||
+5
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.java.typeEnhacement
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
|
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
|
||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||||
@@ -175,6 +176,10 @@ private class EnhancedTypeAnnotations(private val fqNameToMatch: FqName) : Annot
|
|||||||
|
|
||||||
override fun findExternalAnnotation(fqName: FqName) = null
|
override fun findExternalAnnotation(fqName: FqName) = null
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = this.map { AnnotationWithTarget(it, null) }
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations() = emptyList<AnnotationWithTarget>()
|
||||||
|
|
||||||
// Note, that this class may break Annotations contract (!isEmpty && iterator.isEmpty())
|
// Note, that this class may break Annotations contract (!isEmpty && iterator.isEmpty())
|
||||||
// It's a hack that we need unless we have stable "user data" in JetType
|
// It's a hack that we need unless we have stable "user data" in JetType
|
||||||
override fun iterator(): Iterator<AnnotationDescriptor> = emptyList<AnnotationDescriptor>().iterator()
|
override fun iterator(): Iterator<AnnotationDescriptor> = emptyList<AnnotationDescriptor>().iterator()
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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 org.jetbrains.kotlin.descriptors.annotations
|
||||||
|
|
||||||
|
public enum class AnnotationUseSiteTarget() {
|
||||||
|
FIELD,
|
||||||
|
FILE
|
||||||
|
}
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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 org.jetbrains.kotlin.descriptors.annotations
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
public data class AnnotationWithTarget(val annotation: AnnotationDescriptor, val target: AnnotationUseSiteTarget?)
|
||||||
|
|
||||||
|
private class UseSiteTargetedAnnotations(
|
||||||
|
private val original: Annotations,
|
||||||
|
private val additionalAnnotations: Annotations
|
||||||
|
) : Annotations {
|
||||||
|
override fun isEmpty() = original.isEmpty()
|
||||||
|
|
||||||
|
override fun findAnnotation(fqName: FqName) = original.findAnnotation(fqName)
|
||||||
|
|
||||||
|
override fun findExternalAnnotation(fqName: FqName) = original.findExternalAnnotation(fqName)
|
||||||
|
|
||||||
|
private fun getAdditionalTargetedAnnotations() = additionalAnnotations.getUseSiteTargetedAnnotations()
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
|
||||||
|
return original.getUseSiteTargetedAnnotations() + getAdditionalTargetedAnnotations()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAllAnnotations(): List<AnnotationWithTarget> {
|
||||||
|
return original.getAllAnnotations() + getAdditionalTargetedAnnotations()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun iterator() = original.iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AnnotatedWithAdditionalAnnotations(
|
||||||
|
delegate: Annotated?,
|
||||||
|
additional: Annotated
|
||||||
|
) : Annotated {
|
||||||
|
private val annotations: Annotations = UseSiteTargetedAnnotations(delegate?.annotations ?: Annotations.EMPTY, additional.annotations)
|
||||||
|
|
||||||
|
override fun getAnnotations() = annotations
|
||||||
|
}
|
||||||
@@ -27,6 +27,20 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
|
|||||||
|
|
||||||
public fun findExternalAnnotation(fqName: FqName): AnnotationDescriptor?
|
public fun findExternalAnnotation(fqName: FqName): AnnotationDescriptor?
|
||||||
|
|
||||||
|
public fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget>
|
||||||
|
|
||||||
|
public fun getUseSiteTargetedAnnotations(target: AnnotationUseSiteTarget): List<AnnotationDescriptor> {
|
||||||
|
return getUseSiteTargetedAnnotations().fold(arrayListOf<AnnotationDescriptor>()) { list, targeted ->
|
||||||
|
if (target == targeted.target) {
|
||||||
|
list.add(targeted.annotation)
|
||||||
|
}
|
||||||
|
list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns both targeted and annotations without target. Annotation order is preserved.
|
||||||
|
public fun getAllAnnotations(): List<AnnotationWithTarget>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public val EMPTY: Annotations = object : Annotations {
|
public val EMPTY: Annotations = object : Annotations {
|
||||||
override fun isEmpty() = true
|
override fun isEmpty() = true
|
||||||
@@ -35,6 +49,10 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
|
|||||||
|
|
||||||
override fun findExternalAnnotation(fqName: FqName) = null
|
override fun findExternalAnnotation(fqName: FqName) = null
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations() = emptyList<AnnotationWithTarget>()
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = emptyList<AnnotationWithTarget>()
|
||||||
|
|
||||||
override fun iterator() = emptyList<AnnotationDescriptor>().iterator()
|
override fun iterator() = emptyList<AnnotationDescriptor>().iterator()
|
||||||
|
|
||||||
override fun toString() = "EMPTY"
|
override fun toString() = "EMPTY"
|
||||||
@@ -54,14 +72,22 @@ class FilteredAnnotations(
|
|||||||
if (fqNameFilter(fqName)) delegate.findExternalAnnotation(fqName)
|
if (fqNameFilter(fqName)) delegate.findExternalAnnotation(fqName)
|
||||||
else null
|
else null
|
||||||
|
|
||||||
override fun iterator() = delegate.asSequence()
|
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
|
||||||
.filter { annotation ->
|
return delegate.getUseSiteTargetedAnnotations().filter { shouldBeReturned(it.annotation) }
|
||||||
val descriptor = annotation.getType().getConstructor().getDeclarationDescriptor()
|
}
|
||||||
descriptor != null && DescriptorUtils.getFqName(descriptor).let { fqName ->
|
|
||||||
fqName.isSafe() && fqNameFilter(fqName.toSafe())
|
override fun getAllAnnotations(): List<AnnotationWithTarget> {
|
||||||
}
|
return delegate.getAllAnnotations().filter { shouldBeReturned(it.annotation) }
|
||||||
}
|
}
|
||||||
.iterator()
|
|
||||||
|
override fun iterator() = delegate.filter { shouldBeReturned(it) }.iterator()
|
||||||
|
|
||||||
|
private fun shouldBeReturned(annotation: AnnotationDescriptor): Boolean {
|
||||||
|
val descriptor = annotation.getType().getConstructor().getDeclarationDescriptor()
|
||||||
|
return descriptor != null && DescriptorUtils.getFqName(descriptor).let { fqName ->
|
||||||
|
fqName.isSafe() && fqNameFilter(fqName.toSafe())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun isEmpty() = !iterator().hasNext()
|
override fun isEmpty() = !iterator().hasNext()
|
||||||
}
|
}
|
||||||
@@ -77,5 +103,9 @@ class CompositeAnnotations(
|
|||||||
|
|
||||||
override fun findExternalAnnotation(fqName: FqName) = delegates.asSequence().map { it.findExternalAnnotation(fqName) }.filterNotNull().firstOrNull()
|
override fun findExternalAnnotation(fqName: FqName) = delegates.asSequence().map { it.findExternalAnnotation(fqName) }.filterNotNull().firstOrNull()
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations() = delegates.flatMap { it.getUseSiteTargetedAnnotations() }
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = delegates.flatMap { it.getAllAnnotations() }
|
||||||
|
|
||||||
override fun iterator() = delegates.asSequence().flatMap { it.asSequence() }.iterator()
|
override fun iterator() = delegates.asSequence().flatMap { it.asSequence() }.iterator()
|
||||||
}
|
}
|
||||||
+34
-1
@@ -19,8 +19,26 @@ package org.jetbrains.kotlin.descriptors.annotations
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import kotlin.platform.platformStatic
|
||||||
|
|
||||||
|
public class AnnotationsImpl : Annotations {
|
||||||
|
private val annotations: List<AnnotationDescriptor>
|
||||||
|
private val targetedAnnotations: List<AnnotationWithTarget>
|
||||||
|
|
||||||
|
constructor(annotations: List<AnnotationDescriptor>) {
|
||||||
|
this.annotations = annotations
|
||||||
|
this.targetedAnnotations = annotations.map { AnnotationWithTarget(it, null) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// List<AnnotationDescriptor> and List<AnnotationWithTarget> have the same signature
|
||||||
|
private constructor(
|
||||||
|
targetedAnnotations: List<AnnotationWithTarget>,
|
||||||
|
@suppress("UNUSED_PARAMETER") i: Int
|
||||||
|
) {
|
||||||
|
this.targetedAnnotations = targetedAnnotations
|
||||||
|
this.annotations = targetedAnnotations.filter { it.target == null }.map { it.annotation }
|
||||||
|
}
|
||||||
|
|
||||||
public class AnnotationsImpl(private val annotations: List<AnnotationDescriptor>) : Annotations {
|
|
||||||
override fun isEmpty() = annotations.isEmpty()
|
override fun isEmpty() = annotations.isEmpty()
|
||||||
|
|
||||||
override fun findAnnotation(fqName: FqName) = annotations.firstOrNull {
|
override fun findAnnotation(fqName: FqName) = annotations.firstOrNull {
|
||||||
@@ -28,9 +46,24 @@ public class AnnotationsImpl(private val annotations: List<AnnotationDescriptor>
|
|||||||
descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
|
descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
|
||||||
|
return targetedAnnotations
|
||||||
|
.filter { it.target != null }
|
||||||
|
.map { AnnotationWithTarget(it.annotation, it.target!!) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = targetedAnnotations
|
||||||
|
|
||||||
override fun findExternalAnnotation(fqName: FqName) = null
|
override fun findExternalAnnotation(fqName: FqName) = null
|
||||||
|
|
||||||
override fun iterator() = annotations.iterator()
|
override fun iterator() = annotations.iterator()
|
||||||
|
|
||||||
override fun toString() = annotations.toString()
|
override fun toString() = annotations.toString()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
platformStatic
|
||||||
|
public fun create(annotationsWithTargets: List<AnnotationWithTarget>): AnnotationsImpl {
|
||||||
|
return AnnotationsImpl(annotationsWithTargets, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.serialization.deserialization.descriptors
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -40,5 +41,9 @@ class DeserializedAnnotations(
|
|||||||
|
|
||||||
override fun findExternalAnnotation(fqName: FqName) = null
|
override fun findExternalAnnotation(fqName: FqName) = null
|
||||||
|
|
||||||
|
override fun getUseSiteTargetedAnnotations() = emptyList<AnnotationWithTarget>()
|
||||||
|
|
||||||
|
override fun getAllAnnotations() = this.map { AnnotationWithTarget(it, null) }
|
||||||
|
|
||||||
override fun iterator(): Iterator<AnnotationDescriptor> = annotations().iterator()
|
override fun iterator(): Iterator<AnnotationDescriptor> = annotations().iterator()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ annotationList
|
|||||||
;
|
;
|
||||||
|
|
||||||
annotationPrefix:
|
annotationPrefix:
|
||||||
: ("@" (":" "file")?)
|
: ("@" (":" ("file" | "field"))?)
|
||||||
;
|
;
|
||||||
|
|
||||||
unescapedAnnotation
|
unescapedAnnotation
|
||||||
|
|||||||
Reference in New Issue
Block a user