Skip to content

Skip defaults when printing BindingName #1025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 4, 2025
Merged
12 changes: 7 additions & 5 deletions internal/checker/nodebuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ func (b *NodeBuilder) enterContext(enclosingDeclaration *ast.Node, flags nodebui
}

func (b *NodeBuilder) popContext() {
b.impl.ctx = nil
if len(b.ctxStack) > 1 {
b.impl.ctx = b.ctxStack[len(b.ctxStack)-1]
stackSize := len(b.ctxStack)
if stackSize == 0 {
b.impl.ctx = nil
} else {
b.impl.ctx = b.ctxStack[stackSize-1]
b.ctxStack = b.ctxStack[:stackSize-1]
}
b.ctxStack = b.ctxStack[:len(b.ctxStack)-1]
}

func (b *NodeBuilder) exitContext(result *ast.Node) *ast.Node {
Expand Down Expand Up @@ -165,7 +167,7 @@ func (b *NodeBuilder) TypeToTypeNode(typ *Type, enclosingDeclaration *ast.Node,

func NewNodeBuilder(ch *Checker, e *printer.EmitContext) *NodeBuilder {
impl := newNodeBuilderImpl(ch, e)
return &NodeBuilder{impl: &impl, ctxStack: make([]*NodeBuilderContext, 0, 1), host: ch.program}
return &NodeBuilder{impl: impl, ctxStack: make([]*NodeBuilderContext, 0, 1), host: ch.program}
}

func (c *Checker) GetDiagnosticNodeBuilder() *NodeBuilder {
Expand Down
52 changes: 47 additions & 5 deletions internal/checker/nodebuilderimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ type nodeBuilderImpl struct {

// state
ctx *NodeBuilderContext

// reusable visitor
cloneBindingNameVisitor *ast.NodeVisitor
}

const (
Expand All @@ -102,9 +105,10 @@ const (

// Node builder utility functions

func newNodeBuilderImpl(ch *Checker, e *printer.EmitContext) nodeBuilderImpl {
result := nodeBuilderImpl{f: e.Factory.AsNodeFactory(), ch: ch, e: e}
return result
func newNodeBuilderImpl(ch *Checker, e *printer.EmitContext) *nodeBuilderImpl {
b := &nodeBuilderImpl{f: e.Factory.AsNodeFactory(), ch: ch, e: e}
b.cloneBindingNameVisitor = ast.NewNodeVisitor(b.cloneBindingName, b.f, ast.NodeVisitorHooks{})
return b
}

func (b *nodeBuilderImpl) saveRestoreFlags() func() {
Expand Down Expand Up @@ -1468,8 +1472,46 @@ func (b *nodeBuilderImpl) parameterToParameterDeclarationName(parameterSymbol *a
if parameterDeclaration == nil || parameterDeclaration.Name() == nil {
return b.f.NewIdentifier(parameterSymbol.Name)
}
// !!! TODO - symbol tracking of computed names in cloned binding patterns, set singleline emit flags
return b.f.DeepCloneNode(parameterDeclaration.Name())

name := parameterDeclaration.Name()
switch name.Kind {
case ast.KindIdentifier:
cloned := b.f.DeepCloneNode(name)
b.e.SetEmitFlags(cloned, printer.EFNoAsciiEscaping)
return cloned
case ast.KindQualifiedName:
cloned := b.f.DeepCloneNode(name.AsQualifiedName().Right)
b.e.SetEmitFlags(cloned, printer.EFNoAsciiEscaping)
return cloned
default:
return b.cloneBindingName(name)
}
}

func (b *nodeBuilderImpl) cloneBindingName(node *ast.Node) *ast.Node {
if ast.IsComputedPropertyName(node) && b.ch.isLateBindableName(node) {
b.trackComputedName(node.Expression(), b.ctx.enclosingDeclaration)
}

visited := b.cloneBindingNameVisitor.VisitEachChild(node)

if ast.IsBindingElement(visited) {
bindingElement := visited.AsBindingElement()
visited = b.f.UpdateBindingElement(
bindingElement,
bindingElement.DotDotDotToken,
bindingElement.PropertyName,
bindingElement.Name(),
nil, // remove initializer
)
}

if !ast.NodeIsSynthesized(visited) {
visited = b.f.DeepCloneNode(visited)
}

b.e.SetEmitFlags(visited, printer.EFSingleLine|printer.EFNoAsciiEscaping)
return visited
}

func (b *nodeBuilderImpl) symbolTableToDeclarationStatements(symbolTable *ast.SymbolTable) []*ast.Node {
Expand Down
11 changes: 6 additions & 5 deletions internal/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2086,13 +2086,14 @@ func SkipTriviaEx(text string, pos int, options *SkipTriviaOptions) int {
options = &SkipTriviaOptions{}
}

textLen := len(text)
canConsumeStar := false
// Keep in sync with couldStartTrivia
for {
ch, size := utf8.DecodeRuneInString(text[pos:])
switch ch {
case '\r':
if text[pos+1] == '\n' {
if pos+1 < textLen && text[pos+1] == '\n' {
pos++
}
fallthrough
Expand All @@ -2110,10 +2111,10 @@ func SkipTriviaEx(text string, pos int, options *SkipTriviaOptions) int {
if options.StopAtComments {
break
}
if pos+1 < len(text) {
if pos+1 < textLen {
if text[pos+1] == '/' {
pos += 2
for pos < len(text) {
for pos < textLen {
ch, size := utf8.DecodeRuneInString(text[pos:])
if stringutil.IsLineBreak(ch) {
break
Expand All @@ -2125,8 +2126,8 @@ func SkipTriviaEx(text string, pos int, options *SkipTriviaOptions) int {
}
if text[pos+1] == '*' {
pos += 2
for pos < len(text) {
if text[pos] == '*' && text[pos+1] == '/' {
for pos < textLen {
if text[pos] == '*' && (pos+1 < textLen) && text[pos+1] == '/' {
pos += 2
break
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
=== bug25434.js ===
// should not crash while checking
function Test({ b = '' } = {}) {}
>Test : ({ b = "" }?: { b?: string; }) => void
>Test : ({ b }?: { b?: string; }) => void
>b : string
>'' : ""
>{} : {}

Test(({ b = '5' } = {}));
>Test(({ b = '5' } = {})) : void
>Test : ({ b = "" }?: { b?: string; }) => void
>Test : ({ b }?: { b?: string; }) => void
>({ b = '5' } = {}) : {}
>{ b = '5' } = {} : {}
>{ b = '5' } : { b?: any; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

=== contextualTypeForInitalizedVariablesFiltersUndefined.ts ===
const fInferred = ({ a = 0 } = {}) => a;
>fInferred : ({ a = 0 }?: { a?: number | undefined; }) => number
>({ a = 0 } = {}) => a : ({ a = 0 }?: { a?: number | undefined; }) => number
>fInferred : ({ a }?: { a?: number | undefined; }) => number
>({ a = 0 } = {}) => a : ({ a }?: { a?: number | undefined; }) => number
>a : number
>0 : 0
>{} : {}
Expand All @@ -12,9 +12,9 @@ const fInferred = ({ a = 0 } = {}) => a;
// const fInferred: ({ a }?: { a?: number; }) => number

const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a;
>fAnnotated : ({ a = 0 }?: { a?: number | undefined; }) => number
>fInferred : ({ a = 0 }?: { a?: number | undefined; }) => number
>({ a = 0 } = {}) => a : ({ a = 0 }?: { a?: number | undefined; } | undefined) => number
>fAnnotated : ({ a }?: { a?: number | undefined; }) => number
>fInferred : ({ a }?: { a?: number | undefined; }) => number
>({ a = 0 } = {}) => a : ({ a }?: { a?: number | undefined; } | undefined) => number
>a : number
>0 : 0
>{} : {}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,44 +28,44 @@ declare function id5<T extends (x?: number) => any>(input: T): T;
>input : T

const f10 = function ({ foo = 42 }) { return foo };
>f10 : ({ foo = 42 }: { foo?: number | undefined; }) => number
>function ({ foo = 42 }) { return foo } : ({ foo = 42 }: { foo?: number | undefined; }) => number
>f10 : ({ foo }: { foo?: number | undefined; }) => number
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42
>foo : number

const f11 = id1(function ({ foo = 42 }) { return foo });
>f11 : ({ foo = 42 }: { foo?: number | undefined; }) => number
>id1(function ({ foo = 42 }) { return foo }) : ({ foo = 42 }: { foo?: number | undefined; }) => number
>f11 : ({ foo }: { foo?: number | undefined; }) => number
>id1(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo?: number | undefined; }) => number
>id1 : <T>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo = 42 }: { foo?: number | undefined; }) => number
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42
>foo : number

const f12 = id2(function ({ foo = 42 }) { return foo });
>f12 : ({ foo = 42 }: any) => any
>id2(function ({ foo = 42 }) { return foo }) : ({ foo = 42 }: any) => any
>f12 : ({ foo }: any) => any
>id2(function ({ foo = 42 }) { return foo }) : ({ foo }: any) => any
>id2 : <T extends (x: any) => any>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo = 42 }: any) => any
>function ({ foo = 42 }) { return foo } : ({ foo }: any) => any
>foo : any
>42 : 42
>foo : any

const f13 = id3(function ({ foo = 42 }) { return foo });
>f13 : ({ foo = 42 }: { foo: any; }) => any
>id3(function ({ foo = 42 }) { return foo }) : ({ foo = 42 }: { foo: any; }) => any
>f13 : ({ foo }: { foo: any; }) => any
>id3(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo: any; }) => any
>id3 : <T extends (x: { foo: any; }) => any>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo = 42 }: { foo: any; }) => any
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo: any; }) => any
>foo : any
>42 : 42
>foo : any

const f14 = id4(function ({ foo = 42 }) { return foo });
>f14 : ({ foo = 42 }: { foo?: number | undefined; }) => number
>id4(function ({ foo = 42 }) { return foo }) : ({ foo = 42 }: { foo?: number | undefined; }) => number
>f14 : ({ foo }: { foo?: number | undefined; }) => number
>id4(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo?: number | undefined; }) => number
>id4 : <T extends (x: { foo?: number | undefined; }) => any>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo = 42 }: { foo?: number | undefined; }) => number
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42
>foo : number
Expand Down Expand Up @@ -254,7 +254,7 @@ function id<T>(input: T): T { return input }
>input : T

function getFoo ({ foo = 42 }) {
>getFoo : ({ foo = 42 }: { foo?: number | undefined; }) => number
>getFoo : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42

Expand All @@ -263,17 +263,17 @@ function getFoo ({ foo = 42 }) {
}

const newGetFoo = id(getFoo);
>newGetFoo : ({ foo = 42 }: { foo?: number | undefined; }) => number
>id(getFoo) : ({ foo = 42 }: { foo?: number | undefined; }) => number
>newGetFoo : ({ foo }: { foo?: number | undefined; }) => number
>id(getFoo) : ({ foo }: { foo?: number | undefined; }) => number
>id : <T>(input: T) => T
>getFoo : ({ foo = 42 }: { foo?: number | undefined; }) => number
>getFoo : ({ foo }: { foo?: number | undefined; }) => number

const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
>newGetFoo2 : ({ foo = 42 }: { foo?: number | undefined; }) => number
>id(function getFoo ({ foo = 42 }) { return foo;}) : ({ foo = 42 }: { foo?: number | undefined; }) => number
>newGetFoo2 : ({ foo }: { foo?: number | undefined; }) => number
>id(function getFoo ({ foo = 42 }) { return foo;}) : ({ foo }: { foo?: number | undefined; }) => number
>id : <T>(input: T) => T
>function getFoo ({ foo = 42 }) { return foo;} : ({ foo = 42 }: { foo?: number | undefined; }) => number
>getFoo : ({ foo = 42 }: { foo?: number | undefined; }) => number
>function getFoo ({ foo = 42 }) { return foo;} : ({ foo }: { foo?: number | undefined; }) => number
>getFoo : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42

Expand Down
Loading