diff --git a/tools/scripts/tsc/ast.json b/tools/scripts/tsc/ast.json index a133915a10665..cd155f30cb845 100644 --- a/tools/scripts/tsc/ast.json +++ b/tools/scripts/tsc/ast.json @@ -1743,7 +1743,8 @@ "type": "BindingElement", "list": "NodeList" } - ] + ], + "arena": true }, "ParameterDeclaration": { "kind": "Parameter", @@ -1816,7 +1817,8 @@ "type": "Expression", "optional": true } - ] + ], + "arena": true }, "MissingDeclaration": { "extends": [ @@ -2141,7 +2143,8 @@ "type": "ImportAttributes", "optional": true } - ] + ], + "arena": true }, "ExternalModuleReference": { "generateSubtreeFacts": true, @@ -2182,7 +2185,8 @@ "type": "ImportSpecifier", "list": "NodeList" } - ] + ], + "arena": true }, "ExportAssignment": { "extends": [ @@ -2577,7 +2581,8 @@ "optional": true, "visit": "functionBody" } - ] + ], + "arena": true }, "PropertySignatureDeclaration": { "kind": "PropertySignature", @@ -2643,7 +2648,8 @@ "type": "Expression", "optional": true } - ] + ], + "arena": true }, "SemicolonClassElement": { "extends": [ @@ -2930,7 +2936,8 @@ "type": "ConciseBody", "visit": "functionBody" } - ] + ], + "arena": true }, "FunctionExpression": { "extends": [ @@ -3001,7 +3008,8 @@ "name": "Type", "type": "TypeNode" } - ] + ], + "arena": true }, "SatisfiesExpression": { "extends": [ @@ -3229,7 +3237,8 @@ "type": "TemplateSpan", "list": "NodeList" } - ] + ], + "arena": true }, "TemplateSpan": { "generateSubtreeFacts": true, @@ -3245,7 +3254,8 @@ "name": "Literal", "type": "TemplateMiddleOrTail" } - ] + ], + "arena": true }, "TaggedTemplateExpression": { "extends": [ @@ -3307,7 +3317,8 @@ "name": "MultiLine", "type": "bool" } - ] + ], + "arena": true }, "ObjectLiteralExpression": { "generateSubtreeFacts": true, @@ -3326,7 +3337,8 @@ "name": "MultiLine", "type": "bool" } - ] + ], + "arena": true }, "SpreadAssignment": { "extends": [ @@ -3408,7 +3420,8 @@ "type": "Expression", "optional": true } - ] + ], + "arena": true }, "DeleteExpression": { "generateSubtreeFacts": true, @@ -3432,7 +3445,8 @@ "name": "Expression", "type": "Expression" } - ] + ], + "arena": true }, "VoidExpression": { "generateSubtreeFacts": true, @@ -3455,7 +3469,8 @@ "name": "Expression", "type": "Expression" } - ] + ], + "arena": true }, "TypeAssertion": { "kind": "TypeAssertionExpression", @@ -3542,7 +3557,8 @@ "name": "FalseType", "type": "TypeNode" } - ] + ], + "arena": true }, "TypeOperatorNode": { "kind": "TypeOperator", @@ -3575,7 +3591,8 @@ "name": "TypeParameter", "type": "TypeParameterDeclaration" } - ] + ], + "arena": true }, "ArrayTypeNode": { "kind": "ArrayType", @@ -3660,7 +3677,8 @@ "kind": "ThisType", "extends": [ "TypeNodeBase" - ] + ], + "arena": true }, "TypePredicateNode": { "kind": "TypePredicate", @@ -3741,7 +3759,8 @@ "name": "TypeArguments", "inherited": true } - ] + ], + "arena": true }, "MappedTypeNode": { "kind": "MappedType", @@ -3819,7 +3838,8 @@ "type": "TypeNode", "list": "NodeList" } - ] + ], + "arena": true }, "NamedTupleMember": { "extends": [ @@ -3870,7 +3890,8 @@ "name": "Type", "type": "TypeNode" } - ] + ], + "arena": true }, "ParenthesizedTypeNode": { "kind": "ParenthesizedType", @@ -3949,7 +3970,8 @@ "inherited": true, "bitmask": "TokenFlagsTemplateLiteralLikeFlags" } - ] + ], + "arena": true }, "TemplateMiddle": { "extends": [ @@ -3970,7 +3992,8 @@ "inherited": true, "bitmask": "TokenFlagsTemplateLiteralLikeFlags" } - ] + ], + "arena": true }, "TemplateTail": { "extends": [ @@ -3991,7 +4014,8 @@ "inherited": true, "bitmask": "TokenFlagsTemplateLiteralLikeFlags" } - ] + ], + "arena": true }, "TemplateLiteralTypeNode": { "kind": "TemplateLiteralType", @@ -4008,7 +4032,8 @@ "type": "TemplateLiteralTypeSpan", "list": "NodeList" } - ] + ], + "arena": true }, "TemplateLiteralTypeSpan": { "extends": [ @@ -4023,7 +4048,8 @@ "name": "Literal", "type": "TemplateMiddleOrTail" } - ] + ], + "arena": true }, "SyntheticExpression": { "extends": [ @@ -4916,7 +4942,8 @@ "name": "TypeArguments", "inherited": true } - ] + ], + "arena": true }, "ImportClause": { "extends": [ @@ -4942,7 +4969,8 @@ "type": "NamedImportBindings", "optional": true } - ] + ], + "arena": true }, "ImportSpecifier": { "extends": [ diff --git a/tsc/internal/ast/ast_generated.go b/tsc/internal/ast/ast_generated.go index 58aef6d7bc11c..17f2d3520c566 100644 --- a/tsc/internal/ast/ast_generated.go +++ b/tsc/internal/ast/ast_generated.go @@ -20,11 +20,18 @@ var ( type NodeFactory struct { hooks NodeFactoryHooks + arrayLiteralExpressionArena core.Arena[ArrayLiteralExpression] arrayTypeNodeArena core.Arena[ArrayTypeNode] + arrowFunctionArena core.Arena[ArrowFunction] + asExpressionArena core.Arena[AsExpression] + awaitExpressionArena core.Arena[AwaitExpression] binaryExpressionArena core.Arena[BinaryExpression] + bindingElementArena core.Arena[BindingElement] + bindingPatternArena core.Arena[BindingPattern] blockArena core.Arena[Block] callExpressionArena core.Arena[CallExpression] conditionalExpressionArena core.Arena[ConditionalExpression] + conditionalTypeNodeArena core.Arena[ConditionalTypeNode] constructSignatureDeclarationArena core.Arena[ConstructSignatureDeclaration] elementAccessExpressionArena core.Arena[ElementAccessExpression] expressionStatementArena core.Arena[ExpressionStatement] @@ -34,8 +41,12 @@ type NodeFactory struct { heritageClauseArena core.Arena[HeritageClause] identifierArena core.Arena[Identifier] ifStatementArena core.Arena[IfStatement] + importClauseArena core.Arena[ImportClause] + importDeclarationArena core.Arena[ImportDeclaration] importSpecifierArena core.Arena[ImportSpecifier] + importTypeNodeArena core.Arena[ImportTypeNode] indexedAccessTypeNodeArena core.Arena[IndexedAccessTypeNode] + inferTypeNodeArena core.Arena[InferTypeNode] interfaceDeclarationArena core.Arena[InterfaceDeclaration] intersectionTypeNodeArena core.Arena[IntersectionTypeNode] jsdocArena core.Arena[JSDoc] @@ -45,24 +56,41 @@ type NodeFactory struct { keywordExpressionArena core.Arena[KeywordExpression] keywordTypeNodeArena core.Arena[KeywordTypeNode] literalTypeNodeArena core.Arena[LiteralTypeNode] + methodDeclarationArena core.Arena[MethodDeclaration] methodSignatureDeclarationArena core.Arena[MethodSignatureDeclaration] modifierListArena core.Arena[ModifierList] + namedImportsArena core.Arena[NamedImports] nodeListArena core.Arena[NodeList] numericLiteralArena core.Arena[NumericLiteral] + objectLiteralExpressionArena core.Arena[ObjectLiteralExpression] parameterDeclarationArena core.Arena[ParameterDeclaration] parenthesizedExpressionArena core.Arena[ParenthesizedExpression] parenthesizedTypeNodeArena core.Arena[ParenthesizedTypeNode] prefixUnaryExpressionArena core.Arena[PrefixUnaryExpression] propertyAccessExpressionArena core.Arena[PropertyAccessExpression] propertyAssignmentArena core.Arena[PropertyAssignment] + propertyDeclarationArena core.Arena[PropertyDeclaration] propertySignatureDeclarationArena core.Arena[PropertySignatureDeclaration] + restTypeNodeArena core.Arena[RestTypeNode] returnStatementArena core.Arena[ReturnStatement] + shorthandPropertyAssignmentArena core.Arena[ShorthandPropertyAssignment] stringLiteralArena core.Arena[StringLiteral] + templateExpressionArena core.Arena[TemplateExpression] + templateHeadArena core.Arena[TemplateHead] + templateLiteralTypeNodeArena core.Arena[TemplateLiteralTypeNode] + templateLiteralTypeSpanArena core.Arena[TemplateLiteralTypeSpan] + templateMiddleArena core.Arena[TemplateMiddle] + templateSpanArena core.Arena[TemplateSpan] + templateTailArena core.Arena[TemplateTail] + thisTypeNodeArena core.Arena[ThisTypeNode] tokenArena core.Arena[Token] + tupleTypeNodeArena core.Arena[TupleTypeNode] typeAliasDeclarationArena core.Arena[TypeAliasDeclaration] typeLiteralNodeArena core.Arena[TypeLiteralNode] + typeOfExpressionArena core.Arena[TypeOfExpression] typeOperatorNodeArena core.Arena[TypeOperatorNode] typeParameterDeclarationArena core.Arena[TypeParameterDeclaration] + typeQueryNodeArena core.Arena[TypeQueryNode] typeReferenceNodeArena core.Arena[TypeReferenceNode] unionTypeNodeArena core.Arena[UnionTypeNode] variableDeclarationArena core.Arena[VariableDeclaration] @@ -622,13 +650,13 @@ func (f *NodeFactory) NewToken(kind TokenSyntaxKind) *Node { data := &NoSubstitutionTemplateLiteral{} return f.newNode(kind, data.AsNode()) case KindTemplateHead: - data := &TemplateHead{} + data := f.templateHeadArena.New() return f.newNode(kind, data.AsNode()) case KindTemplateMiddle: - data := &TemplateMiddle{} + data := f.templateMiddleArena.New() return f.newNode(kind, data.AsNode()) case KindTemplateTail: - data := &TemplateTail{} + data := f.templateTailArena.New() return f.newNode(kind, data.AsNode()) case KindIdentifier: data := f.identifierArena.New() @@ -1858,7 +1886,7 @@ func (f *NodeFactory) NewBindingPattern(kind Kind, elements *BindingElementList) default: panic("Invalid node kind for BindingPattern") } - data := &BindingPattern{} + data := f.bindingPatternArena.New() data.Elements = elements return f.newNode(kind, data.AsNode()) } @@ -1966,7 +1994,7 @@ type BindingElement struct { } func (f *NodeFactory) NewBindingElement(dotDotDotToken *DotDotDotToken, propertyName *PropertyName, name *BindingName, initializer *Expression) *Node { - data := &BindingElement{} + data := f.bindingElementArena.New() data.DotDotDotToken = dotDotDotToken data.PropertyName = propertyName data.name = name @@ -2584,7 +2612,7 @@ type ImportDeclaration struct { } func (f *NodeFactory) NewImportDeclaration(modifiers *ModifierList, importClause *ImportClauseNode, moduleSpecifier *Expression, attributes *ImportAttributesNode) *Node { - data := &ImportDeclaration{} + data := f.importDeclarationArena.New() data.modifiers = modifiers data.ImportClause = importClause data.ModuleSpecifier = moduleSpecifier @@ -2593,7 +2621,7 @@ func (f *NodeFactory) NewImportDeclaration(modifiers *ModifierList, importClause } func (f *NodeFactory) NewJSImportDeclaration(modifiers *ModifierList, importClause *ImportClauseNode, moduleSpecifier *Expression, attributes *ImportAttributesNode) *Node { - data := &ImportDeclaration{} + data := f.importDeclarationArena.New() data.modifiers = modifiers data.ImportClause = importClause data.ModuleSpecifier = moduleSpecifier @@ -2753,7 +2781,7 @@ type NamedImports struct { } func (f *NodeFactory) NewNamedImports(elements *ImportSpecifierList) *Node { - data := &NamedImports{} + data := f.namedImportsArena.New() data.Elements = elements return f.newNode(KindNamedImports, data.AsNode()) } @@ -3378,7 +3406,7 @@ type MethodDeclaration struct { } func (f *NodeFactory) NewMethodDeclaration(modifiers *ModifierList, asteriskToken *AsteriskToken, name *PropertyName, postfixToken *TokenNode, typeParameters *TypeParameterList, parameters *ParameterList, typeNode *TypeNode, fullSignature *TypeNode, body *FunctionBody) *Node { - data := &MethodDeclaration{} + data := f.methodDeclarationArena.New() data.modifiers = modifiers data.AsteriskToken = asteriskToken data.name = name @@ -3496,7 +3524,7 @@ type PropertyDeclaration struct { } func (f *NodeFactory) NewPropertyDeclaration(modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, typeNode *TypeNode, initializer *Expression) *Node { - data := &PropertyDeclaration{} + data := f.propertyDeclarationArena.New() data.modifiers = modifiers data.name = name data.PostfixToken = postfixToken @@ -3973,7 +4001,7 @@ type ArrowFunction struct { } func (f *NodeFactory) NewArrowFunction(modifiers *ModifierList, typeParameters *TypeParameterList, parameters *ParameterList, typeNode *TypeNode, fullSignature *TypeNode, equalsGreaterThanToken *EqualsGreaterThanToken, body *ConciseBody) *Node { - data := &ArrowFunction{} + data := f.arrowFunctionArena.New() data.modifiers = modifiers data.TypeParameters = typeParameters data.Parameters = parameters @@ -4086,7 +4114,7 @@ type AsExpression struct { } func (f *NodeFactory) NewAsExpression(expression *Expression, typeNode *TypeNode) *Node { - data := &AsExpression{} + data := f.asExpressionArena.New() data.Expression = expression data.Type = typeNode return f.newNode(KindAsExpression, data.AsNode()) @@ -4546,7 +4574,7 @@ type TemplateExpression struct { } func (f *NodeFactory) NewTemplateExpression(head *TemplateHeadNode, templateSpans *TemplateSpanList) *Node { - data := &TemplateExpression{} + data := f.templateExpressionArena.New() data.Head = head data.TemplateSpans = templateSpans return f.newNode(KindTemplateExpression, data.AsNode()) @@ -4591,7 +4619,7 @@ type TemplateSpan struct { } func (f *NodeFactory) NewTemplateSpan(expression *Expression, literal *TemplateMiddleOrTail) *Node { - data := &TemplateSpan{} + data := f.templateSpanArena.New() data.Expression = expression data.Literal = literal return f.newNode(KindTemplateSpan, data.AsNode()) @@ -4729,7 +4757,7 @@ type ArrayLiteralExpression struct { } func (f *NodeFactory) NewArrayLiteralExpression(elements *ElementList, multiLine bool) *Node { - data := &ArrayLiteralExpression{} + data := f.arrayLiteralExpressionArena.New() data.Elements = elements data.MultiLine = multiLine return f.newNode(KindArrayLiteralExpression, data.AsNode()) @@ -4775,7 +4803,7 @@ type ObjectLiteralExpression struct { } func (f *NodeFactory) NewObjectLiteralExpression(properties *NodeList, multiLine bool) *Node { - data := &ObjectLiteralExpression{} + data := f.objectLiteralExpressionArena.New() data.Properties = properties data.MultiLine = multiLine return f.newNode(KindObjectLiteralExpression, data.AsNode()) @@ -4919,7 +4947,7 @@ type ShorthandPropertyAssignment struct { } func (f *NodeFactory) NewShorthandPropertyAssignment(modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, typeNode *TypeNode, equalsToken *EqualsToken, objectAssignmentInitializer *Expression) *Node { - data := &ShorthandPropertyAssignment{} + data := f.shorthandPropertyAssignmentArena.New() data.modifiers = modifiers data.name = name data.PostfixToken = postfixToken @@ -5013,7 +5041,7 @@ type TypeOfExpression struct { } func (f *NodeFactory) NewTypeOfExpression(expression *Expression) *Node { - data := &TypeOfExpression{} + data := f.typeOfExpressionArena.New() data.Expression = expression return f.newNode(KindTypeOfExpression, data.AsNode()) } @@ -5097,7 +5125,7 @@ type AwaitExpression struct { } func (f *NodeFactory) NewAwaitExpression(expression *Expression) *Node { - data := &AwaitExpression{} + data := f.awaitExpressionArena.New() data.Expression = expression return f.newNode(KindAwaitExpression, data.AsNode()) } @@ -5283,7 +5311,7 @@ type ConditionalTypeNode struct { } func (f *NodeFactory) NewConditionalTypeNode(checkType *TypeNode, extendsType *TypeNode, trueType *TypeNode, falseType *TypeNode) *Node { - data := &ConditionalTypeNode{} + data := f.conditionalTypeNodeArena.New() data.CheckType = checkType data.ExtendsType = extendsType data.TrueType = trueType @@ -5367,7 +5395,7 @@ type InferTypeNode struct { } func (f *NodeFactory) NewInferTypeNode(typeParameter *TypeParameterDeclarationNode) *Node { - data := &InferTypeNode{} + data := f.inferTypeNodeArena.New() data.TypeParameter = typeParameter return f.newNode(KindInferType, data.AsNode()) } @@ -5600,7 +5628,7 @@ type ThisTypeNode struct { } func (f *NodeFactory) NewThisTypeNode() *Node { - data := &ThisTypeNode{} + data := f.thisTypeNodeArena.New() return f.newNode(KindThisType, data.AsNode()) } @@ -5761,7 +5789,7 @@ type TypeQueryNode struct { } func (f *NodeFactory) NewTypeQueryNode(exprName *EntityName, typeArguments *TypeList) *Node { - data := &TypeQueryNode{} + data := f.typeQueryNodeArena.New() data.ExprName = exprName data.TypeArguments = typeArguments return f.newNode(KindTypeQuery, data.AsNode()) @@ -5894,7 +5922,7 @@ type TupleTypeNode struct { } func (f *NodeFactory) NewTupleTypeNode(elements *TypeList) *Node { - data := &TupleTypeNode{} + data := f.tupleTypeNodeArena.New() data.Elements = elements return f.newNode(KindTupleType, data.AsNode()) } @@ -6022,7 +6050,7 @@ type RestTypeNode struct { } func (f *NodeFactory) NewRestTypeNode(typeNode *TypeNode) *Node { - data := &RestTypeNode{} + data := f.restTypeNodeArena.New() data.Type = typeNode return f.newNode(KindRestType, data.AsNode()) } @@ -6180,7 +6208,7 @@ type TemplateHead struct { } func (f *NodeFactory) NewTemplateHead(text string, rawText string, templateFlags TokenFlags) *Node { - data := &TemplateHead{} + data := f.templateHeadArena.New() data.Text = text data.RawText = rawText data.TemplateFlags = templateFlags & TokenFlagsTemplateLiteralLikeFlags @@ -6206,7 +6234,7 @@ type TemplateMiddle struct { } func (f *NodeFactory) NewTemplateMiddle(text string, rawText string, templateFlags TokenFlags) *Node { - data := &TemplateMiddle{} + data := f.templateMiddleArena.New() data.Text = text data.RawText = rawText data.TemplateFlags = templateFlags & TokenFlagsTemplateLiteralLikeFlags @@ -6232,7 +6260,7 @@ type TemplateTail struct { } func (f *NodeFactory) NewTemplateTail(text string, rawText string, templateFlags TokenFlags) *Node { - data := &TemplateTail{} + data := f.templateTailArena.New() data.Text = text data.RawText = rawText data.TemplateFlags = templateFlags & TokenFlagsTemplateLiteralLikeFlags @@ -6259,7 +6287,7 @@ type TemplateLiteralTypeNode struct { } func (f *NodeFactory) NewTemplateLiteralTypeNode(head *TemplateHeadNode, templateSpans *TemplateLiteralTypeSpanList) *Node { - data := &TemplateLiteralTypeNode{} + data := f.templateLiteralTypeNodeArena.New() data.Head = head data.TemplateSpans = templateSpans return f.newNode(KindTemplateLiteralType, data.AsNode()) @@ -6299,7 +6327,7 @@ type TemplateLiteralTypeSpan struct { } func (f *NodeFactory) NewTemplateLiteralTypeSpan(typeNode *TypeNode, literal *TemplateMiddleOrTail) *Node { - data := &TemplateLiteralTypeSpan{} + data := f.templateLiteralTypeSpanArena.New() data.Type = typeNode data.Literal = literal return f.newNode(KindTemplateLiteralTypeSpan, data.AsNode()) @@ -8272,7 +8300,7 @@ type ImportTypeNode struct { } func (f *NodeFactory) NewImportTypeNode(isTypeOf bool, argument *TypeNode, attributes *ImportAttributesNode, qualifier *EntityName, typeArguments *TypeList) *Node { - data := &ImportTypeNode{} + data := f.importTypeNodeArena.New() data.IsTypeOf = isTypeOf data.Argument = argument data.Attributes = attributes @@ -8322,7 +8350,7 @@ type ImportClause struct { } func (f *NodeFactory) NewImportClause(phaseModifier ImportPhaseModifierSyntaxKind, name *IdentifierNode, namedBindings *NamedImportBindings) *Node { - data := &ImportClause{} + data := f.importClauseArena.New() data.PhaseModifier = phaseModifier data.name = name data.NamedBindings = namedBindings diff --git a/tsc/internal/ast/utilities.go b/tsc/internal/ast/utilities.go index f178903372dc2..8431c9e16dc29 100644 --- a/tsc/internal/ast/utilities.go +++ b/tsc/internal/ast/utilities.go @@ -2795,13 +2795,17 @@ func GetNodeAtPosition(file *SourceFile, position int, includeJSDoc bool) *Node } } if child == nil { - current.ForEachChild(func(node *Node) bool { - if nodeContainsPosition(node, position) { - child = node - return true - } - return false - }) + if current == file.AsNode() && !file.IsJS() { + child = getTopLevelNodeAtPosition(file, position) + } else { + current.ForEachChild(func(node *Node) bool { + if nodeContainsPosition(node, position) { + child = node + return true + } + return false + }) + } } if child == nil || IsMetaProperty(child) { return current @@ -2810,37 +2814,79 @@ func GetNodeAtPosition(file *SourceFile, position int, includeJSDoc bool) *Node } } +// getTopLevelNodeAtPosition is equivalent to a linear search over the children of +// the source file, but binary searches the statements. This is only valid for +// non-JS files, where the statements are in source order and do not overlap; JS +// files may contain reparsed JSDoc statements whose ranges nest within other +// statements. +func getTopLevelNodeAtPosition(file *SourceFile, position int) *Node { + var statements []*Node + if file.Statements != nil { + statements = file.Statements.Nodes + } + i, _ := slices.BinarySearchFunc(statements, position, func(node *Node, position int) int { + if node.End() <= position { + return -1 + } + return 1 + }) + if i < len(statements) && nodeContainsPosition(statements[i], position) { + return statements[i] + } + if file.EndOfFileToken != nil && nodeContainsPosition(file.EndOfFileToken, position) { + return file.EndOfFileToken + } + return nil +} + func nodeContainsPosition(node *Node, position int) bool { return node.Kind >= KindFirstNode && node.Pos() <= position && (position < node.End() || position == node.End() && node.Kind == KindEndOfFile) } -func findImportOrRequire(text string, start int) (index int, size int) { - index = max(start, 0) - n := len(text) - for index < n { - next := strings.IndexAny(text[index:], "ir") - if next < 0 { - break - } - index += next +// importOrRequireFinder finds successive occurrences of "import" or "require" +// in text. It remembers the next occurrence of each keyword so that each one is +// only searched for again once it has been passed. +type importOrRequireFinder struct { + text string + nextImport int + nextRequire int +} - var expected string - if text[index] == 'i' { - size = 6 - expected = "import" - } else { - size = 7 - expected = "require" - } - if index+size <= n && text[index:index+size] == expected { - return index, size - } - index++ +func newImportOrRequireFinder(text string) importOrRequireFinder { + return importOrRequireFinder{ + text: text, + nextImport: indexFrom(text, "import", 0), + nextRequire: indexFrom(text, "require", 0), } +} +// next returns the index and length of the first "import" or "require" at or after start, or -1. +func (f *importOrRequireFinder) next(start int) (index int, size int) { + if f.nextImport >= 0 && f.nextImport < start { + f.nextImport = indexFrom(f.text, "import", start) + } + if f.nextRequire >= 0 && f.nextRequire < start { + f.nextRequire = indexFrom(f.text, "require", start) + } + if f.nextImport >= 0 && (f.nextRequire < 0 || f.nextImport < f.nextRequire) { + return f.nextImport, len("import") + } + if f.nextRequire >= 0 { + return f.nextRequire, len("require") + } return -1, 0 } +func indexFrom(text string, substr string, start int) int { + if start >= len(text) { + return -1 + } + if i := strings.Index(text[start:], substr); i >= 0 { + return start + i + } + return -1 +} + func ForEachDynamicImportOrRequireCall( file *SourceFile, includeTypeSpaceImports bool, @@ -2848,7 +2894,8 @@ func ForEachDynamicImportOrRequireCall( cb func(node *Node, argument *Expression) bool, ) bool { isJavaScriptFile := IsInJSFile(file.AsNode()) - lastIndex, size := findImportOrRequire(file.Text(), 0) + finder := newImportOrRequireFinder(file.Text()) + lastIndex, size := finder.next(0) for lastIndex >= 0 { node := GetNodeAtPosition(file, lastIndex, isJavaScriptFile && includeTypeSpaceImports) if isJavaScriptFile && IsRequireCall(node, requireStringLiteralLikeArgument) { @@ -2866,7 +2913,7 @@ func ForEachDynamicImportOrRequireCall( } // skip past import/require lastIndex += size - lastIndex, size = findImportOrRequire(file.Text(), lastIndex) + lastIndex, size = finder.next(lastIndex) } return false }