Simplify resolve for control labels by using PSI

Diagnostic `NOT_A_RETURN_LABEL` wasn't quite useful and its eliminating allows to simplify label resolver a lot. It could be also added using PSI
This commit is contained in:
Mikhail Zarechenskiy
2017-04-17 16:02:49 +03:00
parent e79a7d3e94
commit f3ed75998e
5 changed files with 6 additions and 33 deletions
@@ -731,7 +731,6 @@ public interface Errors {
DiagnosticFactory0<KtExpressionWithLabel> BREAK_OR_CONTINUE_IN_WHEN = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpressionWithLabel> BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<KtExpressionWithLabel, String> NOT_A_LOOP_LABEL = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtReturnExpression, String> NOT_A_RETURN_LABEL = DiagnosticFactory1.create(ERROR);
// Control flow / Data flow
@@ -555,7 +555,6 @@ public class DefaultErrorMessages {
MAP.put(BREAK_OR_CONTINUE_IN_WHEN, "'break' and 'continue' are not allowed in 'when' statements. Consider using labels to continue/break from the outer loop");
MAP.put(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY, "'break' or 'continue' jumps across a function or a class boundary");
MAP.put(NOT_A_LOOP_LABEL, "The label ''{0}'' does not denote a loop", STRING);
MAP.put(NOT_A_RETURN_LABEL, "The label ''{0}'' does not reference to a context from which we can return", STRING);
MAP.put(ANONYMOUS_INITIALIZER_IN_INTERFACE, "Anonymous initializers are not allowed in interfaces");
MAP.put(NULLABLE_SUPERTYPE, "A supertype cannot be nullable");
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -623,9 +623,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
}
}
else {
context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
}
}
if (returnedExpression != null) {
@@ -106,32 +106,10 @@ object LabelResolver {
val labelName = expression.getLabelNameAsName()
if (labelElement == null || labelName == null) return null
val element = resolveNamedLabel(labelName, labelElement, context.trace)
if (element != null) return element
val declarationsByLabel = context.scope.getDeclarationsByLabel(labelName)
when (declarationsByLabel.size) {
0 -> {
context.trace.report(UNRESOLVED_REFERENCE.on(labelElement, labelElement))
return null
}
1 -> {
val declarationDescriptor = declarationsByLabel.single()
if (declarationDescriptor is FunctionDescriptor || declarationDescriptor is ClassDescriptor) {
val declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor)
if (declarationElement is KtElement) {
context.trace.record(LABEL_TARGET, labelElement, declarationElement)
return declarationElement
}
}
}
else -> {
BindingContextUtils.reportAmbiguousLabel(context.trace, labelElement, declarationsByLabel)
return null
}
return resolveNamedLabel(labelName, labelElement, context.trace) ?: run {
context.trace.report(UNRESOLVED_REFERENCE.on(labelElement, labelElement))
null
}
return null
}
private fun resolveNamedLabel(
+2 -2
View File
@@ -6,10 +6,10 @@ class A {
if (1 < 2)
return@inner
else
<!RETURN_NOT_ALLOWED!>return@outer<!>
<!RETURN_NOT_ALLOWED!>return@outer<!>
}
if (1 < 2)
<!NOT_A_RETURN_LABEL!>return@A<!>
return<!UNRESOLVED_REFERENCE!>@A<!>
else if (2 < 3)
return<!UNRESOLVED_REFERENCE!>@inner<!>
return@outer