KT-156 Fix the this<Super> syntax

In progress: super<List> must work, but currently it does not, only super<List<Foo>> works, where Foo is ignored.
This commit is contained in:
Andrey Breslav
2011-10-19 19:24:46 +04:00
parent 84951d2585
commit 79ee5cd606
38 changed files with 742 additions and 486 deletions
@@ -1988,7 +1988,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitThisExpression(JetThisExpression expression, StackValue receiver) {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getThisReference());
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return generateThisOrOuter((ClassDescriptor) descriptor);
}
@@ -51,11 +51,6 @@ public class JavaClassMembersScope implements JetScope {
return null;
}
@Override
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
throw new UnsupportedOperationException();
}
@Override
public ClassifierDescriptor getClassifier(@NotNull String name) {
ClassifierDescriptor classifierDescriptor = classifiers.get(name);
@@ -109,6 +109,7 @@ public interface JetNodeTypes {
JetNodeType LABEL_QUALIFIER = new JetNodeType("LABEL_QUALIFIER", JetContainerNode.class);
JetNodeType THIS_EXPRESSION = new JetNodeType("THIS_EXPRESSION", JetThisExpression.class);
JetNodeType SUPER_EXPRESSION = new JetNodeType("SUPER_EXPRESSION", JetSuperExpression.class);
JetNodeType BINARY_EXPRESSION = new JetNodeType("BINARY_EXPRESSION", JetBinaryExpression.class);
JetNodeType BINARY_WITH_TYPE = new JetNodeType("BINARY_WITH_TYPE", JetBinaryExpressionWithTypeRHS.class);
JetNodeType BINARY_WITH_PATTERN = new JetNodeType("BINARY_WITH_PATTERN", JetIsExpression.class); // TODO:
@@ -159,11 +159,14 @@ public interface Errors {
SimpleDiagnosticFactory EQUALS_MISSING = SimpleDiagnosticFactory.create(ERROR, "No method 'equals(Any?) : Boolean' available");
SimpleDiagnosticFactory ASSIGNMENT_IN_EXPRESSION_CONTEXT = SimpleDiagnosticFactory.create(ERROR, "Assignments are not expressions, and only expressions are allowed in this context");
SimpleDiagnosticFactory NAMESPACE_IS_NOT_AN_EXPRESSION = SimpleDiagnosticFactory.create(ERROR, "'namespace' is not an expression");
SimpleDiagnosticFactory NAMESPACE_IS_NOT_AN_EXPRESSION = SimpleDiagnosticFactory.create(ERROR, "'namespace' is not an expression, it can only be used on the left-hand side of a dot ('.')");
ParameterizedDiagnosticFactory1<String> SUPER_IS_NOT_AN_EXPRESSION = ParameterizedDiagnosticFactory1.create(ERROR, "{0} is not an expression, it can only be used on the left-hand side of a dot ('.')");
SimpleDiagnosticFactory DECLARATION_IN_ILLEGAL_CONTEXT = SimpleDiagnosticFactory.create(ERROR, "Declarations are not allowed in this position");
SimpleDiagnosticFactory REF_SETTER_PARAMETER = SimpleDiagnosticFactory.create(ERROR, "Setter parameters can not be 'ref'");
SimpleDiagnosticFactory SETTER_PARAMETER_WITH_DEFAULT_VALUE = SimpleDiagnosticFactory.create(ERROR, "Setter parameters can not have default values");
SimpleDiagnosticFactory NO_THIS = SimpleDiagnosticFactory.create(ERROR, "'this' is not defined in this context");
SimpleDiagnosticFactory SUPER_NOT_AVAILABLE = SimpleDiagnosticFactory.create(ERROR, "No supertypes are accessible in this context");
SimpleDiagnosticFactory AMBIGUOUS_SUPER = SimpleDiagnosticFactory.create(ERROR, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'");
SimpleDiagnosticFactory NOT_A_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Not a supertype");
SimpleDiagnosticFactory NO_WHEN_ENTRIES = SimpleDiagnosticFactory.create(ERROR, "Entries are required for when-expression"); // TODO : Scope, and maybe this should not be an error
SimplePsiElementOnlyDiagnosticFactory<JetBinaryExpressionWithTypeRHS> USELESS_CAST_STATIC_ASSERT_IS_FINE = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed, use ':' instead");
@@ -49,6 +49,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
LPAR, // tuple
THIS_KEYWORD, // this
SUPER_KEYWORD, // super
IF_KEYWORD, // if
WHEN_KEYWORD, // when
@@ -464,7 +465,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* atomicExpression
* : tupleLiteral // or parenthesized element
* : "this" getEntryPoint? ("<" type ">")?
* : "this" label?
* : "super" ("<" type ">")? label?
* : objectLiteral
* : jump
* : if
@@ -490,6 +492,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
else if (at(THIS_KEYWORD)) {
parseThisExpression();
}
else if (at(SUPER_KEYWORD)) {
parseSuperExpression();
}
else if (at(OBJECT_KEYWORD)) {
parseObjectLiteral();
}
@@ -1593,7 +1598,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* "this" getEntryPoint? ("<" type ">")?
* "this" label?
*/
private void parseThisExpression() {
assert _at(THIS_KEYWORD);
@@ -1605,8 +1610,22 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseLabel();
mark.done(THIS_EXPRESSION);
}
/*
* "this" ("<" type ">")? label?
*/
private void parseSuperExpression() {
assert _at(SUPER_KEYWORD);
PsiBuilder.Marker mark = mark();
PsiBuilder.Marker superReference = mark();
advance(); // SUPER_KEYWORD
superReference.done(REFERENCE_EXPRESSION);
if (at(LT)) {
// This may be "this < foo" or "this<foo>", thus the backtracking
// This may be "super < foo" or "super<foo>", thus the backtracking
PsiBuilder.Marker supertype = mark();
myBuilder.disableNewlines();
@@ -1623,7 +1642,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
myBuilder.restoreNewlinesState();
}
mark.done(THIS_EXPRESSION);
parseLabel();
mark.done(SUPER_EXPRESSION);
}
/*
@@ -0,0 +1,20 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
/**
* @author abreslav
*/
public abstract class JetLabelQualifiedInstanceExpression extends JetLabelQualifiedExpression {
public JetLabelQualifiedInstanceExpression(@NotNull ASTNode node) {
super(node);
}
@NotNull
public JetReferenceExpression getInstanceReference() {
return (JetReferenceExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
}
}
@@ -10,13 +10,14 @@ import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.parsing.JetExpressionParsing;
import org.jetbrains.jet.lexer.JetTokens;
import static org.jetbrains.jet.lexer.JetTokens.*;
/**
* @author max
*/
public class JetSimpleNameExpression extends JetReferenceExpression {
public static final TokenSet REFERENCE_TOKENS = TokenSet.orSet(JetTokens.LABELS, TokenSet.create(JetTokens.IDENTIFIER, JetTokens.FIELD_IDENTIFIER, JetTokens.THIS_KEYWORD));
public static final TokenSet REFERENCE_TOKENS = TokenSet.orSet(LABELS, TokenSet.create(IDENTIFIER, FIELD_IDENTIFIER, THIS_KEYWORD, SUPER_KEYWORD));
public JetSimpleNameExpression(@NotNull ASTNode node) {
super(node);
@@ -0,0 +1,39 @@
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;
/**
* @author max
*/
public class JetSuperExpression extends JetLabelQualifiedInstanceExpression {
public JetSuperExpression(@NotNull ASTNode node) {
super(node);
}
@Override
public void accept(@NotNull JetVisitorVoid visitor) {
visitor.visitSuperExpression(this);
}
@Override
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitSuperExpression(this, data);
}
/**
* class A : B, C {
* override fun foo() {
* super<B>.foo()
* super<C>.foo()
* }
* }
*/
@Nullable
public JetTypeReference getSuperTypeQualifier() {
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
}
}
@@ -2,13 +2,11 @@ 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;
/**
* @author max
*/
public class JetThisExpression extends JetLabelQualifiedExpression {
public class JetThisExpression extends JetLabelQualifiedInstanceExpression {
public JetThisExpression(@NotNull ASTNode node) {
super(node);
@@ -23,23 +21,4 @@ public class JetThisExpression extends JetLabelQualifiedExpression {
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitThisExpression(this, data);
}
/**
* class A : B, C {
* override fun foo() {
* this<B>.foo()
* this<C>.foo()
* }
* }
*/
@Nullable
public JetTypeReference getSuperTypeQualifier() {
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
}
@NotNull
public JetReferenceExpression getThisReference() {
return (JetReferenceExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
}
}
@@ -511,7 +511,15 @@ public class JetTreeVisitor<D> extends JetVisitor<Void, D> {
@Override
public Void visitThisExpression(JetThisExpression expression, D data) {
JetReferenceExpression thisReference = expression.getThisReference();
JetReferenceExpression thisReference = expression.getInstanceReference();
thisReference.accept(this, data);
visitLabelQualifiedExpression(expression, data);
return null;
}
@Override
public Void visitSuperExpression(JetSuperExpression expression, D data) {
JetReferenceExpression thisReference = expression.getInstanceReference();
thisReference.accept(this, data);
JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
if (superTypeQualifier != null) {
@@ -280,6 +280,10 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitLabelQualifiedExpression(expression, data);
}
public R visitSuperExpression(JetSuperExpression expression, D data) {
return visitLabelQualifiedExpression(expression, data);
}
public R visitParenthesizedExpression(JetParenthesizedExpression expression, D data) {
return visitExpression(expression, data);
}
@@ -419,4 +423,5 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
public R visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry, D data) {
return visitStringTemplateEntry(entry, data);
}
}
@@ -278,6 +278,10 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitLabelQualifiedExpression(expression);
}
public void visitSuperExpression(JetSuperExpression expression) {
visitLabelQualifiedExpression(expression);
}
public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
visitExpression(expression);
}
@@ -65,11 +65,6 @@ public abstract class AbstractScopeAdapter implements JetScope {
return getWorkerScope().getPropertyByFieldReference(fieldName);
}
@Override
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
return getWorkerScope().getDeclarationDescriptorForUnqualifiedThis();
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -234,7 +234,7 @@ public class TypeResolver {
}
@Nullable
public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType) {
private ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType) {
ClassifierDescriptor classifierDescriptor = resolveClassWithoutErrorReporting(scope, userType);
if (classifierDescriptor == null) {
@@ -86,7 +86,7 @@ public class DataFlowValueFactory {
}
else if (expression instanceof JetThisExpression) {
JetThisExpression thisExpression = (JetThisExpression) expression;
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, thisExpression.getThisReference());
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, thisExpression.getInstanceReference());
if (declarationDescriptor instanceof CallableDescriptor) {
return Pair.create((Object) ((CallableDescriptor) declarationDescriptor).getReceiverParameter(), true);
}
@@ -3,7 +3,6 @@ package org.jetbrains.jet.lang.resolve.scopes;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.Collection;
@@ -109,21 +108,6 @@ public class ChainedScope implements JetScope {
return null;
}
@Override
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
if (DescriptorUtils.definesItsOwnThis(getContainingDeclaration())) {
return getContainingDeclaration();
}
for (JetScope jetScope : scopeChain) {
DeclarationDescriptor containingDeclaration = jetScope.getContainingDeclaration();
if (DescriptorUtils.definesItsOwnThis(containingDeclaration)) {
return containingDeclaration;
}
}
return null;
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -17,7 +17,7 @@ public interface JetScope {
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
throw new UnsupportedOperationException();
throw new UnsupportedOperationException("Don't take containing declaration of the EMPTY scope");
}
@Override
@@ -51,9 +51,6 @@ public interface JetScope {
@Nullable
PropertyDescriptor getPropertyByFieldReference(@NotNull String fieldName);
@Nullable
DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis();
@NotNull
Collection<DeclarationDescriptor> getAllDescriptors();
@@ -51,11 +51,6 @@ public abstract class JetScopeImpl implements JetScope {
return null;
}
@Override
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
return null;
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -109,12 +109,6 @@ public class SubstitutingScope implements JetScope {
throw new UnsupportedOperationException(); // TODO
}
@Override
@Nullable
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
return workerScope.getDeclarationDescriptorForUnqualifiedThis();
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -1,10 +1,12 @@
package org.jetbrains.jet.lang.resolve.scopes;
import com.google.common.collect.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.util.CommonSuppliers;
@@ -51,14 +53,6 @@ public class WritableScopeImpl extends WritableScopeWithImports {
return ownerDeclarationDescriptor;
}
@Override
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
if (DescriptorUtils.definesItsOwnThis(ownerDeclarationDescriptor)) {
return ownerDeclarationDescriptor;
}
return super.getDeclarationDescriptorForUnqualifiedThis();
}
@Override
public void importScope(@NotNull JetScope imported) {
super.importScope(imported);
@@ -64,11 +64,6 @@ public class ErrorUtils {
return null; // TODO : review
}
@Override
public DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis() {
return ERROR_CLASS; // TODO : review
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -15,8 +15,10 @@ import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
@@ -277,62 +279,101 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetType visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) {
JetType result = null;
ReceiverDescriptor thisReceiver = null;
String labelName = expression.getLabelName();
if (labelName != null) {
thisReceiver = context.labelResolver.resolveThisLabel(expression, context, thisReceiver, labelName);
}
else {
thisReceiver = context.scope.getImplicitReceiver();
DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis();
if (declarationDescriptorForUnqualifiedThis != null) {
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptorForUnqualifiedThis);
}
}
ReceiverDescriptor thisReceiver = resolveToReceiver(expression, context, false);
if (thisReceiver != null) {
if (!thisReceiver.exists()) {
context.trace.report(NO_THIS.on(expression));
}
else {
JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
if (superTypeQualifier != null) {
JetTypeElement superTypeElement = superTypeQualifier.getTypeElement();
// Errors are reported by the parser
if (superTypeElement instanceof JetUserType) {
JetUserType typeElement = (JetUserType) superTypeElement;
ClassifierDescriptor classifierCandidate = context.getTypeResolver().resolveClass(context.scope, typeElement);
if (classifierCandidate instanceof ClassDescriptor) {
ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
JetType thisType = thisReceiver.getType();
Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
for (JetType declaredSupertype : supertypes) {
if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
break;
}
}
if (result == null) {
context.trace.report(NOT_A_SUPERTYPE.on(superTypeElement));
}
}
}
}
else {
result = thisReceiver.getType();
}
if (result != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getThisReference(), result);
}
result = thisReceiver.getType();
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
}
}
return DataFlowUtils.checkType(result, expression, context);
}
@Override
public JetType visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) {
if (!context.namespacesAllowed) {
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
return null;
}
JetType result = null;
ReceiverDescriptor thisReceiver = resolveToReceiver(expression, context, true);
if (thisReceiver == null) return null;
if (!thisReceiver.exists()) {
context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
}
else {
JetType thisType = thisReceiver.getType();
Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
if (superTypeQualifier != null) {
JetType supertype = context.getTypeResolver().resolveType(context.scope, superTypeQualifier);
DeclarationDescriptor classifierCandidate = supertype.getConstructor().getDeclarationDescriptor();
if (classifierCandidate instanceof ClassDescriptor) {
ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
for (JetType declaredSupertype : supertypes) {
if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
break;
}
}
}
if (result == null && !ErrorUtils.isErrorType(supertype)) {
context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
}
}
else {
if (supertypes.size() > 1) {
context.trace.report(AMBIGUOUS_SUPER.on(expression));
}
else {
result = substitutor.substitute(supertypes.iterator().next(), Variance.INVARIANT);
}
}
if (result != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
}
}
return DataFlowUtils.checkType(result, expression, context);
}
@Nullable
private ReceiverDescriptor resolveToReceiver(JetLabelQualifiedInstanceExpression expression, ExpressionTypingContext context, boolean onlyClassReceivers) {
ReceiverDescriptor thisReceiver = null;
String labelName = expression.getLabelName();
if (labelName != null) {
thisReceiver = context.labelResolver.resolveThisLabel(expression.getInstanceReference(), expression.getTargetLabel(), context, thisReceiver, labelName);
}
else {
if (onlyClassReceivers) {
List<ReceiverDescriptor> receivers = Lists.newArrayList();
context.scope.getImplicitReceiversHierarchy(receivers);
for (ReceiverDescriptor receiver : receivers) {
if (receiver instanceof ClassReceiver) {
thisReceiver = receiver;
break;
}
}
}
else {
thisReceiver = context.scope.getImplicitReceiver();
}
if (thisReceiver instanceof ThisReceiverDescriptor) {
context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), ((ThisReceiverDescriptor) thisReceiver).getDeclarationDescriptor());
}
}
return thisReceiver;
}
@Override
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
return context.getServices().getBlockReturnedType(context.scope, expression, CoercionStrategy.NO_COERCION, context);
@@ -65,6 +65,7 @@ import java.util.Map;
public final Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists;
public final LabelResolver labelResolver;
// true for positions on the lhs of a '.', i.e. allows namespace results and 'super'
public final boolean namespacesAllowed;
private CallResolver callResolver;
@@ -106,10 +106,9 @@ public class LabelResolver {
return result;
}
public ReceiverDescriptor resolveThisLabel(JetThisExpression expression, ExpressionTypingContext context, ReceiverDescriptor thisReceiver, String labelName) {
public ReceiverDescriptor resolveThisLabel(JetReferenceExpression thisReference, JetSimpleNameExpression targetLabel, ExpressionTypingContext context, ReceiverDescriptor thisReceiver, String labelName) {
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
int size = declarationsByLabel.size();
final JetSimpleNameExpression targetLabel = expression.getTargetLabel();
assert targetLabel != null;
if (size == 1) {
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
@@ -127,7 +126,7 @@ public class LabelResolver {
PsiElement element = context.trace.get(DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
assert element != null;
context.trace.record(LABEL_TARGET, targetLabel, element);
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
context.trace.record(REFERENCE_TARGET, thisReference, declarationDescriptor);
}
else if (size == 0) {
JetElement element = resolveNamedLabel(labelName, targetLabel, false, context);
@@ -137,7 +136,7 @@ public class LabelResolver {
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiverParameter();
if (thisReceiver.exists()) {
context.trace.record(LABEL_TARGET, targetLabel, element);
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
context.trace.record(REFERENCE_TARGET, thisReference, declarationDescriptor);
}
}
else {
@@ -168,6 +168,7 @@ LONG_TEMPLATE_ENTRY_END=\}
"trait" { return JetTokens.TRAIT_KEYWORD ;}
"throw" { return JetTokens.THROW_KEYWORD ;}
"false" { return JetTokens.FALSE_KEYWORD ;}
"super" { return JetTokens.SUPER_KEYWORD ;}
"when" { return JetTokens.WHEN_KEYWORD ;}
"true" { return JetTokens.TRUE_KEYWORD ;}
"type" { return JetTokens.TYPE_KEYWORD ;}
@@ -36,6 +36,7 @@ public interface JetTokens {
JetKeywordToken TYPE_KEYWORD = JetKeywordToken.keyword("type");
JetKeywordToken CLASS_KEYWORD = JetKeywordToken.keyword("class");
JetKeywordToken THIS_KEYWORD = JetKeywordToken.keyword("this");
JetKeywordToken SUPER_KEYWORD = JetKeywordToken.keyword("super");
JetKeywordToken VAL_KEYWORD = JetKeywordToken.keyword("val");
JetKeywordToken VAR_KEYWORD = JetKeywordToken.keyword("var");
JetKeywordToken FUN_KEYWORD = JetKeywordToken.keyword("fun");
@@ -145,7 +146,7 @@ public interface JetTokens {
JetKeywordToken REF_KEYWORD = JetKeywordToken.softKeyword("ref");
TokenSet KEYWORDS = TokenSet.create(NAMESPACE_KEYWORD, AS_KEYWORD, TYPE_KEYWORD, CLASS_KEYWORD, TRAIT_KEYWORD,
THIS_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, FOR_KEYWORD,
THIS_KEYWORD, SUPER_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, FOR_KEYWORD,
NULL_KEYWORD,
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD,
IN_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD,
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -19,7 +19,7 @@ internal class Example<X, T : Comparable<X>>(protected val x : Foo<X, T>, y : So
class
: modifiers ("class" | "trait") SimpleName
typeParameters?
modifiers ("(" primaryConstructorParameter{","} ")")?
modifiers ("(" functionParameter{","} ")")?
(":" annotations delegationSpecifier{","})?
typeConstraints
(classBody? | enumClassBody)
+4 -3
View File
@@ -16,7 +16,7 @@ h3. Precedence
| |Elvis|{{?:}} |
| |Named checks|{{in}}, {{\!in}}, {{is}}, {{\!is}} |
| |Comparison|{{<}}, {{>}}, {{<=}}, {{>=}} |
| |Equality|{{==}}, {{\!==}}, {{===}}, {{\!===}} |
| |Equality|{{==}}, {{\!==}}|
| |Conjunction|{{&&}}|
| |Disjunction|{{\|\|}}|
| |Arrow|{{\->}}|
@@ -113,7 +113,8 @@ atomicExpression
: literalConstant
: functionLiteral
: tupleLiteral
: "this" label? ("<" type ">")?
: "this" label?
: "super" ("<" type ">")? label?
: if
: when
: try
@@ -184,7 +185,7 @@ comparisonOperation
;
equalityOperation
: "!=" : "==" : "===" : "!=="
: "!=" : "=="
;
assignmentOperator
@@ -0,0 +1,49 @@
namespace example;
trait T {
fun foo() {}
}
open class C() {
fun bar() {}
}
class A<E>() : C(), T {
fun test() {
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>
<!SUPER_IS_NOT_AN_EXPRESSION!>super<T><!>
<!AMBIGUOUS_SUPER!>super<!>.foo()
super<T>.foo()
super<C>.bar()
super<T>@A.foo()
super<C>@A.bar()
super<<!NOT_A_SUPERTYPE!>E<!>>.bar()
super<<!NOT_A_SUPERTYPE!>E<!>>@A.bar()
super<<!NOT_A_SUPERTYPE!>Int<!>>.foo()
super<>.foo()
super<<!NOT_A_SUPERTYPE!>fun() : Unit<!>>.foo()
super<<!NOT_A_SUPERTYPE!>()<!>>.foo()
super<T><!UNRESOLVED_REFERENCE!>@B<!>.foo()
super<C><!UNRESOLVED_REFERENCE!>@B<!>.bar()
}
class B : T {
fun test() {
super<T>.foo();
super<<!NOT_A_SUPERTYPE!>C<!>>.bar()
super<C>@A.bar()
super<T>@A.foo()
super<T>@B.foo()
super<<!NOT_A_SUPERTYPE!>C<!>>@B.foo()
super.foo()
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>
<!SUPER_IS_NOT_AN_EXPRESSION!>super<T><!>
}
}
}
fun foo() {
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>
super.foo()
super<Nothing>.foo()
}
+4 -4
View File
@@ -53,8 +53,8 @@ fun foo() {
this@a
this@@
this<A>
this@<A>
this@a<A>
this@@<A>
super<A>
super<A>@
super<A>@a
super<A>@@
}
+18 -18
View File
@@ -412,9 +412,9 @@ JetFile: Labels.jet
LABEL_REFERENCE
PsiElement(ATAT)('@@')
PsiWhiteSpace('\n\n ')
THIS_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(this)('this')
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
@@ -422,43 +422,43 @@ JetFile: Labels.jet
PsiElement(IDENTIFIER)('A')
PsiElement(GT)('>')
PsiWhiteSpace('\n ')
THIS_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(this)('this')
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
PsiElement(GT)('>')
LABEL_QUALIFIER
LABEL_REFERENCE
PsiElement(AT)('@')
PsiWhiteSpace('\n ')
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
PsiElement(GT)('>')
PsiWhiteSpace('\n ')
THIS_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(this)('this')
LABEL_QUALIFIER
LABEL_REFERENCE
PsiElement(LABEL_IDENTIFIER)('@a')
PsiWhiteSpace('\n ')
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
PsiElement(GT)('>')
PsiWhiteSpace('\n ')
THIS_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(this)('this')
LABEL_QUALIFIER
LABEL_REFERENCE
PsiElement(ATAT)('@@')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
PsiElement(GT)('>')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
+1 -1
View File
@@ -15,7 +15,7 @@ fun a(
a : foo = false,
a : foo = null,
a : foo = this,
a : foo = this<sdf>,
a : foo = super<sdf>,
a : foo = (10),
a : foo = (10, "A", 0xf),
a : foo = Foo(bar),
+2 -2
View File
@@ -280,9 +280,9 @@ JetFile: SimpleExpressions.jet
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
THIS_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(this)('this')
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
+7
View File
@@ -0,0 +1,7 @@
// KT-156 Fix the this<Super> syntax
fun foo() {
super.foo();
super<Int>.foo();
super<>.foo();
super<Int>@label.foo();
}
+88
View File
@@ -0,0 +1,88 @@
JetFile: Super.jet
PsiComment(EOL_COMMENT)('// KT-156 Fix the this<Super> syntax')
PsiWhiteSpace('\n')
NAMESPACE
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiElement(GT)('>')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
PsiErrorElement:Type expected
<empty list>
PsiElement(GT)('>')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiElement(GT)('>')
LABEL_QUALIFIER
LABEL_REFERENCE
PsiElement(LABEL_IDENTIFIER)('@label')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
+26
View File
@@ -0,0 +1,26 @@
~T~trait T {
fun foo() {}
}
~C~open class C() {
fun bar() {}
}
~A~class A<E>() : C(), T {
fun test() {
`T`super<T>.foo()
`C`super<C>.bar()
`T`super<T>@A.foo()
`C`super<C>@A.bar()
}
class B : T {
fun test() {
`T`super<T>.foo();
`C`super<C>@A.bar()
`T`super<T>@A.foo()
`T`super<T>@B.foo()
`T`super.foo()
}
}
}
@@ -310,7 +310,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
public void testThis() throws Exception {
assertType("Derived_T<Int>", "this", "Derived_T<Int>");
assertType("Derived_T<Int>", "this<Base_T>", "Base_T<Int>");
assertType("Derived_T<Int>", "super<Base_T>", "Base_T<Int>");
}
public void testLoops() throws Exception {