From 17cc25cd4666f874a6f90490addc2f28d63cfedc Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Tue, 18 Mar 2025 13:07:45 +0530 Subject: [PATCH 1/4] feat: moving nil check to call sites of IsFunctionLikeDeclaration --- internal/ast/utilities.go | 8 ++++---- internal/checker/checker.go | 6 +++--- internal/checker/grammarchecks.go | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index e8262ce04f..23bb27886a 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -494,9 +494,9 @@ func isFunctionLikeDeclarationKind(kind Kind) bool { } // Determines if a node is function-like (but is not a signature declaration) +// ensure node != nil before calling this func IsFunctionLikeDeclaration(node *Node) bool { - // TODO(rbuckton): Move `node != nil` test to call sites - return node != nil && isFunctionLikeDeclarationKind(node.Kind) + return isFunctionLikeDeclarationKind(node.Kind) } func isFunctionLikeKind(kind Kind) bool { @@ -2369,12 +2369,12 @@ func GetImpliedNodeFormatForEmitWorker(sourceFile *SourceFile, options *core.Com } if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS && ( /*sourceFile.packageJsonScope.contents.packageJsonContent.type == "commonjs" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { + tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { return core.ModuleKindCommonJS } if sourceFile.ImpliedNodeFormat == core.ModuleKindESNext && ( /*sourceFile.packageJsonScope?.contents.packageJsonContent.type === "module" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { + tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { return core.ModuleKindESNext } return core.ModuleKindNone diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 045fb6c9c5..bed559fcee 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -7365,7 +7365,7 @@ func (c *Checker) checkSuperExpression(node *ast.Node) *Type { func (c *Checker) isInConstructorArgumentInitializer(node *ast.Node, constructorDecl *ast.Node) bool { return ast.FindAncestorOrQuit(node, func(n *ast.Node) ast.FindAncestorResult { - if ast.IsFunctionLikeDeclaration(n) { + if n != nil && ast.IsFunctionLikeDeclaration(n) { return ast.FindAncestorQuit } if ast.IsParameter(n) && n.Parent == constructorDecl { @@ -11128,7 +11128,7 @@ func (c *Checker) isNodeUsedDuringClassInitialization(node *ast.Node) bool { return ast.FindAncestorOrQuit(node, func(element *ast.Node) ast.FindAncestorResult { if ast.IsConstructorDeclaration(element) && ast.NodeIsPresent(element.Body()) || ast.IsPropertyDeclaration(element) { return ast.FindAncestorTrue - } else if ast.IsClassLike(element) || ast.IsFunctionLikeDeclaration(element) { + } else if ast.IsClassLike(element) || (element != nil && ast.IsFunctionLikeDeclaration(element)) { return ast.FindAncestorQuit } return ast.FindAncestorFalse @@ -18582,7 +18582,7 @@ func (c *Checker) createGeneratorType(yieldType *Type, returnType *Type, nextTyp func (c *Checker) reportErrorsFromWidening(declaration *ast.Node, t *Type, wideningKind WideningKind) { if c.noImplicitAny && t.objectFlags&ObjectFlagsContainsWideningType != 0 { - if wideningKind == WideningKindNormal || ast.IsFunctionLikeDeclaration(declaration) && c.shouldReportErrorsFromWideningWithContextualSignature(declaration, wideningKind) { + if wideningKind == WideningKindNormal || declaration != nil && ast.IsFunctionLikeDeclaration(declaration) && c.shouldReportErrorsFromWideningWithContextualSignature(declaration, wideningKind) { // Report implicit any error within type if possible, otherwise report error on declaration if !c.reportWideningErrorsInType(t) { c.reportImplicitAny(declaration, t, wideningKind) diff --git a/internal/checker/grammarchecks.go b/internal/checker/grammarchecks.go index 15a5e4e7bb..e01febcb9a 100644 --- a/internal/checker/grammarchecks.go +++ b/internal/checker/grammarchecks.go @@ -294,7 +294,7 @@ func (c *Checker) checkGrammarModifiers(node *ast.Node /*Union[HasModifiers, Has parent := node.Parent if node.Kind == ast.KindTypeParameter { - if !(ast.IsFunctionLikeDeclaration(parent) || ast.IsClassLike(parent) || + if !((parent != nil && ast.IsFunctionLikeDeclaration(parent)) || ast.IsClassLike(parent) || ast.IsFunctionTypeNode(parent) || ast.IsConstructorTypeNode(parent) || ast.IsCallSignatureDeclaration(parent) || ast.IsConstructSignatureDeclaration(parent) || ast.IsMethodSignatureDeclaration(parent)) { From bec9f9be466d083fb9c8eb54f421391e3f64a38a Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Tue, 18 Mar 2025 13:13:40 +0530 Subject: [PATCH 2/4] feat: revert whitespace --- internal/ast/utilities.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 23bb27886a..18fb3c3133 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -2369,12 +2369,12 @@ func GetImpliedNodeFormatForEmitWorker(sourceFile *SourceFile, options *core.Com } if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS && ( /*sourceFile.packageJsonScope.contents.packageJsonContent.type == "commonjs" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { + tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { return core.ModuleKindCommonJS } if sourceFile.ImpliedNodeFormat == core.ModuleKindESNext && ( /*sourceFile.packageJsonScope?.contents.packageJsonContent.type === "module" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { + tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { return core.ModuleKindESNext } return core.ModuleKindNone From 57594133bd04c66c38fa7d7e4b4fce58512c797f Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Tue, 18 Mar 2025 13:58:15 +0530 Subject: [PATCH 3/4] feat: also move the nil checks to callers for IsFunctionLike --- internal/ast/utilities.go | 10 +++++----- internal/binder/binder.go | 2 +- internal/checker/checker.go | 10 +++++----- internal/checker/flow.go | 2 +- internal/checker/grammarchecks.go | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 18fb3c3133..e7067f790e 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -514,9 +514,9 @@ func isFunctionLikeKind(kind Kind) bool { } // Determines if a node is function- or signature-like. +// Ensure node != nil before calling this func IsFunctionLike(node *Node) bool { - // TODO(rbuckton): Move `node != nil` test to call sites - return node != nil && isFunctionLikeKind(node.Kind) + return isFunctionLikeKind(node.Kind) } func IsFunctionLikeOrClassStaticBlockDeclaration(node *Node) bool { @@ -1064,7 +1064,7 @@ func CanHaveDecorators(node *Node) bool { } func IsFunctionOrModuleBlock(node *Node) bool { - return IsSourceFile(node) || IsModuleBlock(node) || IsBlock(node) && IsFunctionLike(node.Parent) + return IsSourceFile(node) || IsModuleBlock(node) || IsBlock(node) && node.Parent != nil && IsFunctionLike(node.Parent) } func IsFunctionExpressionOrArrowFunction(node *Node) bool { @@ -2369,12 +2369,12 @@ func GetImpliedNodeFormatForEmitWorker(sourceFile *SourceFile, options *core.Com } if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS && ( /*sourceFile.packageJsonScope.contents.packageJsonContent.type == "commonjs" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { + tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { return core.ModuleKindCommonJS } if sourceFile.ImpliedNodeFormat == core.ModuleKindESNext && ( /*sourceFile.packageJsonScope?.contents.packageJsonContent.type === "module" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { + tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { return core.ModuleKindESNext } return core.ModuleKindNone diff --git a/internal/binder/binder.go b/internal/binder/binder.go index 55e6fff575..ea1779933d 100644 --- a/internal/binder/binder.go +++ b/internal/binder/binder.go @@ -2513,7 +2513,7 @@ func GetContainerFlags(node *ast.Node) ContainerFlags { case ast.KindCatchClause, ast.KindForStatement, ast.KindForInStatement, ast.KindForOfStatement, ast.KindCaseBlock: return ContainerFlagsIsBlockScopedContainer | ContainerFlagsHasLocals case ast.KindBlock: - if ast.IsFunctionLike(node.Parent) || ast.IsClassStaticBlockDeclaration(node.Parent) { + if node.Parent != nil && (ast.IsFunctionLike(node.Parent) || ast.IsClassStaticBlockDeclaration(node.Parent)) { return ContainerFlagsNone } else { return ContainerFlagsIsBlockScopedContainer | ContainerFlagsHasLocals diff --git a/internal/checker/checker.go b/internal/checker/checker.go index bed559fcee..094e911d29 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -5534,7 +5534,7 @@ func (c *Checker) checkVarDeclaredNamesNotShadowed(node *ast.Node) { } // names of block-scoped and function scoped variables can collide only // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting) - namesShareScope := container != nil && (ast.IsBlock(container) && ast.IsFunctionLike(container.Parent) || + namesShareScope := container != nil && (ast.IsBlock(container) && container.Parent != nil && ast.IsFunctionLike(container.Parent) || ast.IsModuleBlock(container) || ast.IsModuleDeclaration(container) || ast.IsSourceFile(container)) // here we know that function scoped variable is "shadowed" by block scoped one // a var declaration can't hoist past a lexical declaration and it results in a SyntaxError at runtime @@ -10862,7 +10862,7 @@ func (c *Checker) isUncalledFunctionReference(node *ast.Node, symbol *ast.Symbol return isCallOrNewExpression(parent) && ast.IsIdentifier(node) && c.hasMatchingArgument(parent, node) } return core.Every(symbol.Declarations, func(d *ast.Node) bool { - return !ast.IsFunctionLike(d) || c.isDeprecatedDeclaration(d) + return d == nil || !ast.IsFunctionLike(d) || c.isDeprecatedDeclaration(d) }) } return true @@ -11305,7 +11305,7 @@ func (c *Checker) tryGetThisTypeAt(node *ast.Node) *Type { } func (c *Checker) tryGetThisTypeAtEx(node *ast.Node, includeGlobalThis bool, container *ast.Node) *Type { - if ast.IsFunctionLike(container) && (!c.isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container) != nil) { + if container != nil && ast.IsFunctionLike(container) && (!c.isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container) != nil) { thisType := c.getThisTypeOfDeclaration(container) // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. // If this is a function in a JS file, it might be a class method. @@ -17983,7 +17983,7 @@ func (c *Checker) getSignaturesOfSymbol(symbol *ast.Symbol) []*Signature { } var result []*Signature for i, decl := range symbol.Declarations { - if !ast.IsFunctionLike(decl) { + if decl == nil || !ast.IsFunctionLike(decl) { continue } // Don't include signature if node is the implementation of an overloaded function. A node is considered @@ -28988,7 +28988,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy fallthrough case ast.KindThisKeyword: container := c.getThisContainer(node, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/) - if ast.IsFunctionLike(container) { + if container != nil && ast.IsFunctionLike(container) { sig := c.getSignatureFromDeclaration(container) if sig.thisParameter != nil { return sig.thisParameter diff --git a/internal/checker/flow.go b/internal/checker/flow.go index e875a0a2a8..1961fdb51e 100644 --- a/internal/checker/flow.go +++ b/internal/checker/flow.go @@ -2166,7 +2166,7 @@ func (c *Checker) hasTypePredicateOrNeverReturnType(sig *Signature) bool { func (c *Checker) getExplicitThisType(node *ast.Node) *Type { container := ast.GetThisContainer(node, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/) - if ast.IsFunctionLike(container) { + if container != nil && ast.IsFunctionLike(container) { signature := c.getSignatureFromDeclaration(container) if signature.thisParameter != nil { return c.getExplicitTypeOfSymbol(signature.thisParameter, nil) diff --git a/internal/checker/grammarchecks.go b/internal/checker/grammarchecks.go index e01febcb9a..6903174740 100644 --- a/internal/checker/grammarchecks.go +++ b/internal/checker/grammarchecks.go @@ -2061,7 +2061,7 @@ func (c *Checker) checkGrammarStatementInAmbientContext(node *ast.Node) bool { if node.Flags&ast.NodeFlagsAmbient != 0 { // Find containing block which is either Block, ModuleBlock, SourceFile links := c.nodeLinks.Get(node) - if !links.hasReportedStatementInAmbientContext && (ast.IsFunctionLike(node.Parent) || ast.IsAccessor(node.Parent)) { + if !links.hasReportedStatementInAmbientContext && (node.Parent != nil && ast.IsFunctionLike(node.Parent) || ast.IsAccessor(node.Parent)) { links.hasReportedStatementInAmbientContext = c.grammarErrorOnFirstToken(node, diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts) return links.hasReportedStatementInAmbientContext } From 699cd2d88329b661d843a46a73e69a5a1ddb0cac Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Tue, 18 Mar 2025 14:11:15 +0530 Subject: [PATCH 4/4] feat: revert whitespace --- internal/ast/utilities.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index e7067f790e..34c24210bb 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -2369,12 +2369,12 @@ func GetImpliedNodeFormatForEmitWorker(sourceFile *SourceFile, options *core.Com } if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS && ( /*sourceFile.packageJsonScope.contents.packageJsonContent.type == "commonjs" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { + tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) { return core.ModuleKindCommonJS } if sourceFile.ImpliedNodeFormat == core.ModuleKindESNext && ( /*sourceFile.packageJsonScope?.contents.packageJsonContent.type === "module" ||*/ // !!! - tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { + tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) { return core.ModuleKindESNext } return core.ModuleKindNone