Add user generic methods (#1849)
This commit is contained in:
1 parent
939e844c03
commit
21d278eba5
160 files changed
+2597
-880
No files matched your search
@@ -237,9 +237,10 @@ class GenericParserImpl {
|
||||
headers.add(makeTerminal(next()));
|
||||
ff(headers);
|
||||
headers.add(parseIdentifier());
|
||||
if (lookahead() == Token.LT) {
|
||||
ff(headers);
|
||||
if (lookahead == Token.LT) {
|
||||
headers.add(parseTypeParameterList(true));
|
||||
ff(headers);
|
||||
headers.add(parseTypeParameterList());
|
||||
}
|
||||
children.add(new Node(NodeType.TYPEALIAS_HEADER, headers));
|
||||
ff(children);
|
||||
@@ -264,7 +265,7 @@ class GenericParserImpl {
|
||||
headers.add(parseIdentifier());
|
||||
if (lookahead() == Token.LT) {
|
||||
ff(headers);
|
||||
headers.add(parseTypeParameterList());
|
||||
headers.add(parseTypeParameterList(true));
|
||||
}
|
||||
if (lookahead() == Token.EXTENDS) {
|
||||
var extend = new ArrayList<Node>();
|
||||
@@ -361,7 +362,7 @@ class GenericParserImpl {
|
||||
children.add(new Node(NodeType.METHOD_HEADER, headers));
|
||||
ff(children);
|
||||
if (lookahead == Token.LT) {
|
||||
children.add(parseTypeParameterList());
|
||||
children.add(parseTypeParameterList(false));
|
||||
ff(children);
|
||||
}
|
||||
children.add(parseParameterList());
|
||||
@@ -533,7 +534,7 @@ class GenericParserImpl {
|
||||
children.add(new Node(NodeType.METHOD_HEADER, headers));
|
||||
ff(children);
|
||||
if (lookahead == Token.LT) {
|
||||
children.add(parseTypeParameterList());
|
||||
children.add(parseTypeParameterList(false));
|
||||
ff(children);
|
||||
}
|
||||
children.add(parseParameterList());
|
||||
@@ -738,12 +739,30 @@ class GenericParserImpl {
|
||||
|
||||
private Node parseUnqualifiedAccessExpr() {
|
||||
var children = new ArrayList<Node>();
|
||||
parseAccess(children);
|
||||
return new Node(NodeType.UNQUALIFIED_ACCESS_EXPR, children);
|
||||
}
|
||||
|
||||
private void parseAccess(List<Node> children) {
|
||||
children.add(parseIdentifier());
|
||||
if (lookahead() == Token.LPAREN && noSemicolonInbetween() && _lookahead.newLinesBetween == 0) {
|
||||
if (lookahead() == Token.DCOLON && noSemicolonInbetween() && _lookahead.newLinesBetween == 0) {
|
||||
children.add(makeTerminal(next()));
|
||||
ff(children);
|
||||
children.add(parseTypeArgumentList());
|
||||
if (lookahead() == Token.LPAREN
|
||||
&& noSemicolonInbetween()
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
ff(children);
|
||||
children.add(parseArgumentList());
|
||||
} else {
|
||||
throw parserError(ErrorMessages.create("unexpectedToken", "("), spanLookahead);
|
||||
}
|
||||
} else if (lookahead() == Token.LPAREN
|
||||
&& noSemicolonInbetween()
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
ff(children);
|
||||
children.add(parseArgumentList());
|
||||
}
|
||||
return new Node(NodeType.UNQUALIFIED_ACCESS_EXPR, children);
|
||||
}
|
||||
|
||||
private Node parseExprAtom(@Nullable String expectation) {
|
||||
@@ -843,11 +862,7 @@ class GenericParserImpl {
|
||||
if (lookahead == Token.DOT) {
|
||||
children.add(makeTerminal(next()));
|
||||
ff(children);
|
||||
children.add(parseIdentifier());
|
||||
if (lookahead() == Token.LPAREN) {
|
||||
ff(children);
|
||||
children.add(parseArgumentList());
|
||||
}
|
||||
parseAccess(children);
|
||||
yield new Node(NodeType.SUPER_ACCESS_EXPR, children);
|
||||
} else {
|
||||
expect(Token.LBRACK, children, "unexpectedToken", "[");
|
||||
@@ -1317,12 +1332,12 @@ class GenericParserImpl {
|
||||
return bodies;
|
||||
}
|
||||
|
||||
private Node parseTypeParameterList() {
|
||||
private Node parseTypeParameterList(boolean allowVarianceModifiers) {
|
||||
var children = new ArrayList<Node>();
|
||||
expect(Token.LT, children, "unexpectedToken", "<");
|
||||
ff(children);
|
||||
var elements = new ArrayList<Node>();
|
||||
parseListOf(Token.GT, elements, this::parseTypeParameter);
|
||||
parseListOf(Token.GT, elements, () -> parseTypeParameter(allowVarianceModifiers));
|
||||
children.add(new Node(NodeType.TYPE_PARAMETER_LIST_ELEMENTS, elements));
|
||||
expect(Token.GT, children, "unexpectedToken2", ",", ">");
|
||||
return new Node(NodeType.TYPE_PARAMETER_LIST, children);
|
||||
@@ -1356,11 +1371,17 @@ class GenericParserImpl {
|
||||
return new Node(NodeType.ARGUMENT_LIST, children);
|
||||
}
|
||||
|
||||
private Node parseTypeParameter() {
|
||||
private Node parseTypeParameter(boolean allowVarianceModifier) {
|
||||
var children = new ArrayList<Node>();
|
||||
if (lookahead == Token.IN) {
|
||||
if (!allowVarianceModifier) {
|
||||
throw parserError("typeParameterVarianceNotAllowed");
|
||||
}
|
||||
children.add(makeTerminal(next()));
|
||||
} else if (lookahead == Token.OUT) {
|
||||
if (!allowVarianceModifier) {
|
||||
throw parserError("typeParameterVarianceNotAllowed");
|
||||
}
|
||||
children.add(makeTerminal(next()));
|
||||
}
|
||||
children.add(parseIdentifier());
|
||||
@@ -1583,6 +1604,7 @@ class GenericParserImpl {
|
||||
case ASSIGN -> NodeType.ASSIGN;
|
||||
case AT -> NodeType.AT;
|
||||
case COLON -> NodeType.COLON;
|
||||
case DCOLON -> NodeType.DCOLON;
|
||||
case COMMA -> NodeType.COMMA;
|
||||
case DOT -> NodeType.DOT;
|
||||
case GT -> NodeType.GT;
|
||||
|
||||
@@ -137,7 +137,12 @@ public final class Lexer {
|
||||
case '}' -> Token.RBRACE;
|
||||
case ',' -> Token.COMMA;
|
||||
case '@' -> Token.AT;
|
||||
case ':' -> Token.COLON;
|
||||
case ':' -> {
|
||||
if (lookahead == ':') {
|
||||
nextChar();
|
||||
yield Token.DCOLON;
|
||||
} else yield Token.COLON;
|
||||
}
|
||||
case '+' -> Token.PLUS;
|
||||
case '%' -> Token.MOD;
|
||||
case '[' -> {
|
||||
|
||||
@@ -365,7 +365,7 @@ final class ParserImpl {
|
||||
var identifier = parseIdentifier();
|
||||
TypeParameterList typePars = null;
|
||||
if (lookahead == Token.LT) {
|
||||
typePars = parseTypeParameterList();
|
||||
typePars = parseTypeParameterList(true);
|
||||
}
|
||||
expect(Token.ASSIGN, "unexpectedToken", "=");
|
||||
var type = parseType();
|
||||
@@ -398,7 +398,7 @@ final class ParserImpl {
|
||||
TypeParameterList typePars = null;
|
||||
var end = name.span();
|
||||
if (lookahead == Token.LT) {
|
||||
typePars = parseTypeParameterList();
|
||||
typePars = parseTypeParameterList(true);
|
||||
end = typePars.span();
|
||||
}
|
||||
children.add(typePars);
|
||||
@@ -500,7 +500,7 @@ final class ParserImpl {
|
||||
children.add(name);
|
||||
TypeParameterList typePars = null;
|
||||
if (lookahead == Token.LT) {
|
||||
typePars = parseTypeParameterList();
|
||||
typePars = parseTypeParameterList(false);
|
||||
}
|
||||
children.add(typePars);
|
||||
var parameterList = parseParameterList();
|
||||
@@ -693,7 +693,7 @@ final class ParserImpl {
|
||||
var identifier = parseIdentifier();
|
||||
TypeParameterList params = null;
|
||||
if (lookahead == Token.LT) {
|
||||
params = parseTypeParameterList();
|
||||
params = parseTypeParameterList(false);
|
||||
}
|
||||
var args = parseParameterList();
|
||||
TypeAnnotation typeAnnotation = null;
|
||||
@@ -831,16 +831,31 @@ final class ParserImpl {
|
||||
case DOT, QDOT -> {
|
||||
var rhs = parseIdentifier();
|
||||
var isNullable = op == Operator.QDOT;
|
||||
TypeArgumentList typeArgumentList = null;
|
||||
if (lookahead == Token.DCOLON
|
||||
&& !precededBySemicolon
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
next();
|
||||
typeArgumentList = parseTypeArgumentList();
|
||||
}
|
||||
ArgumentList argumentList = null;
|
||||
if (lookahead == Token.LPAREN
|
||||
&& !precededBySemicolon
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
argumentList = parseArgumentList();
|
||||
} else if (typeArgumentList != null) {
|
||||
// type args but no args
|
||||
throw new ParserError(ErrorMessages.create("unexpectedToken", "("), spanLookahead);
|
||||
}
|
||||
var lastSpan = argumentList != null ? argumentList.span() : rhs.span();
|
||||
expr =
|
||||
new QualifiedAccessExpr(
|
||||
expr, rhs, isNullable, argumentList, expr.span().endWith(lastSpan));
|
||||
expr,
|
||||
rhs,
|
||||
isNullable,
|
||||
typeArgumentList,
|
||||
argumentList,
|
||||
expr.span().endWith(lastSpan));
|
||||
}
|
||||
default -> {
|
||||
var nextMinPrec = op.isLeftAssoc() ? op.getPrec() + 1 : op.getPrec();
|
||||
@@ -977,13 +992,24 @@ final class ParserImpl {
|
||||
if (lookahead == Token.DOT) {
|
||||
next();
|
||||
var identifier = parseIdentifier();
|
||||
TypeArgumentList typeArgs = null;
|
||||
if (lookahead == Token.DCOLON
|
||||
&& !precededBySemicolon
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
next();
|
||||
typeArgs = parseTypeArgumentList();
|
||||
}
|
||||
if (lookahead == Token.LPAREN
|
||||
&& !precededBySemicolon
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
var args = parseArgumentList();
|
||||
yield new SuperAccessExpr(identifier, args, start.endWith(args.span()));
|
||||
yield new SuperAccessExpr(identifier, typeArgs, args, start.endWith(args.span()));
|
||||
}
|
||||
if (typeArgs != null) {
|
||||
// type args but no args
|
||||
throw new ParserError(ErrorMessages.create("unexpectedToken", "("), spanLookahead);
|
||||
} else {
|
||||
yield new SuperAccessExpr(identifier, null, start.endWith(identifier.span()));
|
||||
yield new SuperAccessExpr(identifier, null, null, start.endWith(identifier.span()));
|
||||
}
|
||||
} else {
|
||||
expect(Token.LBRACK, "unexpectedToken", "[");
|
||||
@@ -1026,14 +1052,25 @@ final class ParserImpl {
|
||||
case STRING_MULTI_START -> parseMultiLineStringLiteralExpr();
|
||||
case IDENTIFIER -> {
|
||||
var identifier = parseIdentifier();
|
||||
TypeArgumentList typeArgs = null;
|
||||
if (lookahead == Token.DCOLON
|
||||
&& !precededBySemicolon
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
next();
|
||||
typeArgs = parseTypeArgumentList();
|
||||
}
|
||||
if (lookahead == Token.LPAREN
|
||||
&& !precededBySemicolon
|
||||
&& _lookahead.newLinesBetween == 0) {
|
||||
var args = parseArgumentList();
|
||||
yield new UnqualifiedAccessExpr(
|
||||
identifier, args, identifier.span().endWith(args.span()));
|
||||
identifier, typeArgs, args, identifier.span().endWith(args.span()));
|
||||
}
|
||||
if (typeArgs != null) {
|
||||
// type args but no args
|
||||
throw new ParserError(ErrorMessages.create("unexpectedToken", "("), spanLookahead);
|
||||
} else {
|
||||
yield new UnqualifiedAccessExpr(identifier, null, identifier.span());
|
||||
yield new UnqualifiedAccessExpr(identifier, null, null, identifier.span());
|
||||
}
|
||||
}
|
||||
case EOF ->
|
||||
@@ -1072,14 +1109,27 @@ final class ParserImpl {
|
||||
if (lookahead == Token.DOT || lookahead == Token.QDOT) {
|
||||
var isNullable = next().token == Token.QDOT;
|
||||
var identifier = parseIdentifier();
|
||||
TypeArgumentList typeArgumentList = null;
|
||||
if (lookahead == Token.DCOLON && !precededBySemicolon && _lookahead.newLinesBetween == 0) {
|
||||
next();
|
||||
typeArgumentList = parseTypeArgumentList();
|
||||
}
|
||||
ArgumentList argumentList = null;
|
||||
if (lookahead == Token.LPAREN && !precededBySemicolon && _lookahead.newLinesBetween == 0) {
|
||||
argumentList = parseArgumentList();
|
||||
} else if (typeArgumentList != null) {
|
||||
// type args but no args
|
||||
throw new ParserError(ErrorMessages.create("unexpectedToken", "("), spanLookahead);
|
||||
}
|
||||
var lastSpan = argumentList != null ? argumentList.span() : identifier.span();
|
||||
var res =
|
||||
new QualifiedAccessExpr(
|
||||
expr, identifier, isNullable, argumentList, expr.span().endWith(lastSpan));
|
||||
expr,
|
||||
identifier,
|
||||
isNullable,
|
||||
typeArgumentList,
|
||||
argumentList,
|
||||
expr.span().endWith(lastSpan));
|
||||
return parseExprRest(res);
|
||||
}
|
||||
// subscript (needs to be in the same line as the expression)
|
||||
@@ -1317,7 +1367,7 @@ final class ParserImpl {
|
||||
var paramList = new ParameterList(params, start.endWith(end));
|
||||
yield new FunctionLiteralExpr(paramList, expr, start.endWith(expr.span()));
|
||||
} else {
|
||||
var exp = new UnqualifiedAccessExpr(identifier, null, identifier.span());
|
||||
var exp = new UnqualifiedAccessExpr(identifier, null, null, identifier.span());
|
||||
yield new ParenthesizedExpr(exp, start.endWith(end));
|
||||
}
|
||||
}
|
||||
@@ -1532,9 +1582,9 @@ final class ParserImpl {
|
||||
return bodies;
|
||||
}
|
||||
|
||||
private TypeParameterList parseTypeParameterList() {
|
||||
private TypeParameterList parseTypeParameterList(boolean allowVarianceModifiers) {
|
||||
var start = expect(Token.LT, "unexpectedToken", "<").span;
|
||||
var pars = parseListOf(Token.COMMA, Token.GT, this::parseTypeParameter);
|
||||
var pars = parseListOf(Token.COMMA, Token.GT, () -> parseTypeParameter(allowVarianceModifiers));
|
||||
var end = expect(Token.GT, "unexpectedToken2", ",", ">").span;
|
||||
return new TypeParameterList(pars, start.endWith(end));
|
||||
}
|
||||
@@ -1556,13 +1606,19 @@ final class ParserImpl {
|
||||
return new ArgumentList(exprs, start.endWith(end));
|
||||
}
|
||||
|
||||
private TypeParameter parseTypeParameter() {
|
||||
private TypeParameter parseTypeParameter(boolean allowVarianceModifier) {
|
||||
TypeParameter.Variance variance = null;
|
||||
var start = spanLookahead;
|
||||
if (lookahead == Token.IN) {
|
||||
if (!allowVarianceModifier) {
|
||||
throw parserError("typeParameterVarianceNotAllowed");
|
||||
}
|
||||
next();
|
||||
variance = TypeParameter.Variance.IN;
|
||||
} else if (lookahead == Token.OUT) {
|
||||
if (!allowVarianceModifier) {
|
||||
throw parserError("typeParameterVarianceNotAllowed");
|
||||
}
|
||||
next();
|
||||
variance = TypeParameter.Variance.OUT;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public enum Token {
|
||||
NOT,
|
||||
QUESTION,
|
||||
COLON,
|
||||
DCOLON,
|
||||
ARROW,
|
||||
EQUAL,
|
||||
NOT_EQUAL,
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.parser.ParserVisitor;
|
||||
import org.pkl.parser.Span;
|
||||
|
||||
public final class ClassMethod extends AbstractNode {
|
||||
public final class ClassMethod extends AbstractNode implements Method {
|
||||
private final int modifiersOffset;
|
||||
private final int nameOffset;
|
||||
private final Span headerSpan;
|
||||
|
||||
@@ -291,8 +291,13 @@ public abstract sealed class Expr extends AbstractNode {
|
||||
|
||||
public static final class UnqualifiedAccessExpr extends Expr {
|
||||
public UnqualifiedAccessExpr(
|
||||
Identifier identifier, @Nullable ArgumentList argumentList, Span span) {
|
||||
super(span, Arrays.asList(identifier, argumentList));
|
||||
Identifier identifier,
|
||||
@Nullable TypeArgumentList typeArgumentList,
|
||||
@Nullable ArgumentList argumentList,
|
||||
Span span) {
|
||||
super(span, Arrays.asList(identifier, typeArgumentList, argumentList));
|
||||
assert typeArgumentList == null || argumentList != null
|
||||
: "UnqualifiedAccessExpr created with typeArgumentList but no argumentList";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -306,8 +311,12 @@ public abstract sealed class Expr extends AbstractNode {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public @Nullable TypeArgumentList getTypeArgumentList() {
|
||||
return (TypeArgumentList) children.get(1);
|
||||
}
|
||||
|
||||
public @Nullable ArgumentList getArgumentList() {
|
||||
return (ArgumentList) children.get(1);
|
||||
return (ArgumentList) children.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,9 +327,12 @@ public abstract sealed class Expr extends AbstractNode {
|
||||
Expr expr,
|
||||
Identifier identifier,
|
||||
boolean isNullable,
|
||||
@Nullable TypeArgumentList typeArgumentList,
|
||||
@Nullable ArgumentList argumentList,
|
||||
Span span) {
|
||||
super(span, Arrays.asList(expr, identifier, argumentList));
|
||||
super(span, Arrays.asList(expr, identifier, typeArgumentList, argumentList));
|
||||
assert typeArgumentList == null || argumentList != null
|
||||
: "QualifiedAccessExpr created with typeArgumentList but no argumentList";
|
||||
this.isNullable = isNullable;
|
||||
}
|
||||
|
||||
@@ -345,14 +357,24 @@ public abstract sealed class Expr extends AbstractNode {
|
||||
return isNullable;
|
||||
}
|
||||
|
||||
public @Nullable TypeArgumentList getTypeArgumentList() {
|
||||
return (TypeArgumentList) children.get(2);
|
||||
}
|
||||
|
||||
public @Nullable ArgumentList getArgumentList() {
|
||||
return (ArgumentList) children.get(2);
|
||||
return (ArgumentList) children.get(3);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SuperAccessExpr extends Expr {
|
||||
public SuperAccessExpr(Identifier identifier, @Nullable ArgumentList argumentList, Span span) {
|
||||
super(span, Arrays.asList(identifier, argumentList));
|
||||
public SuperAccessExpr(
|
||||
Identifier identifier,
|
||||
@Nullable TypeArgumentList typeArgumentList,
|
||||
@Nullable ArgumentList argumentList,
|
||||
Span span) {
|
||||
super(span, Arrays.asList(identifier, typeArgumentList, argumentList));
|
||||
assert typeArgumentList == null || argumentList != null
|
||||
: "SuperAccessExpr created with typeArgumentList but no argumentList";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -366,8 +388,12 @@ public abstract sealed class Expr extends AbstractNode {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public @Nullable TypeArgumentList getTypeArgumentList() {
|
||||
return (TypeArgumentList) children.get(1);
|
||||
}
|
||||
|
||||
public @Nullable ArgumentList getArgumentList() {
|
||||
return (ArgumentList) children.get(1);
|
||||
return (ArgumentList) children.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright © 2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.parser.syntax;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public interface Method {
|
||||
@Nullable Expr getExpr();
|
||||
|
||||
@Nullable TypeAnnotation getTypeAnnotation();
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public abstract sealed class ObjectMember extends AbstractNode {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ObjectMethod extends ObjectMember {
|
||||
public static final class ObjectMethod extends ObjectMember implements Method {
|
||||
private final int identifierOffset;
|
||||
|
||||
public ObjectMethod(List<@Nullable Node> nodes, int identifierOffset, Span span) {
|
||||
|
||||
@@ -52,6 +52,7 @@ public enum NodeType {
|
||||
ASSIGN(NodeKind.TERMINAL),
|
||||
AT(NodeKind.TERMINAL),
|
||||
COLON(NodeKind.TERMINAL),
|
||||
DCOLON(NodeKind.TERMINAL),
|
||||
COMMA(NodeKind.TERMINAL),
|
||||
DOT(NodeKind.TERMINAL),
|
||||
GT(NodeKind.TERMINAL),
|
||||
|
||||
@@ -108,3 +108,6 @@ Documentation comments must be attached to modules, classes, typealiases, method
|
||||
|
||||
wrongShebangPosition=\
|
||||
Shebangs are only allowed at the very beginning of a file.
|
||||
|
||||
typeParameterVarianceNotAllowed=\
|
||||
Variance modifiers may only be applied to type parameters on classes or typealiases.
|
||||
@@ -99,6 +99,8 @@ class ParserComparisonTest {
|
||||
"errors/invalidCharacterEscape.pkl",
|
||||
"errors/invalidCharacterEscape2.pkl",
|
||||
"errors/invalidUnicodeEscape.pkl",
|
||||
"errors/invalidVarianceModifierClassMethod.pkl",
|
||||
"errors/invalidVarianceModifierObjectMethod.pkl",
|
||||
"errors/letExpressionError3.pkl",
|
||||
"errors/unterminatedUnicodeEscape.pkl",
|
||||
"errors/keywordNotAllowedHere1.pkl",
|
||||
|
||||
@@ -507,6 +507,10 @@ class SexpRenderer {
|
||||
buf.append('\n')
|
||||
buf.append(tab)
|
||||
buf.append("(identifier)")
|
||||
if (expr.typeArgumentList !== null) {
|
||||
buf.append('\n')
|
||||
renderTypeArgumentList(expr.typeArgumentList!!)
|
||||
}
|
||||
if (expr.argumentList !== null) {
|
||||
buf.append('\n')
|
||||
renderArgumentList(expr.argumentList!!)
|
||||
@@ -522,6 +526,10 @@ class SexpRenderer {
|
||||
buf.append('\n')
|
||||
buf.append(tab)
|
||||
buf.append("(identifier)")
|
||||
if (expr.typeArgumentList !== null) {
|
||||
buf.append('\n')
|
||||
renderTypeArgumentList(expr.typeArgumentList!!)
|
||||
}
|
||||
if (expr.argumentList !== null) {
|
||||
buf.append('\n')
|
||||
renderArgumentList(expr.argumentList!!)
|
||||
@@ -549,6 +557,10 @@ class SexpRenderer {
|
||||
buf.append('\n')
|
||||
buf.append(tab)
|
||||
buf.append("(identifier)")
|
||||
if (expr.typeArgumentList !== null) {
|
||||
buf.append('\n')
|
||||
renderTypeArgumentList(expr.typeArgumentList!!)
|
||||
}
|
||||
if (expr.argumentList !== null) {
|
||||
buf.append('\n')
|
||||
renderArgumentList(expr.argumentList!!)
|
||||
@@ -958,6 +970,7 @@ class SexpRenderer {
|
||||
buf.append("(identifier)")
|
||||
val tparList = method.typeParameterList
|
||||
if (tparList !== null) {
|
||||
buf.append('\n')
|
||||
renderTypeParameterList(tparList)
|
||||
}
|
||||
buf.append('\n')
|
||||
|
||||
Reference in new issue
Block a user