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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/compiler/fileloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,13 +485,13 @@ func getDefaultResolutionModeForFile(fileName string, meta ast.SourceFileMetaDat
}

func getModeForUsageLocation(fileName string, meta ast.SourceFileMetaData, usage *ast.StringLiteralLike, options *core.CompilerOptions) core.ResolutionMode {
if ast.IsImportDeclaration(usage.Parent) || ast.IsExportDeclaration(usage.Parent) || ast.IsJSDocImportTag(usage.Parent) {
if ast.IsImportDeclaration(usage.Parent) || usage.Parent.Kind == ast.KindJSImportDeclaration || ast.IsExportDeclaration(usage.Parent) || ast.IsJSDocImportTag(usage.Parent) {
isTypeOnly := ast.IsExclusivelyTypeOnlyImportOrExport(usage.Parent)
if isTypeOnly {
var override core.ResolutionMode
var ok bool
switch usage.Parent.Kind {
case ast.KindImportDeclaration:
case ast.KindImportDeclaration, ast.KindJSImportDeclaration:
override, ok = usage.Parent.AsImportDeclaration().Attributes.GetResolutionModeOverride()
case ast.KindExportDeclaration:
override, ok = usage.Parent.AsExportDeclaration().Attributes.GetResolutionModeOverride()
Expand Down
21 changes: 8 additions & 13 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ type Parser struct {
jsdocTagCommentsSpace []string
reparseList []*ast.Node
commonJSModuleIndicator *ast.Node

currentParent *ast.Node
}

var viableKeywordSuggestions = scanner.GetViableKeywordSuggestions()
Expand Down Expand Up @@ -3569,7 +3567,7 @@ func (p *Parser) parseTupleElementType() *ast.TypeNode {
node := p.factory.NewOptionalTypeNode(typeNode.Type())
node.Flags = typeNode.Flags
node.Loc = typeNode.Loc
typeNode.Parent = node
typeNode.Type().Parent = node
return node
}
return typeNode
Expand Down Expand Up @@ -5915,16 +5913,13 @@ func (p *Parser) finishNodeWithEnd(node *ast.Node, pos int, end int) {
node.Flags |= ast.NodeFlagsThisNodeHasError
p.hasParseError = false
}
p.currentParent = node
node.ForEachChild(p.setParent)
}

func (p *Parser) setParent(node *ast.Node) bool {
if node.Parent == nil {
node.Parent = p.currentParent
}
// TODO: panic if attempt to overwrite .Parent with new, different .Parent when jsdoc reparser is fixed to not reuse the same nodes in many places
return false
node.ForEachChild(func(n *ast.Node) bool {
if n.Parent == nil {
n.Parent = node
}
// TODO: panic if attempt to overwrite .Parent with new, different .Parent when jsdoc reparser is fixed to not reuse the same nodes in many places
return false
})
}

func (p *Parser) nextTokenIsSlash() bool {
Expand Down
10 changes: 6 additions & 4 deletions internal/parser/reparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
)

func (p *Parser) finishReparsedNode(node *ast.Node) {
p.currentParent = node
node.ForEachChild(p.setParent)
node.ForEachChild(func(n *ast.Node) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ForEachChild is an indirect call, so is not inlinable and escapes its argument; this is why I had to do the goofy parent setting thing in SetParentsInChildren. I would suspect that this wouldn't work.

n.Parent = node // this overrides an existing parent - the jsdoc reparser does this when it moves nodes from jsdoc into concrete expressions
return false
})
}

func (p *Parser) reparseCommonJS(node *ast.Node, jsdoc []*ast.Node) {
Expand Down Expand Up @@ -37,6 +39,7 @@ func (p *Parser) reparseCommonJS(node *ast.Node, jsdoc []*ast.Node) {
p.commonJSModuleIndicator = export
p.reparseTags(export, jsdoc)
p.finishReparsedNode(export)
p.finishReparsedNode(bin.AsNode()) // TODO: the same node appears in both the new export declaration and the original binary expression - both locations cannot have correct `.Parent` pointers. For now, the binary expression being correctly parented is baselined behavior, since it appears first in the AST.
}
}

Expand Down Expand Up @@ -112,6 +115,7 @@ func (p *Parser) reparseUnhosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Nod
importClause := importTag.ImportClause
importClause.Flags |= ast.NodeFlagsReparsed
importClause.AsImportClause().IsTypeOnly = true
p.finishReparsedNode(importClause)
importDeclaration := p.factory.NewJSImportDeclaration(importTag.Modifiers(), importClause, importTag.ModuleSpecifier, importTag.Attributes)
importDeclaration.Loc = tag.Loc
importDeclaration.Flags = p.contextFlags | ast.NodeFlagsReparsed
Expand Down Expand Up @@ -543,8 +547,6 @@ func (p *Parser) makeNewCast(t *ast.TypeNode, e *ast.Node, isAssertion bool) *as
assert.Flags = p.contextFlags | ast.NodeFlagsReparsed
assert.Loc = core.NewTextRange(e.Pos(), e.End())
p.finishReparsedNode(assert)
t.Parent = assert // force reset parent to the new expression injected into the AST
e.Parent = assert
return assert
}

Expand Down
35 changes: 35 additions & 0 deletions internal/testrunner/compiler_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"testing"

"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/checker"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/repo"
Expand Down Expand Up @@ -174,6 +175,7 @@ func (r *CompilerBaselineRunner) runSingleConfigTest(t *testing.T, testName stri
// !!! Verify all baselines

compilerTest.verifyUnionOrdering(t)
compilerTest.verifyParentPointers(t)
}

type compilerFileBasedTest struct {
Expand Down Expand Up @@ -506,6 +508,39 @@ func (c *compilerTest) verifyUnionOrdering(t *testing.T) {
})
}

func (c *compilerTest) verifyParentPointers(t *testing.T) {
t.Run("source file parent pointers", func(t *testing.T) {
var parent *ast.Node
var verifier func(n *ast.Node) bool
verifier = func(n *ast.Node) bool {
assert.Assert(t, n.Parent != nil, "parent node does not exist")
elab := ""
if !ast.NodeIsSynthesized(n) {
elab += ast.GetSourceFileOfNode(n).Text()[n.Loc.Pos():n.Loc.End()]
} else {
elab += "!synthetic! no text available"
}
if n.Parent.Kind == ast.KindBinaryExpression && parent.Kind == ast.KindJSExportAssignment {
// known current violation of parent pointer invariant, ignore
} else {
assert.Assert(t, n.Parent == parent, "parent node does not match traversed parent: "+n.Kind.String()+": "+elab)
}
oldParent := parent
parent = n
n.ForEachChild(verifier)
parent = oldParent
return false
}
for _, f := range c.result.Program.GetSourceFiles() {
if f.HasNoDefaultLib {
continue
}
parent = f.AsNode()
f.AsNode().ForEachChild(verifier)
}
})
}

func (c *compilerTest) containsUnsupportedOptions() bool {
if len(c.result.Program.UnsupportedExtensions()) != 0 {
return true
Expand Down
Loading