diff --git a/Herebyfile.mjs b/Herebyfile.mjs index b9f3460a12..b5fcc26600 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -189,7 +189,7 @@ export const lib = task({ function buildTsgo(opts) { opts ||= {}; const out = opts.out ?? "./built/local/"; - return $({ cancelSignal: opts.abortSignal, env: opts.env })`go build ${goBuildFlags} ${opts.extraFlags ?? []} ${goBuildTags("noembed")} -o ${out} ./cmd/tsgo`; + return $({ cancelSignal: opts.abortSignal, env: opts.env })`go build ${goBuildFlags} ${opts.extraFlags ?? []} ${options.debug ? goBuildTags("noembed") : goBuildTags("noembed", "release")} -o ${out} ./cmd/tsgo`; } export const tsgoBuild = task({ diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 69d4a62ca6..ea6d64104d 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -260,6 +260,8 @@ func (n *Node) LiteralLikeData() *LiteralLikeBase { return n.data.Litera func (n *Node) TemplateLiteralLikeData() *TemplateLiteralLikeBase { return n.data.TemplateLiteralLikeData() } +func (n *Node) KindString() string { return n.Kind.String() } +func (n *Node) KindValue() int16 { return int16(n.Kind) } type mutableNode Node diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 275fb828ae..41e77d527b 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -8,6 +8,7 @@ import ( "sync/atomic" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/tspath" ) @@ -3154,7 +3155,7 @@ func IsTemplateLiteralToken(node *Node) bool { } func GetExternalModuleImportEqualsDeclarationExpression(node *Node) *Node { - // Debug.assert(isExternalModuleImportEqualsDeclaration(node)) + debug.Assert(IsExternalModuleImportEqualsDeclaration(node)) return node.AsImportEqualsDeclaration().ModuleReference.AsExternalModuleReference().Expression } diff --git a/internal/binder/binder.go b/internal/binder/binder.go index a8265be291..b56d369d00 100644 --- a/internal/binder/binder.go +++ b/internal/binder/binder.go @@ -8,6 +8,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/scanner" "github.com/microsoft/typescript-go/internal/tspath" @@ -149,7 +150,7 @@ func (b *Binder) declareSymbol(symbolTable ast.SymbolTable, parent *ast.Symbol, } func (b *Binder) declareSymbolEx(symbolTable ast.SymbolTable, parent *ast.Symbol, node *ast.Node, includes ast.SymbolFlags, excludes ast.SymbolFlags, isReplaceableByMethod bool, isComputedName bool) *ast.Symbol { - // Debug.assert(isComputedName || !ast.HasDynamicName(node)) + debug.Assert(isComputedName || !ast.HasDynamicName(node)) isDefaultExport := ast.HasSyntacticModifier(node, ast.ModifierFlagsDefault) || ast.IsExportSpecifier(node) && ast.ModuleExportNameIsDefault(node.AsExportSpecifier().Name()) // The exported symbol for an export default function/class node is always named "default" var name string diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 91ab33f1ea..267e63d7c7 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -17,6 +17,7 @@ import ( "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/evaluator" "github.com/microsoft/typescript-go/internal/jsnum" @@ -1542,7 +1543,7 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast. if symbol != nil { parent := errorLocation.Parent if ast.IsQualifiedName(parent) { - // Debug.assert(parent.Left == errorLocation, "Should only be resolving left side of qualified name as a namespace") + debug.Assert(parent.AsQualifiedName().Left == errorLocation, "Should only be resolving left side of qualified name as a namespace") propName := parent.AsQualifiedName().Right.Text() propType := c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), propName) if propType != nil { @@ -1787,7 +1788,7 @@ func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result * } func (c *Checker) checkResolvedBlockScopedVariable(result *ast.Symbol, errorLocation *ast.Node) { - // Debug.assert(!!(result.flags&ast.SymbolFlagsBlockScopedVariable || result.flags&ast.SymbolFlagsClass || result.flags&ast.SymbolFlagsEnum)) + debug.Assert(result.Flags&ast.SymbolFlagsBlockScopedVariable != 0 || result.Flags&ast.SymbolFlagsClass != 0 || result.Flags&ast.SymbolFlagsEnum != 0) if result.Flags&(ast.SymbolFlagsFunction|ast.SymbolFlagsFunctionScopedVariable|ast.SymbolFlagsAssignment) != 0 && result.Flags&ast.SymbolFlagsClass != 0 { // constructor functions aren't block scoped return @@ -1809,7 +1810,7 @@ func (c *Checker) checkResolvedBlockScopedVariable(result *ast.Symbol, errorLoca } else if result.Flags&ast.SymbolFlagsRegularEnum != 0 { diagnostic = c.error(errorLocation, diagnostics.Enum_0_used_before_its_declaration, declarationName) } else { - // Debug.assert(!!(result.flags & ast.SymbolFlagsConstEnum)) + debug.Assert(result.Flags&ast.SymbolFlagsConstEnum != 0) if c.compilerOptions.GetIsolatedModules() { diagnostic = c.error(errorLocation, diagnostics.Enum_0_used_before_its_declaration, declarationName) } @@ -2045,7 +2046,7 @@ func (c *Checker) getTypeOnlyAliasDeclarationEx(symbol *ast.Symbol, include ast. } func (c *Checker) getImmediateAliasedSymbol(symbol *ast.Symbol) *ast.Symbol { - // Debug.assert((symbol.flags&SymbolFlagsAlias) != 0, "Should only get Alias here.") + debug.Assert(symbol.Flags&ast.SymbolFlagsAlias != 0, "Should only get Alias here.") links := c.aliasSymbolLinks.Get(symbol) if links.immediateTarget == nil { node := c.getDeclarationOfAliasSymbol(symbol) @@ -6439,7 +6440,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { switch node.Kind { case ast.KindImportClause, ast.KindImportSpecifier, ast.KindImportEqualsDeclaration: if c.compilerOptions.VerbatimModuleSyntax.IsTrue() { - // Debug.assertIsDefined(node.Name, "An ImportClause with a symbol should have a name") + debug.AssertIsDefined(node.Name(), "An ImportClause with a symbol should have a name") var message *diagnostics.Message switch { case c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ast.IsInternalModuleImportEqualsDeclaration(node): @@ -6934,7 +6935,7 @@ func (c *Checker) checkUnusedRenamedBindingElements() { for _, node := range c.renamedBindingElementsInTypes { if c.symbolReferenceLinks.Get(c.getSymbolOfDeclaration(node)).referenceKinds == 0 { wrappingDeclaration := ast.WalkUpBindingElementsAndPatterns(node) - // Debug.assert(isPartOfParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here") + debug.Assert(ast.IsPartOfParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here") diagnostic := NewDiagnosticForNode(node.Name(), diagnostics.X_0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, scanner.DeclarationNameToString(node.Name()), scanner.DeclarationNameToString(node.PropertyName())) if wrappingDeclaration.Type() == nil { // entire parameter does not have type annotation, suggest adding an annotation @@ -7201,7 +7202,7 @@ func (c *Checker) checkConstEnumAccess(node *ast.Node, t *Type) { // resolve to an import, because imports of ambient const enums get checked // separately in `checkAliasSymbol`. if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.GetFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil { - // Debug.assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0) + debug.Assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0) constEnumDeclaration := t.symbol.ValueDeclaration redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path()) if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && !ast.IsValidTypeOnlyAliasUseSite(node) && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) { @@ -8926,7 +8927,7 @@ func (c *Checker) checkTypeArguments(signature *Signature, typeArgumentNodes []* typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters), isJavaScript) var mapper *TypeMapper for i := range typeArgumentNodes { - // Debug.assert(typeParameters[i] != nil, "Should not call checkTypeArguments with too many type arguments") + debug.Assert(typeParameters[i] != nil, "Should not call checkTypeArguments with too many type arguments") constraint := c.getConstraintOfTypeParameter(typeParameters[i]) if constraint != nil { typeArgumentHeadMessage := core.OrElse(headMessage, diagnostics.Type_0_does_not_satisfy_the_constraint_1) @@ -10299,8 +10300,8 @@ func (c *Checker) checkImportMetaProperty(node *ast.Node) *Type { } else if c.moduleKind < core.ModuleKindES2020 && c.moduleKind != core.ModuleKindSystem { c.error(node, diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_node18_or_nodenext) } - // file := ast.GetSourceFileOfNode(node) - // Debug.assert(file.Flags&ast.NodeFlagsPossiblyContainsImportMeta != 0, "Containing file is missing import meta node flag.") + file := ast.GetSourceFileOfNode(node) + debug.Assert(file.Flags&ast.NodeFlagsPossiblyContainsImportMeta != 0, "Containing file is missing import meta node flag.") if node.Name().Text() == "meta" { return c.getGlobalImportMetaType() } @@ -12720,7 +12721,7 @@ func (c *Checker) checkObjectLiteral(node *ast.Node, checkMode CheckMode) *Type // an ordinary function declaration(section 6.1) with no parameters. // A set accessor declaration is processed in the same manner // as an ordinary function declaration with a single parameter and a Void return type. - // Debug.assert(memberDecl.kind == KindGetAccessor || memberDecl.kind == KindSetAccessor) + debug.Assert(memberDecl.Kind == ast.KindGetAccessor || memberDecl.Kind == ast.KindSetAccessor) c.checkNodeDeferred(memberDecl) } if computedNameType != nil && computedNameType.flags&TypeFlagsStringOrNumberLiteralOrUnique == 0 { @@ -13856,7 +13857,7 @@ func (c *Checker) getSymbolOfPartOfRightHandSideOfImportEquals(entityName *ast.N } // Case 2 in above example // entityName.kind could be a QualifiedName or a Missing identifier - // Debug.assert(entityName.parent.kind == ast.KindImportEqualsDeclaration) + debug.Assert(entityName.Parent.Kind == ast.KindImportEqualsDeclaration) return c.resolveEntityName(entityName, ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace, false /*ignoreErrors*/, dontResolveAlias, nil /*location*/) } @@ -14114,7 +14115,7 @@ func (c *Checker) combineValueAndTypeSymbols(valueSymbol *ast.Symbol, typeSymbol return valueSymbol } result := c.newSymbol(valueSymbol.Flags|typeSymbol.Flags, valueSymbol.Name) - // Debug.assert(valueSymbol.declarations || typeSymbol.declarations) + debug.Assert(len(valueSymbol.Declarations) > 0 || len(typeSymbol.Declarations) > 0) result.Declarations = slices.Compact(slices.Concat(valueSymbol.Declarations, typeSymbol.Declarations)) result.Parent = valueSymbol.Parent if result.Parent == nil { @@ -15269,7 +15270,7 @@ func (c *Checker) getResolvedMembersOrExportsOfSymbol(symbol *ast.Symbol, resolu // @param lateSymbols The late-bound symbols of the parent. // @param decl The member to bind. func (c *Checker) lateBindMember(parent *ast.Symbol, earlySymbols ast.SymbolTable, lateSymbols ast.SymbolTable, decl *ast.Node) *ast.Symbol { - // Debug.assert(decl.Symbol, "The member is expected to have a symbol.") + debug.AssertIsDefined(decl.Symbol(), "The member is expected to have a symbol.") links := c.symbolNodeLinks.Get(decl) if links.resolvedSymbol == nil { // In the event we attempt to resolve the late-bound name of this member recursively, @@ -15356,7 +15357,7 @@ func (c *Checker) lateBindIndexSignature(parent *ast.Symbol, earlySymbols ast.Sy // late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound // members. func (c *Checker) addDeclarationToLateBoundSymbol(symbol *ast.Symbol, member *ast.Node, symbolFlags ast.SymbolFlags) { - // Debug.assert(getCheckFlags(symbol)&ast.CheckFlagsLate != 0, "Expected a late-bound symbol.") + debug.Assert(symbol.CheckFlags&ast.CheckFlagsLate != 0, "Expected a late-bound symbol.") symbol.Flags |= symbolFlags c.lateBoundLinks.Get(member.Symbol()).lateSymbol = symbol if len(symbol.Declarations) == 0 || member.Symbol().Flags&ast.SymbolFlagsReplaceableByMethod == 0 { @@ -15827,7 +15828,7 @@ func (c *Checker) getTypeOfVariableOrParameterOrPropertyWorker(symbol *ast.Symbo members["exports"] = fileSymbol return c.newAnonymousType(symbol, members, nil, nil, nil) } - // Debug.assertIsDefined(symbol.valueDeclaration) + debug.AssertIsDefined(symbol.ValueDeclaration) declaration := symbol.ValueDeclaration if ast.IsSourceFile(declaration) && ast.IsJsonSourceFile(declaration.AsSourceFile()) { statements := declaration.AsSourceFile().Statements.Nodes @@ -15958,7 +15959,7 @@ func (c *Checker) getTypeForVariableLikeDeclaration(declaration *ast.Node, inclu thisParameter := c.getAccessorThisParameter(fn) if thisParameter != nil && declaration == thisParameter { // Use the type from the *getter* - // Debug.assert(thisParameter.Type_ == nil) + debug.AssertNil(thisParameter.Type()) return c.getTypeOfSymbol(getterSignature.thisParameter) } return c.getReturnTypeOfSignature(getterSignature) @@ -17773,7 +17774,7 @@ func (c *Checker) addOptionalityEx(t *Type, isProperty bool, isOptional bool) *T } func (c *Checker) getOptionalType(t *Type, isProperty bool) *Type { - // Debug.assert(c.strictNullChecks) + // debug.Assert(c.strictNullChecks) // TODO: fix bug in isRequiredInitializedParameter missingOrUndefined := core.IfElse(isProperty, c.undefinedOrMissingType, c.undefinedType) if t == missingOrUndefined || t.flags&TypeFlagsUnion != 0 && t.Types()[0] == missingOrUndefined { return t @@ -20269,7 +20270,7 @@ func (c *Checker) getUnionSignatures(signatureLists [][]*Signature) []*Signature for _, signatures := range signatureLists { if !core.Same(signatures, masterList) { signature := signatures[0] - // Debug.assert(signature, "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass") + debug.AssertIsDefined(signature, "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass") if len(signature.typeParameters) != 0 && core.Some(results, func(s *Signature) bool { return len(s.typeParameters) != 0 && !c.compareTypeParametersIdentical(signature.typeParameters, s.typeParameters) }) { @@ -22811,7 +22812,7 @@ func (c *Checker) getOuterTypeParametersOfClassOrInterface(symbol *ast.Symbol) [ return initializer != nil && ast.IsFunctionExpressionOrArrowFunction(initializer) }) } - // Debug.assert(!!declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations") + debug.AssertIsDefined(declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations") return c.getOuterTypeParameters(declaration, false /*includeThisTypes*/) } @@ -23122,7 +23123,7 @@ func (c *Checker) evaluateEntity(expr *ast.Node, location *ast.Node) evaluator.R name := expr.AsElementAccessExpression().ArgumentExpression.Text() member := rootSymbol.Exports[name] if member != nil { - // Debug.assert(ast.GetSourceFileOfNode(member.valueDeclaration) == ast.GetSourceFileOfNode(rootSymbol.valueDeclaration)) + debug.Assert(ast.GetSourceFileOfNode(member.ValueDeclaration) == ast.GetSourceFileOfNode(rootSymbol.ValueDeclaration)) if location != nil { return c.evaluateEnumMember(expr, member, location) } @@ -27582,7 +27583,7 @@ func (c *Checker) getPromisedTypeOfPromiseEx(t *Type, errorNode *ast.Node, thisT } } if len(candidates) == 0 { - // Debug.assertIsDefined(thisTypeForError) + debug.AssertIsDefined(thisTypeForError) if thisTypeForErrorOut != nil { *thisTypeForErrorOut = thisTypeForError } @@ -28778,7 +28779,7 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur break } index := slices.Index(node.Parent.Parameters(), node) - core.IfElse(ast.GetThisParameter(node.Parent) != nil, 1, 0) - // Debug.assert(index >= 0) + debug.Assert(index >= 0) // A parameter declaration decorator will have three arguments (see `ParameterDecorator` in // core.d.ts). var targetType *Type diff --git a/internal/checker/emitresolver.go b/internal/checker/emitresolver.go index a2afa5f99f..9e20254047 100644 --- a/internal/checker/emitresolver.go +++ b/internal/checker/emitresolver.go @@ -8,6 +8,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/evaluator" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/nodebuilder" @@ -574,7 +575,7 @@ func (r *emitResolver) isOptionalParameter(node *ast.Node) bool { if node.Initializer() != nil { signature := r.checker.getSignatureFromDeclaration(node.Parent) parameterIndex := core.FindIndex(node.Parent.Parameters(), func(p *ast.ParameterDeclarationNode) bool { return p == node }) - // Debug.assert(parameterIndex >= 0); // !!! + debug.Assert(parameterIndex >= 0) // Only consider syntactic or instantiated parameters as optional, not `void` parameters as this function is used // in grammar checks and checking for `void` too early results in parameter types widening too early // and causes some noImplicitAny errors to be lost. diff --git a/internal/checker/grammarchecks.go b/internal/checker/grammarchecks.go index e2a1932e5c..dc98b20881 100644 --- a/internal/checker/grammarchecks.go +++ b/internal/checker/grammarchecks.go @@ -8,6 +8,7 @@ import ( "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/scanner" @@ -1264,7 +1265,7 @@ func (c *Checker) checkGrammarForInOrForOfStatement(forInOrOfStatement *ast.ForI diagnostic := createDiagnosticForNode(forInOrOfStatement.AwaitModifier, diagnostics.X_for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules) containingFunc := getContainingFunction(forInOrOfStatement.AsNode()) if containingFunc != nil && containingFunc.Kind != ast.KindConstructor { - // Debug.assert((getFunctionFlags(containingFunc)&FunctionFlagsAsync) == 0, "Enclosing function should never be an async function.") + debug.Assert((getFunctionFlags(containingFunc)&FunctionFlagsAsync) == 0, "Enclosing function should never be an async function.") if hasAsyncModifier(containingFunc) { panic("Enclosing function should never be an async function.") } @@ -2100,7 +2101,7 @@ func (c *Checker) checkGrammarStatementInAmbientContext(node *ast.Node) bool { } else { // We must be parented by a statement. If so, there's no need // to report the error as our parent will have already done it. - // Debug.assert(isStatement(node.parent)); + // debug.Assert(ast.IsStatement(node.Parent)) // !!! commented out in strada - fails if uncommented } } return false diff --git a/internal/checker/jsx.go b/internal/checker/jsx.go index 083953e11f..0a0cfa8f8d 100644 --- a/internal/checker/jsx.go +++ b/internal/checker/jsx.go @@ -7,6 +7,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/parser" @@ -748,13 +749,13 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme } if contextualType != nil && checkMode&CheckModeInferential != 0 && checkMode&CheckModeSkipContextSensitive == 0 && c.isContextSensitive(attributeDecl) { inferenceContext := c.getInferenceContext(attributes) - // Debug.assert(inferenceContext) + debug.AssertIsDefined(inferenceContext) // In CheckMode.Inferential we should always have an inference context inferenceNode := attributeDecl.Initializer().Expression() c.addIntraExpressionInferenceSite(inferenceContext, inferenceNode, exprType) } } else { - // Debug.assert(attributeDecl.Kind == ast.KindJsxSpreadAttribute) + debug.Assert(attributeDecl.Kind == ast.KindJsxSpreadAttribute) if len(attributesTable) != 0 { spread = c.getSpreadType(spread, createJsxAttributesType(), attributesSymbol, objectFlags, false /*readonly*/) attributesTable = make(ast.SymbolTable) @@ -1175,7 +1176,7 @@ func (c *Checker) createSignatureForJSXIntrinsic(node *ast.Node, result *Type) * // The function is intended to be called from a function which has checked that the opening element is an intrinsic element. // @param node an intrinsic JSX opening-like element func (c *Checker) getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node *ast.Node) *Type { - // Debug.assert(c.isJsxIntrinsicTagName(node.TagName())) + debug.Assert(isJsxIntrinsicTagName(node.TagName())) links := c.jsxElementLinks.Get(node) if links.resolvedJsxElementAttributesType != nil { return links.resolvedJsxElementAttributesType diff --git a/internal/checker/nodebuilderimpl.go b/internal/checker/nodebuilderimpl.go index 4227c2fb8c..474a3d05d1 100644 --- a/internal/checker/nodebuilderimpl.go +++ b/internal/checker/nodebuilderimpl.go @@ -9,6 +9,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/module" "github.com/microsoft/typescript-go/internal/modulespecifiers" @@ -902,7 +903,7 @@ func (b *nodeBuilderImpl) getTypeParametersOfClassOrInterface(symbol *ast.Symbol } func (b *nodeBuilderImpl) lookupTypeParameterNodes(chain []*ast.Symbol, index int) *ast.TypeParameterList { - // Debug.assert(chain && 0 <= index && index < chain.length); // !!! + debug.Assert(chain != nil && 0 <= index && index < len(chain)) symbol := chain[index] symbolId := ast.GetSymbolId(symbol) if !b.ctx.hasCreatedTypeParameterSymbolList { @@ -955,8 +956,8 @@ func (b *nodeBuilderImpl) lookupSymbolChainWorker(symbol *ast.Symbol, meaning as if !isTypeParameter && (b.ctx.enclosingDeclaration != nil || b.ctx.flags&nodebuilder.FlagsUseFullyQualifiedType != 0) && (b.ctx.internalFlags&nodebuilder.InternalFlagsDoNotIncludeSymbolChain == 0) { res := b.getSymbolChain(symbol, meaning /*endOfChain*/, true, yieldModuleSymbol) chain = res - // Debug.checkDefined(chain) // !!! - // Debug.assert(chain && chain.length > 0); // !!! + debug.CheckDefined(chain) + debug.Assert(len(chain) > 0) } else { chain = append(chain, symbol) } @@ -1134,7 +1135,7 @@ func tryGetModuleSpecifierFromDeclarationWorker(node *ast.Node) *ast.Node { } return nil default: - // Debug.assertNever(node); // !!! + debug.AssertNever(node) return nil } } @@ -1357,7 +1358,7 @@ func (b *nodeBuilderImpl) isHomomorphicMappedTypeWithNonHomomorphicInstantiation } func (b *nodeBuilderImpl) createMappedTypeNodeFromType(t *Type) *ast.TypeNode { - // Debug.assert(!!(type.flags & TypeFlags.Object)); // !!! + debug.Assert(t.Flags()&TypeFlagsObject != 0) mapped := t.AsMappedType() var readonlyToken *ast.Node if mapped.declaration.ReadonlyToken != nil { @@ -2957,7 +2958,7 @@ func (b *nodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { objectFlags := t.objectFlags if objectFlags&ObjectFlagsReference != 0 { - // Debug.assert(t.flags&TypeFlagsObject != 0) // !!! + debug.Assert(t.Flags()&TypeFlagsObject != 0) if t.AsTypeReference().node != nil { return b.visitAndTransformType(t, (*nodeBuilderImpl).typeReferenceToTypeNode) } else { @@ -3028,7 +3029,7 @@ func (b *nodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { } } if objectFlags&(ObjectFlagsAnonymous|ObjectFlagsMapped) != 0 { - // Debug.assert(t.flags&TypeFlagsObject != 0) // !!! + debug.Assert(t.Flags()&TypeFlagsObject != 0) // The type is an object literal type. return b.createAnonymousTypeNode(t) } diff --git a/internal/checker/nodebuilderscopes.go b/internal/checker/nodebuilderscopes.go index bed04a6635..e6394df456 100644 --- a/internal/checker/nodebuilderscopes.go +++ b/internal/checker/nodebuilderscopes.go @@ -5,6 +5,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/nodebuilder" ) @@ -88,7 +89,7 @@ func (b *nodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] // traverse all ancestors. pushFakeScope := func(kind string, addAll func(addSymbol func(name string, symbol *ast.Symbol))) func() { // We only ever need to look two declarations upward. - // Debug.assert(context.enclosingDeclaration) // !!! + debug.AssertIsDefined(b.ctx.enclosingDeclaration) var existingFakeScope *ast.Node if b.links.Has(b.ctx.enclosingDeclaration) { links := b.links.Get(b.ctx.enclosingDeclaration) @@ -104,7 +105,7 @@ func (b *nodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] } } } - // Debug.assertOptionalNode(existingFakeScope, isBlock) // !!! + debug.AssertOptionalNode(existingFakeScope, ast.IsBlock) var locals ast.SymbolTable if existingFakeScope != nil { diff --git a/internal/checker/relater.go b/internal/checker/relater.go index fdae04e56d..2219197356 100644 --- a/internal/checker/relater.go +++ b/internal/checker/relater.go @@ -9,6 +9,7 @@ import ( "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/scanner" @@ -4672,7 +4673,7 @@ func (r *Relater) reportRelationError(message *diagnostics.Message, source *Type // to be displayed for use-cases like 'assertNever'. if target.flags&TypeFlagsNever == 0 && isLiteralType(source) && !r.c.typeCouldHaveTopLevelSingletonTypes(target) { generalizedSource = r.c.getBaseTypeOfLiteralType(source) - // Debug.assert(!c.isTypeAssignableTo(generalizedSource, target), "generalized source shouldn't be assignable") + debug.Assert(!r.c.isTypeAssignableTo(generalizedSource, target), "generalized source shouldn't be assignable") generalizedSourceType = r.c.getTypeNameForErrorDisplay(generalizedSource) } // If `target` is of indexed access type (and `source` it is not), we use the object type of `target` for better error reporting diff --git a/internal/core/core.go b/internal/core/core.go index a14fb98290..5060f25d16 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -9,6 +9,7 @@ import ( "unicode" "unicode/utf8" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/jsonutil" "github.com/microsoft/typescript-go/internal/stringutil" "github.com/microsoft/typescript-go/internal/tspath" @@ -485,7 +486,7 @@ func GetSpellingSuggestion[T any](name string, candidates []T, getName func(T) s if distance < 0 { continue } - // Debug.assert(distance < bestDistance) // Else `levenshteinWithMax` should return undefined + debug.Assert(distance < bestDistance) // Else `levenshteinWithMax` should return undefined bestDistance = distance bestCandidate = candidate } diff --git a/internal/debug/debug.go b/internal/debug/debug.go new file mode 100644 index 0000000000..2c52678fc1 --- /dev/null +++ b/internal/debug/debug.go @@ -0,0 +1,198 @@ +//go:build !release + +package debug + +import ( + "fmt" + "reflect" +) + +func Assert(expression bool, message ...string) { + if !expression { + var msg string + if len(message) > 0 { + msg = "False expression: " + message[0] + } else { + msg = "False expression." + } + Fail(msg) + } +} + +func isNil[T any](value T) bool { + v := reflect.ValueOf(value) + switch v.Kind() { + case reflect.Pointer, reflect.UnsafePointer, reflect.Interface, reflect.Slice, reflect.Map, reflect.Chan, reflect.Func: + { + return v.IsNil() + } + default: + { + return false + } + } +} + +func AssertNil(value any, message ...string) { + if value != nil && !isNil(value) { + var msg string + if len(message) > 0 { + msg = "Nil expression: " + message[0] + } else { + msg = "Nil expression." + } + Fail(msg) + } +} + +func AssertEqual(a fmt.Stringer, b fmt.Stringer, message ...string) { + if a != b { + var msg string + if len(message) == 0 { + msg = "" + } else { + msg = message[0] + } + Fail(fmt.Sprintf("Expected %s == %s. %s", a.String(), b.String(), msg)) + } +} + +func AssertLessThan(a int, b int, message ...string) { + if a >= b { + var msg string + if len(message) == 0 { + msg = "" + } else { + msg = message[0] + } + Fail(fmt.Sprintf("Expected %d < %d. %s", a, b, msg)) + } +} + +func AssertLessThanOrEqual(a int, b int, message ...string) { + if a > b { + var msg string + if len(message) == 0 { + msg = "" + } else { + msg = message[0] + } + Fail(fmt.Sprintf("Expected %d <= %d. %s", a, b, msg)) + } +} + +func AssertGreaterThan(a int, b int, message ...string) { + if a <= b { + var msg string + if len(message) == 0 { + msg = "" + } else { + msg = message[0] + } + Fail(fmt.Sprintf("Expected %d > %d. %s", a, b, msg)) + } +} + +func AssertGreaterThanOrEqual(a int, b int, message ...string) { + if a < b { + var msg string + if len(message) == 0 { + msg = "" + } else { + msg = message[0] + } + Fail(fmt.Sprintf("Expected %d >= %d. %s", a, b, msg)) + } +} + +func AssertIsDefined(value any, message ...string) { + if value == nil || isNil(value) { // handle all `nil` interfaces + var msg string + if len(message) == 0 { + msg = "" + } else { + msg = message[0] + } + Fail(msg) + } +} + +func CheckDefined[T any](value T, message ...string) T { + AssertIsDefined(value, message...) + return value +} + +func AssertEachIsDefined[TElem any](value []TElem, message ...string) { + for _, elem := range value { + AssertIsDefined(elem, message...) + } +} + +func CheckEachIsDefined[TElem any](value []TElem, message ...string) []TElem { + AssertEachIsDefined(value, message...) + return value +} + +var unexpectedNode []string = []string{"Unexpected node."} + +func AssertEachNode[TElem any](nodes []TElem, test func(elem TElem) bool, message ...string) { + if len(message) == 0 { + message = unexpectedNode + } + for _, elem := range nodes { + AssertNode(elem, test, message...) + } +} + +func AssertNode[TElem any](node TElem, test func(elem TElem) bool, message ...string) { + if len(message) == 0 { + message = unexpectedNode + } + AssertIsDefined(node, message...) + if test != nil { + Assert(test(node), message...) + } +} + +func AssertNotNode[TElem any](node TElem, test func(elem TElem) bool, message ...string) { + if isNil(node) { + return + } + if test == nil { + return + } + if len(message) == 0 { + message = unexpectedNode + } + Assert(!test(node), message...) +} + +func AssertOptionalNode[TElem any](node TElem, test func(elem TElem) bool, message ...string) { + if isNil(node) { + return + } + if test == nil { + return + } + if len(message) == 0 { + message = unexpectedNode + } + Assert(test(node), message...) +} + +func AssertOptionalToken[TElem interface{ KindValue() int16 }](node TElem, kind int16, message ...string) { + if isNil(node) { + return + } + if len(message) == 0 { + message = unexpectedNode + } + Assert(node.KindValue() == kind, message...) +} + +func AssertMissingNode[TElem any](node TElem, message ...string) { + if len(message) == 0 { + message = unexpectedNode + } + Assert(isNil(node), message...) +} diff --git a/internal/debug/release.go b/internal/debug/release.go new file mode 100644 index 0000000000..f96ed90c07 --- /dev/null +++ b/internal/debug/release.go @@ -0,0 +1,26 @@ +//go:build release + +package debug + +import ( + "fmt" +) + +func Assert(expression bool, message ...string) {} +func AssertNil(value any, message ...string) {} +func AssertEqual(a fmt.Stringer, b fmt.Stringer, msg ...string) {} +func AssertLessThan(a int, b int, message ...string) {} +func AssertLessThanOrEqual(a int, b int, message ...string) {} +func AssertGreaterThan(a int, b int, message ...string) {} +func AssertGreaterThanOrEqual(a int, b int, message ...string) {} +func AssertIsDefined(value any, message ...string) {} +func CheckDefined[T any](value T, message ...string) T { return value } +func AssertEachIsDefined[TElem any](value []TElem, message ...string) {} +func CheckEachIsDefined[TElem any](value []TElem, message ...string) []TElem { return value } +func AssertEachNode[TElem any](nodes []TElem, test func(elem TElem) bool, message ...string) {} +func AssertNode[TElem any](node TElem, test func(elem TElem) bool, message ...string) {} +func AssertNotNode[TElem any](node TElem, test func(elem TElem) bool, message ...string) {} +func AssertOptionalNode[TElem any](node TElem, test func(elem TElem) bool, message ...string) {} +func AssertOptionalToken[TElem interface{ KindValue() int }](node TElem, kind int, message ...string) { +} +func AssertMissingNode[TElem any](node TElem, message ...string) {} diff --git a/internal/debug/shared.go b/internal/debug/shared.go new file mode 100644 index 0000000000..81acc4e8cb --- /dev/null +++ b/internal/debug/shared.go @@ -0,0 +1,44 @@ +package debug + +import ( + "fmt" + "runtime" +) + +func Fail(reason string) { + if len(reason) == 0 { + reason = "Debug failure." + } else { + reason = "Debug failure. " + reason + } + runtime.Breakpoint() + panic(reason) +} + +func FailBadSyntaxKind(node interface{ KindString() string }, message ...string) { + var msg string + if len(message) == 0 { + msg = "Unexpected node." + } else { + msg = message[0] + } + Fail(fmt.Sprintf("%s\r\nNode %s was unexpected.", msg, node.KindString())) +} + +func AssertNever(member any, message ...string) { + var msg string + if len(message) == 0 { + msg = "Illegal value:" + } else { + msg = message[0] + } + var detail string + if member, ok := member.(interface{ KindString() string }); ok { + detail = member.KindString() + } else if member, ok := member.(fmt.Stringer); ok { + detail = member.String() + } else { + detail = fmt.Sprintf("%v", member) + } + Fail(fmt.Sprintf("%s %s", msg, detail)) +} diff --git a/internal/format/indent.go b/internal/format/indent.go index f7eab25fea..0dfc596ffd 100644 --- a/internal/format/indent.go +++ b/internal/format/indent.go @@ -7,6 +7,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/astnav" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/scanner" "github.com/microsoft/typescript-go/internal/stringutil" ) @@ -170,7 +171,7 @@ func getActualIndentationForListStartLine(list *ast.NodeList, sourceFile *ast.So } func deriveActualIndentationFromList(list *ast.NodeList, index int, sourceFile *ast.SourceFile, options *FormatCodeSettings) int { - // Debug.assert(index >= 0 && index < list.length); // !!! + debug.Assert(list != nil && index >= 0 && index < len(list.Nodes)) node := list.Nodes[index] @@ -238,7 +239,7 @@ func findFirstNonWhitespaceCharacterAndColumn(startPos int, endPos int, sourceFi func childStartsOnTheSameLineWithElseInIfStatement(parent *ast.Node, child *ast.Node, childStartLine int, sourceFile *ast.SourceFile) bool { if parent.Kind == ast.KindIfStatement && parent.AsIfStatement().ElseStatement == child { elseKeyword := astnav.FindPrecedingToken(sourceFile, child.Pos()) - // Debug.assert(elseKeyword !== undefined); // !!! + debug.AssertIsDefined(elseKeyword) elseKeywordStartLine, _ := getStartLineAndCharacterForNode(elseKeyword, sourceFile) return elseKeywordStartLine == childStartLine } diff --git a/internal/format/rulesmap.go b/internal/format/rulesmap.go index 5c482821a0..c511ddc19e 100644 --- a/internal/format/rulesmap.go +++ b/internal/format/rulesmap.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/debug" ) func getRules(context *formattingContext, rules []*ruleImpl) []*ruleImpl { @@ -31,7 +32,7 @@ func getRules(context *formattingContext, rules []*ruleImpl) []*ruleImpl { } func getRuleBucketIndex(row ast.Kind, column ast.Kind) int { - // Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens") // !!! + debug.Assert(row <= ast.KindLastKeyword && column <= ast.KindLastKeyword, "Must compute formatting context from tokens") return (int(row) * mapRowLength) + int(column) } @@ -150,6 +151,6 @@ func getRuleInsertionIndex(indexBitmap int, maskPosition RulesPosition) int { func increaseInsertionIndex(indexBitmap int, maskPosition RulesPosition) int { value := ((indexBitmap >> maskPosition) & mask) + 1 - // Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); // !!! + debug.Assert((value&mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.") return (indexBitmap & ^(mask << maskPosition)) | (value << maskPosition) } diff --git a/internal/format/scanner.go b/internal/format/scanner.go index 181b823588..5ce691c507 100644 --- a/internal/format/scanner.go +++ b/internal/format/scanner.go @@ -5,6 +5,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/scanner" ) @@ -169,7 +170,7 @@ func fixTokenKind(tokenInfo tokenInfo, container *ast.Node) tokenInfo { } func (s *formattingScanner) readTokenInfo(n *ast.Node) tokenInfo { - // Debug.assert(isOnToken()); // !!! + debug.Assert(s.isOnToken()) // normally scanner returns the smallest available token // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. @@ -203,7 +204,6 @@ func (s *formattingScanner) readTokenInfo(n *ast.Node) tokenInfo { } if s.s.TokenFullStart() != s.savedPos { - // Debug.assert(lastTokenInfo !== undefined); // !!! // readTokenInfo was called before but scan action differs - rescan text s.s.ResetTokenState(s.savedPos) s.s.Scan() @@ -258,14 +258,14 @@ func (s *formattingScanner) getNextToken(n *ast.Node, expectedScanAction scanAct if token == ast.KindGreaterThanToken { s.lastScanAction = actionRescanGreaterThanToken newToken := s.s.ReScanGreaterThanToken() - // Debug.assert(n.kind == newToken); // !!! + debug.Assert(n.Kind == newToken) return newToken } case actionRescanSlashToken: if startsWithSlashToken(token) { s.lastScanAction = actionRescanSlashToken newToken := s.s.ReScanSlashToken() - // Debug.assert(n.kind == newToken); // !!! + debug.Assert(n.Kind == newToken) return newToken } case actionRescanTemplateToken: @@ -285,14 +285,13 @@ func (s *formattingScanner) getNextToken(n *ast.Node, expectedScanAction scanAct case actionScan: break default: - // Debug.assertNever(expectedScanAction); !!! - panic("unhandled scan action kind") + debug.AssertNever(expectedScanAction, "unhandled scan action kind") } return token } func (s *formattingScanner) readEOFTokenRange() TextRangeWithKind { - // Debug.assert(isOnEOF()); // !!! + debug.Assert(s.isOnEOF()) return NewTextRangeWithKind( s.s.TokenFullStart(), s.s.TokenEnd(), diff --git a/internal/format/span.go b/internal/format/span.go index 7c409c02c4..1ae4d56f4a 100644 --- a/internal/format/span.go +++ b/internal/format/span.go @@ -10,6 +10,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/astnav" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/scanner" "github.com/microsoft/typescript-go/internal/stringutil" ) @@ -335,7 +336,7 @@ func (w *formatSpanWorker) processChildNode( isListItem bool, isFirstListItem bool, ) int { - // Debug.assert(!nodeIsSynthesized(child)); // !!! + debug.Assert(!ast.NodeIsSynthesized(child)) if ast.NodeIsMissing(child) || isGrammarError(parent, child) { return inheritedIndentation @@ -397,7 +398,7 @@ func (w *formatSpanWorker) processChildNode( tokenInfo := w.formattingScanner.readTokenInfo(child) // JSX text shouldn't affect indenting if child.Kind != ast.KindJsxText { - // Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); // !!! + debug.Assert(tokenInfo.token.Loc.End() == child.Loc.End(), "Token end is child end") w.consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child, false) return inheritedIndentation } @@ -430,8 +431,9 @@ func (w *formatSpanWorker) processChildNodes( parentStartLine int, parentDynamicIndentation *dynamicIndenter, ) { - // Debug.assert(isNodeArray(nodes)); // !!! - // Debug.assert(!nodeIsSynthesized(nodes)); // !!! + debug.AssertIsDefined(nodes) + debug.Assert(!ast.PositionIsSynthesized(nodes.Pos())) + debug.Assert(!ast.PositionIsSynthesized(nodes.End())) listStartToken := getOpenTokenForList(parent, nodes) @@ -658,7 +660,7 @@ func (w *formatSpanWorker) processPair(currentItem TextRangeWithKind, currentSta dynamicIndentation.recomputeIndentation( /*lineAddedByFormatting*/ true, contextNode) } default: - // Debug.assert(lineAction === LineAction.None); // !!! + debug.Assert(lineAction == LineActionNone) } } @@ -814,7 +816,8 @@ func (w *formatSpanWorker) trimTrailingWhitespacesForLines(line1 int, line2 int, whitespaceStart := w.getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition) if whitespaceStart != -1 { - // Debug.assert(whitespaceStart === lineStartPosition || !isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); // !!! + r, _ := utf8.DecodeRuneInString(w.sourceFile.Text()[whitespaceStart-1:]) + debug.Assert(whitespaceStart == lineStartPosition || !stringutil.IsWhiteSpaceSingleLine(r)) w.recordDelete(whitespaceStart, lineEndPosition+1-whitespaceStart) } } diff --git a/internal/fourslash/baselineutil.go b/internal/fourslash/baselineutil.go index fb29ec8bb5..b2dc636f18 100644 --- a/internal/fourslash/baselineutil.go +++ b/internal/fourslash/baselineutil.go @@ -12,6 +12,7 @@ import ( "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/ls" "github.com/microsoft/typescript-go/internal/lsp/lsproto" "github.com/microsoft/typescript-go/internal/vfs" @@ -181,7 +182,8 @@ func (f *FourslashTest) getBaselineContentForFile( if options.startMarkerPrefix != nil { if startPrefix := options.startMarkerPrefix(span.Location); startPrefix != "" { if fileName == options.marker.FileName() && span.Range.Start == options.marker.LSPosition { - // ts.Debug.assert(!detailPrefixes.has(details[0]), "Expected only single prefix at marker location"); + _, ok := detailPrefixes[*details[0]] + debug.Assert(!ok, "Expected only single prefix at marker location") detailPrefixes[*details[0]] = startPrefix } else if span.contextSpan.Range.Start == span.Range.Start { // Write it at contextSpan instead of textSpan @@ -196,7 +198,8 @@ func (f *FourslashTest) getBaselineContentForFile( if options.endMarkerSuffix != nil { if endSuffix := options.endMarkerSuffix(span.Location); endSuffix != "" { if fileName == options.marker.FileName() && textSpanEnd == options.marker.LSPosition { - // ts.Debug.assert(!detailSuffixes.has(details[0]), "Expected only single suffix at marker location"); + _, ok := detailSuffixes[*details[0]] + debug.Assert(!ok, "Expected only single suffix at marker location") detailSuffixes[*details[0]] = endSuffix } else if *contextSpanEnd == textSpanEnd { // Write it at contextSpan instead of textSpan diff --git a/internal/ls/completions.go b/internal/ls/completions.go index cf2eb9846e..360fee6df5 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -18,6 +18,7 @@ import ( "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/format" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/lsp/lsproto" @@ -5341,7 +5342,7 @@ func getJSDocParamAnnotation( tabstopCounter *int, ) string { if isSnippet { - // !!! Debug.assertIsDefined(tabstopCounter); + debug.AssertIsDefined(tabstopCounter) } if initializer != nil { paramName = getJSDocParamNameWithInitializer(paramName, initializer) @@ -5352,7 +5353,7 @@ func getJSDocParamAnnotation( if isJS { t := "*" if isObject { - // !!! Debug.assert(!dotDotDotToken, `Cannot annotate a rest parameter with type 'object'.`); + debug.AssertNil(dotDotDotToken, `Cannot annotate a rest parameter with type 'object'.`) t = "object" } else { if initializer != nil { diff --git a/internal/ls/findallreferences.go b/internal/ls/findallreferences.go index 51c2c48d50..192c2bad9d 100644 --- a/internal/ls/findallreferences.go +++ b/internal/ls/findallreferences.go @@ -15,6 +15,7 @@ import ( "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/lsp/lsproto" "github.com/microsoft/typescript-go/internal/scanner" @@ -1469,7 +1470,7 @@ func (state *refState) forEachRelatedSymbol( panic("expected symbol.ValueDeclaration to be a parameter") } paramProp1, paramProp2 := state.checker.GetSymbolsOfParameterPropertyDeclaration(symbol.ValueDeclaration, symbol.Name) - // Debug.assert(paramProps.length == 2 && (paramProps[0].flags & SymbolFlags.FunctionScopedVariable) && (paramProps[1].flags & SymbolFlags.Property)); // is [parameter, property] + debug.Assert((paramProp1.Flags&ast.SymbolFlagsFunctionScopedVariable != 0) && (paramProp2.Flags&ast.SymbolFlagsProperty != 0)) // is [parameter, property] if !(paramProp1.Flags&ast.SymbolFlagsFunctionScopedVariable != 0 && paramProp2.Flags&ast.SymbolFlagsProperty != 0) { panic("Expected a parameter and a property") } @@ -1502,7 +1503,7 @@ func (state *refState) forEachRelatedSymbol( return fromRoot(bindingElementPropertySymbol, entryKindSearchedPropertyFoundLocal) } - // Debug.assert(isForRenamePopulateSearchSymbolSet); + debug.Assert(isForRenamePopulateSearchSymbolSet) // due to the above assert and the arguments at the uses of this function, // (onlyIncludeBindingElementAtReferenceLocation <=> !providePrefixAndSuffixTextForRename) holds diff --git a/internal/ls/signaturehelp.go b/internal/ls/signaturehelp.go index 5b48e31994..09284f9594 100644 --- a/internal/ls/signaturehelp.go +++ b/internal/ls/signaturehelp.go @@ -2,6 +2,7 @@ package ls import ( "context" + "fmt" "strings" "github.com/microsoft/typescript-go/internal/ast" @@ -9,6 +10,7 @@ import ( "github.com/microsoft/typescript-go/internal/checker" "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/lsp/lsproto" "github.com/microsoft/typescript-go/internal/nodebuilder" "github.com/microsoft/typescript-go/internal/printer" @@ -246,7 +248,7 @@ func createSignatureHelpItems(candidates []*checker.Signature, resolvedSignature itemSeen = itemSeen + len(item) } - // Debug.assert(selectedItemIndex !== -1) + debug.Assert(selectedItemIndex != -1) flattenedSignatures := []signatureInformation{} for _, item := range items { flattenedSignatures = append(flattenedSignatures, item...) @@ -576,7 +578,8 @@ func getCandidateOrTypeInfo(info *argumentListInfo, c *checker.Checker, sourceFi }, } } - return nil // return Debug.assertNever(invocation); + debug.AssertNever(info.invocation) + return nil } func isSyntacticOwner(startingToken *ast.Node, node *ast.CallLikeExpression, sourceFile *ast.SourceFile) bool { // !!! not tested @@ -617,7 +620,7 @@ func getContainingArgumentInfo(node *ast.Node, sourceFile *ast.SourceFile, check for n := node; !ast.IsSourceFile(n) && (isManuallyInvoked || !ast.IsBlock(n)); n = n.Parent { // If the node is not a subspan of its parent, this is a big problem. // There have been crashes that might be caused by this violation. - // Debug.assert(rangeContainsRange(n.parent, n), "Not a subspan", () => `Child: ${Debug.formatSyntaxKind(n.kind)}, parent: ${Debug.formatSyntaxKind(n.parent.kind)}`); + debug.Assert(RangeContainsRange(n.Parent.Loc, n.Loc), fmt.Sprintf("Not a subspan. Child: %s, parent: %s", n.KindString(), n.Parent.KindString())) argumentInfo := getImmediatelyContainingArgumentOrContextualParameterInfo(n, position, sourceFile, checker) if argumentInfo != nil { return argumentInfo @@ -763,7 +766,7 @@ func getArgumentIndexForTemplatePiece(spanIndex int, node *ast.Node, position in // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` // ^ ^ ^ ^ ^ ^ ^ ^ ^ // Case: 1 1 3 2 1 3 2 2 1 - //Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); + debug.Assert(position >= node.Loc.Pos(), "Assumed 'position' could not occur before node.") if ast.IsTemplateLiteralToken(node) { if isInsideTemplateLiteral(node, position, sourceFile) { return 0 @@ -1117,9 +1120,9 @@ func getArgumentListInfoForTemplate(tagExpression *ast.TaggedTemplateExpression, if !isNoSubstitutionTemplateLiteral(tagExpression.Template) { argumentCount = len(tagExpression.Template.AsTemplateExpression().TemplateSpans.Nodes) + 1 } - // if (argumentIndex !== 0) { - // Debug.assertLessThan(argumentIndex, argumentCount); - // } + if argumentIndex != 0 { + debug.AssertLessThan(argumentIndex, argumentCount) + } return &argumentListInfo{ isTypeParameterList: false, invocation: &invocation{callInvocation: &callInvocation{node: tagExpression.AsNode()}}, diff --git a/internal/ls/utilities.go b/internal/ls/utilities.go index aa8a9f0be6..a1a64ab617 100644 --- a/internal/ls/utilities.go +++ b/internal/ls/utilities.go @@ -12,6 +12,7 @@ import ( "github.com/microsoft/typescript-go/internal/checker" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/lsp/lsproto" "github.com/microsoft/typescript-go/internal/lsutil" @@ -119,10 +120,7 @@ func getLocalSymbolForExportSpecifier(referenceLocation *ast.Identifier, referen } func isExportSpecifierAlias(referenceLocation *ast.Identifier, exportSpecifier *ast.ExportSpecifier) bool { - // Debug.assert(exportSpecifier.PropertyName == referenceLocation || exportSpecifier.Name == referenceLocation); - if !(exportSpecifier.PropertyName == referenceLocation.AsNode() || exportSpecifier.Name() == referenceLocation.AsNode()) { - panic("referenceLocation is not export specifier name or property name") - } + debug.Assert(exportSpecifier.PropertyName == referenceLocation.AsNode() || exportSpecifier.Name() == referenceLocation.AsNode(), "referenceLocation is not export specifier name or property name") propertyName := exportSpecifier.PropertyName if propertyName != nil { // Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol. diff --git a/internal/modulespecifiers/preferences.go b/internal/modulespecifiers/preferences.go index ce11879329..226335fdbb 100644 --- a/internal/modulespecifiers/preferences.go +++ b/internal/modulespecifiers/preferences.go @@ -5,6 +5,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/tspath" ) @@ -219,7 +220,7 @@ func getModuleSpecifierPreferences( } return []ModuleSpecifierEnding{ModuleSpecifierEndingMinimal, ModuleSpecifierEndingIndex, ModuleSpecifierEndingJsExtension} default: - // Debug.assertNever(preferredEnding); // !!! + debug.AssertNever(preferredEnding) } return []ModuleSpecifierEnding{ModuleSpecifierEndingMinimal} } diff --git a/internal/modulespecifiers/specifiers.go b/internal/modulespecifiers/specifiers.go index fb990f12e5..588f5a8b5c 100644 --- a/internal/modulespecifiers/specifiers.go +++ b/internal/modulespecifiers/specifiers.go @@ -8,6 +8,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/module" "github.com/microsoft/typescript-go/internal/outputpaths" "github.com/microsoft/typescript-go/internal/packagejson" @@ -592,7 +593,7 @@ func processEnding( // TODO: possible dead code in strada in this branch to do with declaration file name handling return fileName default: - // Debug.assertNever(allowedEndings[0]); // !!! + debug.AssertNever(allowedEndings[0]) return "" } } diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 9ff64a05a8..8378b7abb6 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -7,6 +7,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/scanner" "github.com/microsoft/typescript-go/internal/tspath" @@ -602,7 +603,7 @@ func (p *Parser) abortParsingListOrMoveToNextToken(kind ParsingContext) bool { func (p *Parser) isInSomeParsingContext() bool { // We should be in at least one parsing context, be it SourceElements while parsing // a SourceFile, or JSDocComment when lazily parsing JSDoc. - // Debug.assert(parsingContext, "Missing parsing context") + debug.Assert(p.parsingContexts != 0, "Missing parsing context") for kind := ParsingContext(0); kind < PCCount; kind++ { if p.parsingContexts&(1<"); + debug.Assert(p.token == ast.KindEqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>") parameter := p.finishNode(p.factory.NewParameterDeclaration(nil /*modifiers*/, nil /*dotDotDotToken*/, identifier, nil /*questionToken*/, nil /*typeNode*/, nil /*initializer*/), identifier.Pos()) parameters := p.newNodeList(parameter.Loc, []*ast.Node{parameter}) equalsGreaterThanToken := p.parseExpectedToken(ast.KindEqualsGreaterThanToken) @@ -4480,7 +4481,7 @@ func (p *Parser) parseUnaryExpressionOrHigher() *ast.Expression { if simpleUnaryExpression.Kind == ast.KindTypeAssertionExpression { p.parseErrorAt(pos, end, diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses) } else { - // Debug.assert(isKeywordOrPunctuation(unaryOperator)) + debug.Assert(isKeywordOrPunctuation(unaryOperator)) p.parseErrorAt(pos, end, diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, scanner.TokenToString(unaryOperator)) } } @@ -4913,7 +4914,7 @@ func (p *Parser) parseAwaitExpression() *ast.Node { } func (p *Parser) parseTypeAssertion() *ast.Node { - // !!! Debug.assert(languageVariant !== core.LanguageVariant.JSX, "Type assertions should never be parsed in JSX; they should be parsed as comparisons or JSX elements/fragments."); + debug.Assert(p.languageVariant != core.LanguageVariantJSX, "Type assertions should never be parsed in JSX; they should be parsed as comparisons or JSX elements/fragments.") pos := p.nodePos() p.parseExpected(ast.KindLessThanToken) typeNode := p.parseType() diff --git a/internal/printer/factory.go b/internal/printer/factory.go index 5860793d36..adbd0a2cf2 100644 --- a/internal/printer/factory.go +++ b/internal/printer/factory.go @@ -7,6 +7,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" ) type NodeFactory struct { @@ -573,7 +574,7 @@ func (f *NodeFactory) NewRestHelper(value *ast.Expression, elements []*ast.Node, propertyName := ast.TryGetPropertyNameOfBindingOrAssignmentElement(element) if propertyName != nil { if ast.IsComputedPropertyName(propertyName) { - // Debug.assertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided."); // !!! + debug.AssertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided.") temp := computedTempVariables[computedTempVariableOffset] computedTempVariableOffset++ // typeof _tmp === "symbol" ? _tmp : _tmp + "" diff --git a/internal/printer/namegenerator.go b/internal/printer/namegenerator.go index f8994e00d0..01a5d4b079 100644 --- a/internal/printer/namegenerator.go +++ b/internal/printer/namegenerator.go @@ -6,6 +6,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" ) // Flags enum to track count of temp variables and a few dedicated names @@ -233,7 +234,7 @@ func (g *NameGenerator) makeName(name *ast.Node) string { case GeneratedIdentifierFlagsAuto: return g.makeTempVariableName(tempFlagsAuto, autoGenerate.Flags.IsReservedInNestedScopes(), ast.IsPrivateIdentifier(name), autoGenerate.Prefix, autoGenerate.Suffix) case GeneratedIdentifierFlagsLoop: - // Debug.assertNode(name, isIdentifier); + debug.AssertNode(name, ast.IsIdentifier) return g.makeTempVariableName(tempFlags_i, autoGenerate.Flags.IsReservedInNestedScopes(), false /*privateName*/, autoGenerate.Prefix, autoGenerate.Suffix) case GeneratedIdentifierFlagsUnique: return g.makeUniqueName( diff --git a/internal/transformers/declarations/transform.go b/internal/transformers/declarations/transform.go index a2776f39ff..0702913b00 100644 --- a/internal/transformers/declarations/transform.go +++ b/internal/transformers/declarations/transform.go @@ -5,6 +5,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/modulespecifiers" @@ -509,7 +510,7 @@ func (tx *DeclarationTransformer) checkName(node *ast.Node) { tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node) } tx.state.errorNameNode = node.Name() - // !!! Debug.assert(hasDynamicName(node as NamedDeclaration)); // Should only be called with dynamic names + debug.Assert(ast.HasDynamicName(node)) // Should only be called with dynamic names entityName := node.Name().AsComputedPropertyName().Expression tx.checkEntityNameVisibility(entityName, tx.enclosingDeclaration) if !tx.suppressNewDiagnosticContexts { @@ -1018,7 +1019,7 @@ func (tx *DeclarationTransformer) ensureType(node *ast.Node, ignorePrivate bool) } else if ast.IsFunctionLike(node) { typeNode = tx.resolver.CreateReturnTypeOfSignatureDeclaration(tx.EmitContext(), node, tx.enclosingDeclaration, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, tx.tracker) } else { - // Debug.assertNever(node); // !!! + debug.AssertNever(node) } tx.state.errorNameNode = oldErrorNameNode @@ -1525,8 +1526,6 @@ func (tx *DeclarationTransformer) ensureTypeParams(node *ast.Node, params *ast.T Nodes: nodes, } } - } else { - // Debug.assertNever(node); // !!! } tx.state.errorNameNode = oldErrorNameNode diff --git a/internal/transformers/estransforms/objectrestspread.go b/internal/transformers/estransforms/objectrestspread.go index c1191a19a2..da70ebc709 100644 --- a/internal/transformers/estransforms/objectrestspread.go +++ b/internal/transformers/estransforms/objectrestspread.go @@ -5,6 +5,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/transformers" ) @@ -862,15 +863,19 @@ func (ch *objectRestSpreadTransformer) emitExpression(node *ast.Node) { } func (ch *objectRestSpreadTransformer) emitAssignment(target *ast.Node, value *ast.Node, location core.TextRange, original *ast.Node) { - // Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression); // !!! + debug.AssertNode(target, ast.IsExpression) expr := ch.Factory().NewAssignmentExpression(ch.Visitor().VisitNode(target), value) expr.Loc = location ch.EmitContext().SetOriginal(expr, original) ch.emitExpression(expr) } +func isBindingName(node *ast.Node) bool { + return node.Kind == ast.KindIdentifier || node.Kind == ast.KindArrayBindingPattern || node.Kind == ast.KindObjectBindingPattern +} + func (ch *objectRestSpreadTransformer) emitBinding(target *ast.Node, value *ast.Node, location core.TextRange, original *ast.Node) { - // Debug.assertNode(target, isBindingName); // !!! + debug.AssertNode(target, isBindingName) if len(ch.ctx.currentExpressions) > 0 { value = ch.Factory().InlineExpressions(append(ch.ctx.currentExpressions, value)) ch.ctx.currentExpressions = nil diff --git a/internal/transformers/estransforms/optionalchain.go b/internal/transformers/estransforms/optionalchain.go index ad3af6984a..26632fffd4 100644 --- a/internal/transformers/estransforms/optionalchain.go +++ b/internal/transformers/estransforms/optionalchain.go @@ -2,6 +2,7 @@ package estransforms import ( "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/transformers" ) @@ -72,7 +73,7 @@ func (ch *optionalChainTransformer) visitPropertyOrElementAccessExpression(node return ch.visitOptionalExpression(node.AsNode(), captureThisArg, isDelete) } expression := ch.Visitor().VisitNode(node.Expression()) - // Debug.assertNotNode(expression, isSyntheticReference); // !!! + debug.AssertNotNode(expression, ast.IsSyntheticReferenceExpression) var thisArg *ast.Expression if captureThisArg { @@ -127,12 +128,16 @@ type flattenResult struct { chain []*ast.Node } +func isNonNullChain(node *ast.Node) bool { + return ast.IsNonNullExpression(node) && node.Flags&ast.NodeFlagsOptionalChain != 0 +} + func flattenChain(chain *ast.Node) flattenResult { - // Debug.assertNotNode(chain, isNonNullChain); // !!! + debug.AssertNotNode(chain, isNonNullChain) links := []*ast.Node{chain} for !ast.IsTaggedTemplateExpression(chain) && chain.QuestionDotToken() == nil { chain = ast.SkipPartiallyEmittedExpressions(chain.Expression()) - // Debug.assertNotNode(chain, isNonNullChain); // !!! + debug.AssertNotNode(chain, isNonNullChain) links = append([]*ast.Node{chain}, links...) } return flattenResult{chain.Expression(), links} diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go index ca6757f048..81edaf6bd1 100644 --- a/internal/tsoptions/tsconfigparsing.go +++ b/internal/tsoptions/tsconfigparsing.go @@ -11,6 +11,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/debug" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/module" @@ -1131,7 +1132,7 @@ func parseJsonConfigFileContentWorker( extraFileExtensions []FileExtensionInfo, extendedConfigCache *collections.SyncMap[tspath.Path, *ExtendedConfigCacheEntry], ) *ParsedCommandLine { - // Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined)); + debug.Assert((json == nil && sourceFile != nil) || (json != nil && sourceFile == nil)) basePathForFileNames := "" if configFileName != "" {