Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion microsoft/typescript-go
Submodule typescript-go updated 3761 files
49 changes: 47 additions & 2 deletions pkg/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ func (n *Node) TemplateLiteralLikeData() *TemplateLiteralLikeBase {
}
func (n *Node) KindString() string { return n.Kind.String() }
func (n *Node) KindValue() int16 { return int16(n.Kind) }
func (n *Node) Decorators() []*Node {
if n.Modifiers() == nil {
return nil
}
return core.Filter(n.Modifiers().Nodes, IsDecorator)
}

type MutableNode Node

Expand Down Expand Up @@ -6300,7 +6306,7 @@ func (node *BinaryExpression) computeSubtreeFacts() SubtreeFacts {
propagateSubtreeFacts(node.Type) |
propagateSubtreeFacts(node.OperatorToken) |
propagateSubtreeFacts(node.Right) |
core.IfElse(node.OperatorToken.Kind == KindInKeyword && IsPrivateIdentifier(node.Left), SubtreeContainsClassFields, SubtreeFactsNone)
core.IfElse(node.OperatorToken.Kind == KindInKeyword && IsPrivateIdentifier(node.Left), SubtreeContainsClassFields|SubtreeContainsPrivateIdentifierInExpression, SubtreeFactsNone)
}

func (node *BinaryExpression) setModifiers(modifiers *ModifierList) { node.modifiers = modifiers }
Expand Down Expand Up @@ -6753,9 +6759,13 @@ func (node *PropertyAccessExpression) Clone(f NodeFactoryCoercible) *Node {
func (node *PropertyAccessExpression) Name() *DeclarationName { return node.name }

func (node *PropertyAccessExpression) computeSubtreeFacts() SubtreeFacts {
privateName := SubtreeFactsNone
if !IsIdentifier(node.name) {
privateName = SubtreeContainsPrivateIdentifierInExpression
}
return propagateSubtreeFacts(node.Expression) |
propagateSubtreeFacts(node.QuestionDotToken) |
propagateSubtreeFacts(node.name)
propagateSubtreeFacts(node.name) | privateName
}

func (node *PropertyAccessExpression) propagateSubtreeFacts() SubtreeFacts {
Expand Down Expand Up @@ -10791,6 +10801,8 @@ type SourceFile struct {
tokenFactory *NodeFactory
declarationMapMu sync.Mutex
declarationMap map[string][]*Node
nameTableOnce sync.Once
nameTable map[string]int
}

func (f *NodeFactory) NewSourceFile(opts SourceFileParseOptions, text string, statements *NodeList, endOfFileToken *TokenNode) *Node {
Expand Down Expand Up @@ -10934,6 +10946,39 @@ func (node *SourceFile) ECMALineMap() []core.TextPos {
return lineMap
}

// GetNameTable returns a map of all names in the file to their positions.
// If the name appears more than once, the value is -1.
func (file *SourceFile) GetNameTable() map[string]int {
file.nameTableOnce.Do(func() {
nameTable := make(map[string]int, file.IdentifierCount)

var walk func(node *Node) bool
walk = func(node *Node) bool {
if IsIdentifier(node) && !isTagName(node) && node.Text() != "" ||
IsStringOrNumericLiteralLike(node) && literalIsName(node) ||
IsPrivateIdentifier(node) {
text := node.Text()
if _, ok := nameTable[text]; ok {
nameTable[text] = -1
} else {
nameTable[text] = node.Pos()
}
}

node.ForEachChild(walk)
jsdocNodes := node.JSDoc(file)
for _, jsdoc := range jsdocNodes {
jsdoc.ForEachChild(walk)
}
return false
}
file.ForEachChild(walk)

file.nameTable = nameTable
})
return file.nameTable
}

func (node *SourceFile) IsBound() bool {
return node.isBound.Load()
}
Expand Down
1 change: 1 addition & 0 deletions pkg/ast/subtreefacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
SubtreeContainsClassFields
SubtreeContainsDecorators
SubtreeContainsIdentifier
SubtreeContainsPrivateIdentifierInExpression

SubtreeFactsComputed // NOTE: This should always be last
SubtreeFactsNone SubtreeFacts = 0
Expand Down
239 changes: 239 additions & 0 deletions pkg/ast/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -3941,3 +3941,242 @@ func IsPotentiallyExecutableNode(node *Node) bool {
}
return IsClassDeclaration(node) || IsEnumDeclaration(node) || IsModuleDeclaration(node)
}

func HasAbstractModifier(node *Node) bool {
return HasSyntacticModifier(node, ModifierFlagsAbstract)
}

func HasAmbientModifier(node *Node) bool {
return HasSyntacticModifier(node, ModifierFlagsAmbient)
}

func NodeCanBeDecorated(useLegacyDecorators bool, node *Node, parent *Node, grandparent *Node) bool {
// private names cannot be used with decorators yet
if useLegacyDecorators && node.Name() != nil && IsPrivateIdentifier(node.Name()) {
return false
}
switch node.Kind {
case KindClassDeclaration:
// class declarations are valid targets
return true
case KindClassExpression:
// class expressions are valid targets for native decorators
return !useLegacyDecorators
case KindPropertyDeclaration:
// property declarations are valid if their parent is a class declaration.
return parent != nil && (useLegacyDecorators && IsClassDeclaration(parent) ||
!useLegacyDecorators && IsClassLike(parent) && !HasAbstractModifier(node) && !HasAmbientModifier(node))
case KindGetAccessor, KindSetAccessor, KindMethodDeclaration:
// if this method has a body and its parent is a class declaration, this is a valid target.
return parent != nil && node.Body() != nil && (useLegacyDecorators && IsClassDeclaration(parent) ||
!useLegacyDecorators && IsClassLike(parent))
case KindParameter:
// TODO(rbuckton): Parameter decorator support for ES decorators must wait until it is standardized
if !useLegacyDecorators {
return false
}
// if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target.
return parent != nil && parent.Body() != nil &&
(parent.Kind == KindConstructor || parent.Kind == KindMethodDeclaration || parent.Kind == KindSetAccessor) &&
GetThisParameter(parent) != node && grandparent != nil && grandparent.Kind == KindClassDeclaration
}

return false
}

func ClassOrConstructorParameterIsDecorated(useLegacyDecorators bool, node *Node) bool {
if nodeIsDecorated(useLegacyDecorators, node, nil, nil) {
return true
}
constructor := GetFirstConstructorWithBody(node)
return constructor != nil && ChildIsDecorated(useLegacyDecorators, constructor, node)
}

func ClassElementOrClassElementParameterIsDecorated(useLegacyDecorators bool, node *Node, parent *Node) bool {
var parameters *NodeList
if IsAccessor(node) {
decls := GetAllAccessorDeclarations(parent.Members(), node)
var firstAccessorWithDecorators *Node
if HasDecorators(decls.FirstAccessor) {
firstAccessorWithDecorators = decls.FirstAccessor
} else if HasDecorators(decls.SecondAccessor) {
firstAccessorWithDecorators = decls.SecondAccessor
}
if firstAccessorWithDecorators == nil || node != firstAccessorWithDecorators {
return false
}
if decls.SetAccessor != nil {
parameters = decls.SetAccessor.Parameters
}
} else if IsMethodDeclaration(node) {
parameters = node.ParameterList()
}
if nodeIsDecorated(useLegacyDecorators, node, parent, nil) {
return true
}
if parameters != nil && len(parameters.Nodes) > 0 {
for _, parameter := range parameters.Nodes {
if IsThisParameter(parameter) {
continue
}
if nodeIsDecorated(useLegacyDecorators, parameter, node, parent) {
return true
}
}
}
return false
}

func nodeIsDecorated(useLegacyDecorators bool, node *Node, parent *Node, grandparent *Node) bool {
return HasDecorators(node) && NodeCanBeDecorated(useLegacyDecorators, node, parent, grandparent)
}

func NodeOrChildIsDecorated(useLegacyDecorators bool, node *Node, parent *Node, grandparent *Node) bool {
return nodeIsDecorated(useLegacyDecorators, node, parent, grandparent) || ChildIsDecorated(useLegacyDecorators, node, parent)
}

func ChildIsDecorated(useLegacyDecorators bool, node *Node, parent *Node) bool {
switch node.Kind {
case KindClassDeclaration, KindClassExpression:
return core.Some(node.Members(), func(m *Node) bool {
return NodeOrChildIsDecorated(useLegacyDecorators, m, node, parent)
})
case KindMethodDeclaration,
KindSetAccessor,
KindConstructor:
return core.Some(node.Parameters(), func(p *Node) bool {
return nodeIsDecorated(useLegacyDecorators, p, node, parent)
})
default:
return false
}
}

type AllAccessorDeclarations struct {
FirstAccessor *AccessorDeclaration
SecondAccessor *AccessorDeclaration
SetAccessor *SetAccessorDeclaration
GetAccessor *GetAccessorDeclaration
}

func GetAllAccessorDeclarationsForDeclaration(accessor *AccessorDeclaration, declarationsOfSymbol []*Node) AllAccessorDeclarations {
var otherKind Kind
if accessor.Kind == KindSetAccessor {
otherKind = KindGetAccessor
} else if accessor.Kind == KindGetAccessor {
otherKind = KindSetAccessor
} else {
panic(fmt.Sprintf("Unexpected node kind %q", accessor.Kind))
}
// otherAccessor := ast.GetDeclarationOfKind(c.getSymbolOfDeclaration(accessor), otherKind)
var otherAccessor *AccessorDeclaration
for _, d := range declarationsOfSymbol {
if d.Kind == otherKind {
otherAccessor = d
break
}
}

var firstAccessor *AccessorDeclaration
var secondAccessor *AccessorDeclaration
if otherAccessor != nil && (otherAccessor.Pos() < accessor.Pos()) {
firstAccessor = otherAccessor
secondAccessor = accessor
} else {
firstAccessor = accessor
secondAccessor = otherAccessor
}

var setAccessor *SetAccessorDeclaration
var getAccessor *GetAccessorDeclaration
if accessor.Kind == KindSetAccessor {
setAccessor = accessor.AsSetAccessorDeclaration()
if otherAccessor != nil {
getAccessor = otherAccessor.AsGetAccessorDeclaration()
}
} else {
getAccessor = accessor.AsGetAccessorDeclaration()
if otherAccessor != nil {
setAccessor = otherAccessor.AsSetAccessorDeclaration()
}
}

return AllAccessorDeclarations{
FirstAccessor: firstAccessor,
SecondAccessor: secondAccessor,
SetAccessor: setAccessor,
GetAccessor: getAccessor,
}
}

func GetAllAccessorDeclarations(parentDeclarations []*Node, accessor *AccessorDeclaration) AllAccessorDeclarations {
if HasDynamicName(accessor) {
// dynamic names can only be match up via checker symbol lookup, just return an object with just this accessor
return GetAllAccessorDeclarationsForDeclaration(accessor, []*Node{accessor})
}

accessorName := GetPropertyNameForPropertyNameNode(accessor.Name())
accessorStatic := IsStatic(accessor)
var matches []*Node
for _, member := range parentDeclarations {
if !IsAccessor(member) || IsStatic(member) != accessorStatic {
continue
}
memberName := GetPropertyNameForPropertyNameNode(member.Name())
if memberName == accessorName {
matches = append(matches, member)
}
}
return GetAllAccessorDeclarationsForDeclaration(accessor, matches)
}

func IsAsyncFunction(node *Node) bool {
switch node.Kind {
case KindFunctionDeclaration, KindFunctionExpression, KindArrowFunction, KindMethodDeclaration:
data := node.BodyData()
return data.Body != nil && data.AsteriskToken == nil && HasSyntacticModifier(node, ModifierFlagsAsync)
}
return false
}

/**
* Gets the most likely element type for a TypeNode. This is not an exhaustive test
* as it assumes a rest argument can only be an array type (either T[], or Array<T>).
*
* @param node The type node.
*
* @internal
*/
func GetRestParameterElementType(node *ParameterDeclarationNode) *Node {
if node == nil {
return node
}
if node.Kind == KindArrayType {
return node.AsArrayTypeNode().ElementType
}
if node.Kind == KindTypeReference && node.AsTypeReferenceNode().TypeArguments != nil {
return core.FirstOrNil(node.AsTypeReferenceNode().TypeArguments.Nodes)
}
return nil
}

func isTagName(node *Node) bool {
return node.Parent != nil && IsJSDocTag(node.Parent) && node.Parent.TagName() == node
}

// We want to store any numbers/strings if they were a name that could be
// related to a declaration. So, if we have 'import x = require("something")'
// then we want 'something' to be in the name table. Similarly, if we have
// "a['propname']" then we want to store "propname" in the name table.
func literalIsName(node *Node) bool {
return IsDeclarationName(node) ||
node.Parent.Kind == KindExternalModuleReference ||
isArgumentOfElementAccessExpression(node) ||
IsLiteralComputedPropertyDeclarationName(node)
}

func isArgumentOfElementAccessExpression(node *Node) bool {
return node != nil && node.Parent != nil &&
node.Parent.Kind == KindElementAccessExpression &&
node.Parent.AsElementAccessExpression().ArgumentExpression == node
}
9 changes: 0 additions & 9 deletions pkg/binder/binder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2648,15 +2648,6 @@ func getOptionalSymbolFlagForNode(node *ast.Node) ast.SymbolFlags {
return core.IfElse(postfixToken != nil && postfixToken.Kind == ast.KindQuestionToken, ast.SymbolFlagsOptional, ast.SymbolFlagsNone)
}

func isAsyncFunction(node *ast.Node) bool {
switch node.Kind {
case ast.KindFunctionDeclaration, ast.KindFunctionExpression, ast.KindArrowFunction, ast.KindMethodDeclaration:
data := node.BodyData()
return data.Body != nil && data.AsteriskToken == nil && ast.HasSyntacticModifier(node, ast.ModifierFlagsAsync)
}
return false
}

func isFunctionSymbol(symbol *ast.Symbol) bool {
d := symbol.ValueDeclaration
if d != nil {
Expand Down
Loading