diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
index 00e5fd1be29..5ca3805069a 100644
--- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
+++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
@@ -287,7 +287,7 @@ public class ExpressionCodegen extends JetVisitor {
for (JetElement statement : statements) {
if (statement instanceof JetProperty) {
- final VariableDescriptor variableDescriptor = bindingContext.getPropertyDescriptor((JetProperty) statement);
+ final VariableDescriptor variableDescriptor = bindingContext.getVariableDescriptor((JetProperty) statement);
final Type type = typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, type.getSize());
}
@@ -309,7 +309,7 @@ public class ExpressionCodegen extends JetVisitor {
for (JetElement statement : statements) {
if (statement instanceof JetProperty) {
JetProperty var = (JetProperty) statement;
- VariableDescriptor variableDescriptor = bindingContext.getPropertyDescriptor(var);
+ VariableDescriptor variableDescriptor = bindingContext.getVariableDescriptor(var);
Type outType = typeMapper.mapType(variableDescriptor.getOutType());
int index = myMap.leave(variableDescriptor);
@@ -923,7 +923,7 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitProperty(JetProperty property) {
- VariableDescriptor variableDescriptor = bindingContext.getPropertyDescriptor(property);
+ VariableDescriptor variableDescriptor = bindingContext.getVariableDescriptor(property);
int index = myMap.getIndex(variableDescriptor);
assert index >= 0;
diff --git a/idea/src/org/jetbrains/jet/lang/JetHighlighter.java b/idea/src/org/jetbrains/jet/lang/JetHighlighter.java
index 0d860195c99..d1e33ef00e8 100644
--- a/idea/src/org/jetbrains/jet/lang/JetHighlighter.java
+++ b/idea/src/org/jetbrains/jet/lang/JetHighlighter.java
@@ -37,6 +37,12 @@ public class JetHighlighter extends SyntaxHighlighterBase {
SyntaxHighlighterColors.KEYWORD.getDefaultAttributes()
);
+ public static final TextAttributesKey JET_PROPERTY_WITH_BACKING_FIELD_IDENTIFIER = TextAttributesKey.createTextAttributesKey(
+ "JET.PROPERTY.WITH.BACKING.FIELD.IDENTIFIER",
+// TODO: proper attributes
+ SyntaxHighlighterColors.NUMBER.getDefaultAttributes()
+ );
+
public static final TextAttributesKey JET_LABEL_IDENTIFIER = TextAttributesKey.createTextAttributesKey(
"JET.LABEL.IDENTIFIER",
// TODO: proper attributes
diff --git a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java
index 3e793893c23..7dd3be4efe5 100644
--- a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java
+++ b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java
@@ -12,13 +12,14 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ErrorHandler;
-import org.jetbrains.jet.lang.psi.JetExpression;
-import org.jetbrains.jet.lang.psi.JetFile;
-import org.jetbrains.jet.lang.psi.JetReferenceExpression;
+import org.jetbrains.jet.lang.JetHighlighter;
+import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.DeclarationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
+import org.jetbrains.jet.lang.types.PropertyDescriptor;
+import org.jetbrains.jet.lang.types.VariableDescriptor;
import java.util.Collection;
import java.util.HashSet;
@@ -77,6 +78,8 @@ public class JetPsiChecker implements Annotator {
holder.createErrorAnnotation(declarationPsiElement, "Redeclaration");
}
}
+
+ highlightBackingFields(holder, file, bindingContext);
}
catch (ProcessCanceledException e) {
throw e;
@@ -88,4 +91,26 @@ public class JetPsiChecker implements Annotator {
}
}
}
+
+ private void highlightBackingFields(final AnnotationHolder holder, JetFile file, final BindingContext bindingContext) {
+ file.acceptChildren(new JetVisitor() {
+ @Override
+ public void visitProperty(JetProperty property) {
+ VariableDescriptor propertyDescriptor = bindingContext.getVariableDescriptor(property);
+ if (propertyDescriptor instanceof PropertyDescriptor) {
+ if (bindingContext.hasBackingField((PropertyDescriptor) propertyDescriptor)) {
+ holder.createInfoAnnotation(
+ property.getNameIdentifier(),
+ "This property has a backing field")
+ .setTextAttributes(JetHighlighter.JET_PROPERTY_WITH_BACKING_FIELD_IDENTIFIER);
+ }
+ }
+ }
+
+ @Override
+ public void visitJetElement(JetElement elem) {
+ elem.acceptChildren(this);
+ }
+ });
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java
index 33337eaf0d3..ac4b9048111 100644
--- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java
+++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java
@@ -12,7 +12,7 @@ public interface BindingContext {
ClassDescriptor getClassDescriptor(JetClass declaration);
TypeParameterDescriptor getTypeParameterDescriptor(JetTypeParameter declaration);
FunctionDescriptor getFunctionDescriptor(JetFunction declaration);
- VariableDescriptor getPropertyDescriptor(JetProperty declaration);
+ VariableDescriptor getVariableDescriptor(JetProperty declaration);
VariableDescriptor getParameterDescriptor(JetParameter declaration);
JetType getExpressionType(JetExpression expression);
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java
index d30ee81bcde..45a44927f89 100644
--- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java
+++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java
@@ -118,7 +118,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
}
@Override
- public VariableDescriptor getPropertyDescriptor(JetProperty declaration) {
+ public VariableDescriptor getVariableDescriptor(JetProperty declaration) {
return (VariableDescriptor) declarationsToDescriptors.get(declaration);
}
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java
index 45787dfa4bb..8ba07b1e507 100644
--- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java
+++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java
@@ -301,9 +301,10 @@ public class TopDownAnalyzer {
super.recordReferenceResolution(expression, descriptor);
if (expression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
- if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
- && descriptor == propertyDescriptor) { // TODO : original?
- recordFieldAccessFromAccessor(propertyDescriptor);
+ if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
+ if (descriptor == propertyDescriptor) { // TODO : original?
+ recordFieldAccessFromAccessor(propertyDescriptor);
+ }
}
}
}
@@ -320,7 +321,6 @@ public class TopDownAnalyzer {
if (setter != null && setterDescriptor != null) {
resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, declaringScope);
}
-
}
}
diff --git a/idea/testData/checker/infos/PropertiesWithBackingFields.jet b/idea/testData/checker/infos/PropertiesWithBackingFields.jet
new file mode 100644
index 00000000000..50dd6ec31c2
--- /dev/null
+++ b/idea/testData/checker/infos/PropertiesWithBackingFields.jet
@@ -0,0 +1,31 @@
+class Test {
+ abstract val x : Int
+ abstract val x1 : Int get
+ abstract val x2 : Int get() = 1
+
+ val a : Int
+ val b : Int get
+ val c = 1
+
+ val c1 = 1
+ get
+ val c2 : Int
+ get() = 1
+ val c3 : Int
+ get() { return 1 }
+ val c4 : Int
+ get() { 1 }
+
+ abstract var y : Int
+ abstract var y1 : Int get
+ abstract var y2 : Int set
+ abstract var y3 : Int set get
+ abstract var y4 : Int set get() = 1
+ abstract var y5 : Int set(x) {} get() = 1
+
+ var v : Int
+ var v1 : Int get
+ var v2 : Int get set
+ var v3 : Int get() = 1; set
+ var v4 : Int get() = 1; set(x){}
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/JetTestCaseBase.java b/idea/tests/org/jetbrains/jet/JetTestCaseBase.java
index 192180c5a8a..5ae4d8ff51e 100644
--- a/idea/tests/org/jetbrains/jet/JetTestCaseBase.java
+++ b/idea/tests/org/jetbrains/jet/JetTestCaseBase.java
@@ -20,6 +20,7 @@ import java.util.List;
*/
public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase {
+ private boolean checkInfos = false;
private String dataPath;
protected final String name;
@@ -28,6 +29,11 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase {
this.name = name;
}
+ public final JetTestCaseBase setCheckInfos(boolean checkInfos) {
+ this.checkInfos = checkInfos;
+ return this;
+ }
+
public static Sdk jdkFromIdeaHome() {
return new JavaSdkImpl().createJdk("JDK", "idea/testData/mockJDK-1.7/jre", true);
}
@@ -57,7 +63,7 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase {
@Override
protected void runTest() throws Throwable {
- doTest(getTestFilePath(), true, false);
+ doTest(getTestFilePath(), true, checkInfos);
}
@NotNull
diff --git a/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java b/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java
index 349989c7fed..ce9c3e649fd 100644
--- a/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java
+++ b/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java
@@ -16,13 +16,20 @@ public class JetPsiCheckerTest extends JetTestCaseBase {
public static Test suite() {
TestSuite suite = new TestSuite();
- suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/", true, new JetTestCaseBase.NamedTestFactory() {
+ suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
+ suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/infos/", false, new JetTestCaseBase.NamedTestFactory() {
+ @NotNull
+ @Override
+ public Test createTest(@NotNull String dataPath, @NotNull String name) {
+ return new JetPsiCheckerTest(dataPath, name).setCheckInfos(true);
+ }
+ }));
return suite;
}
}