vendor tsgo
This commit is contained in:
717
tools/tsgo/internal/ast/precedence.go
Normal file
717
tools/tsgo/internal/ast/precedence.go
Normal file
@@ -0,0 +1,717 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type OperatorPrecedence int
|
||||
|
||||
const (
|
||||
// Expression:
|
||||
// AssignmentExpression
|
||||
// Expression `,` AssignmentExpression
|
||||
OperatorPrecedenceComma OperatorPrecedence = iota
|
||||
// NOTE: `Spread` is higher than `Comma` due to how it is parsed in |ElementList|
|
||||
// SpreadElement:
|
||||
// `...` AssignmentExpression
|
||||
OperatorPrecedenceSpread
|
||||
// AssignmentExpression:
|
||||
// ConditionalExpression
|
||||
// YieldExpression
|
||||
// ArrowFunction
|
||||
// AsyncArrowFunction
|
||||
// LeftHandSideExpression `=` AssignmentExpression
|
||||
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
//
|
||||
// NOTE: AssignmentExpression is broken down into several precedences due to the requirements
|
||||
// of the parenthesizer rules.
|
||||
// AssignmentExpression: YieldExpression
|
||||
// YieldExpression:
|
||||
// `yield`
|
||||
// `yield` AssignmentExpression
|
||||
// `yield` `*` AssignmentExpression
|
||||
OperatorPrecedenceYield
|
||||
// AssignmentExpression: LeftHandSideExpression `=` AssignmentExpression
|
||||
// AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
// AssignmentOperator: one of
|
||||
// `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=`
|
||||
OperatorPrecedenceAssignment
|
||||
// NOTE: `Conditional` is considered higher than `Assignment` here, but in reality they have
|
||||
// the same precedence.
|
||||
// AssignmentExpression: ConditionalExpression
|
||||
// ConditionalExpression:
|
||||
// ShortCircuitExpression
|
||||
// ShortCircuitExpression `?` AssignmentExpression `:` AssignmentExpression
|
||||
OperatorPrecedenceConditional
|
||||
// LogicalORExpression:
|
||||
// LogicalANDExpression
|
||||
// LogicalORExpression `||` LogicalANDExpression
|
||||
OperatorPrecedenceLogicalOR
|
||||
// LogicalANDExpression:
|
||||
// BitwiseORExpression
|
||||
// LogicalANDExprerssion `&&` BitwiseORExpression
|
||||
OperatorPrecedenceLogicalAND
|
||||
// BitwiseORExpression:
|
||||
// BitwiseXORExpression
|
||||
// BitwiseORExpression `|` BitwiseXORExpression
|
||||
OperatorPrecedenceBitwiseOR
|
||||
// BitwiseXORExpression:
|
||||
// BitwiseANDExpression
|
||||
// BitwiseXORExpression `^` BitwiseANDExpression
|
||||
OperatorPrecedenceBitwiseXOR
|
||||
// BitwiseANDExpression:
|
||||
// EqualityExpression
|
||||
// BitwiseANDExpression `&` EqualityExpression
|
||||
OperatorPrecedenceBitwiseAND
|
||||
// EqualityExpression:
|
||||
// RelationalExpression
|
||||
// EqualityExpression `==` RelationalExpression
|
||||
// EqualityExpression `!=` RelationalExpression
|
||||
// EqualityExpression `===` RelationalExpression
|
||||
// EqualityExpression `!==` RelationalExpression
|
||||
OperatorPrecedenceEquality
|
||||
// RelationalExpression:
|
||||
// ShiftExpression
|
||||
// RelationalExpression `<` ShiftExpression
|
||||
// RelationalExpression `>` ShiftExpression
|
||||
// RelationalExpression `<=` ShiftExpression
|
||||
// RelationalExpression `>=` ShiftExpression
|
||||
// RelationalExpression `instanceof` ShiftExpression
|
||||
// RelationalExpression `in` ShiftExpression
|
||||
// [+TypeScript] RelationalExpression `as` Type
|
||||
OperatorPrecedenceRelational
|
||||
// ShiftExpression:
|
||||
// AdditiveExpression
|
||||
// ShiftExpression `<<` AdditiveExpression
|
||||
// ShiftExpression `>>` AdditiveExpression
|
||||
// ShiftExpression `>>>` AdditiveExpression
|
||||
OperatorPrecedenceShift
|
||||
// AdditiveExpression:
|
||||
// MultiplicativeExpression
|
||||
// AdditiveExpression `+` MultiplicativeExpression
|
||||
// AdditiveExpression `-` MultiplicativeExpression
|
||||
OperatorPrecedenceAdditive
|
||||
// MultiplicativeExpression:
|
||||
// ExponentiationExpression
|
||||
// MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
|
||||
// MultiplicativeOperator: one of `*`, `/`, `%`
|
||||
OperatorPrecedenceMultiplicative
|
||||
// ExponentiationExpression:
|
||||
// UnaryExpression
|
||||
// UpdateExpression `**` ExponentiationExpression
|
||||
OperatorPrecedenceExponentiation
|
||||
// UnaryExpression:
|
||||
// UpdateExpression
|
||||
// `delete` UnaryExpression
|
||||
// `void` UnaryExpression
|
||||
// `typeof` UnaryExpression
|
||||
// `+` UnaryExpression
|
||||
// `-` UnaryExpression
|
||||
// `~` UnaryExpression
|
||||
// `!` UnaryExpression
|
||||
// AwaitExpression
|
||||
// UpdateExpression: // TODO: Do we need to investigate the precedence here?
|
||||
// `++` UnaryExpression
|
||||
// `--` UnaryExpression
|
||||
OperatorPrecedenceUnary
|
||||
// UpdateExpression:
|
||||
// LeftHandSideExpression
|
||||
// LeftHandSideExpression `++`
|
||||
// LeftHandSideExpression `--`
|
||||
OperatorPrecedenceUpdate
|
||||
// LeftHandSideExpression:
|
||||
// NewExpression
|
||||
// NewExpression:
|
||||
// MemberExpression
|
||||
// `new` NewExpression
|
||||
OperatorPrecedenceLeftHandSide
|
||||
// LeftHandSideExpression:
|
||||
// OptionalExpression
|
||||
// OptionalExpression:
|
||||
// MemberExpression OptionalChain
|
||||
// CallExpression OptionalChain
|
||||
// OptionalExpression OptionalChain
|
||||
OperatorPrecedenceOptionalChain
|
||||
// LeftHandSideExpression:
|
||||
// CallExpression
|
||||
// CallExpression:
|
||||
// CoverCallExpressionAndAsyncArrowHead
|
||||
// SuperCall
|
||||
// ImportCall
|
||||
// CallExpression Arguments
|
||||
// CallExpression `[` Expression `]`
|
||||
// CallExpression `.` IdentifierName
|
||||
// CallExpression TemplateLiteral
|
||||
// MemberExpression:
|
||||
// PrimaryExpression
|
||||
// MemberExpression `[` Expression `]`
|
||||
// MemberExpression `.` IdentifierName
|
||||
// MemberExpression TemplateLiteral
|
||||
// SuperProperty
|
||||
// MetaProperty
|
||||
// `new` MemberExpression Arguments
|
||||
OperatorPrecedenceMember
|
||||
// TODO: JSXElement?
|
||||
// PrimaryExpression:
|
||||
// `this`
|
||||
// IdentifierReference
|
||||
// Literal
|
||||
// ArrayLiteral
|
||||
// ObjectLiteral
|
||||
// FunctionExpression
|
||||
// ClassExpression
|
||||
// GeneratorExpression
|
||||
// AsyncFunctionExpression
|
||||
// AsyncGeneratorExpression
|
||||
// RegularExpressionLiteral
|
||||
// TemplateLiteral
|
||||
OperatorPrecedencePrimary
|
||||
// PrimaryExpression:
|
||||
// CoverParenthesizedExpressionAndArrowParameterList
|
||||
OperatorPrecedenceParentheses
|
||||
OperatorPrecedenceLowest = OperatorPrecedenceComma
|
||||
OperatorPrecedenceHighest = OperatorPrecedenceParentheses
|
||||
OperatorPrecedenceDisallowComma = OperatorPrecedenceYield
|
||||
// ShortCircuitExpression:
|
||||
// LogicalORExpression
|
||||
// CoalesceExpression
|
||||
// CoalesceExpression:
|
||||
// CoalesceExpressionHead `??` BitwiseORExpression
|
||||
// CoalesceExpressionHead:
|
||||
// CoalesceExpression
|
||||
// BitwiseORExpression
|
||||
OperatorPrecedenceCoalesce = OperatorPrecedenceLogicalOR
|
||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||
// parsing to stop.
|
||||
OperatorPrecedenceInvalid OperatorPrecedence = -1
|
||||
)
|
||||
|
||||
func getOperator(expression *Expression) Kind {
|
||||
switch expression.Kind {
|
||||
case KindBinaryExpression:
|
||||
return expression.AsBinaryExpression().OperatorToken.Kind
|
||||
case KindPrefixUnaryExpression:
|
||||
return expression.AsPrefixUnaryExpression().Operator
|
||||
case KindPostfixUnaryExpression:
|
||||
return expression.AsPostfixUnaryExpression().Operator
|
||||
default:
|
||||
return expression.Kind
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the precedence of an expression
|
||||
func GetExpressionPrecedence(expression *Expression) OperatorPrecedence {
|
||||
operator := getOperator(expression)
|
||||
var flags OperatorPrecedenceFlags
|
||||
if expression.Kind == KindNewExpression && expression.ArgumentList() == nil {
|
||||
flags = OperatorPrecedenceFlagsNewWithoutArguments
|
||||
} else if IsOptionalChain(expression) {
|
||||
flags = OperatorPrecedenceFlagsOptionalChain
|
||||
}
|
||||
return GetOperatorPrecedence(expression.Kind, operator, flags)
|
||||
}
|
||||
|
||||
type OperatorPrecedenceFlags int
|
||||
|
||||
const (
|
||||
OperatorPrecedenceFlagsNone OperatorPrecedenceFlags = 0
|
||||
OperatorPrecedenceFlagsNewWithoutArguments OperatorPrecedenceFlags = 1 << 0
|
||||
OperatorPrecedenceFlagsOptionalChain OperatorPrecedenceFlags = 1 << 1
|
||||
)
|
||||
|
||||
// Gets the precedence of an operator
|
||||
func GetOperatorPrecedence(nodeKind Kind, operatorKind Kind, flags OperatorPrecedenceFlags) OperatorPrecedence {
|
||||
switch nodeKind {
|
||||
case KindSpreadElement:
|
||||
return OperatorPrecedenceSpread
|
||||
case KindYieldExpression:
|
||||
return OperatorPrecedenceYield
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindArrowFunction:
|
||||
return OperatorPrecedenceAssignment
|
||||
case KindConditionalExpression:
|
||||
return OperatorPrecedenceConditional
|
||||
case KindBinaryExpression:
|
||||
switch operatorKind {
|
||||
case KindCommaToken:
|
||||
return OperatorPrecedenceComma
|
||||
|
||||
case KindEqualsToken,
|
||||
KindPlusEqualsToken,
|
||||
KindMinusEqualsToken,
|
||||
KindAsteriskAsteriskEqualsToken,
|
||||
KindAsteriskEqualsToken,
|
||||
KindSlashEqualsToken,
|
||||
KindPercentEqualsToken,
|
||||
KindLessThanLessThanEqualsToken,
|
||||
KindGreaterThanGreaterThanEqualsToken,
|
||||
KindGreaterThanGreaterThanGreaterThanEqualsToken,
|
||||
KindAmpersandEqualsToken,
|
||||
KindCaretEqualsToken,
|
||||
KindBarEqualsToken,
|
||||
KindBarBarEqualsToken,
|
||||
KindAmpersandAmpersandEqualsToken,
|
||||
KindQuestionQuestionEqualsToken:
|
||||
return OperatorPrecedenceAssignment
|
||||
|
||||
default:
|
||||
return GetBinaryOperatorPrecedence(operatorKind)
|
||||
}
|
||||
// TODO: Should prefix `++` and `--` be moved to the `Update` precedence?
|
||||
case KindTypeAssertionExpression,
|
||||
KindNonNullExpression,
|
||||
KindPrefixUnaryExpression,
|
||||
KindTypeOfExpression,
|
||||
KindVoidExpression,
|
||||
KindDeleteExpression,
|
||||
KindAwaitExpression:
|
||||
return OperatorPrecedenceUnary
|
||||
|
||||
case KindPostfixUnaryExpression:
|
||||
return OperatorPrecedenceUpdate
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindPropertyAccessExpression, KindElementAccessExpression:
|
||||
if flags&OperatorPrecedenceFlagsOptionalChain != 0 {
|
||||
return OperatorPrecedenceOptionalChain
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
case KindCallExpression:
|
||||
if flags&OperatorPrecedenceFlagsOptionalChain != 0 {
|
||||
return OperatorPrecedenceOptionalChain
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindNewExpression:
|
||||
if flags&OperatorPrecedenceFlagsNewWithoutArguments != 0 {
|
||||
return OperatorPrecedenceLeftHandSide
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindTaggedTemplateExpression, KindMetaProperty, KindExpressionWithTypeArguments:
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
case KindAsExpression,
|
||||
KindSatisfiesExpression:
|
||||
return OperatorPrecedenceRelational
|
||||
|
||||
case KindThisKeyword,
|
||||
KindSuperKeyword,
|
||||
KindImportKeyword,
|
||||
KindIdentifier,
|
||||
KindPrivateIdentifier,
|
||||
KindNullKeyword,
|
||||
KindTrueKeyword,
|
||||
KindFalseKeyword,
|
||||
KindNumericLiteral,
|
||||
KindBigIntLiteral,
|
||||
KindStringLiteral,
|
||||
KindArrayLiteralExpression,
|
||||
KindObjectLiteralExpression,
|
||||
KindFunctionExpression,
|
||||
KindClassExpression,
|
||||
KindRegularExpressionLiteral,
|
||||
KindNoSubstitutionTemplateLiteral,
|
||||
KindTemplateExpression,
|
||||
KindOmittedExpression,
|
||||
KindJsxElement,
|
||||
KindJsxSelfClosingElement,
|
||||
KindJsxFragment,
|
||||
KindMissingDeclaration:
|
||||
return OperatorPrecedencePrimary
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to support emit. consider backporting
|
||||
case KindParenthesizedExpression:
|
||||
return OperatorPrecedenceParentheses
|
||||
|
||||
default:
|
||||
return OperatorPrecedenceInvalid
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the precedence of a binary operator
|
||||
func GetBinaryOperatorPrecedence(operatorKind Kind) OperatorPrecedence {
|
||||
switch operatorKind {
|
||||
case KindQuestionQuestionToken:
|
||||
return OperatorPrecedenceCoalesce
|
||||
case KindBarBarToken:
|
||||
return OperatorPrecedenceLogicalOR
|
||||
case KindAmpersandAmpersandToken:
|
||||
return OperatorPrecedenceLogicalAND
|
||||
case KindBarToken:
|
||||
return OperatorPrecedenceBitwiseOR
|
||||
case KindCaretToken:
|
||||
return OperatorPrecedenceBitwiseXOR
|
||||
case KindAmpersandToken:
|
||||
return OperatorPrecedenceBitwiseAND
|
||||
case KindEqualsEqualsToken, KindExclamationEqualsToken, KindEqualsEqualsEqualsToken, KindExclamationEqualsEqualsToken:
|
||||
return OperatorPrecedenceEquality
|
||||
case KindLessThanToken, KindGreaterThanToken, KindLessThanEqualsToken, KindGreaterThanEqualsToken,
|
||||
KindInstanceOfKeyword, KindInKeyword, KindAsKeyword, KindSatisfiesKeyword:
|
||||
return OperatorPrecedenceRelational
|
||||
case KindLessThanLessThanToken, KindGreaterThanGreaterThanToken, KindGreaterThanGreaterThanGreaterThanToken:
|
||||
return OperatorPrecedenceShift
|
||||
case KindPlusToken, KindMinusToken:
|
||||
return OperatorPrecedenceAdditive
|
||||
case KindAsteriskToken, KindSlashToken, KindPercentToken:
|
||||
return OperatorPrecedenceMultiplicative
|
||||
case KindAsteriskAsteriskToken:
|
||||
return OperatorPrecedenceExponentiation
|
||||
}
|
||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||
// parsing to stop.
|
||||
return OperatorPrecedenceInvalid
|
||||
}
|
||||
|
||||
// Gets the leftmost expression of an expression, e.g. `a` in `a.b`, `a[b]`, `a++`, `a+b`, `a?b:c`, `a as B`, etc.
|
||||
func GetLeftmostExpression(node *Expression, stopAtCallExpressions bool) *Expression {
|
||||
for {
|
||||
switch node.Kind {
|
||||
case KindPostfixUnaryExpression:
|
||||
node = node.AsPostfixUnaryExpression().Operand
|
||||
continue
|
||||
case KindBinaryExpression:
|
||||
node = node.AsBinaryExpression().Left
|
||||
continue
|
||||
case KindConditionalExpression:
|
||||
node = node.AsConditionalExpression().Condition
|
||||
continue
|
||||
case KindTaggedTemplateExpression:
|
||||
node = node.AsTaggedTemplateExpression().Tag
|
||||
continue
|
||||
case KindCallExpression:
|
||||
if stopAtCallExpressions {
|
||||
return node
|
||||
}
|
||||
fallthrough
|
||||
case KindAsExpression,
|
||||
KindElementAccessExpression,
|
||||
KindPropertyAccessExpression,
|
||||
KindNonNullExpression,
|
||||
KindPartiallyEmittedExpression,
|
||||
KindSatisfiesExpression:
|
||||
node = node.Expression()
|
||||
continue
|
||||
}
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
type TypePrecedence int32
|
||||
|
||||
const (
|
||||
// Conditional precedence (lowest)
|
||||
//
|
||||
// Type[Extends]:
|
||||
// ConditionalTypeNode[?Extends]
|
||||
//
|
||||
// ConditionalTypeNode[Extends]:
|
||||
// [~Extends] UnionTypeNode `extends` Type[+Extends] `?` Type[~Extends] `:` Type[~Extends]
|
||||
//
|
||||
TypePrecedenceConditional TypePrecedence = iota
|
||||
|
||||
// JSDoc precedence (optional and variadic types)
|
||||
//
|
||||
// JSDocType:
|
||||
// `...`? Type `=`?
|
||||
TypePrecedenceJSDoc
|
||||
|
||||
// Function precedence
|
||||
//
|
||||
// Type[Extends]:
|
||||
// ConditionalTypeNode[?Extends]
|
||||
// FunctionTypeNode[?Extends]
|
||||
// ConstructorTypeNode[?Extends]
|
||||
//
|
||||
// ConditionalTypeNode[Extends]:
|
||||
// UnionTypeNode
|
||||
//
|
||||
// FunctionTypeNode[Extends]:
|
||||
// TypeParameters? ArrowParameters `=>` Type[?Extends]
|
||||
//
|
||||
// ConstructorTypeNode[Extends]:
|
||||
// `abstract`? TypeParameters? ArrowParameters `=>` Type[?Extends]
|
||||
//
|
||||
TypePrecedenceFunction
|
||||
|
||||
// Union precedence
|
||||
//
|
||||
// UnionTypeNode:
|
||||
// `|`? UnionTypeNoBar
|
||||
//
|
||||
// UnionTypeNoBar:
|
||||
// IntersectionTypeNode
|
||||
// UnionTypeNoBar `|` IntersectionTypeNode
|
||||
//
|
||||
TypePrecedenceUnion
|
||||
|
||||
// Intersection precedence
|
||||
//
|
||||
// IntersectionTypeNode:
|
||||
// `&`? IntersectionTypeNoAmpersand
|
||||
//
|
||||
// IntersectionTypeNoAmpersand:
|
||||
// TypeOperatorNode
|
||||
// IntersectionTypeNoAmpersand `&` TypeOperatorNode
|
||||
//
|
||||
TypePrecedenceIntersection
|
||||
|
||||
// TypeOperatorNode precedence
|
||||
//
|
||||
// TypeOperatorNode:
|
||||
// PostfixType
|
||||
// InferTypeNode
|
||||
// `keyof` TypeOperatorNode
|
||||
// `unique` TypeOperatorNode
|
||||
// `readonly` PostfixType
|
||||
//
|
||||
// InferTypeNode:
|
||||
// `infer` BindingIdentifier
|
||||
// `infer` BindingIdentifier `extends` Type[+Extends]
|
||||
//
|
||||
TypePrecedenceTypeOperator
|
||||
|
||||
// Postfix precedence
|
||||
//
|
||||
// PostfixType:
|
||||
// NonArrayType
|
||||
// OptionalTypeNode
|
||||
// ArrayTypeNode
|
||||
// IndexedAccessTypeNode
|
||||
//
|
||||
// OptionalTypeNode:
|
||||
// PostfixType `?`
|
||||
//
|
||||
// ArrayTypeNode:
|
||||
// PostfixType `[` `]`
|
||||
//
|
||||
// IndexedAccessTypeNode:
|
||||
// PostfixType `[` Type[~Extends] `]`
|
||||
//
|
||||
TypePrecedencePostfix
|
||||
|
||||
// NonArray precedence (highest)
|
||||
//
|
||||
// NonArrayType:
|
||||
// KeywordType
|
||||
// LiteralTypeNode
|
||||
// ThisTypeNode
|
||||
// ImportType
|
||||
// TypeQueryNode
|
||||
// MappedTypeNode
|
||||
// TypeLiteralNode
|
||||
// TupleTypeNode
|
||||
// ParenthesizedTypeNode
|
||||
// TypePredicateNode
|
||||
// TypeReferenceNode
|
||||
// TemplateType
|
||||
//
|
||||
// KeywordType: one of
|
||||
// `any` `unknown` `string` `number` `bigint`
|
||||
// `symbol` `boolean` `undefined` `never` `object`
|
||||
// `intrinsic` `void`
|
||||
//
|
||||
// LiteralTypeNode:
|
||||
// StringLiteral
|
||||
// NoSubstitutionTemplateLiteral
|
||||
// NumericLiteral
|
||||
// BigIntLiteral
|
||||
// `-` NumericLiteral
|
||||
// `-` BigIntLiteral
|
||||
// `true`
|
||||
// `false`
|
||||
// `null`
|
||||
//
|
||||
// ThisTypeNode:
|
||||
// `this`
|
||||
//
|
||||
// ImportType:
|
||||
// `typeof`? `import` `(` Type[~Extends] `,`? `)` ImportTypeQualifier? TypeArguments?
|
||||
// `typeof`? `import` `(` Type[~Extends] `,` ImportTypeAttributes `,`? `)` ImportTypeQualifier? TypeArguments?
|
||||
//
|
||||
// ImportTypeQualifier:
|
||||
// `.` EntityName
|
||||
//
|
||||
// ImportTypeAttributes:
|
||||
// `{` `with` `:` ImportAttributes `,`? `}`
|
||||
//
|
||||
// TypeQueryNode:
|
||||
//
|
||||
// MappedTypeNode:
|
||||
// `{` MappedTypePrefix? MappedTypePropertyName MappedTypeSuffix? `:` Type[~Extends] `;` `}`
|
||||
//
|
||||
// MappedTypePrefix:
|
||||
// `readonly`
|
||||
// `+` `readonly`
|
||||
// `-` `readonly`
|
||||
//
|
||||
// MappedTypePropertyName:
|
||||
// `[` BindingIdentifier `in` Type[~Extends] `]`
|
||||
// `[` BindingIdentifier `in` Type[~Extends] `as` Type[~Extends] `]`
|
||||
//
|
||||
// MappedTypeSuffix:
|
||||
// `?`
|
||||
// `+` `?`
|
||||
// `-` `?`
|
||||
//
|
||||
// TypeLiteralNode:
|
||||
// `{` TypeElementList `}`
|
||||
//
|
||||
// TypeElementList:
|
||||
// [empty]
|
||||
// TypeElementList TypeElement
|
||||
//
|
||||
// TypeElement:
|
||||
// PropertySignatureDeclaration
|
||||
// MethodSignatureDeclaration
|
||||
// IndexSignatureDeclaration
|
||||
// CallSignatureDeclaration
|
||||
// ConstructSignatureDeclaration
|
||||
//
|
||||
// PropertySignatureDeclaration:
|
||||
// PropertyName `?`? TypeAnnotation? `;`
|
||||
//
|
||||
// MethodSignatureDeclaration:
|
||||
// PropertyName `?`? TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
// `get` PropertyName TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;` // GetAccessorDeclaration
|
||||
// `set` PropertyName TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;` // SetAccessorDeclaration
|
||||
//
|
||||
// IndexSignatureDeclaration:
|
||||
// `[` IdentifierName`]` TypeAnnotation `;`
|
||||
//
|
||||
// CallSignatureDeclaration:
|
||||
// TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
//
|
||||
// ConstructSignatureDeclaration:
|
||||
// `new` TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
//
|
||||
// TupleTypeNode:
|
||||
// `[` `]`
|
||||
// `[` NamedTupleElementTypes `,`? `]`
|
||||
// `[` TupleElementTypes `,`? `]`
|
||||
//
|
||||
// NamedTupleElementTypes:
|
||||
// NamedTupleMember
|
||||
// NamedTupleElementTypes `,` NamedTupleMember
|
||||
//
|
||||
// NamedTupleMember:
|
||||
// IdentifierName `?`? `:` Type[~Extends]
|
||||
// `...` IdentifierName `:` Type[~Extends]
|
||||
//
|
||||
// TupleElementTypes:
|
||||
// TupleElementType
|
||||
// TupleElementTypes `,` TupleElementType
|
||||
//
|
||||
// TupleElementType:
|
||||
// Type[~Extends]
|
||||
// OptionalTypeNode
|
||||
// RestTypeNode
|
||||
//
|
||||
// RestTypeNode:
|
||||
// `...` Type[~Extends]
|
||||
//
|
||||
// ParenthesizedTypeNode:
|
||||
// `(` Type[~Extends] `)`
|
||||
//
|
||||
// TypePredicateNode:
|
||||
// `asserts`? TypePredicateParameterName
|
||||
// `asserts`? TypePredicateParameterName `is` Type[~Extends]
|
||||
//
|
||||
// TypePredicateParameterName:
|
||||
// `this`
|
||||
// IdentifierReference
|
||||
//
|
||||
// TypeReferenceNode:
|
||||
// EntityName TypeArguments?
|
||||
//
|
||||
// TemplateType:
|
||||
// TemplateHead Type[~Extends] TemplateTypeSpans
|
||||
//
|
||||
// TemplateTypeSpans:
|
||||
// TemplateTail
|
||||
// TemplateTypeMiddleList TemplateTail
|
||||
//
|
||||
// TemplateTypeMiddleList:
|
||||
// TemplateMiddle Type[~Extends]
|
||||
// TemplateTypeMiddleList TemplateMiddle Type[~Extends]
|
||||
//
|
||||
// TypeArguments:
|
||||
// `<` TypeArgumentList `,`? `>`
|
||||
//
|
||||
// TypeArgumentList:
|
||||
// Type[~Extends]
|
||||
// TypeArgumentList `,` Type[~Extends]
|
||||
//
|
||||
TypePrecedenceNonArray
|
||||
|
||||
TypePrecedenceLowest = TypePrecedenceConditional
|
||||
TypePrecedenceHighest = TypePrecedenceNonArray
|
||||
)
|
||||
|
||||
// Gets the precedence of a TypeNode
|
||||
func GetTypeNodePrecedence(n *TypeNode) TypePrecedence {
|
||||
switch n.Kind {
|
||||
case KindConditionalType:
|
||||
return TypePrecedenceConditional
|
||||
case KindJSDocOptionalType, KindJSDocVariadicType:
|
||||
return TypePrecedenceJSDoc
|
||||
case KindFunctionType, KindConstructorType:
|
||||
return TypePrecedenceFunction
|
||||
case KindUnionType:
|
||||
return TypePrecedenceUnion
|
||||
case KindIntersectionType:
|
||||
return TypePrecedenceIntersection
|
||||
case KindTypeOperator:
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindInferType:
|
||||
if n.AsInferTypeNode().TypeParameter.AsTypeParameterDeclaration().Constraint != nil {
|
||||
// `infer T extends U` must be treated as FunctionTypeNode precedence as the `extends` clause eagerly consumes
|
||||
// TypeNode
|
||||
return TypePrecedenceFunction
|
||||
}
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindIndexedAccessType, KindArrayType, KindOptionalType:
|
||||
return TypePrecedencePostfix
|
||||
case KindTypeQuery:
|
||||
// TypeQueryNode is actually a NonArrayType, but we treat it as TypeOperatorNode
|
||||
// precedence so that it is parenthesized when used in a PostfixType
|
||||
// context (e.g., `(typeof C)[]` instead of `typeof C[]`)
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindAnyKeyword,
|
||||
KindUnknownKeyword,
|
||||
KindStringKeyword,
|
||||
KindNumberKeyword,
|
||||
KindBigIntKeyword,
|
||||
KindSymbolKeyword,
|
||||
KindBooleanKeyword,
|
||||
KindUndefinedKeyword,
|
||||
KindNeverKeyword,
|
||||
KindObjectKeyword,
|
||||
KindIntrinsicKeyword,
|
||||
KindVoidKeyword,
|
||||
KindJSDocAllType,
|
||||
KindJSDocNullableType,
|
||||
KindJSDocNonNullableType,
|
||||
KindLiteralType,
|
||||
KindTypePredicate,
|
||||
KindTypeReference,
|
||||
KindTypeLiteral,
|
||||
KindTupleType,
|
||||
KindRestType,
|
||||
KindParenthesizedType,
|
||||
KindThisType,
|
||||
KindMappedType,
|
||||
KindNamedTupleMember,
|
||||
KindTemplateLiteralType,
|
||||
KindImportType,
|
||||
// These occur in pseudo-types like `f<T>.C`, where `f` is a generic function and `C` is a local type
|
||||
KindPropertyAccessExpression,
|
||||
KindExpressionWithTypeArguments:
|
||||
return TypePrecedenceNonArray
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled TypeNode: %v", n.Kind))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user