Merge branch 'master' of git+ssh://git.labs.intellij.net/jet

This commit is contained in:
Nikolay Krasko
2011-11-30 19:54:35 +04:00
227 changed files with 1131 additions and 576 deletions
@@ -142,5 +142,5 @@ public interface JetNodeTypes {
JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class);
JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class);
JetNodeType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME", JetContainerNode.class);
JetNodeType NAMESPACE_HEADER = new JetNodeType("NAMESPACE_HEADER", JetNamespaceHeader.class);
}
@@ -35,26 +35,30 @@ public class JetControlFlowProcessor {
this.trace = trace;
}
public void generate(@NotNull JetDeclaration subroutineElement, @NotNull JetExpression body) {
generateSubroutineControlFlow(subroutineElement, Collections.singletonList(body));
}
public void generateSubroutineControlFlow(@NotNull JetDeclaration subroutineElement, @NotNull List<? extends JetElement> body) {
builder.enterSubroutine(subroutineElement);
for (JetElement statement : body) {
statement.accept(new CFPVisitor(false));
public void generate(@NotNull JetDeclaration subroutine) {
builder.enterSubroutine(subroutine);
if (subroutine instanceof JetDeclarationWithBody) {
JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
CFPVisitor cfpVisitor = new CFPVisitor(false);
List<JetParameter> valueParameters = declarationWithBody.getValueParameters();
for (JetParameter valueParameter : valueParameters) {
valueParameter.accept(cfpVisitor);
}
JetExpression bodyExpression = declarationWithBody.getBodyExpression();
if (bodyExpression != null) {
bodyExpression.accept(cfpVisitor);
}
}
builder.exitSubroutine(subroutineElement);
else {
subroutine.accept(new CFPVisitor(false));
}
builder.exitSubroutine(subroutine);
}
private void processLocalDeclaration(@NotNull JetDeclaration subroutineElement, @NotNull JetExpression body) {
processLocalDeclaration(subroutineElement, Collections.singletonList(body));
}
private void processLocalDeclaration(@NotNull JetDeclaration subroutineElement, @NotNull List<? extends JetElement> body) {
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
Label afterDeclaration = builder.createUnboundLabel();
builder.nondeterministicJump(afterDeclaration);
generateSubroutineControlFlow(subroutineElement, body);
generate(subroutine);
builder.bindLabel(afterDeclaration);
}
@@ -569,6 +573,12 @@ public class JetControlFlowProcessor {
}
}
@Override
public void visitParameter(JetParameter parameter) {
builder.declare(parameter);
builder.write(parameter, parameter);
}
@Override
public void visitBlockExpression(JetBlockExpression expression) {
List<JetElement> statements = expression.getStatements();
@@ -582,20 +592,13 @@ public class JetControlFlowProcessor {
@Override
public void visitNamedFunction(JetNamedFunction function) {
JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) {
processLocalDeclaration(function, bodyExpression);
}
processLocalDeclaration(function);
}
@Override
public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
if (bodyExpression != null) {
List<JetElement> statements = bodyExpression.getStatements();
processLocalDeclaration(functionLiteral, statements);
}
processLocalDeclaration(functionLiteral);
builder.read(expression);
}
@@ -19,6 +19,7 @@ import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetMainDetector;
import java.util.*;
@@ -68,7 +69,7 @@ public class JetFlowInformationProvider {
}
};
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace);
new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration, bodyExpression);
new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration);
wrappedTrace.close();
}
@@ -479,13 +480,27 @@ public class JetFlowInformationProvider {
}
else if (instruction instanceof VariableDeclarationInstruction) {
JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
if (element instanceof JetProperty) {
if (element instanceof JetNamedDeclaration) {
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
PsiElement elementToMark = nameIdentifier != null ? nameIdentifier : element;
if (enterData.get(variableDescriptor) == VariableStatus.UNUSED) {
trace.report(Errors.UNUSED_VARIABLE.on((JetNamedDeclaration) element, elementToMark, variableDescriptor));
if (element instanceof JetProperty) {
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, elementToMark, variableDescriptor));
}
else if (element instanceof JetParameter) {
PsiElement psiElement = element.getParent().getParent();
if (psiElement instanceof JetFunction) {
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
assert descriptor instanceof FunctionDescriptor;
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, elementToMark, variableDescriptor));
}
}
}
}
else if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN) {
else if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN && element instanceof JetProperty) {
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, elementToMark, variableDescriptor));
}
}
@@ -46,6 +46,12 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements
@Override
public String toString() {
return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + "]";
try {
return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + "]";
} catch (Throwable e) {
// DescriptionRenderer may throw if this is not yet completely initialized
// It is very inconvenient while debugging
return super.toString();
}
}
}
@@ -83,10 +83,10 @@ public class FunctionDescriptorUtil {
return parameterScope;
}
public static void initializeFromFunctionType(@NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType) {
public static void initializeFromFunctionType(@NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType, @NotNull ReceiverDescriptor expectedThisObject) {
assert JetStandardClasses.isFunctionType(functionType);
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
ReceiverDescriptor.NO_RECEIVER,
expectedThisObject,
Collections.<TypeParameterDescriptor>emptyList(),
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
JetStandardClasses.getReturnTypeFromFunctionType(functionType),
@@ -118,6 +118,16 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
return getOutType();
}
@Override
public JetType getInType() {
return super.getInType();
}
@Override
@NotNull
public JetType getOutType() {
return super.getOutType();
}
public boolean isVar() {
return isVar;
@@ -14,7 +14,7 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
JetType outType = variableDescriptor.getOutType();
assert outType != null;
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
FunctionDescriptorUtil.initializeFromFunctionType(result, outType);
FunctionDescriptorUtil.initializeFromFunctionType(result, outType, variableDescriptor.getExpectedThisObject());
return result;
}
@@ -147,8 +147,9 @@ public interface Errors {
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT);
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
PsiElementOnlyDiagnosticFactory1<JetNamedDeclaration, DeclarationDescriptor> UNUSED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(WARNING, "Variable ''{0}'' is never used", NAME);
PsiElementOnlyDiagnosticFactory1<JetNamedDeclaration, DeclarationDescriptor> ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(WARNING, "Variable ''{0}'' is assigned but never accessed", NAME);
UnusedElementDiagnosticFactory<JetProperty, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", NAME);
UnusedElementDiagnosticFactory<JetParameter, VariableDescriptor> UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, "Parameter ''{0}'' is never used", NAME);
UnusedElementDiagnosticFactory<JetNamedDeclaration, DeclarationDescriptor> ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is assigned but never accessed", NAME);
PsiElementOnlyDiagnosticFactory2<JetElement, JetElement, DeclarationDescriptor> UNUSED_VALUE = new PsiElementOnlyDiagnosticFactory2<JetElement, JetElement, DeclarationDescriptor>(WARNING, "The value ''{0}'' assigned to ''{1}'' is never used", NAME) {
@Override
protected String makeMessageForA(@NotNull JetElement element) {
@@ -0,0 +1,23 @@
package org.jetbrains.jet.lang.diagnostics;
import com.intellij.psi.PsiElement;
/**
* @author svtk
*/
public class UnusedElementDiagnosticFactory<T extends PsiElement, A> extends PsiElementOnlyDiagnosticFactory1<T, A> {
public static <T extends PsiElement, A> UnusedElementDiagnosticFactory<T, A> create(Severity severity, String messageStub) {
return new UnusedElementDiagnosticFactory<T, A>(severity, messageStub);
}
public static <T extends PsiElement, A> UnusedElementDiagnosticFactory<T, A> create(Severity severity, String messageStub, Renderer renderer) {
return new UnusedElementDiagnosticFactory<T, A>(severity, messageStub, renderer);
}
public UnusedElementDiagnosticFactory(Severity severity, String message, Renderer renderer) {
super(severity, message, renderer);
}
protected UnusedElementDiagnosticFactory(Severity severity, String message) {
super(severity, message);
}
}
@@ -115,17 +115,18 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers "namespace" SimpleName{"."} SEMI?
* ;
*/
PsiBuilder.Marker namespaceHeader = mark();
PsiBuilder.Marker firstEntry = mark();
parseModifierList(MODIFIER_LIST, true);
if (at(NAMESPACE_KEYWORD)) {
advance(); // NAMESPACE_KEYWORD
parseNamespaceName();
if (at(LBRACE)) {
// Because it's blocked namespace and it will be parsed as one of top level objects
firstEntry.rollbackTo();
namespaceHeader.done(NAMESPACE_HEADER);
return;
}
@@ -135,6 +136,7 @@ public class JetParsing extends AbstractJetParsing {
} else {
firstEntry.rollbackTo();
}
namespaceHeader.done(NAMESPACE_HEADER);
// TODO: Duplicate with parsing imports in parseToplevelDeclarations
while (at(IMPORT_KEYWORD)) {
@@ -145,12 +147,18 @@ public class JetParsing extends AbstractJetParsing {
/* SimpleName{"."} */
private void parseNamespaceName() {
PsiBuilder.Marker nsName = mark();
expect(IDENTIFIER, "Expecting qualified name", NAMESPACE_NAME_RECOVERY_SET);
while (!eol() && at(DOT)) {
advance(); // DOT
while (true) {
expect(IDENTIFIER, "Namespace name must be a '.'-separated identifier list", NAMESPACE_NAME_RECOVERY_SET);
if (at(DOT)) {
nsName.done(REFERENCE_EXPRESSION);
advance(); // DOT
nsName = mark();
}
else {
nsName.drop();
break;
}
}
nsName.done(NAMESPACE_NAME);
}
/*
@@ -378,6 +386,7 @@ public class JetParsing extends AbstractJetParsing {
*/
private JetNodeType parseNamespaceBlock() {
assert _at(NAMESPACE_KEYWORD);
PsiBuilder.Marker namespaceHeader = mark();
advance(); // NAMESPACE_KEYWORD
if (at(LBRACE)) {
@@ -386,6 +395,7 @@ public class JetParsing extends AbstractJetParsing {
else {
parseNamespaceName();
}
namespaceHeader.done(NAMESPACE_HEADER);
if (!at(LBRACE)) {
error("A namespace block in '{...}' expected");
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import java.util.ArrayList;
@@ -26,6 +27,7 @@ public class JetAnnotatedExpression extends JetExpression {
return visitor.visitAnnotatedExpression(this, data);
}
@Nullable
public JetExpression getBaseExpression() {
return findChildByClass(JetExpression.class);
}
@@ -39,18 +39,23 @@ public class JetNamespace extends JetNamedDeclaration {
}
public String getName() {
PsiElement nameIdentifier = getNameIdentifier();
return nameIdentifier != null ? nameIdentifier.getText() : "";
String name = super.getName();
return name == null ? "" : name;
}
@NotNull
public JetNamespaceHeader getHeader() {
return (JetNamespaceHeader) findChildByType(JetNodeTypes.NAMESPACE_HEADER);
}
@Override
public PsiElement getNameIdentifier() {
return findChildByType(JetNodeTypes.NAMESPACE_NAME);
return getHeader().getNameIdentifier();
}
@Override
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException(); // TODO
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
/**
* @author abreslav
*/
public class JetNamespaceHeader extends JetElement {
public JetNamespaceHeader(@NotNull ASTNode node) {
super(node);
}
@NotNull
public List<JetSimpleNameExpression> getParentNamespaceNames() {
return findChildrenByType(JetNodeTypes.REFERENCE_EXPRESSION);
}
@Nullable
public PsiElement getNameIdentifier() {
return findChildByType(JetTokens.IDENTIFIER);
}
@Override
public String getName() {
PsiElement nameIdentifier = getNameIdentifier();
return nameIdentifier == null ? "" : nameIdentifier.getText();
}
}
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableAsFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType;
@@ -43,6 +44,9 @@ public class BindingContextUtils {
if (descriptor instanceof VariableDescriptor) {
return (VariableDescriptor) descriptor;
}
if (descriptor instanceof VariableAsFunctionDescriptor) {
return ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
}
return null;
}
@@ -69,19 +69,7 @@ public class TypeHierarchyResolver {
declaration.accept(new JetVisitorVoid() {
@Override
public void visitNamespace(JetNamespace namespace) {
String name = JetPsiUtil.safeName(namespace.getName());
NamespaceDescriptorImpl namespaceDescriptor = owner.getNamespace(name);
if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptorImpl(
owner.getOriginal(),
Collections.<AnnotationDescriptor>emptyList(), // TODO: annotations
name
);
namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope"));
owner.addNamespace(namespaceDescriptor);
context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor);
}
NamespaceDescriptorImpl namespaceDescriptor = createNamespaceDescriptorPathIfNeeded(namespace, owner);
context.getNamespaceDescriptors().put(namespace, namespaceDescriptor);
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace()));
@@ -202,6 +190,35 @@ public class TypeHierarchyResolver {
}
}
private NamespaceDescriptorImpl createNamespaceDescriptorPathIfNeeded(JetNamespace namespace, NamespaceLike owner) {
NamespaceLike currentOwner = owner;
for (JetSimpleNameExpression nameExpression : namespace.getHeader().getParentNamespaceNames()) {
currentOwner = createNamespaceDescriptorIfNeeded(null, currentOwner, JetPsiUtil.safeName(nameExpression.getReferencedName()));
context.getTrace().record(REFERENCE_TARGET, nameExpression, currentOwner);
}
String name = JetPsiUtil.safeName(namespace.getName());
return createNamespaceDescriptorIfNeeded(namespace, currentOwner, name);
}
@NotNull
private NamespaceDescriptorImpl createNamespaceDescriptorIfNeeded(@Nullable JetNamespace namespace, @NotNull NamespaceLike owner, @NotNull String name) {
NamespaceDescriptorImpl namespaceDescriptor = owner.getNamespace(name);
if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptorImpl(
owner.getOriginal(),
Collections.<AnnotationDescriptor>emptyList(), // TODO: annotations
name
);
namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope"));
owner.addNamespace(namespaceDescriptor);
if (namespace != null) {
context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor);
}
}
return namespaceDescriptor;
}
@NotNull
private ClassKind getClassKind(@NotNull JetClass jetClass) {
if (jetClass.isTrait()) return ClassKind.TRAIT;
@@ -185,7 +185,7 @@ public class CallResolver {
}
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
@@ -64,20 +64,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
scope = explicitReceiver.getType().getMemberScope();
explicitReceiver = NO_RECEIVER;
}
doComputeTasks(scope, explicitReceiver, call, name, result, AutoCastService.NO_AUTO_CASTS);
doComputeTasks(scope, explicitReceiver, call, name, result, new AutoCastServiceImpl(dataFlowInfo, bindingContext));
List<ReceiverDescriptor> receivers;
if (explicitReceiver.exists()) {
receivers = Collections.singletonList(explicitReceiver);
}
else {
receivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers);
}
for (ReceiverDescriptor receiverToCast : receivers) {
assert receiverToCast.exists();
doComputeTasks(scope, receiverToCast, call, name, result, new AutoCastServiceImpl(dataFlowInfo, bindingContext));
}
return result;
}
@@ -87,7 +75,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
scope.getImplicitReceiversHierarchy(implicitReceivers);
if (receiver.exists()) {
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
Collection<ResolvedCallImpl<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name));
List<ResolvedCallImpl<D>> nonlocals = Lists.newArrayList();
List<ResolvedCallImpl<D>> locals = Lists.newArrayList();
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.resolve.calls.autocasts;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
@@ -21,7 +22,9 @@ public class AutoCastServiceImpl implements AutoCastService {
@NotNull
@Override
public List<ReceiverDescriptor> getVariantsForReceiver(@NotNull ReceiverDescriptor receiverDescriptor) {
return AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverDescriptor);
List<ReceiverDescriptor> variants = Lists.newArrayList(AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverDescriptor));
variants.add(receiverDescriptor);
return variants;
}
@NotNull
@@ -17,6 +17,9 @@ public class AutoCastUtils {
private AutoCastUtils() {}
/**
* @return variants @param receiverToCast may be cast to according to @param dataFlowInfo, @param receiverToCast itself is NOT included
*/
public static List<ReceiverDescriptor> getAutoCastVariants(@NotNull final BindingContext bindingContext, @NotNull final DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiverToCast) {
return receiverToCast.accept(new ReceiverDescriptorVisitor<List<ReceiverDescriptor>, Object>() {
@Override
@@ -102,7 +102,7 @@ public class DataFlowInfo {
boolean changed = false;
changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB.invert()));
changed |= putNullability(builder, b, nullabilityOfA.refine(nullabilityOfA.invert()));
changed |= putNullability(builder, b, nullabilityOfB.refine(nullabilityOfA.invert()));
return changed ? new DataFlowInfo(ImmutableMap.copyOf(builder), typeInfo) : this;
}
@@ -250,7 +250,8 @@ public class CompileTimeConstantResolver {
if (error != null) {
return error;
}
return new StringValue(unescapedText);
return new StringValue(unescapedText.substring(3, unescapedText.length() - 3));
}
@NotNull
@@ -299,11 +299,19 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override
public void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor) {
if (!fieldName.startsWith("$")) {
throw new IllegalStateException();
}
getPropertyDescriptorsByFieldNames().put(fieldName, propertyDescriptor);
}
@Override
public PropertyDescriptor getPropertyByFieldReference(@NotNull String fieldName) {
if (!fieldName.startsWith("$")) {
throw new IllegalStateException();
}
PropertyDescriptor descriptor = getPropertyDescriptorsByFieldNames().get(fieldName);
if (descriptor != null) return descriptor;
return super.getPropertyByFieldReference(fieldName);
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.types.expressions;
import com.intellij.lang.ASTNode;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
@@ -14,7 +13,6 @@ import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
import static org.jetbrains.jet.lang.diagnostics.Errors.ELSE_MISPLACED_IN_WHEN;
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
/**
@@ -22,11 +20,9 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO
*/
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, ExpressionTypingContext> implements ExpressionTypingInternals {
private static ExpressionTypingVisitorDispatcher BASIC_DISPATCHER = new ExpressionTypingVisitorDispatcher(null);
@NotNull
public static ExpressionTypingFacade create() {
return BASIC_DISPATCHER;
return new ExpressionTypingVisitorDispatcher(null);
}
@NotNull
@@ -73,9 +73,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@Nullable
public abstract KnownType getValue();
public abstract boolean equate(TypeValue other);
}
private static class UnknownType extends TypeValue {
private class UnknownType extends TypeValue {
private final TypeParameterDescriptor typeParameterDescriptor;
private final Variance positionVariance;
@@ -87,6 +89,24 @@ public class ConstraintSystemImpl implements ConstraintSystem {
this.positionVariance = positionVariance;
}
@Override
public void addUpperBound(@NotNull TypeValue bound) {
addBound(bound, getLowerBounds());
super.addUpperBound(bound);
}
@Override
public void addLowerBound(@NotNull TypeValue bound) {
addBound(bound, getUpperBounds());
super.addLowerBound(bound);
}
private void addBound(TypeValue bound, Set<TypeValue> oppositeBounds) {
if (oppositeBounds.contains(bound)) {
this.equate(bound);
}
}
@NotNull
public TypeParameterDescriptor getTypeParameterDescriptor() {
return typeParameterDescriptor;
@@ -139,6 +159,18 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return value;
}
@Override
public boolean equate(TypeValue other) {
if (other instanceof KnownType) {
KnownType knownType = (KnownType) other;
return setValue(knownType);
}
assert other instanceof UnknownType;
mergeUnknowns((UnknownType) other, this);
return true;
}
public boolean setValue(@NotNull KnownType value) {
if (this.value != null) {
// If we have already assigned a value to this unknown,
@@ -186,6 +218,15 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public String toString() {
return type.toString();
}
@Override
public boolean equate(TypeValue other) {
if (other instanceof KnownType) {
KnownType knownType = (KnownType) other;
return TypeUtils.equalTypes(type, knownType.getType());
}
return other.equate(this);
}
}
private final Map<JetType, KnownType> knownTypes = Maps.newHashMap();
@@ -233,25 +274,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
if (aValue instanceof UnknownType) {
UnknownType aUnknown = (UnknownType) aValue;
if (bValue instanceof UnknownType) {
UnknownType bUnknown = (UnknownType) bValue;
mergeUnknowns(aUnknown, bUnknown);
}
else {
if (!aUnknown.setValue((KnownType) bValue)) return false;
}
}
else if (bValue instanceof UnknownType) {
UnknownType bUnknown = (UnknownType) bValue;
if (!bUnknown.setValue((KnownType) aValue)) return false;
}
else {
return TypeUtils.equalTypes(a, b);
}
return true;
return aValue.equate(bValue);
}
@Override
@@ -267,9 +290,15 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
// If some of the types is an unknown, the constraint is already generated, and we should carry on
// If some of the types is an unknown, the constraint must be generated, and we should carry on
// otherwise there can be no solution, and we should fail
return someUnknown(getTypeValueFor(subtype), getTypeValueFor(supertype));
TypeValue subTypeValue = getTypeValueFor(subtype);
TypeValue superTypeValue = getTypeValueFor(supertype);
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
if (someUnknown) {
addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue);
}
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
@@ -17,17 +17,20 @@ public class JetMainDetector {
public static boolean hasMain(List<JetDeclaration> declarations) {
for (JetDeclaration declaration : declarations) {
if (declaration instanceof JetNamedFunction) {
JetNamedFunction function = (JetNamedFunction) declaration;
if ("main".equals(function.getName())) {
List<JetParameter> parameters = function.getValueParameters();
if (parameters.size() == 1) {
JetTypeReference reference = parameters.get(0).getTypeReference();
if (reference != null && reference.getText().equals("Array<String>")) { // TODO correct check
return true;
}
}
}
if (isMain((JetNamedFunction) declaration)) return true;
}
}
return false;
}
public static boolean isMain(JetNamedFunction function) {
if ("main".equals(function.getName())) {
List<JetParameter> parameters = function.getValueParameters();
if (parameters.size() == 1) {
JetTypeReference reference = parameters.get(0).getTypeReference();
if (reference != null && reference.getText().equals("Array<String>")) { // TODO correct check
return true;
}
}
}
return false;