JET-126 Put 'where'-clause after the declaration

This commit is contained in:
Andrey Breslav
2011-07-08 22:44:56 +04:00
parent addfc6a421
commit c2435f0f24
13 changed files with 154 additions and 126 deletions
+5 -1
View File
@@ -21,6 +21,7 @@ class
typeParameters? typeParameters?
("wraps" valueParameters? | modifiers valueParameters?)? ("wraps" valueParameters? | modifiers valueParameters?)?
(":" annotations delegationSpecifier{","})? (":" annotations delegationSpecifier{","})?
typeConstraints
(classBody? | enumClassBody) (classBody? | enumClassBody)
; ;
@@ -40,7 +41,6 @@ explicitDelegation
typeParameters typeParameters
: "<" typeParameter{","} ">" : "<" typeParameter{","} ">"
("where" typeConstraint{","})?
; ;
typeParameter typeParameter
@@ -51,6 +51,10 @@ typeParameter
bq. See [Generic classes|Generics#Generic classes] bq. See [Generic classes|Generics#Generic classes]
*/ */
typeConstraints
: ("where" typeConstraint{","})?
;
typeConstraint typeConstraint
: annotations SimpleName ":" type : annotations SimpleName ":" type
: annotations "class" "object" SimpleName ":" type : annotations "class" "object" SimpleName ":" type
+2
View File
@@ -83,6 +83,7 @@ function
(type "." | annotations/*for receiver type*/)? (type "." | annotations/*for receiver type*/)?
SimpleName SimpleName
typeParameters? valueParameters (":" type)? typeParameters? valueParameters (":" type)?
typeConstraints
functionBody? functionBody?
; ;
@@ -95,6 +96,7 @@ property
: modifiers ("val" | "var") : modifiers ("val" | "var")
typeParameters? (type "." | annotations)? typeParameters? (type "." | annotations)?
SimpleName (":" type)? SimpleName (":" type)?
typeConstraints
("=" expression SEMI?)? ("=" expression SEMI?)?
(getter? setter? | setter? getter?) SEMI? (getter? setter? | setter? getter?) SEMI?
; ;
+1 -1
View File
@@ -9,5 +9,5 @@ enumClassBody
; ;
enumEntry enumEntry
: modifiers SimpleName typeParameters? valueParameters? (":" initializer{","})? classBody? : modifiers SimpleName typeParameters? valueParameters? (":" initializer{","})? typeConstraints classBody?
; ;
+1 -1
View File
@@ -53,5 +53,5 @@ bq. See [Namespaces]
[undocumented] [undocumented]
typedef typedef
: modifiers "type" SimpleName typeParameters? "=" type : modifiers "type" SimpleName (typeParameters typeConstraints)? "=" type
; ;
+2 -2
View File
@@ -36,8 +36,8 @@ pattern
decomposerPattern decomposerPattern
: type : type
// TODO : typeParameters will be consumed by the expression // TODO : typeArguments will be consumed by the expression
: elvisExpression typeParameters? "@" tuplePattern : elvisExpression typeArguments? "@" tuplePattern
; ;
constantPattern constantPattern
@@ -384,6 +384,7 @@ public class JetParsing extends AbstractJetParsing {
* ("wraps" "(" primaryConstructorParameter{","} ")") | * ("wraps" "(" primaryConstructorParameter{","} ")") |
* (modifiers "(" primaryConstructorParameter{","} ")"))? * (modifiers "(" primaryConstructorParameter{","} ")"))?
* (":" attributes delegationSpecifier{","})? * (":" attributes delegationSpecifier{","})?
* typeConstraints
* (classBody? | enumClassBody) * (classBody? | enumClassBody)
* ; * ;
*/ */
@@ -392,7 +393,7 @@ public class JetParsing extends AbstractJetParsing {
advance(); // CLASS_KEYWORD advance(); // CLASS_KEYWORD
expect(IDENTIFIER, "Class name expected", CLASS_NAME_RECOVERY_SET); expect(IDENTIFIER, "Class name expected", CLASS_NAME_RECOVERY_SET);
parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET); boolean typeParametersDeclared = parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET);
if (at(WRAPS_KEYWORD)) { if (at(WRAPS_KEYWORD)) {
advance(); // WRAPS_KEYWORD advance(); // WRAPS_KEYWORD
@@ -414,6 +415,8 @@ public class JetParsing extends AbstractJetParsing {
parseDelegationSpecifierList(); parseDelegationSpecifierList();
} }
parseTypeConstraintsGuarded(typeParametersDeclared);
if (at(LBRACE)) { if (at(LBRACE)) {
if (enumClass) { if (enumClass) {
parseEnumClassBody(); parseEnumClassBody();
@@ -473,7 +476,7 @@ public class JetParsing extends AbstractJetParsing {
/* /*
* enumEntry * enumEntry
* : modifiers SimpleName typeParameters? primaryConstructorParameters? (":" initializer{","})? classBody? * : modifiers SimpleName typeParameters? primaryConstructorParameters? (":" initializer{","})? typeConstraints classBody?
* ; * ;
*/ */
private void parseEnumEntry() { private void parseEnumEntry() {
@@ -483,7 +486,7 @@ public class JetParsing extends AbstractJetParsing {
advance(); // IDENTIFIER advance(); // IDENTIFIER
nameAsDeclaration.done(OBJECT_DECLARATION_NAME); nameAsDeclaration.done(OBJECT_DECLARATION_NAME);
parseTypeParameterList(TokenSet.create(COLON, LPAR, SEMICOLON, LBRACE)); boolean typeParametersDeclared = parseTypeParameterList(TokenSet.create(COLON, LPAR, SEMICOLON, LBRACE));
if (at(LPAR)) { if (at(LPAR)) {
parseValueParameterList(false, TokenSet.create(COLON, SEMICOLON, LBRACE)); parseValueParameterList(false, TokenSet.create(COLON, SEMICOLON, LBRACE));
@@ -495,6 +498,8 @@ public class JetParsing extends AbstractJetParsing {
parseInitializerList(); parseInitializerList();
} }
parseTypeConstraintsGuarded(typeParametersDeclared);
if (at(LBRACE)) { if (at(LBRACE)) {
parseClassBody(); parseClassBody();
} }
@@ -725,7 +730,7 @@ public class JetParsing extends AbstractJetParsing {
/* /*
* typedef * typedef
* : modifiers "type" SimpleName typeParameters? "=" type * : modifiers "type" SimpleName (typeParameters typeConstraints)? "=" type
* ; * ;
*/ */
public JetNodeType parseTypeDef() { public JetNodeType parseTypeDef() {
@@ -735,7 +740,9 @@ public class JetParsing extends AbstractJetParsing {
expect(IDENTIFIER, "Type name expected", TokenSet.orSet(TokenSet.create(LT, EQ, SEMICOLON), TOPLEVEL_OBJECT_FIRST)); expect(IDENTIFIER, "Type name expected", TokenSet.orSet(TokenSet.create(LT, EQ, SEMICOLON), TOPLEVEL_OBJECT_FIRST));
parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET); if (parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET)) {
parseTypeConstraints();
}
expect(EQ, "Expecting '='", TokenSet.orSet(TOPLEVEL_OBJECT_FIRST, TokenSet.create(SEMICOLON))); expect(EQ, "Expecting '='", TokenSet.orSet(TOPLEVEL_OBJECT_FIRST, TokenSet.create(SEMICOLON)));
@@ -751,6 +758,7 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers ("val" | "var") * : modifiers ("val" | "var")
* typeParameters? (type "." | attributes)? * typeParameters? (type "." | attributes)?
* SimpleName (":" type)? * SimpleName (":" type)?
* typeConstraints
* ("=" element SEMI?)? * ("=" element SEMI?)?
* (getter? setter? | setter? getter?) SEMI? * (getter? setter? | setter? getter?) SEMI?
* ; * ;
@@ -766,9 +774,7 @@ public class JetParsing extends AbstractJetParsing {
errorAndAdvance("Expecting 'val' or 'var'"); errorAndAdvance("Expecting 'val' or 'var'");
} }
if (at(LT)) { boolean typeParametersDeclared = at(LT) ? parseTypeParameterList(TokenSet.create(IDENTIFIER, EQ, COLON, SEMICOLON)) : false;
parseTypeParameterList(TokenSet.create(IDENTIFIER, EQ, COLON, SEMICOLON));
}
TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, SEMICOLON); TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, SEMICOLON);
@@ -794,6 +800,8 @@ public class JetParsing extends AbstractJetParsing {
parseTypeRef(); parseTypeRef();
} }
parseTypeConstraintsGuarded(typeParametersDeclared);
if (local) { if (local) {
if (at(EQ)) { if (at(EQ)) {
advance(); // EQ advance(); // EQ
@@ -900,6 +908,7 @@ public class JetParsing extends AbstractJetParsing {
* (type "." | attributes)? * (type "." | attributes)?
* SimpleName * SimpleName
* typeParameters? functionParameters (":" type)? * typeParameters? functionParameters (":" type)?
* typeConstraints
* functionBody? * functionBody?
* ; * ;
*/ */
@@ -934,6 +943,7 @@ public class JetParsing extends AbstractJetParsing {
else { else {
error.drop(); error.drop();
} }
typeParameterListOccurred = true;
} }
parseValueParameterList(false, valueParametersFollow); parseValueParameterList(false, valueParametersFollow);
@@ -944,6 +954,8 @@ public class JetParsing extends AbstractJetParsing {
parseTypeRef(); parseTypeRef();
} }
parseTypeConstraintsGuarded(typeParameterListOccurred);
if (at(SEMICOLON)) { if (at(SEMICOLON)) {
advance(); // SEMICOLON advance(); // SEMICOLON
} }
@@ -1088,11 +1100,11 @@ public class JetParsing extends AbstractJetParsing {
/* /*
* typeParameters * typeParameters
* : ("<" typeParameter{","} ">" * : ("<" typeParameter{","} ">"
* ("where" typeConstraint{","})?)?
* ; * ;
*/ */
private void parseTypeParameterList(TokenSet recoverySet) { private boolean parseTypeParameterList(TokenSet recoverySet) {
PsiBuilder.Marker list = mark(); PsiBuilder.Marker list = mark();
boolean result = false;
if (at(LT)) { if (at(LT)) {
myBuilder.disableNewlines(); myBuilder.disableNewlines();
@@ -1108,12 +1120,34 @@ public class JetParsing extends AbstractJetParsing {
expect(GT, "Missing '>'", recoverySet); expect(GT, "Missing '>'", recoverySet);
myBuilder.restoreNewlinesState(); myBuilder.restoreNewlinesState();
result = true;
if (at(WHERE_KEYWORD)) {
parseTypeConstraintList();
}
} }
list.done(TYPE_PARAMETER_LIST); list.done(TYPE_PARAMETER_LIST);
return result;
}
/*
* typeConstraints
* : ("where" typeConstraint{","})?
* ;
*/
private void parseTypeConstraintsGuarded(boolean typeParameterListOccurred) {
PsiBuilder.Marker error = mark();
boolean constraints = parseTypeConstraints();
if (constraints && !typeParameterListOccurred) {
error.error("Type constraints are not allowed when no type parameters declared");
}
else {
error.drop();
}
}
private boolean parseTypeConstraints() {
if (at(WHERE_KEYWORD)) {
parseTypeConstraintList();
return true;
}
return false;
} }
/* /*
@@ -2,10 +2,8 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.JetNodeTypes;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -20,17 +18,6 @@ public class JetTypeParameterList extends JetElement {
return findChildrenByType(JetNodeTypes.TYPE_PARAMETER); return findChildrenByType(JetNodeTypes.TYPE_PARAMETER);
} }
@Nullable
public JetTypeConstraintList getTypeConstraintList() {
return (JetTypeConstraintList) findChildByType(JetNodeTypes.TYPE_CONSTRAINT_LIST);
}
@NotNull
public List<JetTypeConstraint> getAdditionalConstraints() {
JetTypeConstraintList list = getTypeConstraintList();
return list != null ? list.getConstraints() : Collections.<JetTypeConstraint>emptyList();
}
@Override @Override
public void accept(JetVisitor visitor) { public void accept(JetVisitor visitor) {
visitor.visitTypeParameterList(this); visitor.visitTypeParameterList(this);
@@ -21,13 +21,14 @@ public class JetTypeParameterListOwner extends JetNamedDeclaration {
return (JetTypeParameterList) findChildByType(JetNodeTypes.TYPE_PARAMETER_LIST); return (JetTypeParameterList) findChildByType(JetNodeTypes.TYPE_PARAMETER_LIST);
} }
@Nullable
public JetTypeConstraintList getTypeConstraintList() {
return (JetTypeConstraintList) findChildByType(JetNodeTypes.TYPE_CONSTRAINT_LIST);
}
@NotNull @NotNull
public List<JetTypeConstraint> getTypeConstaints() { public List<JetTypeConstraint> getTypeConstaints() {
JetTypeParameterList typeParameterList = getTypeParameterList(); JetTypeConstraintList typeConstraintList = getTypeConstraintList();
if (typeParameterList == null) {
return Collections.emptyList();
}
JetTypeConstraintList typeConstraintList = typeParameterList.getTypeConstraintList();
if (typeConstraintList == null) { if (typeConstraintList == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
+4 -4
View File
@@ -14,14 +14,14 @@ class D() {
class object : A(), B () {} class object : A(), B () {}
} }
class Test1<T : A> class Test1<T : A>()
where where
T : B, T : B,
<error>B</error> : T, // error <error>B</error> : T, // error
class object T : A, class object T : A,
class object T : B, class object T : B,
class object <error>B</error> : T class object <error>B</error> : T
() { {
fun test(t : T) { fun test(t : T) {
T.foo() T.foo()
@@ -46,14 +46,14 @@ class Buzz<T> where T : <warning>Bar<<error>Int</error>></warning>, T : <error>n
class X<T : <warning>Foo</warning>> class X<T : <warning>Foo</warning>>
class Y<<error>T</error> : <warning>Foo</warning>> where T : <warning>Bar<Foo></warning> class Y<<error>T</error> : <warning>Foo</warning>> where T : <warning>Bar<Foo></warning>
fun <T : A> fun <T : A> test2(t : T)
where where
T : B, T : B,
<error>B</error> : T, <error>B</error> : T,
class object <error>B</error> : T, class object <error>B</error> : T,
class object T : B, class object T : B,
class object T : A class object T : A
test2(t : T) { {
T.foo() T.foo()
T.bar() T.bar()
t.foo() t.foo()
@@ -8,6 +8,6 @@ class MyInt() {
} }
} }
fun toDefault<T: Any> where class object T: Default(t: T) = T.defaultValue() fun toDefault<T: Any>(t: T) where class object T: Default = T.defaultValue()
fun box(): String = if (toDefault<MyInt>(MyInt()) == 610) "OK" else "fail" fun box(): String = if (toDefault<MyInt>(MyInt()) == 610) "OK" else "fail"
+29 -29
View File
@@ -9,36 +9,36 @@ JetFile: TypeConstraints.jet
TYPE_PARAMETER TYPE_PARAMETER
PsiElement(IDENTIFIER)('T') PsiElement(IDENTIFIER)('T')
PsiElement(GT)('>') PsiElement(GT)('>')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiElement(where)('where') PsiElement(where)('where')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
TYPE_CONSTRAINT_LIST TYPE_CONSTRAINT_LIST
TYPE_CONSTRAINT TYPE_CONSTRAINT
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T') PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
TYPE_CONSTRAINT PsiElement(COLON)(':')
PsiElement(class)('class') PsiWhiteSpace(' ')
PsiWhiteSpace(' ') TYPE_REFERENCE
PsiElement(object)('object') USER_TYPE
PsiWhiteSpace(' ') REFERENCE_EXPRESSION
REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('T')
PsiElement(IDENTIFIER)('T') PsiElement(COMMA)(',')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiElement(COLON)(':') TYPE_CONSTRAINT
PsiWhiteSpace(' ') PsiElement(class)('class')
TYPE_REFERENCE PsiWhiteSpace(' ')
USER_TYPE PsiElement(object)('object')
REFERENCE_EXPRESSION PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('T') REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
CLASS_BODY CLASS_BODY
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
@@ -16,9 +16,9 @@ class List<T> {
} }
fun <E, T, R> where fun <E, T, R> Map<E, T>.map(f : fun (E) : R) : T<R> where
T : Iterable<E>, T : Iterable<E>,
class object T : Buildable<E, T> Map<E, T>.map(f : fun (E) : R) : T<R> = { class object T : Buildable<E, T> = {
val builder = T.newBuilder() val builder = T.newBuilder()
for (e in this) { for (e in this) {
builder += f(e) builder += f(e)
@@ -211,59 +211,6 @@ JetFile: PolymorphicClassObjects.jet
TYPE_PARAMETER TYPE_PARAMETER
PsiElement(IDENTIFIER)('R') PsiElement(IDENTIFIER)('R')
PsiElement(GT)('>') PsiElement(GT)('>')
PsiWhiteSpace(' ')
PsiElement(where)('where')
PsiWhiteSpace('\n ')
TYPE_CONSTRAINT_LIST
TYPE_CONSTRAINT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Iterable')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('E')
PsiElement(GT)('>')
PsiElement(COMMA)(',')
PsiWhiteSpace('\n ')
TYPE_CONSTRAINT
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Buildable')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('E')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiElement(GT)('>')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
TYPE_REFERENCE TYPE_REFERENCE
USER_TYPE USER_TYPE
@@ -329,6 +276,59 @@ JetFile: PolymorphicClassObjects.jet
PsiElement(IDENTIFIER)('R') PsiElement(IDENTIFIER)('R')
PsiElement(GT)('>') PsiElement(GT)('>')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiElement(where)('where')
PsiWhiteSpace('\n ')
TYPE_CONSTRAINT_LIST
TYPE_CONSTRAINT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Iterable')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('E')
PsiElement(GT)('>')
PsiElement(COMMA)(',')
PsiWhiteSpace('\n ')
TYPE_CONSTRAINT
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Buildable')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('E')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('T')
PsiElement(GT)('>')
PsiWhiteSpace(' ')
PsiElement(EQ)('=') PsiElement(EQ)('=')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
FUNCTION_LITERAL_EXPRESSION FUNCTION_LITERAL_EXPRESSION