Merge branch 'master' of git+ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+23
@@ -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();
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
+3
@@ -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
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -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
-5
@@ -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
|
||||
|
||||
+51
-22
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user