Autocasts implemented
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
package org.jetbrains.jet.lang;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class CollectingErrorHandler extends ErrorHandler {
|
||||||
|
private final List<JetDiagnostic> diagnostics;
|
||||||
|
|
||||||
|
public CollectingErrorHandler() {
|
||||||
|
this(Lists.<JetDiagnostic>newArrayList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CollectingErrorHandler(List<JetDiagnostic> diagnostics) {
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JetDiagnostic> getDiagnostics() {
|
||||||
|
return diagnostics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
|
||||||
|
diagnostics.add(new JetDiagnostic.UnresolvedReferenceError(referenceExpression));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
|
||||||
|
diagnostics.add(new JetDiagnostic.TypeMismatchError(expression, expectedType, actualType));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
|
||||||
|
diagnostics.add(new JetDiagnostic.RedeclarationError(existingDescriptor, redeclaredDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
|
||||||
|
diagnostics.add(new JetDiagnostic.GenericError(node, errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
|
||||||
|
diagnostics.add(new JetDiagnostic.GenericWarning(node, message));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package org.jetbrains.jet.lang;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class ErrorHandlerAdapter extends ErrorHandler {
|
||||||
|
protected ErrorHandler worker;
|
||||||
|
|
||||||
|
public ErrorHandlerAdapter(ErrorHandler worker) {
|
||||||
|
this.worker = worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
|
||||||
|
worker.unresolvedReference(referenceExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
|
||||||
|
worker.typeMismatch(expression, expectedType, actualType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
|
||||||
|
worker.redeclaration(existingDescriptor, redeclaredDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
|
||||||
|
worker.genericError(node, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
|
||||||
|
worker.genericWarning(node, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package org.jetbrains.jet.lang;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class ErrorHandlerWithRegions extends ErrorHandler {
|
||||||
|
|
||||||
|
public class DiagnosticsRegion {
|
||||||
|
private final CollectingErrorHandler errorHandler;
|
||||||
|
private boolean committed = false;
|
||||||
|
|
||||||
|
private DiagnosticsRegion(CollectingErrorHandler errorHandler) {
|
||||||
|
this.errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CollectingErrorHandler getErrorHandler() {
|
||||||
|
assert !committed;
|
||||||
|
return errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit() {
|
||||||
|
assert !committed;
|
||||||
|
AnalyzingUtils.applyHandler(parent, errorHandler.getDiagnostics());
|
||||||
|
committed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ErrorHandler parent;
|
||||||
|
private final Stack<CollectingErrorHandler> workers;
|
||||||
|
private ErrorHandler worker;
|
||||||
|
|
||||||
|
public ErrorHandlerWithRegions(ErrorHandler parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.worker = parent;
|
||||||
|
this.workers = new Stack<CollectingErrorHandler>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openRegion() {
|
||||||
|
CollectingErrorHandler newWorker = new CollectingErrorHandler();
|
||||||
|
workers.push(newWorker);
|
||||||
|
worker = newWorker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeAndCommitCurrentRegion() {
|
||||||
|
assert !workers.isEmpty();
|
||||||
|
CollectingErrorHandler region = workers.pop();
|
||||||
|
AnalyzingUtils.applyHandler(parent, region.getDiagnostics());
|
||||||
|
|
||||||
|
setWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiagnosticsRegion closeAndReturnCurrentRegion() {
|
||||||
|
assert !workers.isEmpty();
|
||||||
|
CollectingErrorHandler currentWorker = workers.pop();
|
||||||
|
setWorker();
|
||||||
|
return new DiagnosticsRegion(currentWorker);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setWorker() {
|
||||||
|
worker = workers.isEmpty() ? parent : workers.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
|
||||||
|
worker.unresolvedReference(referenceExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
|
||||||
|
worker.typeMismatch(expression, expectedType, actualType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
|
||||||
|
worker.redeclaration(existingDescriptor, redeclaredDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
|
||||||
|
worker.genericError(node, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
|
||||||
|
worker.genericWarning(node, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import com.intellij.lexer.Lexer;
|
|||||||
import com.intellij.openapi.editor.HighlighterColors;
|
import com.intellij.openapi.editor.HighlighterColors;
|
||||||
import com.intellij.openapi.editor.SyntaxHighlighterColors;
|
import com.intellij.openapi.editor.SyntaxHighlighterColors;
|
||||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||||
|
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||||
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
|
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
|
||||||
import com.intellij.psi.TokenType;
|
import com.intellij.psi.TokenType;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
@@ -14,6 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lexer.JetLexer;
|
import org.jetbrains.jet.lexer.JetLexer;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -54,7 +56,7 @@ public class JetHighlighter extends SyntaxHighlighterBase {
|
|||||||
SyntaxHighlighterColors.NUMBER.getDefaultAttributes()
|
SyntaxHighlighterColors.NUMBER.getDefaultAttributes()
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final TextAttributesKey JET_STRING = TextAttributesKey.createTextAttributesKey(
|
public static final TextAttributesKey JET_STRING = TextAttributesKey.createTextAttributesKey(
|
||||||
"JET.STRING",
|
"JET.STRING",
|
||||||
SyntaxHighlighterColors.STRING.getDefaultAttributes()
|
SyntaxHighlighterColors.STRING.getDefaultAttributes()
|
||||||
);
|
);
|
||||||
@@ -69,6 +71,14 @@ public class JetHighlighter extends SyntaxHighlighterBase {
|
|||||||
HighlighterColors.BAD_CHARACTER.getDefaultAttributes()
|
HighlighterColors.BAD_CHARACTER.getDefaultAttributes()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final TextAttributesKey JET_AUTO_CAST_EXPRESSION;
|
||||||
|
static {
|
||||||
|
TextAttributes clone = SyntaxHighlighterColors.STRING.getDefaultAttributes().clone();
|
||||||
|
clone.setFontType(Font.PLAIN);
|
||||||
|
// TODO: proper attributes
|
||||||
|
JET_AUTO_CAST_EXPRESSION = TextAttributesKey.createTextAttributesKey("JET.AUTO.CAST.EXPRESSION", clone);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Lexer getHighlightingLexer() {
|
public Lexer getHighlightingLexer() {
|
||||||
return new JetLexer();
|
return new JetLexer();
|
||||||
|
|||||||
@@ -88,6 +88,22 @@ public class JetPsiChecker implements Annotator {
|
|||||||
AnalyzingUtils.applyHandler(errorHandler, bindingContext);
|
AnalyzingUtils.applyHandler(errorHandler, bindingContext);
|
||||||
|
|
||||||
highlightBackingFields(holder, file, bindingContext);
|
highlightBackingFields(holder, file, bindingContext);
|
||||||
|
|
||||||
|
file.acceptChildren(new JetVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitExpression(JetExpression expression) {
|
||||||
|
JetType autoCast = bindingContext.getAutoCastType(expression);
|
||||||
|
if (autoCast != null) {
|
||||||
|
holder.createInfoAnnotation(expression, "Automatically cast to " + autoCast).setTextAttributes(JetHighlighter.JET_AUTO_CAST_EXPRESSION);
|
||||||
|
}
|
||||||
|
expression.acceptChildren(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJetElement(JetElement element) {
|
||||||
|
element.acceptChildren(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (ProcessCanceledException e) {
|
catch (ProcessCanceledException e) {
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.psi.JetNamespace;
|
|||||||
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
|
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,7 +116,12 @@ public class AnalyzingUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void applyHandler(@NotNull ErrorHandler errorHandler, @NotNull BindingContext bindingContext) {
|
public static void applyHandler(@NotNull ErrorHandler errorHandler, @NotNull BindingContext bindingContext) {
|
||||||
for (JetDiagnostic jetDiagnostic : bindingContext.getDiagnostics()) {
|
Collection<JetDiagnostic> diagnostics = bindingContext.getDiagnostics();
|
||||||
|
applyHandler(errorHandler, diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyHandler(@NotNull ErrorHandler errorHandler, @NotNull Collection<JetDiagnostic> diagnostics) {
|
||||||
|
for (JetDiagnostic jetDiagnostic : diagnostics) {
|
||||||
jetDiagnostic.acceptHandler(errorHandler);
|
jetDiagnostic.acceptHandler(errorHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.JetDiagnostic;
|
import org.jetbrains.jet.lang.JetDiagnostic;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -41,5 +43,8 @@ public interface BindingContext {
|
|||||||
|
|
||||||
ConstructorDescriptor resolveSuperConstructor(JetDelegatorToSuperCall superCall);
|
ConstructorDescriptor resolveSuperConstructor(JetDelegatorToSuperCall superCall);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetType getAutoCastType(@NotNull JetExpression expression);
|
||||||
|
|
||||||
Collection<JetDiagnostic> getDiagnostics();
|
Collection<JetDiagnostic> getDiagnostics();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.ErrorHandler;
|
import org.jetbrains.jet.lang.ErrorHandlerWithRegions;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -35,8 +35,10 @@ public interface BindingTrace {
|
|||||||
|
|
||||||
void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor);
|
void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor);
|
||||||
|
|
||||||
|
void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
ErrorHandler getErrorHandler();
|
ErrorHandlerWithRegions getErrorHandler();
|
||||||
|
|
||||||
boolean isProcessed(@NotNull JetExpression expression);
|
boolean isProcessed(@NotNull JetExpression expression);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.ErrorHandler;
|
import org.jetbrains.jet.lang.ErrorHandlerWithRegions;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -14,6 +14,11 @@ import org.jetbrains.jet.lang.types.JetType;
|
|||||||
public class BindingTraceAdapter implements BindingTrace {
|
public class BindingTraceAdapter implements BindingTrace {
|
||||||
private final BindingTrace originalTrace;
|
private final BindingTrace originalTrace;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type) {
|
||||||
|
originalTrace.recordAutoCast(expression, type);
|
||||||
|
}
|
||||||
|
|
||||||
public BindingTraceAdapter(BindingTrace originalTrace) {
|
public BindingTraceAdapter(BindingTrace originalTrace) {
|
||||||
this.originalTrace = originalTrace;
|
this.originalTrace = originalTrace;
|
||||||
}
|
}
|
||||||
@@ -63,7 +68,7 @@ public class BindingTraceAdapter implements BindingTrace {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ErrorHandler getErrorHandler() {
|
public ErrorHandlerWithRegions getErrorHandler() {
|
||||||
return originalTrace.getErrorHandler();
|
return originalTrace.getErrorHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.lang.ASTNode;
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.ErrorHandler;
|
import org.jetbrains.jet.lang.CollectingErrorHandler;
|
||||||
|
import org.jetbrains.jet.lang.ErrorHandlerWithRegions;
|
||||||
import org.jetbrains.jet.lang.JetDiagnostic;
|
import org.jetbrains.jet.lang.JetDiagnostic;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -32,39 +32,15 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
|
|||||||
private final Set<JetElement> statements = new HashSet<JetElement>();
|
private final Set<JetElement> statements = new HashSet<JetElement>();
|
||||||
private final Set<PropertyDescriptor> backingFieldRequired = new HashSet<PropertyDescriptor>();
|
private final Set<PropertyDescriptor> backingFieldRequired = new HashSet<PropertyDescriptor>();
|
||||||
private final Set<JetExpression> processed = Sets.newHashSet();
|
private final Set<JetExpression> processed = Sets.newHashSet();
|
||||||
|
private final Map<JetExpression, JetType> autoCasts = Maps.newHashMap();
|
||||||
|
|
||||||
private Collection<JetDiagnostic> diagnostics = Lists.newArrayList();
|
private final List<JetDiagnostic> diagnostics = Lists.newArrayList();
|
||||||
private ErrorHandler errorHandler = new ErrorHandler() {
|
private final ErrorHandlerWithRegions errorHandler = new ErrorHandlerWithRegions(new CollectingErrorHandler(diagnostics));
|
||||||
@Override
|
|
||||||
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
|
|
||||||
diagnostics.add(new JetDiagnostic.UnresolvedReferenceError(referenceExpression));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
|
|
||||||
diagnostics.add(new JetDiagnostic.TypeMismatchError(expression, expectedType, actualType));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
|
|
||||||
diagnostics.add(new JetDiagnostic.RedeclarationError(existingDescriptor, redeclaredDescriptor));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
|
|
||||||
diagnostics.add(new JetDiagnostic.GenericError(node, errorMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
|
|
||||||
diagnostics.add(new JetDiagnostic.GenericWarning(node, message));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ErrorHandler getErrorHandler() {
|
public ErrorHandlerWithRegions getErrorHandler() {
|
||||||
return errorHandler;
|
return errorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +109,11 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
|
|||||||
backingFieldRequired.add(propertyDescriptor);
|
backingFieldRequired.add(propertyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type) {
|
||||||
|
safePut(autoCasts, expression, type);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void recordBlock(JetFunctionLiteralExpression expression) {
|
public void recordBlock(JetFunctionLiteralExpression expression) {
|
||||||
blocks.add(expression);
|
blocks.add(expression);
|
||||||
@@ -281,6 +262,11 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
|
|||||||
return descriptor instanceof ConstructorDescriptor ? (ConstructorDescriptor) descriptor : null;
|
return descriptor instanceof ConstructorDescriptor ? (ConstructorDescriptor) descriptor : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getAutoCastType(@NotNull JetExpression expression) {
|
||||||
|
return autoCasts.get(expression);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<JetDiagnostic> getDiagnostics() {
|
public Collection<JetDiagnostic> getDiagnostics() {
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import java.util.*;
|
|||||||
public class DataFlowInfo {
|
public class DataFlowInfo {
|
||||||
|
|
||||||
private static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<VariableDescriptor, NullabilityFlags>of(), Multimaps.forMap(Collections.<VariableDescriptor, JetType>emptyMap()));
|
private static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<VariableDescriptor, NullabilityFlags>of(), Multimaps.forMap(Collections.<VariableDescriptor, JetType>emptyMap()));
|
||||||
public static final Supplier<SortedSet<JetType>> SORTED_SET_SUPPLIER = new Supplier<SortedSet<JetType>>() {
|
public static final Supplier<List<JetType>> ARRAY_LIST_SUPPLIER = new Supplier<List<JetType>>() {
|
||||||
@Override
|
@Override
|
||||||
public SortedSet<JetType> get() {
|
public List<JetType> get() {
|
||||||
return new TreeSet<JetType>();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ public class DataFlowInfo {
|
|||||||
public DataFlowInfo isInstanceOf(@NotNull VariableDescriptor variableDescriptor, @NotNull JetType type) {
|
public DataFlowInfo isInstanceOf(@NotNull VariableDescriptor variableDescriptor, @NotNull JetType type) {
|
||||||
Multimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
|
Multimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
|
||||||
newTypeInfo.put(variableDescriptor, type);
|
newTypeInfo.put(variableDescriptor, type);
|
||||||
return new DataFlowInfo(getEqualsToNullMap(variableDescriptor, false), newTypeInfo);
|
return new DataFlowInfo(getEqualsToNullMap(variableDescriptor, !type.isNullable()), newTypeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataFlowInfo and(DataFlowInfo other) {
|
public DataFlowInfo and(DataFlowInfo other) {
|
||||||
@@ -107,7 +107,7 @@ public class DataFlowInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<VariableDescriptor, JetType> copyTypeInfo() {
|
private Multimap<VariableDescriptor, JetType> copyTypeInfo() {
|
||||||
Multimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newSortedSetMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), SORTED_SET_SUPPLIER);
|
Multimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), ARRAY_LIST_SUPPLIER);
|
||||||
newTypeInfo.putAll(typeInfo);
|
newTypeInfo.putAll(typeInfo);
|
||||||
return newTypeInfo;
|
return newTypeInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.intellij.psi.tree.IElementType;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
|
import org.jetbrains.jet.lang.ErrorHandlerWithRegions;
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -1346,12 +1347,14 @@ public class JetTypeInferrer {
|
|||||||
condition.accept(new JetVisitor() {
|
condition.accept(new JetVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitIsExpression(JetIsExpression expression) {
|
public void visitIsExpression(JetIsExpression expression) {
|
||||||
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression.getLeftHandSide());
|
if (conditionValue) {
|
||||||
if (variableDescriptor != null) {
|
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression.getLeftHandSide());
|
||||||
JetPattern pattern = expression.getPattern();
|
if (variableDescriptor != null) {
|
||||||
if (pattern instanceof JetTypePattern) {
|
JetPattern pattern = expression.getPattern();
|
||||||
JetTypePattern jetTypePattern = (JetTypePattern) pattern;
|
if (pattern instanceof JetTypePattern) {
|
||||||
result[0] = dataFlowInfo.isInstanceOf(variableDescriptor, trace.getBindingContext().resolveTypeReference(jetTypePattern.getTypeReference()));
|
JetTypePattern jetTypePattern = (JetTypePattern) pattern;
|
||||||
|
result[0] = dataFlowInfo.isInstanceOf(variableDescriptor, trace.getBindingContext().resolveTypeReference(jetTypePattern.getTypeReference()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1642,25 +1645,37 @@ public class JetTypeInferrer {
|
|||||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||||
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false, dataFlowInfo).getType(receiverExpression);
|
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false, dataFlowInfo).getType(receiverExpression);
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
|
ErrorHandlerWithRegions errorHandler = trace.getErrorHandler();
|
||||||
|
errorHandler.openRegion();
|
||||||
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
|
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
|
||||||
|
|
||||||
if (selectorReturnType == null) {
|
if (selectorReturnType != null) {
|
||||||
|
errorHandler.closeAndCommitCurrentRegion();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorHandlerWithRegions.DiagnosticsRegion regionToCommit = errorHandler.closeAndReturnCurrentRegion();
|
||||||
|
|
||||||
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(receiverExpression);
|
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(receiverExpression);
|
||||||
if (variableDescriptor != null) {
|
if (variableDescriptor != null) {
|
||||||
Collection<JetType> possibleTypes = dataFlowInfo.getPossibleTypes(variableDescriptor);
|
Collection<JetType> possibleTypes = dataFlowInfo.getPossibleTypes(variableDescriptor);
|
||||||
for (JetType possibleType : possibleTypes) {
|
for (JetType possibleType : possibleTypes) {
|
||||||
|
errorHandler.openRegion();
|
||||||
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression);
|
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression);
|
||||||
if (selectorReturnType != null) {
|
if (selectorReturnType != null) {
|
||||||
|
regionToCommit = errorHandler.closeAndReturnCurrentRegion();
|
||||||
|
trace.recordAutoCast(receiverExpression, possibleType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regionToCommit.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression.getOperationSign() == JetTokens.QUEST) {
|
if (expression.getOperationSign() == JetTokens.QUEST) {
|
||||||
if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
|
if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
|
||||||
// TODO : more comprehensible error message
|
// TODO : more comprehensible error message
|
||||||
trace.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
|
errorHandler.typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
|
||||||
}
|
}
|
||||||
result = TypeUtils.makeNullable(receiverType);
|
result = TypeUtils.makeNullable(receiverType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
class A() {
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B() : A() {
|
||||||
|
fun bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f9() {
|
||||||
|
val a : A?
|
||||||
|
a?.foo()
|
||||||
|
a?.<error>bar</error>()
|
||||||
|
if (a is B) {
|
||||||
|
<info descr="Automatically cast to B">a</info>.bar()
|
||||||
|
a.foo()
|
||||||
|
}
|
||||||
|
a?.foo()
|
||||||
|
a?.<error>bar</error>()
|
||||||
|
if (!(a is B)) {
|
||||||
|
a?.<error>bar</error>()
|
||||||
|
a?.foo()
|
||||||
|
}
|
||||||
|
if (!(a is B) || <info descr="Automatically cast to B">a</info>.bar() == ()) {
|
||||||
|
a?.<error>bar</error>()
|
||||||
|
}
|
||||||
|
if (!(a is B)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
<info descr="Automatically cast to B">a</info>.bar()
|
||||||
|
a.foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f10() {
|
||||||
|
val a : A?
|
||||||
|
if (!(a is B)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(a is B)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.ErrorHandler;
|
import org.jetbrains.jet.lang.ErrorHandler;
|
||||||
|
import org.jetbrains.jet.lang.ErrorHandlerWithRegions;
|
||||||
import org.jetbrains.jet.lang.JetDiagnostic;
|
import org.jetbrains.jet.lang.JetDiagnostic;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -63,10 +64,15 @@ public class JetTestUtils {
|
|||||||
public void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor) {
|
public void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ErrorHandler getErrorHandler() {
|
public ErrorHandlerWithRegions getErrorHandler() {
|
||||||
return ErrorHandler.DO_NOTHING;
|
return new ErrorHandlerWithRegions(ErrorHandler.DO_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -178,6 +184,11 @@ public class JetTestUtils {
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getAutoCastType(@NotNull JetExpression expression) {
|
||||||
|
throw new UnsupportedOperationException(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<JetDiagnostic> getDiagnostics() {
|
public Collection<JetDiagnostic> getDiagnostics() {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
|
|||||||
Reference in New Issue
Block a user