Mark dynamic calls in for's, delegated properties and multi-declarations
This commit is contained in:
@@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.diagnostics.rendering.AbstractDiagnosticWithParame
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.DiagnosticFactoryToRendererMap;
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.DiagnosticRenderer;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
@@ -128,14 +129,14 @@ public class CheckerTestUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDynamicCall(@NotNull JetReferenceExpression expression) {
|
||||
public void reportDynamicCall(@NotNull JetElement element) {
|
||||
if (markDynamicCalls) {
|
||||
newDiagnostic(expression, DebugInfoDiagnosticFactory.DYNAMIC);
|
||||
newDiagnostic(element, DebugInfoDiagnosticFactory.DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
private void newDiagnostic(JetReferenceExpression expression, DebugInfoDiagnosticFactory factory) {
|
||||
debugAnnotations.add(new DebugInfoDiagnostic(expression, factory));
|
||||
private void newDiagnostic(JetElement element, DebugInfoDiagnosticFactory factory) {
|
||||
debugAnnotations.add(new DebugInfoDiagnostic(element, factory));
|
||||
}
|
||||
});
|
||||
// this code is used in tests and in internal action 'copy current file as diagnostic test'
|
||||
@@ -523,8 +524,8 @@ public class CheckerTestUtil {
|
||||
}
|
||||
|
||||
public static class DebugInfoDiagnostic extends AbstractDiagnosticForTests {
|
||||
public DebugInfoDiagnostic(@NotNull JetExpression reference, @NotNull DebugInfoDiagnosticFactory factory) {
|
||||
super(reference, factory);
|
||||
public DebugInfoDiagnostic(@NotNull JetElement element, @NotNull DebugInfoDiagnosticFactory factory) {
|
||||
super(element, factory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,17 +23,22 @@ import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.tasks.TasksPackage;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -42,8 +47,9 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
|
||||
public class DebugInfoUtil {
|
||||
private static final TokenSet MAY_BE_UNRESOLVED = TokenSet.create(IN_KEYWORD, NOT_IN);
|
||||
private static final TokenSet EXCLUDED = TokenSet.create(
|
||||
COLON, AS_KEYWORD, AS_SAFE, IS_KEYWORD, NOT_IS, OROR, ANDAND, EQ, EQEQEQ, EXCLEQEQEQ, ELVIS, EXCLEXCL, IN_KEYWORD, NOT_IN);
|
||||
COLON, AS_KEYWORD, AS_SAFE, IS_KEYWORD, NOT_IS, OROR, ANDAND, EQ, EQEQEQ, EXCLEQEQEQ, ELVIS, EXCLEXCL);
|
||||
|
||||
public abstract static class DebugInfoReporter {
|
||||
|
||||
@@ -57,7 +63,7 @@ public class DebugInfoUtil {
|
||||
|
||||
public abstract void reportUnresolvedWithTarget(@NotNull JetReferenceExpression expression, @NotNull String target);
|
||||
|
||||
public void reportDynamicCall(@NotNull JetReferenceExpression expression) { }
|
||||
public void reportDynamicCall(@NotNull JetElement element) { }
|
||||
}
|
||||
|
||||
public static void markDebugAnnotations(
|
||||
@@ -89,17 +95,51 @@ public class DebugInfoUtil {
|
||||
|
||||
root.acceptChildren(new JetTreeVisitorVoid() {
|
||||
|
||||
@Override
|
||||
public void visitForExpression(@NotNull JetForExpression expression) {
|
||||
JetExpression range = expression.getLoopRange();
|
||||
if (reportIfDynamicCall(range, range, LOOP_RANGE_ITERATOR_RESOLVED_CALL) ||
|
||||
reportIfDynamicCall(range, range, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL) ||
|
||||
reportIfDynamicCall(range, range, LOOP_RANGE_NEXT_RESOLVED_CALL)) {
|
||||
// for side-effect of the condition only
|
||||
}
|
||||
super.visitForExpression(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration) {
|
||||
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
reportIfDynamicCall(entry, entry, COMPONENT_RESOLVED_CALL);
|
||||
}
|
||||
super.visitMultiDeclaration(multiDeclaration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProperty(@NotNull JetProperty property) {
|
||||
VariableDescriptor descriptor = bindingContext.get(VARIABLE, property);
|
||||
if (descriptor instanceof PropertyDescriptor && property.getDelegate() != null) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (reportIfDynamicCall(property.getDelegate(), propertyDescriptor.getGetter(), DELEGATED_PROPERTY_RESOLVED_CALL)
|
||||
|| reportIfDynamicCall(property.getDelegate(), propertyDescriptor.getSetter(), DELEGATED_PROPERTY_RESOLVED_CALL)
|
||||
|| reportIfDynamicCall(property.getDelegate(), propertyDescriptor, DELEGATED_PROPERTY_PD_RESOLVED_CALL)) {
|
||||
// for side-effect of the condition only
|
||||
}
|
||||
}
|
||||
super.visitProperty(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(@NotNull JetReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (!BindingContextUtils.isExpressionWithValidReference(expression, bindingContext)){
|
||||
return;
|
||||
}
|
||||
IElementType referencedNameElementType = null;
|
||||
if (expression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) expression;
|
||||
IElementType elementType = expression.getNode().getElementType();
|
||||
if (elementType == JetNodeTypes.OPERATION_REFERENCE) {
|
||||
IElementType referencedNameElementType = nameExpression.getReferencedNameElementType();
|
||||
referencedNameElementType = nameExpression.getReferencedNameElementType();
|
||||
if (EXCLUDED.contains(referencedNameElementType)) {
|
||||
return;
|
||||
}
|
||||
@@ -117,9 +157,7 @@ public class DebugInfoUtil {
|
||||
if (declarationDescriptor != null) {
|
||||
target = declarationDescriptor.toString();
|
||||
|
||||
if (TasksPackage.isDynamic(declarationDescriptor)) {
|
||||
debugInfoReporter.reportDynamicCall(expression);
|
||||
}
|
||||
reportIfDynamic(expression, declarationDescriptor, debugInfoReporter);
|
||||
}
|
||||
if (target == null) {
|
||||
PsiElement labelTarget = bindingContext.get(LABEL_TARGET, expression);
|
||||
@@ -141,6 +179,10 @@ public class DebugInfoUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (MAY_BE_UNRESOLVED.contains(referencedNameElementType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean resolved = target != null;
|
||||
boolean markedWithError = markedWithErrorElements.containsKey(expression);
|
||||
if (expression instanceof JetArrayAccessExpression &&
|
||||
@@ -165,7 +207,22 @@ public class DebugInfoUtil {
|
||||
debugInfoReporter.reportMissingUnresolved(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private <E extends JetElement, K, D extends CallableDescriptor> boolean reportIfDynamicCall(E element, K key, WritableSlice<K, ResolvedCall<D>> slice) {
|
||||
ResolvedCall<D> resolvedCall = bindingContext.get(slice, key);
|
||||
if (resolvedCall != null) {
|
||||
return reportIfDynamic(element, resolvedCall.getResultingDescriptor(), debugInfoReporter);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean reportIfDynamic(JetElement element, DeclarationDescriptor declarationDescriptor, DebugInfoReporter debugInfoReporter) {
|
||||
if (TasksPackage.isDynamic(declarationDescriptor)) {
|
||||
debugInfoReporter.reportDynamicCall(element);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user