Add warning for ambiguous annotated expression syntax
#KT-14238 In Progress
This commit is contained in:
@@ -115,8 +115,8 @@ public interface KtNodeTypes {
|
||||
KtNodeType BREAK = new KtNodeType("BREAK", KtBreakExpression.class);
|
||||
KtNodeType IF = new KtNodeType("IF", KtIfExpression.class);
|
||||
KtNodeType CONDITION = new KtNodeType("CONDITION", KtContainerNode.class);
|
||||
KtNodeType THEN = new KtNodeType("THEN", KtContainerNode.class);
|
||||
KtNodeType ELSE = new KtNodeType("ELSE", KtContainerNode.class);
|
||||
KtNodeType THEN = new KtNodeType("THEN", KtContainerNodeForControlStructureBody.class);
|
||||
KtNodeType ELSE = new KtNodeType("ELSE", KtContainerNodeForControlStructureBody.class);
|
||||
KtNodeType TRY = new KtNodeType("TRY", KtTryExpression.class);
|
||||
KtNodeType CATCH = new KtNodeType("CATCH", KtCatchClause.class);
|
||||
KtNodeType FINALLY = new KtNodeType("FINALLY", KtFinallySection.class);
|
||||
@@ -124,7 +124,7 @@ public interface KtNodeTypes {
|
||||
KtNodeType WHILE = new KtNodeType("WHILE", KtWhileExpression.class);
|
||||
KtNodeType DO_WHILE = new KtNodeType("DO_WHILE", KtDoWhileExpression.class);
|
||||
KtNodeType LOOP_RANGE = new KtNodeType("LOOP_RANGE", KtContainerNode.class);
|
||||
KtNodeType BODY = new KtNodeType("BODY", KtContainerNode.class);
|
||||
KtNodeType BODY = new KtNodeType("BODY", KtContainerNodeForControlStructureBody.class);
|
||||
KtNodeType BLOCK = new KtNodeType("BLOCK", KtBlockExpression.class);
|
||||
|
||||
IElementType LAMBDA_EXPRESSION = new IErrorCounterReparseableElementType("LAMBDA_EXPRESSION", KotlinLanguage.INSTANCE) {
|
||||
|
||||
@@ -180,6 +180,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotatedExpression> ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<PsiElement> ILLEGAL_SINCE_KOTLIN_VALUE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);
|
||||
|
||||
+4
@@ -725,6 +725,10 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL, "An annotation parameter must be a class literal (T::class)");
|
||||
MAP.put(ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT, "Default value of annotation parameter must be a compile-time constant");
|
||||
|
||||
MAP.put(ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE,
|
||||
"Annotations on block-level expressions are being parsed differently depending on presence of a new line after them. " +
|
||||
"Use new line if whole block-level expression must be annotated or wrap annotated expression in parentheses");
|
||||
|
||||
MAP.put(CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, "Const 'val' are only allowed on top level or in objects");
|
||||
MAP.put(CONST_VAL_WITH_DELEGATE, "Const 'val' should not have a delegate");
|
||||
MAP.put(CONST_VAL_WITH_GETTER, "Const 'val' should not have a getter");
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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
|
||||
|
||||
class KtContainerNodeForControlStructureBody(node: ASTNode) : KtContainerNode(node)
|
||||
+35
@@ -1539,12 +1539,47 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
protected void resolveAnnotationsOnExpression(KtAnnotatedExpression expression, ExpressionTypingContext context) {
|
||||
if (isAnnotatedExpressionInBlockLevelBinary(expression)) {
|
||||
context.trace.report(ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE.on(expression));
|
||||
}
|
||||
|
||||
if (!(expression.getBaseExpression() instanceof KtObjectLiteralExpression)) {
|
||||
// annotations on object literals are resolved later inside LazyClassDescriptor
|
||||
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAnnotatedExpressionInBlockLevelBinary(KtAnnotatedExpression annotatedExpression) {
|
||||
PsiElement current = annotatedExpression;
|
||||
PsiElement parent = current.getParent();
|
||||
|
||||
// Here we implicitly assume that grammar rules are:
|
||||
// blockLevelExpression = annotations expression
|
||||
// expression = binaryExpression
|
||||
// binaryExpression = prefixExpression <op> prefixExpression
|
||||
// prefixExpression = annotations expression
|
||||
|
||||
// If there is no binary parent, annotations are being parsed the same way independently of newline after them
|
||||
if (!(parent instanceof KtBinaryExpression)) return false;
|
||||
|
||||
while (parent instanceof KtBinaryExpression) {
|
||||
// if we came not from the left parent, there's no need to report an error
|
||||
if (((KtBinaryExpression) parent).getLeft() != current) {
|
||||
return false;
|
||||
}
|
||||
current = parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
return isParentForBlockLevelExpression(parent);
|
||||
}
|
||||
|
||||
private static boolean isParentForBlockLevelExpression(@Nullable PsiElement parent) {
|
||||
return parent instanceof KtBlockExpression ||
|
||||
parent instanceof KtContainerNodeForControlStructureBody ||
|
||||
parent instanceof KtWhenEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KotlinTypeInfo visitKtElement(@NotNull KtElement element, ExpressionTypingContext context) {
|
||||
context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
|
||||
|
||||
Reference in New Issue
Block a user