Vars modified in closures are marked with a MUST_BE_WRAPPED_IN_A_REF key

This commit is contained in:
Andrey Breslav
2011-10-13 19:11:20 +04:00
parent 86c83a6336
commit 22223cb6b0
5 changed files with 61 additions and 4 deletions
@@ -44,9 +44,12 @@ public interface BindingContext {
WritableSlice<JetExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice("PROCESSED");
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT");
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED");
WritableSlice<VariableDescriptor, Boolean> MUST_BE_WRAPPED_IN_A_REF = Slices.createSimpleSetSlice("MUST_BE_WRAPPED_IN_A_REF");
enum DeferredTypeKey {DEFERRED_TYPE_KEY}
WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice("DEFERRED_TYPES");
WritableSlice<DeferredTypeKey, DeferredType> DEFERRED_TYPE = new CollectionSliceWrapper<DeferredTypeKey, DeferredType>(DEFERRED_TYPES, CommonSuppliers.<DeferredType>getArrayListSupplier());
WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) {
@@ -2815,13 +2815,20 @@ public class JetTypeInferrer {
// }
}
if (left instanceof JetSimpleNameExpression) {
JetSimpleNameExpression variable = (JetSimpleNameExpression) left;
String referencedName = variable.getReferencedName();
if (variable.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
JetSimpleNameExpression simpleName = (JetSimpleNameExpression) left;
String referencedName = simpleName.getReferencedName();
if (simpleName.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
&& referencedName != null) {
PropertyDescriptor property = context.scope.getPropertyByFieldReference(referencedName);
if (property != null) {
context.trace.record(BindingContext.VARIABLE_ASSIGNMENT, variable, property);
context.trace.record(BindingContext.VARIABLE_ASSIGNMENT, simpleName, property);
}
}
VariableDescriptor variable = AutoCastUtils.getVariableDescriptorFromSimpleName(context.trace.getBindingContext(), simpleName);
if (variable != null) {
DeclarationDescriptor containingDeclaration = variable.getContainingDeclaration();
if (context.scope.getContainingDeclaration() != containingDeclaration && containingDeclaration instanceof CallableDescriptor) {
context.trace.record(MUST_BE_WRAPPED_IN_A_REF, variable);
}
}
}
@@ -97,6 +97,15 @@ public class JetHighlighter extends SyntaxHighlighterBase {
JET_AUTO_CAST_EXPRESSION = TextAttributesKey.createTextAttributesKey("JET.AUTO.CAST.EXPRESSION", clone);
}
public static final TextAttributesKey JET_WRAPPED_INTO_REF;
static {
TextAttributes attributes = new TextAttributes();
attributes.setEffectType(EffectType.LINE_UNDERSCORE);
attributes.setEffectColor(Color.BLACK);
JET_WRAPPED_INTO_REF = TextAttributesKey.createTextAttributesKey("JET.WRAPPED.INTO.REF", attributes);
}
public static final TextAttributesKey JET_AUTOCREATED_IT;
static {
@@ -3,6 +3,7 @@ package org.jetbrains.jet.plugin.annotations;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
@@ -117,9 +118,28 @@ public class JetPsiChecker implements Annotator {
holder.createInfoAnnotation(expression, "Automatically declared based on the expected type").setTextAttributes(JetHighlighter.JET_AUTOCREATED_IT);
}
}
markVariableAsWrappedIfNeeded(expression.getNode(), target);
super.visitSimpleNameExpression(expression);
}
private void markVariableAsWrappedIfNeeded(ASTNode node, DeclarationDescriptor target) {
if (target instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) target;
if (bindingContext.get(MUST_BE_WRAPPED_IN_A_REF, variableDescriptor)) {
holder.createInfoAnnotation(node, "Wrapped into a ref-object to be modifier when captured in a closure").setTextAttributes(JetHighlighter.JET_WRAPPED_INTO_REF);
}
}
}
@Override
public void visitProperty(JetProperty property) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
markVariableAsWrappedIfNeeded(property.getNameIdentifier().getNode(), declarationDescriptor);
super.visitProperty(property);
}
@Override
public void visitExpression(JetExpression expression) {
JetType autoCast = bindingContext.get(AUTOCAST, expression);
@@ -0,0 +1,18 @@
fun notContainsBreak() {
var <info>a</info> = 1
val v = {
<info>a</info> = 2
}
var <info>x</info> = 1
val b = object {
fun foo() {
<info>x</info> = 2
}
}
var <info>y</info> = 1
fun foo() {
<info>y</info> = 1
}
}