From 50198f57356df86043bf26eb18f478bd011b1086 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Mon, 28 Apr 2025 15:19:56 -0700 Subject: [PATCH 01/16] start implementing global completion symbol collection --- internal/ast/ast.go | 21 ++ internal/ast/utilities.go | 4 + internal/checker/checker.go | 188 +++++------ internal/checker/grammarchecks.go | 2 +- internal/checker/jsx.go | 8 +- internal/checker/relater.go | 2 +- internal/checker/services.go | 31 +- internal/checker/utilities.go | 6 +- internal/ls/completions.go | 499 ++++++++++++++++++++++++++++++ internal/ls/utilities.go | 185 +++++++++++ 10 files changed, 840 insertions(+), 106 deletions(-) diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 3a748397bc..3f7eb454f0 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -781,6 +781,20 @@ func (n *Node) ModuleSpecifier() *Expression { panic("Unhandled case in Node.ModuleSpecifier: " + n.Kind.String()) } +func (n *Node) Statement() *Statement { + switch n.Kind { + case KindDoStatement: + return n.AsDoStatement().Statement + case KindWhileStatement: + return n.AsWhileStatement().Statement + case KindForStatement: + return n.AsForStatement().Statement + case KindForInStatement, KindForOfStatement: + return n.AsForInOrOfStatement().Statement + } + panic("Unhandled case in Node.Statement: " + n.Kind.String()) +} + // Determines if `n` contains `descendant` by walking up the `Parent` pointers from `descendant`. This method panics if // `descendant` or one of its ancestors is not parented except when that node is a `SourceFile`. func (n *Node) Contains(descendant *Node) bool { @@ -1695,6 +1709,8 @@ type ( AnyValidImportOrReExport = Node // (ImportDeclaration | ExportDeclaration | JSDocImportTag) & { moduleSpecifier: StringLiteral } | ImportEqualsDeclaration & { moduleReference: ExternalModuleReference & { expression: StringLiteral }} | RequireOrImportCall | ValidImportTypeNode ValidImportTypeNode = Node // ImportTypeNode & { argument: LiteralTypeNode & { literal: StringLiteral } } NumericOrStringLikeLiteral = Node // StringLiteralLike | NumericLiteral + TypeOnlyImportDeclaration = Node // ImportClause | ImportEqualsDeclaration | ImportSpecifier | NamespaceImport with isTypeOnly: true + ObjectLiteralLike = Node // ObjectLiteralExpression | ObjectBindingPattern ) // Aliases for node singletons @@ -1737,6 +1753,7 @@ type ( JsxClosingFragmentNode = Node SourceFileNode = Node PropertyAccessExpressionNode = Node + TypeLiteral = Node ) type ( @@ -6943,6 +6960,10 @@ func (node *IntersectionTypeNode) Clone(f NodeFactoryCoercible) *Node { return cloneNode(f.AsNodeFactory().NewIntersectionTypeNode(node.Types), node.AsNode(), f.AsNodeFactory().hooks) } +func IsIntersectionTypeNode(node *Node) bool { + return node.Kind == KindIntersectionType +} + // ConditionalTypeNode type ConditionalTypeNode struct { diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index ffe9baee60..9f37f3fa51 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -2801,3 +2801,7 @@ func ForEachChildAndJSDoc(node *Node, sourceFile *SourceFile, v Visitor) bool { } return node.ForEachChild(v) } + +func IsTypeReferenceType(node *Node) bool { + return node.Kind == KindTypeReference || node.Kind == KindExpressionWithTypeArguments +} diff --git a/internal/checker/checker.go b/internal/checker/checker.go index b8faefb747..622e1e2955 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -1093,7 +1093,7 @@ func (c *Checker) getGlobalTypeAliasResolver(name string, arity int, reportError // Resolve to the global value symbol by the given name, or nil otherwise func (c *Checker) getGlobalValueSymbolResolver(name string, reportErrors bool) func() *ast.Symbol { return core.Memoize(func() *ast.Symbol { - return c.getGlobalSymbol(name, ast.SymbolFlagsValue, core.IfElse(reportErrors, diagnostics.Cannot_find_global_value_0, nil)) + return c.GetGlobalSymbol(name, ast.SymbolFlagsValue, core.IfElse(reportErrors, diagnostics.Cannot_find_global_value_0, nil)) }) } @@ -1106,7 +1106,7 @@ func (c *Checker) getGlobalTypesResolver(names []string, arity int, reportErrors } func (c *Checker) getGlobalTypeAliasSymbol(name string, arity int, reportErrors bool) *ast.Symbol { - symbol := c.getGlobalSymbol(name, ast.SymbolFlagsTypeAlias, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) + symbol := c.GetGlobalSymbol(name, ast.SymbolFlagsTypeAlias, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) if symbol == nil { return nil } @@ -1123,7 +1123,7 @@ func (c *Checker) getGlobalTypeAliasSymbol(name string, arity int, reportErrors } func (c *Checker) getGlobalType(name string, arity int, reportErrors bool) *Type { - symbol := c.getGlobalSymbol(name, ast.SymbolFlagsType, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) + symbol := c.GetGlobalSymbol(name, ast.SymbolFlagsType, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) if symbol != nil { if symbol.Flags&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface) != 0 { t := c.getDeclaredTypeOfSymbol(symbol) @@ -1153,7 +1153,7 @@ func getGlobalTypeDeclaration(symbol *ast.Symbol) *ast.Declaration { return nil } -func (c *Checker) getGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { +func (c *Checker) GetGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { // Don't track references for global symbols anyway, so value if `isReference` is arbitrary return c.resolveName(nil, name, meaning, diagnostic, false /*isUse*/, false /*excludeGlobals*/) } @@ -1711,7 +1711,7 @@ func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result * c.error(errorLocation, diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, scanner.DeclarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.Name()), scanner.DeclarationNameToString(errorLocation)) } } - if errorLocation != nil && meaning&ast.SymbolFlagsValue != 0 && result.Flags&ast.SymbolFlagsAlias != 0 && result.Flags&ast.SymbolFlagsValue == 0 && !isValidTypeOnlyAliasUseSite(errorLocation) { + if errorLocation != nil && meaning&ast.SymbolFlagsValue != 0 && result.Flags&ast.SymbolFlagsAlias != 0 && result.Flags&ast.SymbolFlagsValue == 0 && !IsValidTypeOnlyAliasUseSite(errorLocation) { typeOnlyDeclaration := c.getTypeOnlyAliasDeclarationEx(result, ast.SymbolFlagsValue) if typeOnlyDeclaration != nil { message := core.IfElse(ast.NodeKindIs(typeOnlyDeclaration, ast.KindExportSpecifier, ast.KindExportDeclaration, ast.KindNamespaceExport), @@ -2370,7 +2370,7 @@ func (c *Checker) checkJSDocTypeIsInJsFile(node *ast.Node) { message := core.IfElse(postfix, diagnostics.X_0_at_the_end_of_a_type_is_not_valid_TypeScript_syntax_Did_you_mean_to_write_1, diagnostics.X_0_at_the_start_of_a_type_is_not_valid_TypeScript_syntax_Did_you_mean_to_write_1) - t := c.getTypeFromTypeNode(node.Type()) + t := c.GetTypeFromTypeNode(node.Type()) if ast.IsJSDocNullableType(node) && t != c.neverType && t != c.voidType { t = c.getNullableType(t, core.IfElse(postfix, TypeFlagsUndefined, TypeFlagsNullable)) } @@ -2515,7 +2515,7 @@ func (c *Checker) checkSignatureDeclaration(node *ast.Node) { if returnTypeNode != nil { functionFlags := getFunctionFlags(node) if (functionFlags & (FunctionFlagsInvalid | FunctionFlagsGenerator)) == FunctionFlagsGenerator { - returnType := c.getTypeFromTypeNode(returnTypeNode) + returnType := c.GetTypeFromTypeNode(returnTypeNode) if returnType == c.voidType { c.error(returnTypeNode, diagnostics.A_generator_cannot_have_a_void_type_annotation) } else { @@ -2539,7 +2539,7 @@ func (c *Checker) checkSignatureDeclaration(node *ast.Node) { // that in turn supplies a `resolve` function as one of its arguments and results in an // object with a callable `then` signature. func (c *Checker) checkAsyncFunctionReturnType(node *ast.Node, returnTypeNode *ast.Node) { - returnType := c.getTypeFromTypeNode(returnTypeNode) + returnType := c.GetTypeFromTypeNode(returnTypeNode) if c.isErrorType(returnType) { return } @@ -2757,7 +2757,7 @@ func (c *Checker) checkTypeReferenceNode(node *ast.Node) { } func (c *Checker) checkTypeReferenceOrImport(node *ast.Node) { - t := c.getTypeFromTypeNode(node) + t := c.GetTypeFromTypeNode(node) if !c.isErrorType(t) { if len(node.TypeArguments()) != 0 { typeParameters := c.getTypeParametersForTypeReferenceOrImport(node) @@ -2988,7 +2988,7 @@ func (c *Checker) checkTupleType(node *ast.Node) { for _, e := range elements { flags := c.getTupleElementFlags(e) if flags&ElementFlagsVariadic != 0 { - t := c.getTypeFromTypeNode(e.Type()) + t := c.GetTypeFromTypeNode(e.Type()) if !c.isArrayLikeType(t) { c.error(e, diagnostics.A_rest_element_type_must_be_an_array_type) break @@ -3015,12 +3015,12 @@ func (c *Checker) checkTupleType(node *ast.Node) { } } c.checkSourceElements(elements) - c.getTypeFromTypeNode(node) + c.GetTypeFromTypeNode(node) } func (c *Checker) checkUnionOrIntersectionType(node *ast.Node) { node.ForEachChild(c.checkSourceElement) - c.getTypeFromTypeNode(node) + c.GetTypeFromTypeNode(node) } func (c *Checker) checkThisType(node *ast.Node) { @@ -3066,10 +3066,10 @@ func (c *Checker) checkInferType(node *ast.Node) { func (c *Checker) checkTemplateLiteralType(node *ast.Node) { for _, span := range node.AsTemplateLiteralTypeNode().TemplateSpans.Nodes { c.checkSourceElement(span.Type()) - t := c.getTypeFromTypeNode(span.Type()) + t := c.GetTypeFromTypeNode(span.Type()) c.checkTypeAssignableTo(t, c.templateConstraintType, span.Type(), nil) } - c.getTypeFromTypeNode(node) + c.GetTypeFromTypeNode(node) } func (c *Checker) checkImportType(node *ast.Node) { @@ -3129,7 +3129,7 @@ func (c *Checker) checkNamedTupleMember(node *ast.Node) { c.grammarErrorOnNode(tupleMember.Type, diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type) } c.checkSourceElement(node.Type()) - c.getTypeFromTypeNode(node) + c.GetTypeFromTypeNode(node) } func (c *Checker) checkIndexedAccessType(node *ast.Node) { @@ -3959,7 +3959,7 @@ func (c *Checker) checkCatchClause(node *ast.Node) { c.checkVariableLikeDeclaration(declaration) typeNode := declaration.Type() if typeNode != nil { - t := c.getTypeFromTypeNode(typeNode) + t := c.GetTypeFromTypeNode(typeNode) if t != nil && t.flags&TypeFlagsAnyOrUnknown == 0 { c.grammarErrorOnFirstToken(typeNode, diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified) } @@ -4071,7 +4071,7 @@ func (c *Checker) checkClassLikeDeclaration(node *ast.Node) { c.error(expr, diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments) } c.checkTypeReferenceNode(typeRefNode) - t := c.getReducedType(c.getTypeFromTypeNode(typeRefNode)) + t := c.getReducedType(c.GetTypeFromTypeNode(typeRefNode)) if !c.isErrorType(t) { if c.isValidBaseType(t) { genericDiag := core.IfElse(t.symbol != nil && t.symbol.Flags&ast.SymbolFlagsClass != 0, @@ -4143,14 +4143,14 @@ func (c *Checker) areTypeParametersIdentical(declarations []*ast.Node, targetPar targetConstraint := c.getConstraintOfTypeParameter(target) // relax check if later interface augmentation has no constraint, it's more broad and is OK to merge with // a more constrained interface (this could be generalized to a full hierarchy check, but that's maybe overkill) - if constraintNode != nil && targetConstraint != nil && !c.isTypeIdenticalTo(c.getTypeFromTypeNode(constraintNode), targetConstraint) { + if constraintNode != nil && targetConstraint != nil && !c.isTypeIdenticalTo(c.GetTypeFromTypeNode(constraintNode), targetConstraint) { return false } // If the type parameter node has a default and it is not identical to the default // for the type parameter at this position, we report an error. defaultNode := source.AsTypeParameter().DefaultType targetDefault := c.getDefaultFromTypeParameter(target) - if defaultNode != nil && targetDefault != nil && !c.isTypeIdenticalTo(c.getTypeFromTypeNode(defaultNode), targetDefault) { + if defaultNode != nil && targetDefault != nil && !c.isTypeIdenticalTo(c.GetTypeFromTypeNode(defaultNode), targetDefault) { return false } } @@ -4590,7 +4590,7 @@ func (c *Checker) checkTypeForDuplicateIndexSignatures(node *ast.Node) { if ast.IsIndexSignatureDeclaration(declaration) { parameters := declaration.Parameters() if len(parameters) == 1 && parameters[0].Type() != nil { - for _, t := range c.getTypeFromTypeNode(parameters[0].Type()).Distributed() { + for _, t := range c.GetTypeFromTypeNode(parameters[0].Type()).Distributed() { indexSignatureMap[t] = append(indexSignatureMap[t], declaration) } } @@ -6889,7 +6889,7 @@ func (c *Checker) getQuickTypeOfExpression(node *ast.Node) *Type { } return c.getReturnTypeOfSingleNonGenericCallSignature(c.checkNonNullExpression(expr.Expression())) case ast.IsAssertionExpression(expr) && !ast.IsConstTypeReference(expr.Type()): - return c.getTypeFromTypeNode(expr.Type()) + return c.GetTypeFromTypeNode(expr.Type()) case ast.IsLiteralExpression(node) || ast.IsBooleanLiteral(node): return c.checkExpression(node) } @@ -8803,7 +8803,7 @@ func (c *Checker) hasCorrectTypeArgumentArity(signature *Signature, typeArgument func (c *Checker) checkTypeArguments(signature *Signature, typeArgumentNodes []*ast.Node, reportErrors bool, headMessage *diagnostics.Message) []*Type { typeParameters := signature.typeParameters - typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) + typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.GetTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) var mapper *TypeMapper for i := range typeArgumentNodes { // Debug.assert(typeParameters[i] != nil, "Should not call checkTypeArguments with too many type arguments") @@ -9142,7 +9142,7 @@ func (c *Checker) getTypeArgumentsFromNodes(typeArgumentNodes []*ast.Node, typeP if len(typeArgumentNodes) > len(typeParameters) { typeArgumentNodes = typeArgumentNodes[:len(typeParameters)] } - typeArguments := core.Map(typeArgumentNodes, c.getTypeFromTypeNode) + typeArguments := core.Map(typeArgumentNodes, c.GetTypeFromTypeNode) for len(typeArguments) < len(typeParameters) { t := c.getDefaultFromTypeParameter(typeParameters[len(typeArguments)]) if t == nil { @@ -9752,7 +9752,7 @@ func (c *Checker) inferFromAnnotatedParameters(sig *Signature, context *Signatur declaration := sig.parameters[i].ValueDeclaration typeNode := declaration.Type() if typeNode != nil { - source := c.addOptionalityEx(c.getTypeFromTypeNode(typeNode), false /*isProperty*/, isOptionalDeclaration(declaration)) + source := c.addOptionalityEx(c.GetTypeFromTypeNode(typeNode), false /*isProperty*/, isOptionalDeclaration(declaration)) target := c.getTypeAtPosition(context, i) c.inferTypes(inferenceContext.inferences, source, target, InferencePriorityNone, false) } @@ -10133,7 +10133,7 @@ func (c *Checker) checkSatisfiesExpression(node *ast.Node) *Type { func (c *Checker) checkSatisfiesExpressionWorker(expression *ast.Node, target *ast.Node, checkMode CheckMode) *Type { exprType := c.checkExpressionEx(expression, checkMode) - targetType := c.getTypeFromTypeNode(target) + targetType := c.GetTypeFromTypeNode(target) if c.isErrorType(targetType) { return targetType } @@ -11350,7 +11350,7 @@ func (c *Checker) getEnclosingClassFromThisParameter(node *ast.Node) *Type { thisParameter := getThisParameterFromNodeContext(node) var thisType *Type if thisParameter != nil && thisParameter.AsParameterDeclaration().Type != nil { - thisType = c.getTypeFromTypeNode(thisParameter.AsParameterDeclaration().Type) + thisType = c.GetTypeFromTypeNode(thisParameter.AsParameterDeclaration().Type) } if thisType != nil { // 2. The constraint of a type parameter used for an explicit 'this' parameter @@ -11640,12 +11640,12 @@ func (c *Checker) checkAssertion(node *ast.Node, checkMode CheckMode) *Type { links.exprType = exprType c.checkSourceElement(typeNode) c.checkNodeDeferred(node) - return c.getTypeFromTypeNode(typeNode) + return c.GetTypeFromTypeNode(typeNode) } func (c *Checker) checkAssertionDeferred(node *ast.Node) { exprType := c.getRegularTypeOfObjectLiteral(c.getBaseTypeOfLiteralType(c.assertionLinks.Get(node).exprType)) - targetType := c.getTypeFromTypeNode(node.Type()) + targetType := c.GetTypeFromTypeNode(node.Type()) if !c.isErrorType(targetType) { widenedType := c.getWidenedType(exprType) if !c.isTypeComparableTo(targetType, widenedType) { @@ -13908,7 +13908,7 @@ func (c *Checker) getPropertyOfVariable(symbol *ast.Symbol, name string) *ast.Sy if symbol.Flags&ast.SymbolFlagsVariable != 0 { typeAnnotation := symbol.ValueDeclaration.AsVariableDeclaration().Type if typeAnnotation != nil { - return c.resolveSymbol(c.getPropertyOfType(c.getTypeFromTypeNode(typeAnnotation), name)) + return c.resolveSymbol(c.getPropertyOfType(c.GetTypeFromTypeNode(typeAnnotation), name)) } } return nil @@ -15731,7 +15731,7 @@ func (c *Checker) getConstraintFromTypeParameter(t *Type) *Type { } else { constraintDeclaration := c.getConstraintDeclaration(t) if constraintDeclaration != nil { - constraint = c.getTypeFromTypeNode(constraintDeclaration) + constraint = c.GetTypeFromTypeNode(constraintDeclaration) if constraint.flags&TypeFlagsAny != 0 && !c.isErrorType(constraint) { // use stringNumberSymbolType as the base constraint for mapped type key constraints (unknown isn;t assignable to that, but `any` was), // use unknown otherwise @@ -15817,11 +15817,11 @@ func (c *Checker) getInferredTypeParameterConstraint(t *Type, omitTypeReferences ast.IsMappedTypeNode(parent.Parent.AsConditionalTypeNode().CheckType) && parent.Parent.AsConditionalTypeNode().CheckType.AsMappedTypeNode().Type != nil: checkMappedType := parent.Parent.AsConditionalTypeNode().CheckType - nodeType := c.getTypeFromTypeNode(checkMappedType.AsMappedTypeNode().Type) + nodeType := c.GetTypeFromTypeNode(checkMappedType.AsMappedTypeNode().Type) checkMappedTypeParameter := checkMappedType.AsMappedTypeNode().TypeParameter mapper := newSimpleTypeMapper(c.getDeclaredTypeOfTypeParameter(c.getSymbolOfDeclaration(checkMappedTypeParameter)), core.IfElse(checkMappedTypeParameter.AsTypeParameter().Constraint != nil, - c.getTypeFromTypeNode(checkMappedTypeParameter.AsTypeParameter().Constraint), + c.GetTypeFromTypeNode(checkMappedTypeParameter.AsTypeParameter().Constraint), c.stringNumberSymbolType)) inferences = append(inferences, c.instantiateType(nodeType, mapper)) } @@ -15835,7 +15835,7 @@ func (c *Checker) getInferredTypeParameterConstraint(t *Type, omitTypeReferences } func (c *Checker) getTypeParametersForTypeReferenceOrImport(node *ast.Node) []*Type { - t := c.getTypeFromTypeNode(node) + t := c.GetTypeFromTypeNode(node) if !c.isErrorType(t) { symbol := c.getResolvedSymbolOrNil(node) if symbol != nil { @@ -15862,7 +15862,7 @@ func (c *Checker) getTypeParametersForTypeAndSymbol(t *Type, symbol *ast.Symbol) func (c *Checker) getEffectiveTypeArgumentAtIndex(node *ast.Node, typeParameters []*Type, index int) *Type { typeArguments := node.TypeArguments() if index < len(typeArguments) { - return c.getTypeFromTypeNode(typeArguments[index]) + return c.GetTypeFromTypeNode(typeArguments[index]) } return c.getEffectiveTypeArguments(node, typeParameters)[index] } @@ -17712,7 +17712,7 @@ func getBaseTypeNodeOfClass(t *Type) *ast.Node { func (c *Checker) getInstantiatedConstructorsForTypeArguments(t *Type, typeArgumentNodes []*ast.Node, location *ast.Node) []*Signature { signatures := c.getConstructorsForTypeArguments(t, typeArgumentNodes, location) - typeArguments := core.Map(typeArgumentNodes, c.getTypeFromTypeNode) + typeArguments := core.Map(typeArgumentNodes, c.GetTypeFromTypeNode) return core.SameMap(signatures, func(sig *Signature) *Signature { if len(sig.typeParameters) != 0 { return c.getSignatureInstantiation(sig, typeArguments, nil) @@ -17940,7 +17940,7 @@ func (c *Checker) resolveBaseTypesOfInterface(t *Type) { for _, declaration := range t.symbol.Declarations { if ast.IsInterfaceDeclaration(declaration) { for _, node := range ast.GetExtendsHeritageClauseElements(declaration) { - baseType := c.getReducedType(c.getTypeFromTypeNode(node)) + baseType := c.getReducedType(c.GetTypeFromTypeNode(node)) if !c.isErrorType(baseType) { if c.isValidBaseType(baseType) { if t != baseType && !c.hasBaseType(baseType, t) { @@ -18089,9 +18089,9 @@ func (c *Checker) getIndexInfosOfIndexSymbol(indexSymbol *ast.Symbol, siblingSym if typeNode != nil { valueType := c.anyType if returnTypeNode != nil { - valueType = c.getTypeFromTypeNode(returnTypeNode) + valueType = c.GetTypeFromTypeNode(returnTypeNode) } - forEachType(c.getTypeFromTypeNode(typeNode), func(keyType *Type) { + forEachType(c.GetTypeFromTypeNode(typeNode), func(keyType *Type) { if c.isValidIndexKeyType(keyType) && findIndexInfo(indexInfos, keyType) == nil { indexInfo := c.newIndexInfo(keyType, valueType, hasModifier(declaration, ast.ModifierFlagsReadonly), declaration) indexInfos = append(indexInfos, indexInfo) @@ -18473,7 +18473,7 @@ func (c *Checker) getReturnTypeFromAnnotation(declaration *ast.Node) *Type { } returnType := declaration.Type() if returnType != nil { - return c.getTypeFromTypeNode(returnType) + return c.GetTypeFromTypeNode(returnType) } if ast.IsGetAccessorDeclaration(declaration) && c.hasBindableName(declaration) { return c.getAnnotatedAccessorType(ast.GetDeclarationOfKind(c.getSymbolOfDeclaration(declaration), ast.KindSetAccessor)) @@ -18484,7 +18484,7 @@ func (c *Checker) getReturnTypeFromAnnotation(declaration *ast.Node) *Type { func (c *Checker) getAnnotatedAccessorType(accessor *ast.Node) *Type { node := c.getAnnotatedAccessorTypeNode(accessor) if node != nil { - return c.getTypeFromTypeNode(node) + return c.GetTypeFromTypeNode(node) } return nil } @@ -20328,9 +20328,9 @@ func (c *Checker) getTypeArguments(t *Type) []*Type { case ast.KindTypeReference: typeArguments = append(n.OuterTypeParameters(), c.getEffectiveTypeArguments(node, n.LocalTypeParameters())...) case ast.KindArrayType: - typeArguments = []*Type{c.getTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} + typeArguments = []*Type{c.GetTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} case ast.KindTupleType: - typeArguments = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.getTypeFromTypeNode) + typeArguments = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.GetTypeFromTypeNode) default: panic("Unhandled case in getTypeArguments") } @@ -20355,7 +20355,7 @@ func (c *Checker) getTypeArguments(t *Type) []*Type { } func (c *Checker) getEffectiveTypeArguments(node *ast.Node, typeParameters []*Type) []*Type { - return c.fillMissingTypeArguments(core.Map(node.TypeArguments(), c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) + return c.fillMissingTypeArguments(core.Map(node.TypeArguments(), c.GetTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) } // Gets the minimum number of type arguments needed to satisfy all non-optional type parameters. @@ -20434,7 +20434,7 @@ func (c *Checker) getResolvedTypeParameterDefault(t *Type) *Type { return nil }) if defaultDeclaration != nil { - defaultType = c.getTypeFromTypeNode(defaultDeclaration) + defaultType = c.GetTypeFromTypeNode(defaultDeclaration) } } if d.resolvedDefaultType == c.resolvingDefaultType { @@ -21023,7 +21023,7 @@ func (c *Checker) getNameTypeFromMappedType(t *Type) *Type { return nil } if m.nameType == nil { - m.nameType = c.instantiateType(c.getTypeFromTypeNode(m.declaration.NameType), m.mapper) + m.nameType = c.instantiateType(c.GetTypeFromTypeNode(m.declaration.NameType), m.mapper) } return m.nameType } @@ -21032,7 +21032,7 @@ func (c *Checker) getTemplateTypeFromMappedType(t *Type) *Type { m := t.AsMappedType() if m.templateType == nil { if m.declaration.Type != nil { - m.templateType = c.instantiateType(c.addOptionalityEx(c.getTypeFromTypeNode(m.declaration.Type) /*isProperty*/, true, getMappedTypeModifiers(t)&MappedTypeModifiersIncludeOptional != 0), m.mapper) + m.templateType = c.instantiateType(c.addOptionalityEx(c.GetTypeFromTypeNode(m.declaration.Type) /*isProperty*/, true, getMappedTypeModifiers(t)&MappedTypeModifiersIncludeOptional != 0), m.mapper) } else { m.templateType = c.errorType } @@ -21133,12 +21133,12 @@ func instantiateList[T comparable](c *Checker, values []T, m *TypeMapper, instan func (c *Checker) tryGetTypeFromTypeNode(node *ast.Node) *Type { typeNode := node.Type() if typeNode != nil { - return c.getTypeFromTypeNode(typeNode) + return c.GetTypeFromTypeNode(typeNode) } return nil } -func (c *Checker) getTypeFromTypeNode(node *ast.Node) *Type { +func (c *Checker) GetTypeFromTypeNode(node *ast.Node) *Type { return c.getConditionalFlowTypeOfType(c.getTypeFromTypeNodeWorker(node), node) } @@ -21147,18 +21147,18 @@ func (c *Checker) getTypeFromTypeNodeWorker(node *ast.Node) *Type { case ast.KindAnyKeyword, ast.KindJSDocAllType: return c.anyType case ast.KindJSDocNonNullableType: - return c.getTypeFromTypeNode(node.AsJSDocNonNullableType().Type) + return c.GetTypeFromTypeNode(node.AsJSDocNonNullableType().Type) case ast.KindJSDocNullableType: - t := c.getTypeFromTypeNode(node.AsJSDocNullableType().Type) + t := c.GetTypeFromTypeNode(node.AsJSDocNullableType().Type) if c.strictNullChecks { return c.getNullableType(t, TypeFlagsNull) } else { return t } case ast.KindJSDocVariadicType: - return c.createArrayType(c.getTypeFromTypeNode(node.AsJSDocVariadicType().Type)) + return c.createArrayType(c.GetTypeFromTypeNode(node.AsJSDocVariadicType().Type)) case ast.KindJSDocOptionalType: - return c.addOptionality(c.getTypeFromTypeNode(node.AsJSDocOptionalType().Type)) + return c.addOptionality(c.GetTypeFromTypeNode(node.AsJSDocOptionalType().Type)) case ast.KindUnknownKeyword: return c.unknownType case ast.KindStringKeyword: @@ -21207,7 +21207,7 @@ func (c *Checker) getTypeFromTypeNodeWorker(node *ast.Node) *Type { case ast.KindNamedTupleMember: return c.getTypeFromNamedTupleTypeNode(node) case ast.KindParenthesizedType: - return c.getTypeFromTypeNode(node.AsParenthesizedTypeNode().Type) + return c.GetTypeFromTypeNode(node.AsParenthesizedTypeNode().Type) case ast.KindRestType: return c.getTypeFromRestTypeNode(node) case ast.KindFunctionType, ast.KindConstructorType, ast.KindTypeLiteral: @@ -21283,8 +21283,8 @@ func (c *Checker) getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node *as func (c *Checker) getTypeFromIndexedAccessTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { - objectType := c.getTypeFromTypeNode(node.AsIndexedAccessTypeNode().ObjectType) - indexType := c.getTypeFromTypeNode(node.AsIndexedAccessTypeNode().IndexType) + objectType := c.GetTypeFromTypeNode(node.AsIndexedAccessTypeNode().ObjectType) + indexType := c.GetTypeFromTypeNode(node.AsIndexedAccessTypeNode().IndexType) potentialAlias := c.getAliasForTypeNode(node) links.resolvedType = c.getIndexedAccessTypeEx(objectType, indexType, AccessFlagsNone, node, potentialAlias) } @@ -21297,7 +21297,7 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type { argType := node.AsTypeOperatorNode().Type switch node.AsTypeOperatorNode().Operator { case ast.KindKeyOfKeyword: - links.resolvedType = c.getIndexType(c.getTypeFromTypeNode(argType)) + links.resolvedType = c.getIndexType(c.GetTypeFromTypeNode(argType)) case ast.KindUniqueKeyword: if argType.Kind == ast.KindSymbolKeyword { links.resolvedType = c.getESSymbolLikeTypeForNode(ast.WalkUpParenthesizedTypes(node.Parent)) @@ -21305,7 +21305,7 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type { links.resolvedType = c.errorType } case ast.KindReadonlyKeyword: - links.resolvedType = c.getTypeFromTypeNode(argType) + links.resolvedType = c.GetTypeFromTypeNode(argType) default: panic("Unhandled case in getTypeFromTypeOperatorNode") } @@ -21476,7 +21476,7 @@ func (c *Checker) getTypeFromClassOrInterfaceReference(node *ast.Node, symbol *a } func (c *Checker) getTypeArgumentsFromNode(node *ast.Node) []*Type { - return core.Map(node.TypeArguments(), c.getTypeFromTypeNode) + return core.Map(node.TypeArguments(), c.GetTypeFromTypeNode) } func (c *Checker) checkNoTypeArguments(node *ast.Node, symbol *ast.Symbol) bool { @@ -21831,7 +21831,7 @@ func (c *Checker) getTupleElementType(t *Type, index int) *Type { func (c *Checker) getTypeFromTypeAliasReference(node *ast.Node, symbol *ast.Symbol) *Type { typeArguments := node.TypeArguments() if symbol.CheckFlags&ast.CheckFlagsUnresolved != 0 { - alias := &TypeAlias{symbol: symbol, typeArguments: core.Map(typeArguments, c.getTypeFromTypeNode)} + alias := &TypeAlias{symbol: symbol, typeArguments: core.Map(typeArguments, c.GetTypeFromTypeNode)} key := getAliasKey(alias) errorType := c.errorTypes[key] if errorType == nil { @@ -21865,7 +21865,7 @@ func (c *Checker) getTypeFromTypeAliasReference(node *ast.Node, symbol *ast.Symb var aliasTypeArguments []*Type if newAliasSymbol != nil { aliasTypeArguments = c.getTypeArgumentsForAliasSymbol(newAliasSymbol) - } else if isTypeReferenceType(node) { + } else if ast.IsTypeReferenceType(node) { aliasSymbol := c.resolveTypeReferenceName(node, ast.SymbolFlagsAlias, true /*ignoreErrors*/) // refers to an alias import/export/reexport - by making sure we use the target as an aliasSymbol, // we ensure the exported symbol is used to refer to the type when it is reserialized later @@ -22095,7 +22095,7 @@ func (c *Checker) getDeclaredTypeOfTypeAlias(symbol *ast.Symbol) *Type { } declaration := core.Find(symbol.Declarations, ast.IsTypeOrJSTypeAliasDeclaration) typeNode := declaration.AsTypeAliasDeclaration().Type - t := c.getTypeFromTypeNode(typeNode) + t := c.GetTypeFromTypeNode(typeNode) if c.popTypeResolution() { typeParameters := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) if len(typeParameters) != 0 { @@ -22277,7 +22277,7 @@ func (c *Checker) evaluateEntity(expr *ast.Node, location *ast.Node) evaluator.R return evaluator.NewResult(nil, false, false, false) } if expr.Kind == ast.KindIdentifier { - if isInfinityOrNaNString(expr.Text()) && (symbol == c.getGlobalSymbol(expr.Text(), ast.SymbolFlagsValue, nil /*diagnostic*/)) { + if isInfinityOrNaNString(expr.Text()) && (symbol == c.GetGlobalSymbol(expr.Text(), ast.SymbolFlagsValue, nil /*diagnostic*/)) { // Technically we resolved a global lib file here, but the decision to treat this as numeric // is more predicated on the fact that the single-file resolution *didn't* resolve to a // different meaning of `Infinity` or `NaN`. Transpilers handle this no problem. @@ -22376,9 +22376,9 @@ func (c *Checker) getTypeFromArrayOrTupleTypeNode(node *ast.Node) *Type { } else { var elementTypes []*Type if node.Kind == ast.KindArrayType { - elementTypes = []*Type{c.getTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} + elementTypes = []*Type{c.GetTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} } else { - elementTypes = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.getTypeFromTypeNode) + elementTypes = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.GetTypeFromTypeNode) } links.resolvedType = c.createNormalizedTypeReference(target, elementTypes) } @@ -22412,7 +22412,7 @@ func (c *Checker) getTypeFromNamedTupleTypeNode(node *ast.Node) *Type { if node.AsNamedTupleMember().DotDotDotToken != nil { links.resolvedType = c.getTypeFromRestTypeNode(node) } else { - links.resolvedType = c.addOptionalityEx(c.getTypeFromTypeNode(node.Type()), true /*isProperty*/, node.AsNamedTupleMember().QuestionToken != nil) + links.resolvedType = c.addOptionalityEx(c.GetTypeFromTypeNode(node.Type()), true /*isProperty*/, node.AsNamedTupleMember().QuestionToken != nil) } } return links.resolvedType @@ -22424,7 +22424,7 @@ func (c *Checker) getTypeFromRestTypeNode(node *ast.Node) *Type { if elementTypeNode != nil { typeNode = elementTypeNode } - return c.getTypeFromTypeNode(typeNode) + return c.GetTypeFromTypeNode(typeNode) } func (c *Checker) getArrayElementTypeNode(node *ast.Node) *ast.Node { @@ -22448,14 +22448,14 @@ func (c *Checker) getArrayElementTypeNode(node *ast.Node) *ast.Node { } func (c *Checker) getTypeFromOptionalTypeNode(node *ast.Node) *Type { - return c.addOptionalityEx(c.getTypeFromTypeNode(node.AsOptionalTypeNode().Type), true /*isProperty*/, true /*isOptional*/) + return c.addOptionalityEx(c.GetTypeFromTypeNode(node.AsOptionalTypeNode().Type), true /*isProperty*/, true /*isOptional*/) } func (c *Checker) getTypeFromUnionTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { alias := c.getAliasForTypeNode(node) - links.resolvedType = c.getUnionTypeEx(core.Map(node.AsUnionTypeNode().Types.Nodes, c.getTypeFromTypeNode), UnionReductionLiteral, alias, nil /*origin*/) + links.resolvedType = c.getUnionTypeEx(core.Map(node.AsUnionTypeNode().Types.Nodes, c.GetTypeFromTypeNode), UnionReductionLiteral, alias, nil /*origin*/) } return links.resolvedType } @@ -22464,7 +22464,7 @@ func (c *Checker) getTypeFromIntersectionTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { alias := c.getAliasForTypeNode(node) - types := core.Map(node.AsIntersectionTypeNode().Types.Nodes, c.getTypeFromTypeNode) + types := core.Map(node.AsIntersectionTypeNode().Types.Nodes, c.GetTypeFromTypeNode) // We perform no supertype reduction for X & {} or {} & X, where X is one of string, number, bigint, // or a pattern literal template type. This enables union types like "a" | "b" | string & {} or // "aa" | "ab" | `a${string}` which preserve the literal types for purposes of statement completion. @@ -22490,7 +22490,7 @@ func (c *Checker) getTypeFromTemplateTypeNode(node *ast.Node) *Type { texts[0] = node.AsTemplateLiteralTypeNode().Head.Text() for i, span := range spans.Nodes { texts[i+1] = span.AsTemplateLiteralTypeSpan().Literal.Text() - types[i] = c.getTypeFromTypeNode(span.AsTemplateLiteralTypeSpan().Type) + types[i] = c.GetTypeFromTypeNode(span.AsTemplateLiteralTypeSpan().Type) } links.resolvedType = c.getTemplateLiteralType(texts, types) } @@ -22514,7 +22514,7 @@ func (c *Checker) getTypeFromMappedTypeNode(node *ast.Node) *Type { func (c *Checker) getTypeFromConditionalTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { - checkType := c.getTypeFromTypeNode(node.AsConditionalTypeNode().CheckType) + checkType := c.GetTypeFromTypeNode(node.AsConditionalTypeNode().CheckType) alias := c.getAliasForTypeNode(node) allOuterTypeParameters := c.getOuterTypeParameters(node, true /*includeThisTypes*/) var outerTypeParameters []*Type @@ -22526,7 +22526,7 @@ func (c *Checker) getTypeFromConditionalTypeNode(node *ast.Node) *Type { root := &ConditionalRoot{ node: node.AsConditionalTypeNode(), checkType: checkType, - extendsType: c.getTypeFromTypeNode(node.AsConditionalTypeNode().ExtendsType), + extendsType: c.GetTypeFromTypeNode(node.AsConditionalTypeNode().ExtendsType), isDistributive: checkType.flags&TypeFlagsTypeParameter != 0, inferTypeParameters: c.getInferTypeParameters(node), outerTypeParameters: outerTypeParameters, @@ -22628,11 +22628,11 @@ func (c *Checker) getConditionalType(root *ConditionalRoot, mapper *TypeMapper, if checkType.flags&TypeFlagsAny != 0 || forConstraint && inferredExtendsType.flags&TypeFlagsNever == 0 && someType(c.getPermissiveInstantiation(inferredExtendsType), func(t *Type) bool { return c.isTypeAssignableTo(t, c.getPermissiveInstantiation(checkType)) }) { - extraTypes = append(extraTypes, c.instantiateType(c.getTypeFromTypeNode(root.node.TrueType), core.OrElse(combinedMapper, mapper))) + extraTypes = append(extraTypes, c.instantiateType(c.GetTypeFromTypeNode(root.node.TrueType), core.OrElse(combinedMapper, mapper))) } // If falseType is an immediately nested conditional type that isn't distributive or has an // identical checkType, switch to that type and loop. - falseType := c.getTypeFromTypeNode(root.node.FalseType) + falseType := c.GetTypeFromTypeNode(root.node.FalseType) if falseType.flags&TypeFlagsConditional != 0 { newRoot := falseType.AsConditionalType().root if newRoot.node.Parent == root.node.AsNode() && (!newRoot.isDistributive || newRoot.checkType == root.checkType) { @@ -22658,7 +22658,7 @@ func (c *Checker) getConditionalType(root *ConditionalRoot, mapper *TypeMapper, // type Foo = T extends { x: string } ? string : number // doesn't immediately resolve to 'string' instead of being deferred. if inferredExtendsType.flags&TypeFlagsAnyOrUnknown != 0 || c.isTypeAssignableTo(c.getRestrictiveInstantiation(checkType), c.getRestrictiveInstantiation(inferredExtendsType)) { - trueType := c.getTypeFromTypeNode(root.node.TrueType) + trueType := c.GetTypeFromTypeNode(root.node.TrueType) trueMapper := core.OrElse(combinedMapper, mapper) if newRoot, newRootMapper := c.getTailRecursionRoot(trueType, trueMapper); newRoot != nil { root = newRoot @@ -22784,7 +22784,7 @@ func (c *Checker) permissiveMapperWorker(t *Type) *Type { func (c *Checker) getTrueTypeFromConditionalType(t *Type) *Type { d := t.AsConditionalType() if d.resolvedTrueType == nil { - d.resolvedTrueType = c.instantiateType(c.getTypeFromTypeNode(d.root.node.TrueType), d.mapper) + d.resolvedTrueType = c.instantiateType(c.GetTypeFromTypeNode(d.root.node.TrueType), d.mapper) } return d.resolvedTrueType } @@ -22792,7 +22792,7 @@ func (c *Checker) getTrueTypeFromConditionalType(t *Type) *Type { func (c *Checker) getFalseTypeFromConditionalType(t *Type) *Type { d := t.AsConditionalType() if d.resolvedFalseType == nil { - d.resolvedFalseType = c.instantiateType(c.getTypeFromTypeNode(d.root.node.FalseType), d.mapper) + d.resolvedFalseType = c.instantiateType(c.GetTypeFromTypeNode(d.root.node.FalseType), d.mapper) } return d.resolvedFalseType } @@ -22801,7 +22801,7 @@ func (c *Checker) getInferredTrueTypeFromConditionalType(t *Type) *Type { d := t.AsConditionalType() if d.resolvedInferredTrueType == nil { if d.combinedMapper != nil { - d.resolvedInferredTrueType = c.instantiateType(c.getTypeFromTypeNode(d.root.node.TrueType), d.combinedMapper) + d.resolvedInferredTrueType = c.instantiateType(c.GetTypeFromTypeNode(d.root.node.TrueType), d.combinedMapper) } else { d.resolvedInferredTrueType = c.getTrueTypeFromConditionalType(t) } @@ -23202,7 +23202,7 @@ func (c *Checker) getConditionalFlowTypeOfType(t *Type, node *ast.Node) *Type { constraints = append(constraints, constraint) } } else if t.flags&TypeFlagsTypeParameter != 0 && ast.IsMappedTypeNode(parent) && parent.AsMappedTypeNode().NameType == nil && node == parent.AsMappedTypeNode().Type { - mappedType := c.getTypeFromTypeNode(parent) + mappedType := c.GetTypeFromTypeNode(parent) if c.getTypeParameterFromMappedType(mappedType) == c.getActualTypeVariable(t) { typeParameter := c.getHomomorphicTypeVariable(mappedType) if typeParameter != nil { @@ -23225,8 +23225,8 @@ func (c *Checker) getImpliedConstraint(t *Type, checkNode *ast.Node, extendsNode switch { case isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode): return c.getImpliedConstraint(t, checkNode.AsTupleTypeNode().Elements.Nodes[0], extendsNode.AsTupleTypeNode().Elements.Nodes[0]) - case c.getActualTypeVariable(c.getTypeFromTypeNode(checkNode)) == c.getActualTypeVariable(t): - return c.getTypeFromTypeNode(extendsNode) + case c.getActualTypeVariable(c.GetTypeFromTypeNode(checkNode)) == c.getActualTypeVariable(t): + return c.GetTypeFromTypeNode(extendsNode) } return nil } @@ -25190,7 +25190,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy } if hasPropName { if accessFlags&AccessFlagsContextual != 0 { - t := c.getTypeOfPropertyOfContextualType(objectType, propName) + t := c.GetTypeOfPropertyOfContextualType(objectType, propName) if t == nil { t = c.anyType } @@ -26247,7 +26247,7 @@ func (c *Checker) getModifiersTypeFromMappedType(t *Type) *Type { // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves // 'keyof T' to a literal union type and we can't recover T from that type. - m.modifiersType = c.instantiateType(c.getTypeFromTypeNode(c.getConstraintDeclarationForMappedType(t).AsTypeOperatorNode().Type), m.mapper) + m.modifiersType = c.instantiateType(c.GetTypeFromTypeNode(c.getConstraintDeclarationForMappedType(t).AsTypeOperatorNode().Type), m.mapper) } else { // Otherwise, get the declared constraint type, and if the constraint type is a type parameter, // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T', @@ -27162,7 +27162,7 @@ func (c *Checker) getContextualType(node *ast.Node, contextFlags ContextFlags) * if isConstAssertion(parent) { return c.getContextualType(parent, contextFlags) } - return c.getTypeFromTypeNode(getAssertedTypeNode(parent)) + return c.GetTypeFromTypeNode(getAssertedTypeNode(parent)) case ast.KindBinaryExpression: return c.getContextualTypeForBinaryOperand(node, contextFlags) case ast.KindPropertyAssignment, @@ -27184,7 +27184,7 @@ func (c *Checker) getContextualType(node *ast.Node, contextFlags ContextFlags) * case ast.KindNonNullExpression: return c.getContextualType(parent, contextFlags) case ast.KindSatisfiesExpression: - return c.getTypeFromTypeNode(parent.AsSatisfiesExpression().Type) + return c.GetTypeFromTypeNode(parent.AsSatisfiesExpression().Type) case ast.KindExportAssignment: return c.tryGetTypeFromTypeNode(parent) case ast.KindJsxExpression: @@ -27228,7 +27228,7 @@ func (c *Checker) getContextualTypeForInitializerExpression(node *ast.Node, cont func (c *Checker) getContextualTypeForVariableLikeDeclaration(declaration *ast.Node, contextFlags ContextFlags) *Type { typeNode := declaration.Type() if typeNode != nil { - return c.getTypeFromTypeNode(typeNode) + return c.GetTypeFromTypeNode(typeNode) } switch declaration.Kind { case ast.KindParameter: @@ -27402,7 +27402,7 @@ func (c *Checker) getContextualTypeForBindingElement(declaration *ast.Node, cont func (c *Checker) getContextualTypeForStaticPropertyDeclaration(declaration *ast.Node, contextFlags ContextFlags) *Type { if ast.IsExpression(declaration.Parent) { if parentType := c.getContextualType(declaration.Parent, contextFlags); parentType != nil { - return c.getTypeOfPropertyOfContextualType(parentType, c.getSymbolOfDeclaration(declaration).Name) + return c.GetTypeOfPropertyOfContextualType(parentType, c.getSymbolOfDeclaration(declaration).Name) } } return nil @@ -27685,7 +27685,7 @@ func (c *Checker) getContextualTypeForObjectLiteralElement(element *ast.Node, co if name != nil && ast.IsComputedPropertyName(name) { exprType := c.checkExpression(name.Expression()) if isTypeUsableAsPropertyName(exprType) { - propType := c.getTypeOfPropertyOfContextualType(t, getPropertyNameFromType(exprType)) + propType := c.GetTypeOfPropertyOfContextualType(t, getPropertyNameFromType(exprType)) if propType != nil { return propType } @@ -27758,7 +27758,7 @@ func (c *Checker) getContextualTypeForElementExpression(t *Type, index int, leng // If element index is known and a contextual property with that name exists, return it. Otherwise return the // iterated or element type of the contextual type. if firstSpreadIndex < 0 || index < firstSpreadIndex { - propType := c.getTypeOfPropertyOfContextualType(t, strconv.Itoa(index)) + propType := c.GetTypeOfPropertyOfContextualType(t, strconv.Itoa(index)) if propType != nil { return propType } @@ -27784,7 +27784,7 @@ func (c *Checker) getContextualTypeForSubstitutionExpression(template *ast.Node, } func (c *Checker) getContextualImportAttributeType(node *ast.Node) *Type { - return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().Text()) + return c.GetTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().Text()) } // Returns the effective arguments for an expression that works like a function invocation. @@ -28293,7 +28293,7 @@ func (c *Checker) getClassElementPropertyKeyType(element *ast.Node) *Type { panic("Unhandled case in getClassElementPropertyKeyType") } -func (c *Checker) getTypeOfPropertyOfContextualType(t *Type, name string) *Type { +func (c *Checker) GetTypeOfPropertyOfContextualType(t *Type, name string) *Type { return c.getTypeOfPropertyOfContextualTypeEx(t, name, nil) } @@ -29429,7 +29429,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy objectType = c.getTypeOfExpression(parent.Expression()) } } else if ast.IsLiteralTypeNode(parent) && ast.IsIndexedAccessTypeNode(grandParent) { - objectType = c.getTypeFromTypeNode(grandParent.AsIndexedAccessTypeNode().ObjectType) + objectType = c.GetTypeFromTypeNode(grandParent.AsIndexedAccessTypeNode().ObjectType) } if objectType != nil { @@ -29508,7 +29508,7 @@ func (c *Checker) getSymbolOfNameOrPropertyAccessExpression(name *ast.Node) *ast if ast.IsEntityName(name) { possibleImportNode := isImportTypeQualifierPart(name) if possibleImportNode != nil { - c.getTypeFromTypeNode(possibleImportNode) + c.GetTypeFromTypeNode(possibleImportNode) sym := c.getResolvedSymbolOrNil(name) return core.IfElse(sym == c.unknownSymbol, nil, sym) } @@ -29636,7 +29636,7 @@ func (c *Checker) getTypeOfNode(node *ast.Node) *Type { } if ast.IsPartOfTypeNode(node) { - typeFromTypeNode := c.getTypeFromTypeNode(node) + typeFromTypeNode := c.GetTypeFromTypeNode(node) if classType != nil { return c.getTypeWithThisArgument( typeFromTypeNode, diff --git a/internal/checker/grammarchecks.go b/internal/checker/grammarchecks.go index 6e61fdaaf8..d8896ee273 100644 --- a/internal/checker/grammarchecks.go +++ b/internal/checker/grammarchecks.go @@ -834,7 +834,7 @@ func (c *Checker) checkGrammarIndexSignatureParameters(node *ast.IndexSignatureD if typeNode == nil { return c.grammarErrorOnNode(parameter.Name(), diagnostics.An_index_signature_parameter_must_have_a_type_annotation) } - t := c.getTypeFromTypeNode(typeNode) + t := c.GetTypeFromTypeNode(typeNode) if someType(t, func(t *Type) bool { return t.flags&TypeFlagsStringOrNumberLiteralOrUnique != 0 }) || c.isGenericType(t) { diff --git a/internal/checker/jsx.go b/internal/checker/jsx.go index 10a172eec6..9bc8a5e131 100644 --- a/internal/checker/jsx.go +++ b/internal/checker/jsx.go @@ -211,7 +211,7 @@ func (c *Checker) getContextualTypeForJsxAttribute(attribute *ast.Node, contextF if attributesType == nil || IsTypeAny(attributesType) { return nil } - return c.getTypeOfPropertyOfContextualType(attributesType, attribute.Name().Text()) + return c.GetTypeOfPropertyOfContextualType(attributesType, attribute.Name().Text()) } return c.getContextualType(attribute.Parent, contextFlags) } @@ -238,7 +238,7 @@ func (c *Checker) getContextualTypeForChildJsxExpression(node *ast.Node, child * } realChildren := getSemanticJsxChildren(node.Children().Nodes) childIndex := slices.Index(realChildren, child) - childFieldType := c.getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) + childFieldType := c.GetTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) if childFieldType == nil { return nil } @@ -715,7 +715,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme } var childrenContextualType *Type if contextualType := c.getApparentTypeOfContextualType(openingLikeElement.Attributes(), ContextFlagsNone); contextualType != nil { - childrenContextualType = c.getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName) + childrenContextualType = c.GetTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName) } // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process childrenPropSymbol := c.newSymbol(ast.SymbolFlagsProperty, jsxChildrenPropertyName) @@ -1221,7 +1221,7 @@ func (c *Checker) getJsxNamespaceAt(location *ast.Node) *ast.Symbol { } } // JSX global fallback - s := c.resolveSymbol(c.getGlobalSymbol(JsxNames.JSX, ast.SymbolFlagsNamespace, nil /*diagnostic*/)) + s := c.resolveSymbol(c.GetGlobalSymbol(JsxNames.JSX, ast.SymbolFlagsNamespace, nil /*diagnostic*/)) if s == c.unknownSymbol { return nil } diff --git a/internal/checker/relater.go b/internal/checker/relater.go index 56dfb8cdd8..52239e034a 100644 --- a/internal/checker/relater.go +++ b/internal/checker/relater.go @@ -2055,7 +2055,7 @@ func (c *Checker) createTypePredicateFromTypePredicateNode(node *ast.Node, signa predicateNode := node.AsTypePredicateNode() var t *Type if predicateNode.Type != nil { - t = c.getTypeFromTypeNode(predicateNode.Type) + t = c.GetTypeFromTypeNode(predicateNode.Type) } if ast.IsThisTypeNode(predicateNode.ParameterName) { kind := core.IfElse(predicateNode.AssertsModifier != nil, TypePredicateKindAssertsThis, TypePredicateKindThis) diff --git a/internal/checker/services.go b/internal/checker/services.go index 9b5863d2ae..5484e35197 100644 --- a/internal/checker/services.go +++ b/internal/checker/services.go @@ -131,7 +131,7 @@ func (c *Checker) isValidPropertyAccess(node *ast.Node, propertyName string) boo case ast.KindQualifiedName: return c.isValidPropertyAccessWithType(node, false /*isSuper*/, propertyName, c.getWidenedType(c.checkExpression(node.AsQualifiedName().Left))) case ast.KindImportType: - return c.isValidPropertyAccessWithType(node, false /*isSuper*/, propertyName, c.getTypeFromTypeNode(node)) + return c.isValidPropertyAccessWithType(node, false /*isSuper*/, propertyName, c.GetTypeFromTypeNode(node)) } panic("Unexpected node kind in isValidPropertyAccess: " + node.Kind.String()) } @@ -398,3 +398,32 @@ func (c *Checker) tryGetTarget(symbol *ast.Symbol) *ast.Symbol { func (c *Checker) GetExportSymbolOfSymbol(symbol *ast.Symbol) *ast.Symbol { return c.getMergedSymbol(core.IfElse(symbol.ExportSymbol != nil, symbol.ExportSymbol, symbol)) } + +func (c *Checker) GetTypeArgumentConstraint(node *ast.Node) *Type { + if !ast.IsTypeNode(node) { + return nil + } + return c.getTypeArgumentConstraint(node) +} + +func (c *Checker) getTypeArgumentConstraint(node *ast.Node) *Type { + typeReferenceNode := core.IfElse(ast.IsTypeReferenceType(node.Parent), node.Parent, nil) + if typeReferenceNode == nil { + return nil + } + typeParameters := c.getTypeParametersForTypeReferenceOrImport(typeReferenceNode) + if len(typeParameters) == 0 { + return nil + } + + typeParamIndex := core.FindIndex(typeReferenceNode.TypeArguments(), func(n *ast.Node) bool { + return n == node + }) + constraint := c.getConstraintOfTypeParameter(typeParameters[typeParamIndex]) + if constraint != nil { + return c.instantiateType( + constraint, + newTypeMapper(typeParameters, c.getEffectiveTypeArguments(typeReferenceNode, typeParameters))) + } + return nil +} diff --git a/internal/checker/utilities.go b/internal/checker/utilities.go index bff81e1ef7..8d2651c970 100644 --- a/internal/checker/utilities.go +++ b/internal/checker/utilities.go @@ -219,7 +219,7 @@ func getNameFromImportDeclaration(node *ast.Node) *ast.Node { return nil } -func isValidTypeOnlyAliasUseSite(useSite *ast.Node) bool { +func IsValidTypeOnlyAliasUseSite(useSite *ast.Node) bool { return useSite.Flags&ast.NodeFlagsAmbient != 0 || ast.IsPartOfTypeQuery(useSite) || isIdentifierInNonEmittingHeritageClause(useSite) || @@ -1014,10 +1014,6 @@ func getContainingFunctionOrClassStaticBlock(node *ast.Node) *ast.Node { return ast.FindAncestor(node.Parent, ast.IsFunctionLikeOrClassStaticBlockDeclaration) } -func isTypeReferenceType(node *ast.Node) bool { - return node.Kind == ast.KindTypeReference || node.Kind == ast.KindExpressionWithTypeArguments -} - func isNodeDescendantOf(node *ast.Node, ancestor *ast.Node) bool { for node != nil { if node == ancestor { diff --git a/internal/ls/completions.go b/internal/ls/completions.go index b003ed90d3..c6cc9ffb3b 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -107,6 +107,8 @@ var allCommitCharacters = []string{".", ",", ";"} // Commit characters valid at expression positions where we could be inside a parameter list. var noCommaCommitCharacters = []string{".", ";"} +var emptyCommitCharacters = []string{} + type sortText string const ( @@ -200,6 +202,10 @@ func (s *symbolOriginInfo) asObjectLiteralMethod() *symbolOriginInfoObjectLitera return s.data.(*symbolOriginInfoObjectLiteralMethod) } +type symbolOriginInfoTypeOnlyAlias struct { + declaration *ast.TypeOnlyImportDeclaration +} + // Special values for `CompletionInfo['source']` used to disambiguate // completion items with the same `name`. (Each completion item must // have a unique name/source combination, because those two fields @@ -232,6 +238,14 @@ type uniqueNamesMap = map[string]bool type literalValue any // string | jsnum.Number | PseudoBigInt +type globalsSearch int + +const ( + globalsSearchContinue globalsSearch = iota + globalsSearchSuccess + globalsSearchFail +) + func (l *LanguageService) getCompletionsAtPosition( program *compiler.Program, file *ast.SourceFile, @@ -711,6 +725,195 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position } } + // Aggregates relevant symbols for completion in object literals in type argument positions. + tryGetObjectTypeLiteralInTypeArgumentCompletionSymbols := func() globalsSearch { + typeLiteralNode := tryGetTypeLiteralNode(contextToken) + if typeLiteralNode == nil { + return globalsSearchContinue + } + + intersectionTypeNode := core.IfElse( + ast.IsIntersectionTypeNode(typeLiteralNode.Parent), + typeLiteralNode.Parent, + nil) + containerTypeNode := core.IfElse( + intersectionTypeNode != nil, + intersectionTypeNode, + typeLiteralNode) + + containerExpectedType := getConstraintOfTypeArgumentProperty(containerTypeNode, typeChecker) + if containerExpectedType == nil { + return globalsSearchContinue + } + + containerActualType := typeChecker.GetTypeFromTypeNode(containerTypeNode) + + members := getPropertiesForCompletion(containerExpectedType, typeChecker) + existingMembers := getPropertiesForCompletion(containerActualType, typeChecker) + + existingMemberNames := core.Set[string]{} + for _, member := range existingMembers { + existingMemberNames.Add(member.Name) + } + + symbols = append( + symbols, + core.Filter(members, func(member *ast.Symbol) bool { return !existingMemberNames.Has(member.Name) })...) + + completionKind = CompletionKindObjectPropertyDeclaration + isNewIdentifierLocation = true + + return globalsSearchSuccess + } + + // Aggregates relevant symbols for completion in object literals and object binding patterns. + // Relevant symbols are stored in the captured 'symbols' variable. + tryGetObjectLikeCompletionSymbols := func() globalsSearch { + if contextToken != nil && contextToken.Kind == ast.KindDotDotDotToken { + return globalsSearchContinue + } + objectLikeContainer := tryGetObjectLikeCompletionContainer(contextToken, position, file) + if objectLikeContainer == nil { + return globalsSearchContinue + } + + return globalsSearchContinue // !!! + } + + getGlobalCompletions := func() globalsSearch { + if tryGetFunctionLikeBodyCompletionContainer(contextToken) != nil { + keywordFilters = KeywordCompletionFiltersFunctionLikeBodyKeywords + } else { + keywordFilters = KeywordCompletionFiltersAll + } + // Get all entities in the current scope. + completionKind = CompletionKindGlobal + isNewIdentifierLocation, defaultCommitCharacters = computeCommitCharactersAndIsNewIdentifier(contextToken, file, position) + + if previousToken != contextToken { + if previousToken == nil { + panic("Expected 'contextToken' to be defined when different from 'previousToken'.") + } + } + + // We need to find the node that will give us an appropriate scope to begin + // aggregating completion candidates. This is achieved in 'getScopeNode' + // by finding the first node that encompasses a position, accounting for whether a node + // is "complete" to decide whether a position belongs to the node. + // + // However, at the end of an identifier, we are interested in the scope of the identifier + // itself, but fall outside of the identifier. For instance: + // + // xyz => x$ + // + // the cursor is outside of both the 'x' and the arrow function 'xyz => x', + // so 'xyz' is not returned in our results. + // + // We define 'adjustedPosition' so that we may appropriately account for + // being at the end of an identifier. The intention is that if requesting completion + // at the end of an identifier, it should be effectively equivalent to requesting completion + // anywhere inside/at the beginning of the identifier. So in the previous case, the + // 'adjustedPosition' will work as if requesting completion in the following: + // + // xyz => $x + // + // If previousToken !== contextToken, then + // - 'contextToken' was adjusted to the token prior to 'previousToken' + // because we were at the end of an identifier. + // - 'previousToken' is defined. + var adjustedPosition int + if previousToken != contextToken { + adjustedPosition = astnav.GetStartOfNode(previousToken, file, false /*includeJSDoc*/) + } else { + adjustedPosition = position + } + + scopeNode := getScopeNode(contextToken, adjustedPosition, file) + if scopeNode == nil { + scopeNode = file.AsNode() + } + isInSnippetScope = isSnippetScope(scopeNode) + + symbolMeanings := core.IfElse(isTypeOnlyLocation, ast.SymbolFlagsNone, ast.SymbolFlagsValue) | + ast.SymbolFlagsType | ast.SymbolFlagsNamespace | ast.SymbolFlagsAlias + typeOnlyAliasNeedsPromotion := previousToken != nil && !checker.IsValidTypeOnlyAliasUseSite(previousToken) + + symbols = append(symbols, typeChecker.GetSymbolsInScope(scopeNode, symbolMeanings)...) + core.CheckEachDefined(symbols, "getSymbolsInScope() should all be defined") + for _, symbol := range symbols { + symbolId := ast.GetSymbolId(symbol) + if !typeChecker.IsArgumentsSymbol(symbol) && + !core.Some(symbol.Declarations, func(decl *ast.Declaration) bool { + return ast.GetSourceFileOfNode(decl) == file + }) { + symbolToSortTextMap[symbolId] = SortTextGlobalsOrKeywords + } + if typeOnlyAliasNeedsPromotion && symbol.Flags&ast.SymbolFlagsValue == 0 { + typeOnlyAliasDeclaration := core.Find(symbol.Declarations, ast.IsTypeOnlyImportDeclaration) + if typeOnlyAliasDeclaration != nil { + origin := &symbolOriginInfo{ + kind: symbolOriginInfoKindTypeOnlyAlias, + data: &symbolOriginInfoTypeOnlyAlias{declaration: typeOnlyAliasDeclaration}, + } + symbolToOriginInfoMap[symbolId] = origin + } + } + } + + // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` + if scopeNode.Kind != ast.KindSourceFile { + thisType := typeChecker.TryGetThisTypeAtEx( + scopeNode, + false, /*includeGlobalThis*/ + core.IfElse(ast.IsClassLike(scopeNode.Parent), scopeNode, nil)) + if thisType != nil && !isProbablyGlobalType(thisType, file, typeChecker) { + for _, symbol := range getPropertiesForCompletion(thisType, typeChecker) { + symbolId := ast.GetSymbolId(symbol) + symbols = append(symbols, symbol) + symbolToOriginInfoMap[symbolId] = &symbolOriginInfo{kind: symbolOriginInfoKindThisType} + symbolToSortTextMap[symbolId] = SortTextSuggestedClassMembers + } + } + } + + // !!! auto imports + // collectAutoImports() + + if isTypeOnlyLocation { + if contextToken != nil && ast.IsAssertionExpression(contextToken.Parent) { + keywordFilters = KeywordCompletionFiltersTypeAssertionKeywords + } else { + keywordFilters = KeywordCompletionFiltersTypeKeywords + } + } + + return globalsSearchSuccess + } + + tryGetGlobalSymbols := func() bool { + var result globalsSearch + globalSearchFuncs := []func() globalsSearch{ + // !!! + tryGetObjectTypeLiteralInTypeArgumentCompletionSymbols, + // tryGetObjectLikeCompletionSymbols, + // tryGetImportCompletionSymbols, + // tryGetImportOrExportClauseCompletionSymbols, + // tryGetImportAttributesCompletionSymbols, + // tryGetLocalNamedExportCompletionSymbols, + // tryGetConstructorCompletion, + // tryGetClassLikeCompletionSymbols, + // tryGetJsxCompletionSymbols, + getGlobalCompletions, + } + for _, globalSearchFunc := range globalSearchFuncs { + result = globalSearchFunc() + if result != globalsSearchContinue { + break + } + } + return result == globalsSearchSuccess + } + if isRightOfDot || isRightOfQuestionDot { getTypeScriptMemberSymbols() } else if isRightOfOpenTag { @@ -2508,3 +2711,299 @@ func isMemberCompletionKind(kind CompletionKind) bool { kind == CompletionKindMemberLike || kind == CompletionKindPropertyAccess } + +func tryGetFunctionLikeBodyCompletionContainer(contextToken *ast.Node) *ast.Node { + if contextToken == nil { + return nil + } + + var prev *ast.Node + container := ast.FindAncestorOrQuit(contextToken, func(node *ast.Node) ast.FindAncestorResult { + if ast.IsClassLike(node) { + return ast.FindAncestorQuit + } + if ast.IsFunctionLikeDeclaration(node) && prev == node.Body() { + return ast.FindAncestorTrue + } + prev = node + return ast.FindAncestorFalse + }) + return container +} + +func computeCommitCharactersAndIsNewIdentifier( + contextToken *ast.Node, + file *ast.SourceFile, + position int) (isNewIdentifierLocation bool, defaultCommitCharacters []string) { + if contextToken == nil { + return false, allCommitCharacters + } + containingNodeKind := contextToken.Parent.Kind + tokenKind := keywordForNode(contextToken) + // Previous token may have been a keyword that was converted to an identifier. + switch tokenKind { + case ast.KindCommaToken: + switch containingNodeKind { + // func( a, | + // new C(a, | + case ast.KindCallExpression, ast.KindNewExpression: + expression := contextToken.Parent.Expression() + // func\n(a, | + if getLineOfPosition(file, expression.End()) != getLineOfPosition(file, position) { + return true, noCommaCommitCharacters + } + return true, allCommitCharacters + // const x = (a, | + case ast.KindBinaryExpression: + return true, noCommaCommitCharacters + // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ + // var x: (s: string, list| + // const obj = { x, | + case ast.KindConstructor, ast.KindFunctionType, ast.KindObjectLiteralExpression: + return true, emptyCommitCharacters + // [a, | + case ast.KindArrayLiteralExpression: + return true, allCommitCharacters + default: + return false, allCommitCharacters + } + case ast.KindOpenParenToken: + switch containingNodeKind { + // func( | + // new C(a| + case ast.KindCallExpression, ast.KindNewExpression: + expression := contextToken.Parent.Expression() + // func\n( | + if getLineOfPosition(file, expression.End()) != getLineOfPosition(file, position) { + return true, noCommaCommitCharacters + } + return true, allCommitCharacters + // const x = (a| + case ast.KindParenthesizedExpression: + return true, noCommaCommitCharacters + // constructor( | + // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ + case ast.KindConstructor, ast.KindParenthesizedType: + return true, emptyCommitCharacters + default: + return false, allCommitCharacters + } + case ast.KindOpenBracketToken: + switch containingNodeKind { + // [ | + // [ | : string ] + // [ | : string ] + // [ | /* this can become an index signature */ + case ast.KindArrayLiteralExpression, ast.KindIndexSignature, ast.KindTupleType, ast.KindComputedPropertyName: + return true, allCommitCharacters + default: + return false, allCommitCharacters + } + // module | + // namespace | + // import | + case ast.KindModuleKeyword, ast.KindNamespaceKeyword, ast.KindImportKeyword: + return true, emptyCommitCharacters + case ast.KindDotToken: + switch containingNodeKind { + // module A.| + case ast.KindModuleDeclaration: + return true, emptyCommitCharacters + default: + return false, allCommitCharacters + } + case ast.KindOpenBraceToken: + switch containingNodeKind { + // class A { | + // const obj = { | + case ast.KindClassDeclaration, ast.KindObjectLiteralExpression: + return true, emptyCommitCharacters + default: + return false, allCommitCharacters + } + case ast.KindEqualsToken: + switch containingNodeKind { + // const x = a| + // x = a| + case ast.KindVariableDeclaration, ast.KindBinaryExpression: + return true, allCommitCharacters + default: + return false, allCommitCharacters + } + case ast.KindTemplateHead: + // `aa ${| + return containingNodeKind == ast.KindTemplateExpression, allCommitCharacters + case ast.KindTemplateMiddle: + // `aa ${10} dd ${| + return containingNodeKind == ast.KindTemplateSpan, allCommitCharacters + case ast.KindAsyncKeyword: + // const obj = { async c|() + // const obj = { async c| + if containingNodeKind == ast.KindMethodDeclaration || containingNodeKind == ast.KindShorthandPropertyAssignment { + return true, emptyCommitCharacters + } + return false, allCommitCharacters + case ast.KindAsteriskToken: + // const obj = { * c| + if containingNodeKind == ast.KindMethodDeclaration { + return true, emptyCommitCharacters + } + return false, allCommitCharacters + } + + if isClassMemberCompletionKeyword(tokenKind) { + return true, emptyCommitCharacters + } + + return false, allCommitCharacters +} + +func keywordForNode(node *ast.Node) ast.Kind { + if ast.IsIdentifier(node) { + return scanner.IdentifierToKeywordKind(node.AsIdentifier()) + } + return node.Kind +} + +// Finds the first node that "embraces" the position, so that one may +// accurately aggregate locals from the closest containing scope. +func getScopeNode(initialToken *ast.Node, position int, file *ast.SourceFile) *ast.Node { + scope := initialToken + for scope != nil && !positionBelongsToNode(scope, position, file) { + scope = scope.Parent + } + return scope +} + +func isSnippetScope(scopeNode *ast.Node) bool { + switch scopeNode.Kind { + case ast.KindSourceFile, + ast.KindTemplateExpression, + ast.KindJsxExpression, + ast.KindBlock: + return true + default: + return ast.IsStatement(scopeNode) + } +} + +// Determines if a type is exactly the same type resolved by the global 'self', 'global', or 'globalThis'. +func isProbablyGlobalType(t *checker.Type, file *ast.SourceFile, typeChecker *checker.Checker) bool { + // The type of `self` and `window` is the same in lib.dom.d.ts, but `window` does not exist in + // lib.webworker.d.ts, so checking against `self` is also a check against `window` when it exists. + selfSymbol := typeChecker.GetGlobalSymbol("self", ast.SymbolFlagsValue, nil /*diagnostic*/) + if selfSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(selfSymbol, file.AsNode()) == t { + return true + } + globalSymbol := typeChecker.GetGlobalSymbol("global", ast.SymbolFlagsValue, nil /*diagnostic*/) + if globalSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(globalSymbol, file.AsNode()) == t { + return true + } + globalThisSymbol := typeChecker.GetGlobalSymbol("globalThis", ast.SymbolFlagsValue, nil /*diagnostic*/) + if globalThisSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(globalThisSymbol, file.AsNode()) == t { + return true + } + return false +} + +func tryGetTypeLiteralNode(node *ast.Node) *ast.TypeLiteral { + if node == nil { + return nil + } + + parent := node.Parent + switch node.Kind { + case ast.KindOpenBraceToken: + if ast.IsTypeLiteralNode(parent) { + return parent + } + case ast.KindSemicolonToken, ast.KindCommaToken, ast.KindIdentifier: + if parent.Kind == ast.KindPropertySignature && ast.IsTypeLiteralNode(parent.Parent) { + return parent.Parent + } + } + + return nil +} + +func getConstraintOfTypeArgumentProperty(node *ast.Node, typeChecker *checker.Checker) *checker.Type { + if node == nil { + return nil + } + + if ast.IsTypeNode(node) && ast.IsTypeReferenceType(node.Parent) { + return typeChecker.GetTypeArgumentConstraint(node) + } + + t := getConstraintOfTypeArgumentProperty(node.Parent, typeChecker) + if t == nil { + return nil + } + + switch node.Kind { + case ast.KindPropertySignature: + return typeChecker.GetTypeOfPropertyOfContextualType(t, node.Symbol().Name) + case ast.KindIntersectionType, ast.KindTypeLiteral, ast.KindUnionType: + return t + } + + return nil +} + +func tryGetObjectLikeCompletionContainer(contextToken *ast.Node, position int, file *ast.SourceFile) *ast.ObjectLiteralLike { + if contextToken == nil { + return nil + } + + parent := contextToken.Parent + switch contextToken.Kind { + // const x = { | + // const x = { a: 0, | + case ast.KindOpenBraceToken, ast.KindCommaToken: + if ast.IsObjectLiteralExpression(parent) || ast.IsObjectBindingPattern(parent) { + return parent + } + case ast.KindAsteriskToken: + if ast.IsMethodDeclaration(parent) && ast.IsObjectLiteralExpression(parent.Parent) { + return parent.Parent + } + case ast.KindAsyncKeyword: + if ast.IsObjectLiteralExpression(parent.Parent) { + return parent.Parent + } + case ast.KindIdentifier: + if contextToken.Text() == "async" && ast.IsShorthandPropertyAssignment(parent) { + return parent.Parent + } else { + if ast.IsObjectLiteralExpression(parent.Parent) && + (ast.IsSpreadAssignment(parent) || + ast.IsShorthandPropertyAssignment(parent) && + getLineOfPosition(file, contextToken.End()) != getLineOfPosition(file, position)) { + return parent.Parent + } + ancestorNode := ast.FindAncestor(parent, ast.IsPropertyAssignment) + if ancestorNode != nil && getLastToken(ancestorNode, file) == contextToken && ast.IsObjectLiteralExpression(ancestorNode.Parent) { + return ancestorNode.Parent + } + } + default: + if parent.Parent != nil && parent.Parent.Parent != nil && + (ast.IsMethodDeclaration(parent.Parent) || + ast.IsGetAccessorDeclaration(parent.Parent) || + ast.IsSetAccessorDeclaration(parent.Parent)) && + ast.IsObjectLiteralExpression(parent.Parent.Parent) { + return parent.Parent.Parent + } + if ast.IsSpreadAssignment(parent) && ast.IsObjectLiteralExpression(parent.Parent) { + return parent.Parent + } + ancestorNode := ast.FindAncestor(parent, ast.IsPropertyAssignment) + if contextToken.Kind != ast.KindColonToken && + ancestorNode != nil && getLastToken(ancestorNode, file) == contextToken && + ast.IsObjectLiteralExpression(ancestorNode.Parent) { + return ancestorNode.Parent + } + } + + return nil +} diff --git a/internal/ls/utilities.go b/internal/ls/utilities.go index 719588ae09..8fbd46e536 100644 --- a/internal/ls/utilities.go +++ b/internal/ls/utilities.go @@ -82,6 +82,10 @@ func assertHasRealPosition(node *ast.Node) { } } +func hasChildOfKind(containingNode *ast.Node, kind ast.Kind, sourceFile *ast.SourceFile) bool { + return findChildOfKind(containingNode, kind, sourceFile) != nil +} + func findChildOfKind(containingNode *ast.Node, kind ast.Kind, sourceFile *ast.SourceFile) *ast.Node { lastNodePos := containingNode.Pos() scanner := scanner.GetScannerForSourceFile(sourceFile, lastNodePos) @@ -425,3 +429,184 @@ func isArgumentOfElementAccessExpression(node *ast.Node) bool { func isTagName(node *ast.Node) bool { return node.Parent != nil && ast.IsJSDocTag(node.Parent) && node.Parent.TagName() == node } + +// Assumes `candidate.pos <= position` holds. +func positionBelongsToNode(candidate *ast.Node, position int, file *ast.SourceFile) bool { + if candidate.Pos() > position { + panic("Expected candidate.pos <= position") + } + return position < candidate.End() || !isCompletedNode(candidate, file) +} + +func isCompletedNode(n *ast.Node, sourceFile *ast.SourceFile) bool { + if n == nil || ast.NodeIsMissing(n) { + return false + } + + switch n.Kind { + case ast.KindClassDeclaration, + ast.KindInterfaceDeclaration, + ast.KindEnumDeclaration, + ast.KindObjectLiteralExpression, + ast.KindObjectBindingPattern, + ast.KindTypeLiteral, + ast.KindBlock, + ast.KindModuleBlock, + ast.KindCaseBlock, + ast.KindNamedImports, + ast.KindNamedExports: + return nodeEndsWith(n, ast.KindCloseBraceToken, sourceFile) + + case ast.KindCatchClause: + return isCompletedNode(n.AsCatchClause().Block, sourceFile) + + case ast.KindNewExpression: + if n.AsNewExpression().Arguments == nil { + return true + } + fallthrough + + case ast.KindCallExpression, + ast.KindParenthesizedExpression, + ast.KindParenthesizedType: + return nodeEndsWith(n, ast.KindCloseParenToken, sourceFile) + + case ast.KindFunctionType, + ast.KindConstructorType: + return isCompletedNode(n.Type(), sourceFile) + + case ast.KindConstructor, + ast.KindGetAccessor, + ast.KindSetAccessor, + ast.KindFunctionDeclaration, + ast.KindFunctionExpression, + ast.KindMethodDeclaration, + ast.KindMethodSignature, + ast.KindConstructSignature, + ast.KindCallSignature, + ast.KindArrowFunction: + if n.Body() != nil { + return isCompletedNode(n.Body(), sourceFile) + } + if n.Type() != nil { + return isCompletedNode(n.Type(), sourceFile) + } + // Even though type parameters can be unclosed, we can get away with + // having at least a closing paren. + return hasChildOfKind(n, ast.KindCloseParenToken, sourceFile) + + case ast.KindModuleDeclaration: + return n.AsModuleDeclaration().Body != nil && isCompletedNode(n.AsModuleDeclaration().Body, sourceFile) + + case ast.KindIfStatement: + if n.AsIfStatement().ElseStatement != nil { + return isCompletedNode(n.AsIfStatement().ElseStatement, sourceFile) + } + return isCompletedNode(n.AsIfStatement().ThenStatement, sourceFile) + + case ast.KindExpressionStatement: + return isCompletedNode(n.AsExpressionStatement().Expression, sourceFile) || + hasChildOfKind(n, ast.KindSemicolonToken, sourceFile) + + case ast.KindArrayLiteralExpression, + ast.KindArrayBindingPattern, + ast.KindElementAccessExpression, + ast.KindComputedPropertyName, + ast.KindTupleType: + return nodeEndsWith(n, ast.KindCloseBracketToken, sourceFile) + + case ast.KindIndexSignature: + if n.AsIndexSignatureDeclaration().Type != nil { + return isCompletedNode(n.AsIndexSignatureDeclaration().Type, sourceFile) + } + return hasChildOfKind(n, ast.KindCloseBracketToken, sourceFile) + + case ast.KindCaseClause, + ast.KindDefaultClause: + // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicity always consider them non-completed + return false + + case ast.KindForStatement, + ast.KindForInStatement, + ast.KindForOfStatement, + ast.KindWhileStatement: + return isCompletedNode(n.Statement(), sourceFile) + case ast.KindDoStatement: + // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')'; + if hasChildOfKind(n, ast.KindWhileKeyword, sourceFile) { + return nodeEndsWith(n, ast.KindCloseParenToken, sourceFile) + } + return isCompletedNode(n.AsDoStatement().Statement, sourceFile) + + case ast.KindTypeQuery: + return isCompletedNode(n.AsTypeQueryNode().ExprName, sourceFile) + + case ast.KindTypeOfExpression, + ast.KindDeleteExpression, + ast.KindVoidExpression, + ast.KindYieldExpression, + ast.KindSpreadElement: + return isCompletedNode(n.Expression(), sourceFile) + + case ast.KindTaggedTemplateExpression: + return isCompletedNode(n.AsTaggedTemplateExpression().Template, sourceFile) + + case ast.KindTemplateExpression: + if n.AsTemplateExpression().TemplateSpans == nil { + return false + } + lastSpan := core.LastOrNil(n.AsTemplateExpression().TemplateSpans.Nodes) + return isCompletedNode(lastSpan, sourceFile) + + case ast.KindTemplateSpan: + return ast.NodeIsPresent(n.AsTemplateSpan().Literal) + + case ast.KindExportDeclaration, + ast.KindImportDeclaration: + return ast.NodeIsPresent(n.ModuleSpecifier()) + + case ast.KindPrefixUnaryExpression: + return isCompletedNode(n.AsPrefixUnaryExpression().Operand, sourceFile) + + case ast.KindBinaryExpression: + return isCompletedNode(n.AsBinaryExpression().Right, sourceFile) + + case ast.KindConditionalExpression: + return isCompletedNode(n.AsConditionalExpression().WhenFalse, sourceFile) + + default: + return true + } +} + +// Checks if node ends with 'expectedLastToken'. +// If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'. +func nodeEndsWith(n *ast.Node, expectedLastToken ast.Kind, sourceFile *ast.SourceFile) bool { + var lastChildNode *ast.Node + ast.ForEachChildAndJSDoc(n, sourceFile, func(node *ast.Node) bool { // !!! This can be extracted into its own `findLastChildNode` function. + if node == nil || node.Flags&ast.NodeFlagsReparsed != 0 { + return false + } + lastChildNode = node + return false + }) + if lastChildNode == nil { + return false + } + lastNodeAndTokens := []*ast.Node{lastChildNode} + scanner := scanner.GetScannerForSourceFile(sourceFile, lastChildNode.End()) + for startPos := lastChildNode.End(); startPos < n.End(); { + tokenKind := scanner.Token() + tokenFullStart := scanner.TokenFullStart() + tokenEnd := scanner.TokenEnd() + token := sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, n) + lastNodeAndTokens = append(lastNodeAndTokens, token) + } + lastChild := lastNodeAndTokens[len(lastNodeAndTokens)-1] + if lastChild.Kind == expectedLastToken { + return true + } else if lastChild.Kind == ast.KindSemicolonToken && len(lastNodeAndTokens) > 1 { + return lastNodeAndTokens[len(lastNodeAndTokens)-2].Kind == expectedLastToken + } + return false +} From 82f24863c87aa79e8427e1ddb6a8483322868b6b Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 30 Apr 2025 15:20:58 -0700 Subject: [PATCH 02/16] finish global symbol collecting functions --- internal/ast/ast.go | 43 ++ internal/ast/utilities.go | 67 ++- internal/checker/checker.go | 230 ++++----- internal/checker/flow.go | 30 +- internal/checker/inference.go | 22 +- internal/checker/jsx.go | 16 +- internal/checker/relater.go | 38 +- internal/checker/services.go | 51 +- internal/checker/types.go | 8 + internal/checker/utilities.go | 15 +- internal/ls/completions.go | 892 +++++++++++++++++++++++++++++++++- internal/ls/utilities.go | 14 + 12 files changed, 1225 insertions(+), 201 deletions(-) diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 3f7eb454f0..79b0d27c64 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -795,6 +795,43 @@ func (n *Node) Statement() *Statement { panic("Unhandled case in Node.Statement: " + n.Kind.String()) } +func (n *Node) PropertyList() *NodeList { + switch n.Kind { + case KindObjectLiteralExpression: + return n.AsObjectLiteralExpression().Properties + case KindJsxAttribute: + return n.AsJsxAttributes().Properties + } + panic("Unhandled case in Node.PropertyList: " + n.Kind.String()) +} + +func (n *Node) Properties() []*Node { + list := n.PropertyList() + if list != nil { + return list.Nodes + } + return nil +} + +func (n *Node) ElementList() *NodeList { + switch n.Kind { + case KindNamedImports: + return n.AsNamedImports().Elements + case KindNamedExports: + return n.AsNamedExports().Elements + } + + panic("Unhandled case in Node.ElementList: " + n.Kind.String()) +} + +func (n *Node) Elements() []*Node { + list := n.ElementList() + if list != nil { + return list.Nodes + } + return nil +} + // Determines if `n` contains `descendant` by walking up the `Parent` pointers from `descendant`. This method panics if // `descendant` or one of its ancestors is not parented except when that node is a `SourceFile`. func (n *Node) Contains(descendant *Node) bool { @@ -1711,6 +1748,9 @@ type ( NumericOrStringLikeLiteral = Node // StringLiteralLike | NumericLiteral TypeOnlyImportDeclaration = Node // ImportClause | ImportEqualsDeclaration | ImportSpecifier | NamespaceImport with isTypeOnly: true ObjectLiteralLike = Node // ObjectLiteralExpression | ObjectBindingPattern + ObjectTypeDeclaration = Node // ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode + JsxOpeningLikeElement = Node // JsxOpeningElement | JsxSelfClosingElement + NamedImportsOrExports = Node // NamedImports | NamedExports ) // Aliases for node singletons @@ -1754,6 +1794,9 @@ type ( SourceFileNode = Node PropertyAccessExpressionNode = Node TypeLiteral = Node + ObjectLiteralExpressionNode = Node + ConstructorDeclarationNode = Node + NamedExportsNode = Node ) type ( diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 9f37f3fa51..c64c400419 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -1525,14 +1525,14 @@ func GetExtendsHeritageClauseElement(node *Node) *ExpressionWithTypeArgumentsNod } func GetExtendsHeritageClauseElements(node *Node) []*ExpressionWithTypeArgumentsNode { - return getHeritageElements(node, KindExtendsKeyword) + return GetHeritageElements(node, KindExtendsKeyword) } func GetImplementsHeritageClauseElements(node *Node) []*ExpressionWithTypeArgumentsNode { - return getHeritageElements(node, KindImplementsKeyword) + return GetHeritageElements(node, KindImplementsKeyword) } -func getHeritageElements(node *Node, kind Kind) []*Node { +func GetHeritageElements(node *Node, kind Kind) []*Node { clause := getHeritageClause(node, kind) if clause != nil { return clause.AsHeritageClause().Types.Nodes @@ -2805,3 +2805,64 @@ func ForEachChildAndJSDoc(node *Node, sourceFile *SourceFile, v Visitor) bool { func IsTypeReferenceType(node *Node) bool { return node.Kind == KindTypeReference || node.Kind == KindExpressionWithTypeArguments } + +func IsVariableLike(node *Node) bool { + switch node.Kind { + case KindBindingElement, KindEnumMember, KindParameter, KindPropertyAssignment, KindPropertyDeclaration, + KindPropertySignature, KindShorthandPropertyAssignment, KindVariableDeclaration: + return true + } + return false +} + +func HasInitializer(node *Node) bool { + switch node.Kind { + case KindVariableDeclaration, KindParameter, KindBindingElement, KindPropertyDeclaration, + KindPropertyAssignment, KindEnumMember, KindForStatement, KindForInStatement, KindForOfStatement, + KindJsxAttribute: + return node.Initializer() != nil + default: + return false + } +} + +func GetTypeAnnotationNode(node *Node) *TypeNode { + switch node.Kind { + case KindVariableDeclaration, KindParameter, KindPropertySignature, KindPropertyDeclaration, + KindTypePredicate, KindParenthesizedType, KindTypeOperator, KindMappedType, KindTypeAssertionExpression, + KindAsExpression, KindSatisfiesExpression, KindTypeAliasDeclaration, KindJSTypeAliasDeclaration, + KindNamedTupleMember, KindOptionalType, KindRestType, KindTemplateLiteralTypeSpan, KindJSDocTypeExpression, + KindJSDocPropertyTag, KindJSDocNullableType, KindJSDocNonNullableType, KindJSDocOptionalType: + return node.Type() + default: + funcLike := node.FunctionLikeData() + if funcLike != nil { + return funcLike.Type + } + return nil + } +} + +func IsObjectTypeDeclaration(node *Node) bool { + return IsClassLike(node) || IsInterfaceDeclaration(node) || IsTypeLiteralNode(node) +} + +func IsClassOrTypeElement(node *Node) bool { + return IsClassElement(node) || IsTypeElement(node) +} + +func GetClassExtendsHeritageElement(node *Node) *ExpressionWithTypeArgumentsNode { + heritageElements := GetHeritageElements(node, KindExtendsKeyword) + if len(heritageElements) > 0 { + return heritageElements[0] + } + return nil +} + +func GetImplementsTypeNodes(node *Node) []*ExpressionWithTypeArgumentsNode { + return GetHeritageElements(node, KindImplementsKeyword) +} + +func IsTypeKeywordToken(node *Node) bool { + return node.Kind == KindTypeKeyword +} diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 622e1e2955..c3a3505c87 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -926,7 +926,7 @@ func NewChecker(program Program) *Checker { c.trueType = c.newLiteralType(TypeFlagsBooleanLiteral, true, c.regularTrueType) c.regularTrueType.AsLiteralType().freshType = c.trueType c.trueType.AsLiteralType().freshType = c.trueType - c.booleanType = c.getUnionType([]*Type{c.regularFalseType, c.regularTrueType}) + c.booleanType = c.GetUnionType([]*Type{c.regularFalseType, c.regularTrueType}) c.esSymbolType = c.newIntrinsicType(TypeFlagsESSymbol, "symbol") c.voidType = c.newIntrinsicType(TypeFlagsVoid, "void") c.neverType = c.newIntrinsicType(TypeFlagsNever, "never") @@ -934,11 +934,11 @@ func NewChecker(program Program) *Checker { c.implicitNeverType = c.newIntrinsicType(TypeFlagsNever, "never") c.unreachableNeverType = c.newIntrinsicType(TypeFlagsNever, "never") c.nonPrimitiveType = c.newIntrinsicType(TypeFlagsNonPrimitive, "object") - c.stringOrNumberType = c.getUnionType([]*Type{c.stringType, c.numberType}) - c.stringNumberSymbolType = c.getUnionType([]*Type{c.stringType, c.numberType, c.esSymbolType}) - c.numberOrBigIntType = c.getUnionType([]*Type{c.numberType, c.bigintType}) + c.stringOrNumberType = c.GetUnionType([]*Type{c.stringType, c.numberType}) + c.stringNumberSymbolType = c.GetUnionType([]*Type{c.stringType, c.numberType, c.esSymbolType}) + c.numberOrBigIntType = c.GetUnionType([]*Type{c.numberType, c.bigintType}) c.numericStringType = c.getTemplateLiteralType([]string{"", ""}, []*Type{c.numberType}) // The `${number}` type - c.templateConstraintType = c.getUnionType([]*Type{c.stringType, c.numberType, c.booleanType, c.bigintType, c.nullType, c.undefinedType}) + c.templateConstraintType = c.GetUnionType([]*Type{c.stringType, c.numberType, c.booleanType, c.bigintType, c.nullType, c.undefinedType}) c.uniqueLiteralType = c.newIntrinsicType(TypeFlagsNever, "never") // Special `never` flagged by union reduction to behave as a literal c.uniqueLiteralMapper = newFunctionTypeMapper(c.getUniqueLiteralTypeForTypeParameter) c.reportUnreliableMapper = newFunctionTypeMapper(c.reportUnreliableWorker) @@ -973,7 +973,7 @@ func NewChecker(program Program) *Checker { c.emptyStringType = c.getStringLiteralType("") c.zeroType = c.getNumberLiteralType(0) c.zeroBigIntType = c.getBigIntLiteralType(jsnum.PseudoBigInt{}) - c.typeofType = c.getUnionType(core.Map(slices.Sorted(maps.Keys(typeofNEFacts)), c.getStringLiteralType)) + c.typeofType = c.GetUnionType(core.Map(slices.Sorted(maps.Keys(typeofNEFacts)), c.getStringLiteralType)) c.flowLoopCache = make(map[FlowLoopKey]*Type) c.flowNodeReachable = make(map[*ast.FlowNode]bool) c.flowNodePostSuper = make(map[*ast.FlowNode]bool) @@ -2989,7 +2989,7 @@ func (c *Checker) checkTupleType(node *ast.Node) { flags := c.getTupleElementFlags(e) if flags&ElementFlagsVariadic != 0 { t := c.GetTypeFromTypeNode(e.Type()) - if !c.isArrayLikeType(t) { + if !c.IsArrayLikeType(t) { c.error(e, diagnostics.A_rest_element_type_must_be_an_array_type) break } @@ -4236,7 +4236,7 @@ func (c *Checker) checkKindsOfPropertyMemberOverrides(t *Type, baseType *Type) { } var notImplementedInfo map[*ast.Node]MemberInfo basePropertyCheck: - for _, baseProperty := range c.getPropertiesOfType(baseType) { + for _, baseProperty := range c.GetPropertiesOfType(baseType) { base := c.getTargetSymbol(baseProperty) if base.Flags&ast.SymbolFlagsPrototype != 0 { continue @@ -4246,7 +4246,7 @@ basePropertyCheck: continue } derived := c.getTargetSymbol(baseSymbol) - baseDeclarationFlags := getDeclarationModifierFlagsFromSymbol(base) + baseDeclarationFlags := GetDeclarationModifierFlagsFromSymbol(base) // In order to resolve whether the inherited method was overridden in the base class or not, // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated* // type declaration, derived and base resolve to the same symbol even in the case of generic classes. @@ -4285,7 +4285,7 @@ basePropertyCheck: } } else { // derived overrides base. - derivedDeclarationFlags := getDeclarationModifierFlagsFromSymbol(derived) + derivedDeclarationFlags := GetDeclarationModifierFlagsFromSymbol(derived) if baseDeclarationFlags&ast.ModifierFlagsPrivate != 0 || derivedDeclarationFlags&ast.ModifierFlagsPrivate != 0 { // either base or derived property is private - not override, skip it continue @@ -4456,7 +4456,7 @@ func (c *Checker) checkMemberForOverrideModifier(node *ast.Node, staticType *Typ } func (c *Checker) getSuggestedSymbolForNonexistentClassMember(name string, baseType *Type) *ast.Symbol { - return c.getSpellingSuggestionForName(name, c.getPropertiesOfType(baseType), ast.SymbolFlagsClassMember) + return c.getSpellingSuggestionForName(name, c.GetPropertiesOfType(baseType), ast.SymbolFlagsClassMember) } func (c *Checker) checkIndexConstraints(t *Type, symbol *ast.Symbol, isStaticIndex bool) { @@ -4717,7 +4717,7 @@ func (c *Checker) checkInheritedPropertiesAreIdentical(t *Type, typeNode *ast.No } identical := true for _, base := range baseTypes { - properties := c.getPropertiesOfType(c.getTypeWithThisArgument(base, t.AsInterfaceType().thisType, false)) + properties := c.GetPropertiesOfType(c.getTypeWithThisArgument(base, t.AsInterfaceType().thisType, false)) for _, prop := range properties { if existing, ok := seen[prop.Name]; !ok { seen[prop.Name] = InheritanceInfo{prop: prop, containingType: base} @@ -5517,14 +5517,14 @@ func (c *Checker) checkVariableLikeDeclaration(node *ast.Node) { globalAsyncDisposableType := c.getGlobalAsyncDisposableType() globalDisposableType := c.getGlobalDisposableType() if globalAsyncDisposableType != c.emptyObjectType && globalDisposableType != c.emptyObjectType { - optionalDisposableType := c.getUnionType([]*Type{globalAsyncDisposableType, globalDisposableType, c.nullType, c.undefinedType}) + optionalDisposableType := c.GetUnionType([]*Type{globalAsyncDisposableType, globalDisposableType, c.nullType, c.undefinedType}) c.checkTypeAssignableTo(c.widenTypeForVariableLikeDeclaration(initializerType, node, false), optionalDisposableType, initializer, diagnostics.The_initializer_of_an_await_using_declaration_must_be_either_an_object_with_a_Symbol_asyncDispose_or_Symbol_dispose_method_or_be_null_or_undefined) } } else if blockScopeKind == ast.NodeFlagsUsing { globalDisposableType := c.getGlobalDisposableType() if globalDisposableType != c.emptyObjectType { - optionalDisposableType := c.getUnionType([]*Type{globalDisposableType, c.nullType, c.undefinedType}) + optionalDisposableType := c.GetUnionType([]*Type{globalDisposableType, c.nullType, c.undefinedType}) c.checkTypeAssignableTo(c.widenTypeForVariableLikeDeclaration(initializerType, node, false), optionalDisposableType, initializer, diagnostics.The_initializer_of_a_using_declaration_must_be_either_an_object_with_a_Symbol_dispose_method_or_be_null_or_undefined) } @@ -5532,7 +5532,7 @@ func (c *Checker) checkVariableLikeDeclaration(node *ast.Node) { } if len(symbol.Declarations) > 1 { if core.Some(symbol.Declarations, func(d *ast.Declaration) bool { - return d != node && isVariableLike(d) && !c.areDeclarationFlagsIdentical(d, node) + return d != node && ast.IsVariableLike(d) && !c.areDeclarationFlagsIdentical(d, node) }) { c.error(name, diagnostics.All_declarations_of_0_must_have_identical_modifiers, scanner.DeclarationNameToString(name)) } @@ -5773,7 +5773,7 @@ func (c *Checker) getIteratedTypeOrElementType(use IterationUse, inputType *Type } } } - if !c.isArrayLikeType(arrayType) { + if !c.IsArrayLikeType(arrayType) { if errorNode != nil { // Which error we report depends on whether we allow strings or if there was a // string constituent. For example, if the input type is number | string, we @@ -5997,7 +5997,7 @@ func (c *Checker) getIterationTypeUnion(iterationTypes []IterationTypes, f func( if len(types) == 0 { return nil } - return c.getUnionType(types) + return c.GetUnionType(types) } func (c *Checker) getAsyncFromSyncIterationTypes(iterationTypes IterationTypes, errorNode *ast.Node) IterationTypes { @@ -6165,7 +6165,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes if methodName != "throw" { var methodParameterType *Type if methodParameterTypes != nil { - methodParameterType = c.getUnionType(methodParameterTypes) + methodParameterType = c.GetUnionType(methodParameterTypes) } else { methodParameterType = c.unknownType } @@ -6198,7 +6198,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes yieldType = iterationTypes.yieldType returnTypes = append(returnTypes, iterationTypes.returnType) } - return IterationTypes{yieldType, c.getUnionType(returnTypes), nextType} + return IterationTypes{yieldType, c.GetUnionType(returnTypes), nextType} } // Gets the *yield* and *return* types of an `IteratorResult`-like type. @@ -7622,7 +7622,7 @@ func (c *Checker) checkArrayLiteral(node *ast.Node, checkMode CheckMode) *Type { case ast.IsSpreadElement(e): spreadType := c.checkExpressionEx(e.AsSpreadElement().Expression, checkMode) switch { - case c.isArrayLikeType(spreadType): + case c.IsArrayLikeType(spreadType): elementTypes[i] = spreadType elementInfos[i] = TupleElementInfo{flags: ElementFlagsVariadic} case inDestructuringPattern: @@ -7828,7 +7828,7 @@ func (c *Checker) checkIndexedAccessIndexType(t *Type, accessNode *ast.Node) *Ty propertyName := c.getPropertyNameFromIndex(indexType, accessNode) if propertyName != ast.InternalSymbolNameMissing { propertySymbol := c.getConstituentProperty(objectType, propertyName) - if propertySymbol != nil && getDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsNonPublicAccessibilityModifier != 0 { + if propertySymbol != nil && GetDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsNonPublicAccessibilityModifier != 0 { c.error(accessNode, diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, propertyName) return c.errorType } @@ -8384,7 +8384,7 @@ func (c *Checker) resolveInstanceofExpression(node *ast.Node, candidatesOutArray if len(callSignatures) != 0 { return c.resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlagsNone, nil) } - } else if !(c.typeHasCallOrConstructSignatures(rightType) || c.isTypeSubtypeOf(rightType, c.globalFunctionType)) { + } else if !(c.TypeHasCallOrConstructSignatures(rightType) || c.isTypeSubtypeOf(rightType, c.globalFunctionType)) { c.error(right, diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_either_of_type_any_a_class_function_or_other_type_assignable_to_the_Function_interface_type_or_an_object_type_with_a_Symbol_hasInstance_method) return c.resolveErrorCall(node) } @@ -10719,7 +10719,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l } propType = indexInfo.valueType if c.compilerOptions.NoUncheckedIndexedAccess == core.TSTrue && getAssignmentTargetKind(node) != AssignmentKindDefinite { - propType = c.getUnionType([]*Type{propType, c.missingType}) + propType = c.GetUnionType([]*Type{propType, c.missingType}) } if c.compilerOptions.NoPropertyAccessFromIndexSignature == core.TSTrue && ast.IsPropertyAccessExpression(node) { c.error(right, diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, right.Text()) @@ -10852,7 +10852,7 @@ func (c *Checker) getPrivateIdentifierPropertyOfType(leftType *Type, lexicallySc func (c *Checker) checkPrivateIdentifierPropertyAccess(leftType *Type, right *ast.Node, lexicallyScopedIdentifier *ast.Symbol) bool { // Either the identifier could not be looked up in the lexical scope OR the lexically scoped identifier did not exist on the type. // Find a private identifier with the same description on the type. - properties := c.getPropertiesOfType(leftType) + properties := c.GetPropertiesOfType(leftType) var propertyOnType *ast.Symbol for _, symbol := range properties { decl := symbol.ValueDeclaration @@ -10950,7 +10950,7 @@ func (c *Checker) getSuggestedLibForNonExistentProperty(missingProperty string, } func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, containingType *Type) *ast.Symbol { - props := c.getPropertiesOfType(containingType) + props := c.GetPropertiesOfType(containingType) parent := name.Parent if ast.IsPropertyAccessExpression(parent) { props = core.Filter(props, func(prop *ast.Symbol) bool { @@ -10969,7 +10969,7 @@ func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, conta // @param type the type whose property we are checking. // @param property the accessed property's symbol. func (c *Checker) isValidPropertyAccessForCompletions(node *ast.Node, t *Type, property *ast.Symbol) bool { - return c.isPropertyAccessible(node, ast.IsPropertyAccessExpression(node) && node.Expression().Kind == ast.KindSuperKeyword, false /*isWrite*/, t, property) + return c.IsPropertyAccessible(node, ast.IsPropertyAccessExpression(node) && node.Expression().Kind == ast.KindSuperKeyword, false /*isWrite*/, t, property) // Previously we validated the 'this' type of methods but this adversely affected performance. See #31377 for more context. } @@ -10981,7 +10981,7 @@ func (c *Checker) isValidPropertyAccessForCompletions(node *ast.Node, t *Type, p // @param isWrite whether this is a write access, e.g. `++foo.x`. // @param containingType type where the property comes from. // @param property property symbol. -func (c *Checker) isPropertyAccessible(node *ast.Node, isSuper bool, isWrite bool, containingType *Type, property *ast.Symbol) bool { +func (c *Checker) IsPropertyAccessible(node *ast.Node, isSuper bool, isWrite bool, containingType *Type, property *ast.Symbol) bool { // Short-circuiting for improved performance. if IsTypeAny(containingType) { return true @@ -11287,7 +11287,7 @@ func (c *Checker) getDeclaringClass(prop *ast.Symbol) *Type { // Return true if source property is a valid override of protected parts of target property. func (c *Checker) isValidOverrideOf(sourceProp *ast.Symbol, targetProp *ast.Symbol) bool { return !c.forEachProperty(targetProp, func(tp *ast.Symbol) bool { - if getDeclarationModifierFlagsFromSymbol(tp)&ast.ModifierFlagsProtected != 0 { + if GetDeclarationModifierFlagsFromSymbol(tp)&ast.ModifierFlagsProtected != 0 { return !c.isPropertyInClassDerivedFrom(sourceProp, c.getDeclaringClass(tp)) } return false @@ -11824,7 +11824,7 @@ func (c *Checker) checkBinaryLikeExpression(left *ast.Node, operatorToken *ast.N if !c.strictNullChecks { t = c.getBaseTypeOfLiteralType(rightType) } - resultType = c.getUnionType([]*Type{c.extractDefinitelyFalsyTypes(t), rightType}) + resultType = c.GetUnionType([]*Type{c.extractDefinitelyFalsyTypes(t), rightType}) } if operator == ast.KindAmpersandAmpersandEqualsToken { c.checkAssignmentOperator(left, operator, right, leftType, rightType) @@ -11987,7 +11987,7 @@ func (c *Checker) checkArrayLiteralDestructuringElementAssignment(node *ast.Node if !ast.IsOmittedExpression(element) { if !ast.IsSpreadElement(element) { indexType := c.getNumberLiteralType(jsnum.Number(elementIndex)) - if c.isArrayLikeType(sourceType) { + if c.IsArrayLikeType(sourceType) { // We create a synthetic expression so that getIndexedAccessType doesn't get confused // when the element is a SyntaxKind.ElementAccessExpression. accessFlags := AccessFlagsExpressionPosition | core.IfElse(c.hasDefaultValue(element), AccessFlagsAllowMissing, 0) @@ -12399,7 +12399,7 @@ func (c *Checker) getExactOptionalUnassignableProperties(source *Type, target *T if isTupleType(source) && isTupleType(target) { return nil } - return core.Filter(c.getPropertiesOfType(target), func(targetProp *ast.Symbol) bool { + return core.Filter(c.GetPropertiesOfType(target), func(targetProp *ast.Symbol) bool { return c.isExactOptionalPropertyMismatch(c.getTypeOfPropertyOfType(source, targetProp.Name), c.getTypeOfSymbol(targetProp)) }) } @@ -12628,7 +12628,7 @@ func (c *Checker) checkObjectLiteral(node *ast.Node, checkMode CheckMode) *Type } func (c *Checker) checkSpreadPropOverrides(t *Type, props ast.SymbolTable, spread *ast.Node) { - for _, right := range c.getPropertiesOfType(t) { + for _, right := range c.GetPropertiesOfType(t) { if right.Flags&ast.SymbolFlagsOptional == 0 { if left := props[right.Name]; left != nil { diagnostic := c.error(left.ValueDeclaration, diagnostics.X_0_is_specified_more_than_once_so_this_usage_will_be_overwritten, left.Name) @@ -12703,15 +12703,15 @@ func (c *Checker) getSpreadType(left *Type, right *Type, symbol *ast.Symbol, obj } else { indexInfos = c.getUnionIndexInfos([]*Type{left, right}) } - for _, rightProp := range c.getPropertiesOfType(right) { - if getDeclarationModifierFlagsFromSymbol(rightProp)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { + for _, rightProp := range c.GetPropertiesOfType(right) { + if GetDeclarationModifierFlagsFromSymbol(rightProp)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { skippedPrivateMembers.Add(rightProp.Name) } else if c.isSpreadableProperty(rightProp) { members[rightProp.Name] = c.getSpreadSymbol(rightProp, readonly) } } - for _, leftProp := range c.getPropertiesOfType(left) { + for _, leftProp := range c.GetPropertiesOfType(left) { if skippedPrivateMembers.Has(leftProp.Name) || !c.isSpreadableProperty(leftProp) { continue } @@ -12772,7 +12772,7 @@ func (c *Checker) getUnionIndexInfos(types []*Type) []*IndexInfo { for _, info := range sourceInfos { indexType := info.keyType if core.Every(types, func(t *Type) bool { return c.getIndexInfoOfType(t, indexType) != nil }) { - valueType := c.getUnionType(core.Map(types, func(t *Type) *Type { + valueType := c.GetUnionType(core.Map(types, func(t *Type) *Type { return c.getIndexTypeOfType(t, indexType) })) isReadonly := core.Some(types, func(t *Type) bool { return c.getIndexInfoOfType(t, indexType).isReadonly }) @@ -12811,8 +12811,8 @@ func (c *Checker) tryMergeUnionOfObjectTypeAndEmptyObject(t *Type, readonly bool } // gets the type as if it had been spread, but where everything in the spread is made optional members := make(ast.SymbolTable) - for _, prop := range c.getPropertiesOfType(firstType) { - if getDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { + for _, prop := range c.GetPropertiesOfType(firstType) { + if GetDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { // do nothing, skip privates } else if c.isSpreadableProperty(prop) { isSetonlyAccessor := prop.Flags&ast.SymbolFlagsSetAccessor != 0 && prop.Flags&ast.SymbolFlagsGetAccessor == 0 @@ -13068,7 +13068,7 @@ func (c *Checker) isReadonlySymbol(symbol *ast.Symbol) bool { // Object.defineProperty assignments with writable false or no setter // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) return symbol.CheckFlags&ast.CheckFlagsReadonly != 0 || - symbol.Flags&ast.SymbolFlagsProperty != 0 && getDeclarationModifierFlagsFromSymbol(symbol)&ast.ModifierFlagsReadonly != 0 || + symbol.Flags&ast.SymbolFlagsProperty != 0 && GetDeclarationModifierFlagsFromSymbol(symbol)&ast.ModifierFlagsReadonly != 0 || symbol.Flags&ast.SymbolFlagsVariable != 0 && c.getDeclarationNodeFlagsFromSymbol(symbol)&ast.NodeFlagsConstant != 0 || symbol.Flags&ast.SymbolFlagsAccessor != 0 && symbol.Flags&ast.SymbolFlagsSetAccessor == 0 || symbol.Flags&ast.SymbolFlagsEnumMember != 0 @@ -15121,7 +15121,7 @@ func (c *Checker) getTypeOfSymbolWithDeferredType(symbol *ast.Symbol) *Type { if links.resolvedType == nil { deferred := c.deferredSymbolLinks.Get(symbol) if deferred.parent.flags&TypeFlagsUnion != 0 { - links.resolvedType = c.getUnionType(deferred.constituents) + links.resolvedType = c.GetUnionType(deferred.constituents) } else { links.resolvedType = c.getIntersectionType(deferred.constituents) } @@ -15135,7 +15135,7 @@ func (c *Checker) getWriteTypeOfSymbolWithDeferredType(symbol *ast.Symbol) *Type deferred := c.deferredSymbolLinks.Get(symbol) if len(deferred.writeConstituents) != 0 { if deferred.parent.flags&TypeFlagsUnion != 0 { - links.writeType = c.getUnionType(deferred.writeConstituents) + links.writeType = c.GetUnionType(deferred.writeConstituents) } else { links.writeType = c.getIntersectionType(deferred.writeConstituents) } @@ -15925,7 +15925,7 @@ func (c *Checker) getDefaultConstraintOfConditionalType(t *Type) *Type { case IsTypeAny(falseConstraint): d.resolvedDefaultConstraint = trueConstraint default: - d.resolvedDefaultConstraint = c.getUnionType([]*Type{trueConstraint, falseConstraint}) + d.resolvedDefaultConstraint = c.GetUnionType([]*Type{trueConstraint, falseConstraint}) } } return d.resolvedDefaultConstraint @@ -16429,7 +16429,7 @@ func (c *Checker) getBindingElementTypeFromParentType(declaration *ast.Node, par } else { t = c.createArrayType(elementType) } - } else if c.isArrayLikeType(parentType) { + } else if c.IsArrayLikeType(parentType) { indexType := c.getNumberLiteralType(jsnum.Number(index)) declaredType := core.OrElse(c.getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.Name(), nil), c.errorType) t = c.getFlowTypeOfDestructuring(declaration, declaredType) @@ -16463,12 +16463,12 @@ func (c *Checker) getRestType(source *Type, properties []*ast.Node, symbol *ast. return c.getRestType(t, properties, symbol) }) } - omitKeyType := c.getUnionType(core.Map(properties, c.getLiteralTypeFromPropertyName)) + omitKeyType := c.GetUnionType(core.Map(properties, c.getLiteralTypeFromPropertyName)) var spreadableProperties []*ast.Symbol var unspreadableToRestKeys []*Type - for _, prop := range c.getPropertiesOfType(source) { + for _, prop := range c.GetPropertiesOfType(source) { literalTypeFromProperty := c.getLiteralTypeFromProperty(prop, TypeFlagsStringOrNumberLiteralOrUnique, false) - if !c.isTypeAssignableTo(literalTypeFromProperty, omitKeyType) && getDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) == 0 && c.isSpreadableProperty(prop) { + if !c.isTypeAssignableTo(literalTypeFromProperty, omitKeyType) && GetDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) == 0 && c.isSpreadableProperty(prop) { spreadableProperties = append(spreadableProperties, prop) } else { unspreadableToRestKeys = append(unspreadableToRestKeys, literalTypeFromProperty) @@ -16479,7 +16479,7 @@ func (c *Checker) getRestType(source *Type, properties []*ast.Node, symbol *ast. // If the type we're spreading from has properties that cannot // be spread into the rest type (e.g. getters, methods), ensure // they are explicitly omitted, as they would in the non-generic case. - omitKeyType = c.getUnionType(append([]*Type{omitKeyType}, unspreadableToRestKeys...)) + omitKeyType = c.GetUnionType(append([]*Type{omitKeyType}, unspreadableToRestKeys...)) } if omitKeyType.flags&TypeFlagsNever != 0 { return source @@ -16721,7 +16721,7 @@ func (c *Checker) getWidenedTypeForAssignmentDeclaration(symbol *ast.Symbol) *Ty types = core.AppendIfUnique(types, c.checkExpressionForMutableLocation(declaration.AsBinaryExpression().Right, CheckModeNormal)) } } - return c.getWidenedType(c.getUnionType(types)) + return c.getWidenedType(c.GetUnionType(types)) } func (c *Checker) widenTypeForVariableLikeDeclaration(t *Type, declaration *ast.Node, reportErrors bool) *Type { @@ -16911,7 +16911,7 @@ func (c *Checker) getPropertiesOfContext(context *WideningContext) []*ast.Symbol var names collections.OrderedMap[string, *ast.Symbol] for _, t := range c.getSiblingsOfContext(context) { if isObjectLiteralType(t) && t.objectFlags&ObjectFlagsContainsSpread == 0 { - for _, prop := range c.getPropertiesOfType(t) { + for _, prop := range c.GetPropertiesOfType(t) { names.Set(prop.Name, prop) } } @@ -17094,7 +17094,7 @@ func (c *Checker) getOptionalType(t *Type, isProperty bool) *Type { if t == missingOrUndefined || t.flags&TypeFlagsUnion != 0 && t.Types()[0] == missingOrUndefined { return t } - return c.getUnionType([]*Type{t, missingOrUndefined}) + return c.GetUnionType([]*Type{t, missingOrUndefined}) } // Add undefined or null or both to a type if they are missing. @@ -17104,11 +17104,11 @@ func (c *Checker) getNullableType(t *Type, flags TypeFlags) *Type { case missing == 0: return t case missing == TypeFlagsUndefined: - return c.getUnionType([]*Type{t, c.undefinedType}) + return c.GetUnionType([]*Type{t, c.undefinedType}) case missing == TypeFlagsNull: - return c.getUnionType([]*Type{t, c.nullType}) + return c.GetUnionType([]*Type{t, c.nullType}) } - return c.getUnionType([]*Type{t, c.undefinedType, c.nullType}) + return c.GetUnionType([]*Type{t, c.undefinedType, c.nullType}) } func (c *Checker) GetNonNullableType(t *Type) *Type { @@ -17152,7 +17152,7 @@ func (c *Checker) isVarConstLike(node *ast.Node) bool { } func (c *Checker) getEffectivePropertyNameForPropertyNameNode(node *ast.PropertyName) (string, bool) { - name := getPropertyNameForPropertyNameNode(node) + name := GetPropertyNameForPropertyNameNode(node) switch { case name != ast.InternalSymbolNameMissing: return name, true @@ -17283,7 +17283,7 @@ func (c *Checker) reportCircularityError(symbol *ast.Symbol) *Type { return c.anyType } -func (c *Checker) getPropertiesOfType(t *Type) []*ast.Symbol { +func (c *Checker) GetPropertiesOfType(t *Type) []*ast.Symbol { t = c.getReducedApparentType(t) if t.flags&TypeFlagsUnionOrIntersection != 0 { return c.getPropertiesOfUnionOrIntersectionType(t) @@ -17304,7 +17304,7 @@ func (c *Checker) getPropertiesOfUnionOrIntersectionType(t *Type) []*ast.Symbol var checked core.Set[string] props := []*ast.Symbol{} for _, current := range d.types { - for _, prop := range c.getPropertiesOfType(current) { + for _, prop := range c.GetPropertiesOfType(current) { if !checked.Has(prop.Name) { checked.Add(prop.Name) combinedProp := c.getPropertyOfUnionOrIntersectionType(t, prop.Name, t.flags&TypeFlagsIntersection != 0 /*skipObjectFunctionPropertyAugment*/) @@ -17576,7 +17576,7 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters if thisArgument != nil { instantiatedBaseType = c.getTypeWithThisArgument(c.instantiateType(baseType, mapper), thisArgument, false /*needsApparentType*/) } - members = c.addInheritedMembers(members, c.getPropertiesOfType(instantiatedBaseType)) + members = c.addInheritedMembers(members, c.GetPropertiesOfType(instantiatedBaseType)) callSignatures = core.Concatenate(callSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindCall)) constructSignatures = core.Concatenate(constructSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindConstruct)) var inheritedIndexInfos []*IndexInfo @@ -17644,7 +17644,7 @@ func (c *Checker) getTupleBaseType(t *Type) *Type { elementTypes[i] = tp } } - return c.createArrayTypeEx(c.getUnionType(elementTypes), t.AsTupleType().readonly) + return c.createArrayTypeEx(c.GetUnionType(elementTypes), t.AsTupleType().readonly) } func (c *Checker) resolveBaseTypesOfClass(t *Type) { @@ -18992,7 +18992,7 @@ func (c *Checker) checkIfExpressionRefinesParameter(fn *ast.Node, expr *ast.Node func (c *Checker) addOptionalTypeMarker(t *Type) *Type { if c.strictNullChecks { - return c.getUnionType([]*Type{t, c.optionalType}) + return c.GetUnionType([]*Type{t, c.optionalType}) } return t } @@ -19072,7 +19072,7 @@ func (c *Checker) resolveAnonymousTypeMembers(t *Type) { baseConstructorType := c.getBaseConstructorTypeOfClass(classType) if baseConstructorType.flags&(TypeFlagsObject|TypeFlagsIntersection|TypeFlagsTypeVariable) != 0 { members = maps.Clone(members) - c.addInheritedMembers(members, c.getPropertiesOfType(baseConstructorType)) + c.addInheritedMembers(members, c.GetPropertiesOfType(baseConstructorType)) c.setStructuredTypeMembers(t, members, nil, nil, nil) } else if baseConstructorType == c.anyType { baseConstructorIndexInfo = &IndexInfo{keyType: c.stringType, valueType: c.anyType} @@ -19305,9 +19305,9 @@ func (c *Checker) resolveMappedTypeMembers(t *Type) { // property symbol's name type be the union of those enum member types. if existingProp := members[propName]; existingProp != nil { valueLinks := c.valueSymbolLinks.Get(existingProp) - valueLinks.nameType = c.getUnionType([]*Type{valueLinks.nameType, propNameType}) + valueLinks.nameType = c.GetUnionType([]*Type{valueLinks.nameType, propNameType}) mappedLinks := c.mappedSymbolLinks.Get(existingProp) - mappedLinks.keyType = c.getUnionType([]*Type{mappedLinks.keyType, keyType}) + mappedLinks.keyType = c.GetUnionType([]*Type{mappedLinks.keyType, keyType}) } else { var modifiersProp *ast.Symbol if isTypeUsableAsPropertyName(keyType) { @@ -19733,7 +19733,7 @@ func (c *Checker) appendIndexInfo(indexInfos []*IndexInfo, newInfo *IndexInfo, u var valueType *Type var isReadonly bool if union { - valueType = c.getUnionType([]*Type{info.valueType, newInfo.valueType}) + valueType = c.GetUnionType([]*Type{info.valueType, newInfo.valueType}) isReadonly = info.isReadonly || newInfo.isReadonly } else { valueType = c.getIntersectionType([]*Type{info.valueType, newInfo.valueType}) @@ -19853,7 +19853,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s prop := c.getPropertyOfTypeEx(t, name, skipObjectFunctionPropertyAugment, false) var modifiers ast.ModifierFlags if prop != nil { - modifiers = getDeclarationModifierFlagsFromSymbol(prop) + modifiers = GetDeclarationModifierFlagsFromSymbol(prop) if prop.Flags&ast.SymbolFlagsClassMember != 0 { if isUnion { optionalFlag |= prop.Flags & ast.SymbolFlagsOptional @@ -20018,13 +20018,13 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s return result } if isUnion { - links.resolvedType = c.getUnionType(propTypes) + links.resolvedType = c.GetUnionType(propTypes) } else { links.resolvedType = c.getIntersectionType(propTypes) } if writeTypes != nil { if isUnion { - links.writeType = c.getUnionType(writeTypes) + links.writeType = c.GetUnionType(writeTypes) } else { links.writeType = c.getIntersectionType(writeTypes) } @@ -20220,7 +20220,7 @@ func (c *Checker) getReducedUnionType(unionType *Type) *Type { if core.Same(reducedTypes, unionType.Types()) { return unionType } - reduced := c.getUnionType(reducedTypes) + reduced := c.GetUnionType(reducedTypes) if reduced.flags&TypeFlagsUnion != 0 { reduced.AsUnionType().resolvedReducedType = reduced } @@ -21055,11 +21055,11 @@ func (c *Checker) getApparentMappedTypeKeys(nameType *Type, targetType *Type) *T c.forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlagsStringOrNumberLiteralOrUnique, false, func(t *Type) { mappedKeys = append(mappedKeys, c.instantiateType(nameType, appendTypeMapping(targetType.Mapper(), c.getTypeParameterFromMappedType(targetType), t))) }) - return c.getUnionType(mappedKeys) + return c.GetUnionType(mappedKeys) } func (c *Checker) forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(t *Type, include TypeFlags, stringsOnly bool, cb func(keyType *Type)) { - for _, prop := range c.getPropertiesOfType(t) { + for _, prop := range c.GetPropertiesOfType(t) { cb(c.getLiteralTypeFromProperty(prop, include, false)) } if t.flags&TypeFlagsAny != 0 { @@ -21642,7 +21642,7 @@ func (n *TupleNormalizer) normalize(c *Checker, elementTypes []*Type, elementInf } else { // Treat everything else as an array type and create a rest element. var s *Type - if c.isArrayLikeType(t) { + if c.IsArrayLikeType(t) { s = c.getIndexTypeOfType(t, c.numberType) } if s == nil { @@ -21671,7 +21671,7 @@ func (n *TupleNormalizer) normalize(c *Checker, elementTypes []*Type, elementInf } types = append(types, t) } - n.types[n.firstRestIndex] = c.getUnionType(types) + n.types[n.firstRestIndex] = c.GetUnionType(types) n.types = slices.Delete(n.types, n.firstRestIndex+1, n.lastOptionalOrRestIndex+1) n.infos = slices.Delete(n.infos, n.firstRestIndex+1, n.lastOptionalOrRestIndex+1) } @@ -21768,7 +21768,7 @@ func (c *Checker) getElementTypeOfArrayType(t *Type) *Type { return nil } -func (c *Checker) isArrayLikeType(t *Type) bool { +func (c *Checker) IsArrayLikeType(t *Type) bool { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray return c.isArrayType(t) || t.flags&TypeFlagsNullable == 0 && c.isTypeAssignableTo(t, c.anyReadonlyArrayType) @@ -21796,7 +21796,7 @@ func (c *Checker) isTupleLikeType(t *Type) bool { if isTupleType(t) || c.getPropertyOfType(t, "0") != nil { return true } - if c.isArrayLikeType(t) { + if c.IsArrayLikeType(t) { if lengthType := c.getTypeOfPropertyOfType(t, "length"); lengthType != nil { return everyType(lengthType, func(t *Type) bool { return t.flags&TypeFlagsNumberLiteral != 0 }) } @@ -21805,7 +21805,7 @@ func (c *Checker) isTupleLikeType(t *Type) bool { } func (c *Checker) isArrayOrTupleLikeType(t *Type) bool { - return c.isArrayLikeType(t) || c.isTupleLikeType(t) + return c.IsArrayLikeType(t) || c.isTupleLikeType(t) } func (c *Checker) isArrayOrTupleOrIntersection(t *Type) bool { @@ -22683,7 +22683,7 @@ func (c *Checker) getConditionalType(root *ConditionalRoot, mapper *TypeMapper, break } if extraTypes != nil { - return c.getUnionType(append(extraTypes, result)) + return c.GetUnionType(append(extraTypes, result)) } return result } @@ -23039,7 +23039,7 @@ func (c *Checker) createTupleTargetType(elementInfos []TupleElementInfo, readonl for i := minLength; i <= arity; i++ { literalTypes = append(literalTypes, c.getNumberLiteralType(jsnum.Number(i))) } - c.valueSymbolLinks.Get(lengthSymbol).resolvedType = c.getUnionType(literalTypes) + c.valueSymbolLinks.Get(lengthSymbol).resolvedType = c.GetUnionType(literalTypes) } members[lengthSymbol.Name] = lengthSymbol t := c.newObjectType(ObjectFlagsTuple|ObjectFlagsReference, nil) @@ -23094,7 +23094,7 @@ func (c *Checker) getTupleElementTypeOutOfStartCount(t *Type, index jsnum.Number return c.undefinedType } if undefinedLikeType != nil && index >= jsnum.Number(getTotalFixedElementCount(t.TargetTupleType())) { - return c.getUnionType([]*Type{restType, undefinedLikeType}) + return c.GetUnionType([]*Type{restType, undefinedLikeType}) } return restType }) @@ -23208,7 +23208,7 @@ func (c *Checker) getConditionalFlowTypeOfType(t *Type, node *ast.Node) *Type { if typeParameter != nil { constraint := c.getConstraintOfTypeParameter(typeParameter) if constraint != nil && everyType(constraint, c.isArrayOrTupleType) { - constraints = append(constraints, c.getUnionType([]*Type{c.numberType, c.numericStringType})) + constraints = append(constraints, c.GetUnionType([]*Type{c.numberType, c.numericStringType})) } } } @@ -23267,7 +23267,7 @@ func (c *Checker) createWideningType(nonWideningType *Type) *Type { func (c *Checker) createUnknownUnionType() *Type { if c.strictNullChecks { - return c.getUnionType([]*Type{c.undefinedType, c.nullType, c.unknownEmptyObjectType}) + return c.GetUnionType([]*Type{c.undefinedType, c.nullType, c.unknownEmptyObjectType}) } return c.unknownType } @@ -23823,7 +23823,7 @@ func (c *Checker) getUnionOrIntersectionType(types []*Type, isUnion bool, unionR return c.getIntersectionType(types) } -func (c *Checker) getUnionType(types []*Type) *Type { +func (c *Checker) GetUnionType(types []*Type) *Type { return c.getUnionTypeEx(types, UnionReductionLiteral, nil /*alias*/, nil /*origin*/) } @@ -24153,7 +24153,7 @@ func (c *Checker) removeSubtypes(types []*Type, hasObjectTypes bool) []*Type { // a subtype of just `A` or just `B`. When we encounter such a type parameter, we therefore check if the // type parameter is a subtype of a union of all the other types. if source.flags&TypeFlagsTypeParameter != 0 && c.getBaseConstraintOrType(source).flags&TypeFlagsUnion != 0 { - if c.isTypeRelatedTo(source, c.getUnionType(core.Map(types, func(t *Type) *Type { + if c.isTypeRelatedTo(source, c.GetUnionType(core.Map(types, func(t *Type) *Type { if t == source { return c.neverType } @@ -24169,7 +24169,7 @@ func (c *Checker) removeSubtypes(types []*Type, hasObjectTypes bool) []*Type { var keyProperty *ast.Symbol var keyPropertyType *Type if source.flags&(TypeFlagsObject|TypeFlagsIntersection|TypeFlagsInstantiableNonPrimitive) != 0 { - keyProperty = core.Find(c.getPropertiesOfType(source), func(p *ast.Symbol) bool { + keyProperty = core.Find(c.GetPropertiesOfType(source), func(p *ast.Symbol) bool { return isUnitType(c.getTypeOfSymbol(p)) }) } @@ -24848,7 +24848,7 @@ func (c *Checker) getIndexTypeEx(t *Type, indexFlags IndexFlags) *Type { case t.flags&TypeFlagsUnion != 0: return c.getIntersectionType(core.Map(t.Types(), func(t *Type) *Type { return c.getIndexTypeEx(t, indexFlags) })) case t.flags&TypeFlagsIntersection != 0: - return c.getUnionType(core.Map(t.Types(), func(t *Type) *Type { return c.getIndexTypeEx(t, indexFlags) })) + return c.GetUnionType(core.Map(t.Types(), func(t *Type) *Type { return c.getIndexTypeEx(t, indexFlags) })) case t.objectFlags&ObjectFlagsMapped != 0: return c.getIndexTypeForMappedType(t, indexFlags) case t == c.wildcardType: @@ -24877,7 +24877,7 @@ func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, inclu origin = c.newIndexType(t, IndexFlagsNone) } var types []*Type - for _, prop := range c.getPropertiesOfType(t) { + for _, prop := range c.GetPropertiesOfType(t) { types = append(types, c.getLiteralTypeFromProperty(prop, include, false)) } for _, info := range c.getIndexInfosOfType(t) { @@ -24893,7 +24893,7 @@ func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, inclu } func (c *Checker) getLiteralTypeFromProperty(prop *ast.Symbol, include TypeFlags, includeNonPublic bool) *Type { - if includeNonPublic || getDeclarationModifierFlagsFromSymbol(prop)&ast.ModifierFlagsNonPublicAccessibilityModifier == 0 { + if includeNonPublic || GetDeclarationModifierFlagsFromSymbol(prop)&ast.ModifierFlagsNonPublicAccessibilityModifier == 0 { t := c.valueSymbolLinks.Get(c.getLateBoundSymbol(prop)).nameType if t == nil { if prop.Name == ast.InternalSymbolNameDefault { @@ -24925,7 +24925,7 @@ func (c *Checker) getLiteralTypeFromPropertyName(name *ast.Node) *Type { if ast.IsComputedPropertyName(name) { return c.getRegularTypeOfLiteralType(c.checkComputedPropertyName(name)) } - propertyName := getPropertyNameForPropertyNameNode(name) + propertyName := GetPropertyNameForPropertyNameNode(name) if propertyName != ast.InternalSymbolNameMissing { return c.getStringLiteralType(propertyName) } @@ -25087,11 +25087,11 @@ func (c *Checker) getIndexTypeForMappedType(t *Type, indexFlags IndexFlags) *Typ // original constraintType, so we can return the union that preserves aliases/origin data if possible. var result *Type if indexFlags&IndexFlagsNoIndexSignatures != 0 { - result = c.filterType(c.getUnionType(keyTypes), func(t *Type) bool { + result = c.filterType(c.GetUnionType(keyTypes), func(t *Type) bool { return t.flags&(TypeFlagsAny|TypeFlagsString) == 0 }) } else { - result = c.getUnionType(keyTypes) + result = c.GetUnionType(keyTypes) } if result.flags&TypeFlagsUnion != 0 && constraintType.flags&TypeFlagsUnion != 0 && getTypeListKey(result.Types()) == getTypeListKey(constraintType.Types()) { return constraintType @@ -25226,7 +25226,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy case accessExpression != nil && getAssignmentTargetKind(accessExpression) != AssignmentKindDefinite: return c.getFlowTypeOfReference(accessExpression, propType) case accessNode != nil && ast.IsIndexedAccessTypeNode(accessNode) && c.containsMissingType(propType): - return c.getUnionType([]*Type{propType, c.undefinedType}) + return c.GetUnionType([]*Type{propType, c.undefinedType}) default: return propType } @@ -25278,7 +25278,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy indexNode := getIndexNodeForAccessExpression(accessNode) c.error(indexNode, diagnostics.Type_0_cannot_be_used_as_an_index_type, c.TypeToString(indexType)) if accessFlags&AccessFlagsIncludeUndefined != 0 { - return c.getUnionType([]*Type{indexInfo.valueType, c.missingType}) + return c.GetUnionType([]*Type{indexInfo.valueType, c.missingType}) } else { return indexInfo.valueType } @@ -25293,7 +25293,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy (indexType.symbol != nil && indexType.flags&TypeFlagsEnumLiteral != 0 && c.getParentOfSymbol(indexType.symbol) == objectType.symbol)) { - return c.getUnionType([]*Type{indexInfo.valueType, c.missingType}) + return c.GetUnionType([]*Type{indexInfo.valueType, c.missingType}) } return indexInfo.valueType } @@ -25309,7 +25309,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy types := core.Map(objectType.AsStructuredType().properties, func(prop *ast.Symbol) *Type { return c.getTypeOfSymbol(prop) }) - return c.getUnionType(append(types, c.undefinedType)) + return c.GetUnionType(append(types, c.undefinedType)) } } if objectType.symbol == c.globalThisSymbol && hasPropName && c.globalThisSymbol.Exports[propName] != nil && c.globalThisSymbol.Exports[propName].Flags&ast.SymbolFlagsBlockScoped != 0 { @@ -25388,7 +25388,7 @@ func (c *Checker) typeHasStaticProperty(propName string, containingType *Type) b } func (c *Checker) getSuggestionForNonexistentProperty(name string, containingType *Type) string { - symbol := c.getSpellingSuggestionForName(name, c.getPropertiesOfType(containingType), ast.SymbolFlagsValue) + symbol := c.getSpellingSuggestionForName(name, c.GetPropertiesOfType(containingType), ast.SymbolFlagsValue) if symbol != nil { return symbol.Name } @@ -25512,13 +25512,13 @@ func (c *Checker) getPropertyNameFromIndex(indexType *Type, accessNode *ast.Node return getPropertyNameFromType(indexType) } if accessNode != nil && ast.IsPropertyName(accessNode) { - return getPropertyNameForPropertyNameNode(accessNode) + return GetPropertyNameForPropertyNameNode(accessNode) } return ast.InternalSymbolNameMissing } func (c *Checker) isStringIndexSignatureOnlyTypeWorker(t *Type) bool { - return t.flags&TypeFlagsObject != 0 && !c.isGenericMappedType(t) && len(c.getPropertiesOfType(t)) == 0 && len(c.getIndexInfosOfType(t)) == 1 && c.getIndexInfoOfType(t, c.stringType) != nil || + return t.flags&TypeFlagsObject != 0 && !c.isGenericMappedType(t) && len(c.GetPropertiesOfType(t)) == 0 && len(c.getIndexInfosOfType(t)) == 1 && c.getIndexInfoOfType(t, c.stringType) != nil || t.flags&TypeFlagsUnionOrIntersection != 0 && core.Every(t.Types(), c.isStringIndexSignatureOnlyType) } @@ -25673,7 +25673,7 @@ func (c *Checker) computeBaseConstraint(t *Type, stack []RecursionId) *Type { } switch { case t.flags&TypeFlagsUnion != 0 && len(constraints) == len(types): - return c.getUnionType(constraints) + return c.GetUnionType(constraints) case t.flags&TypeFlagsIntersection != 0 && len(constraints) != 0: return c.getIntersectionType(constraints) } @@ -25822,8 +25822,8 @@ func (c *Checker) compareProperties(sourceProp *ast.Symbol, targetProp *ast.Symb if sourceProp == targetProp { return TernaryTrue } - sourcePropAccessibility := getDeclarationModifierFlagsFromSymbol(sourceProp) & ast.ModifierFlagsNonPublicAccessibilityModifier - targetPropAccessibility := getDeclarationModifierFlagsFromSymbol(targetProp) & ast.ModifierFlagsNonPublicAccessibilityModifier + sourcePropAccessibility := GetDeclarationModifierFlagsFromSymbol(sourceProp) & ast.ModifierFlagsNonPublicAccessibilityModifier + targetPropAccessibility := GetDeclarationModifierFlagsFromSymbol(targetProp) & ast.ModifierFlagsNonPublicAccessibilityModifier if sourcePropAccessibility != targetPropAccessibility { return TernaryFalse } @@ -25979,7 +25979,7 @@ func (c *Checker) containsUndefinedType(t *Type) bool { return t.flags&TypeFlagsUndefined != 0 } -func (c *Checker) typeHasCallOrConstructSignatures(t *Type) bool { +func (c *Checker) TypeHasCallOrConstructSignatures(t *Type) bool { return t.flags&TypeFlagsStructuredType != 0 && len(c.resolveStructuredTypeMembers(t).signatures) != 0 } @@ -26098,7 +26098,7 @@ func (c *Checker) distributeObjectOverIndexType(objectType *Type, indexType *Typ if writing { return c.getIntersectionType(types) } - return c.getUnionType(types) + return c.GetUnionType(types) } return nil } @@ -26114,7 +26114,7 @@ func (c *Checker) distributeIndexOverObjectType(objectType *Type, indexType *Typ if objectType.flags&TypeFlagsIntersection != 0 || writing { return c.getIntersectionType(types) } - return c.getUnionType(types) + return c.GetUnionType(types) } return nil } @@ -26143,7 +26143,7 @@ func (c *Checker) getSimplifiedConditionalType(t *Type, writing bool) *Type { // Invokes union simplification logic to determine if an intersection is considered empty as a union constituent func (c *Checker) isIntersectionEmpty(type1 *Type, type2 *Type) bool { - return c.getUnionType([]*Type{c.intersectTypes(type1, type2), c.neverType}).flags&TypeFlagsNever != 0 + return c.GetUnionType([]*Type{c.intersectTypes(type1, type2), c.neverType}).flags&TypeFlagsNever != 0 } func (c *Checker) getSimplifiedTypeOrConstraint(t *Type) *Type { @@ -26775,7 +26775,7 @@ func (c *Checker) getPromisedTypeOfPromiseEx(t *Type, errorNode *ast.Node, thisT } return nil } - onfulfilledParameterType := c.getTypeWithFacts(c.getUnionType(core.Map(candidates, c.getTypeOfFirstParameterOfSignature)), TypeFactsNEUndefinedOrNull) + onfulfilledParameterType := c.getTypeWithFacts(c.GetUnionType(core.Map(candidates, c.getTypeOfFirstParameterOfSignature)), TypeFactsNEUndefinedOrNull) if IsTypeAny(onfulfilledParameterType) { return nil } @@ -27099,7 +27099,7 @@ func (c *Checker) substituteIndexedMappedType(objectType *Type, index *Type) *Ty // Return true if an indexed access with the given object and index types could access an optional property. func (c *Checker) couldAccessOptionalProperty(objectType *Type, indexType *Type) bool { indexConstraint := c.getBaseConstraintOfType(indexType) - return indexConstraint != nil && core.Some(c.getPropertiesOfType(objectType), func(p *ast.Symbol) bool { + return indexConstraint != nil && core.Some(c.GetPropertiesOfType(objectType), func(p *ast.Symbol) bool { return p.Flags&ast.SymbolFlagsOptional != 0 && c.isTypeAssignableTo(c.getLiteralTypeFromProperty(p, TypeFlagsStringOrNumberLiteralOrUnique, false), indexConstraint) }) } @@ -27300,7 +27300,7 @@ func (c *Checker) getSpreadArgumentType(args []*ast.Node, index int, argCount in } else { spreadType = c.checkExpressionWithContextualType(arg.Expression(), restType, context, checkMode) } - if c.isArrayLikeType(spreadType) { + if c.IsArrayLikeType(spreadType) { return c.getMutableArrayOrTupleType(spreadType) } if ast.IsSpreadElement(arg) { @@ -27322,7 +27322,7 @@ func (c *Checker) getSpreadArgumentType(args []*ast.Node, index int, argCount in } else { spreadType = c.checkExpression(arg.Expression()) } - if c.isArrayLikeType(spreadType) { + if c.IsArrayLikeType(spreadType) { t = spreadType info.flags = ElementFlagsVariadic } else { @@ -27431,7 +27431,7 @@ func (c *Checker) getContextualTypeForReturnExpression(node *ast.Node, contextFl if functionFlags&FunctionFlagsAsync != 0 { // Get the awaited type without the `Awaited` alias contextualAwaitedType := c.mapType(contextualReturnType, c.getAwaitedTypeNoAlias) - return c.getUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) + return c.GetUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) } // Regular function or Generator function return contextualReturnType @@ -27524,7 +27524,7 @@ func (c *Checker) getContextualTypeForYieldOperand(node *ast.Node, contextFlags generatorType := c.createGeneratorType(yieldType, returnType, nextType, false /*isAsyncGenerator*/) if isAsyncGenerator { asyncGeneratorType := c.createGeneratorType(yieldType, returnType, nextType, true /*isAsyncGenerator*/) - return c.getUnionType([]*Type{generatorType, asyncGeneratorType}) + return c.GetUnionType([]*Type{generatorType, asyncGeneratorType}) } return generatorType } @@ -27539,7 +27539,7 @@ func (c *Checker) getContextualTypeForAwaitOperand(node *ast.Node, contextFlags if contextualType != nil { contextualAwaitedType := c.getAwaitedTypeNoAlias(contextualType) if contextualAwaitedType != nil { - return c.getUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) + return c.GetUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) } } return nil @@ -27916,7 +27916,7 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur // "static" or "constructor" side of the class). targetType := c.getTypeOfSymbol(c.getSymbolOfDeclaration(node)) targetParam := c.newParameter("target", targetType) - links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam}, c.getUnionType([]*Type{targetType, c.voidType})) + links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam}, c.GetUnionType([]*Type{targetType, c.voidType})) case ast.KindParameter: if !ast.IsConstructorDeclaration(node.Parent) && !(ast.IsMethodDeclaration(node.Parent) || ast.IsSetAccessorDeclaration(node.Parent) && ast.IsClassLike(node.Parent.Parent)) { break @@ -27960,9 +27960,9 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur if hasPropDesc { descriptorType := c.newTypedPropertyDescriptorType(c.getTypeOfNode(node)) descriptorParam := c.newParameter("descriptor", descriptorType) - links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam, descriptorParam}, c.getUnionType([]*Type{returnType, c.voidType})) + links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam, descriptorParam}, c.GetUnionType([]*Type{returnType, c.voidType})) } else { - links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam}, c.getUnionType([]*Type{returnType, c.voidType})) + links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam}, c.GetUnionType([]*Type{returnType, c.voidType})) } } } @@ -28241,7 +28241,7 @@ func (c *Checker) newClassFieldDecoratorInitializerMutatorType(thisType *Type, v func (c *Checker) newESDecoratorCallSignature(targetType *Type, contextType *Type, nonOptionalReturnType *Type) *Signature { targetParam := c.newParameter("target", targetType) contextParam := c.newParameter("context", contextType) - returnType := c.getUnionType([]*Type{nonOptionalReturnType, c.voidType}) + returnType := c.GetUnionType([]*Type{nonOptionalReturnType, c.voidType}) return c.newCallSignature(nil, nil /*thisParameter*/, []*ast.Symbol{targetParam, contextParam}, returnType) } @@ -28517,7 +28517,7 @@ func (c *Checker) discriminateContextualTypeByObjectMembers(node *ast.Node, cont } return false }) - discriminantMembers := core.Filter(c.getPropertiesOfType(contextualType), func(s *ast.Symbol) bool { + discriminantMembers := core.Filter(c.GetPropertiesOfType(contextualType), func(s *ast.Symbol) bool { return s.Flags&ast.SymbolFlagsOptional != 0 && node.Symbol().Members[s.Name] == nil && c.isDiscriminantProperty(contextualType, s.Name) }) discriminator := &ObjectLiteralDiscriminator{c: c, props: discriminantProperties, members: discriminantMembers} @@ -28912,7 +28912,7 @@ func (c *Checker) removeNullableByIntersection(t *Type, targetFacts TypeFacts, o return t } // By default we intersect with a union of {} and the opposite nullable. - emptyAndOtherUnion := c.getUnionType([]*Type{c.emptyObjectType, otherType}) + emptyAndOtherUnion := c.GetUnionType([]*Type{c.emptyObjectType, otherType}) // For each constituent type that can compare equal to the target nullable, intersect with the above union // if the type doesn't already include the opposite nullable and the constituent can compare equal to the // opposite nullable; otherwise, just intersect with {}. diff --git a/internal/checker/flow.go b/internal/checker/flow.go index 58dcf30b9c..c816d11f82 100644 --- a/internal/checker/flow.go +++ b/internal/checker/flow.go @@ -333,7 +333,7 @@ func (c *Checker) narrowTypeByAssertion(f *FlowState, t *Type, expr *ast.Node) * return c.narrowTypeByAssertion(f, c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Left), node.AsBinaryExpression().Right) } if node.AsBinaryExpression().OperatorToken.Kind == ast.KindBarBarToken { - return c.getUnionType([]*Type{c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Left), c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Right)}) + return c.GetUnionType([]*Type{c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Left), c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Right)}) } } return c.narrowType(f, t, node, true /*assumeTrue*/) @@ -531,10 +531,10 @@ func (c *Checker) narrowTypeByBinaryExpression(f *FlowState, t *Type, expr *ast. if assumeTrue { return c.narrowType(f, c.narrowType(f, t, expr.Left, true /*assumeTrue*/), expr.Right, true /*assumeTrue*/) } - return c.getUnionType([]*Type{c.narrowType(f, t, expr.Left, false /*assumeTrue*/), c.narrowType(f, t, expr.Right, false /*assumeTrue*/)}) + return c.GetUnionType([]*Type{c.narrowType(f, t, expr.Left, false /*assumeTrue*/), c.narrowType(f, t, expr.Right, false /*assumeTrue*/)}) case ast.KindBarBarToken: if assumeTrue { - return c.getUnionType([]*Type{c.narrowType(f, t, expr.Left, true /*assumeTrue*/), c.narrowType(f, t, expr.Right, true /*assumeTrue*/)}) + return c.GetUnionType([]*Type{c.narrowType(f, t, expr.Left, true /*assumeTrue*/), c.narrowType(f, t, expr.Right, true /*assumeTrue*/)}) } return c.narrowType(f, c.narrowType(f, t, expr.Left, false /*assumeTrue*/), expr.Right, false /*assumeTrue*/) } @@ -646,7 +646,7 @@ func (c *Checker) narrowTypeByTypeName(t *Type, typeName string) *Type { if t.flags&TypeFlagsAny != 0 { return t } - return c.getUnionType([]*Type{c.narrowTypeByTypeFacts(t, c.nonPrimitiveType, TypeFactsTypeofEQObject), c.narrowTypeByTypeFacts(t, c.nullType, TypeFactsEQNull)}) + return c.GetUnionType([]*Type{c.narrowTypeByTypeFacts(t, c.nonPrimitiveType, TypeFactsTypeofEQObject), c.narrowTypeByTypeFacts(t, c.nullType, TypeFactsEQNull)}) case "function": if t.flags&TypeFlagsAny != 0 { return t @@ -942,7 +942,7 @@ func (c *Checker) getInstanceType(constructorType *Type) *Type { } constructSignatures := c.getSignaturesOfType(constructorType, SignatureKindConstruct) if len(constructSignatures) != 0 { - return c.getUnionType(core.Map(constructSignatures, func(signature *Signature) *Type { + return c.GetUnionType(core.Map(constructSignatures, func(signature *Signature) *Type { return c.getReturnTypeOfSignature(c.getErasedSignature(signature)) })) } @@ -1087,9 +1087,9 @@ func (c *Checker) narrowTypeBySwitchOnDiscriminant(t *Type, data *ast.FlowSwitch return t } } - return c.getUnionType(core.IfElse(groundClauseTypes == nil, clauseTypes, groundClauseTypes)) + return c.GetUnionType(core.IfElse(groundClauseTypes == nil, clauseTypes, groundClauseTypes)) } - discriminantType := c.getUnionType(clauseTypes) + discriminantType := c.GetUnionType(clauseTypes) var caseType *Type if discriminantType.flags&TypeFlagsNever != 0 { caseType = c.neverType @@ -1113,7 +1113,7 @@ func (c *Checker) narrowTypeBySwitchOnDiscriminant(t *Type, data *ast.FlowSwitch if caseType.flags&TypeFlagsNever != 0 { return defaultType } - return c.getUnionType([]*Type{caseType, defaultType}) + return c.GetUnionType([]*Type{caseType, defaultType}) } func (c *Checker) narrowTypeBySwitchOnTypeOf(t *Type, data *ast.FlowSwitchClauseData) *Type { @@ -1138,7 +1138,7 @@ func (c *Checker) narrowTypeBySwitchOnTypeOf(t *Type, data *ast.FlowSwitchClause } // In the non-default cause we create a union of the type narrowed by each of the listed cases. clauseWitnesses := witnesses[clauseStart:clauseEnd] - return c.getUnionType(core.Map(clauseWitnesses, func(text string) *Type { + return c.GetUnionType(core.Map(clauseWitnesses, func(text string) *Type { if text != "" { return c.narrowTypeByTypeName(t, text) } @@ -1174,7 +1174,7 @@ func (c *Checker) narrowTypeBySwitchOnTrue(f *FlowState, t *Type, data *ast.Flow return t } // Now, narrow based on the cases in this set. - return c.getUnionType(core.Map(clauses[clauseStart:clauseEnd], func(clause *ast.Node) *Type { + return c.GetUnionType(core.Map(clauses[clauseStart:clauseEnd], func(clause *ast.Node) *Type { if clause.Kind == ast.KindCaseClause { return c.narrowType(f, t, clause.Expression(), true /*assumeTrue*/) } @@ -1195,7 +1195,7 @@ func (c *Checker) narrowTypeBySwitchOnDiscriminantProperty(t *Type, access *ast. accessedName, _ := c.getAccessedPropertyName(access) if accessedName != "" && c.getKeyPropertyName(t) == accessedName { clauseTypes := c.getSwitchClauseTypes(data.SwitchStatement)[data.ClauseStart:data.ClauseEnd] - candidate := c.getUnionType(core.Map(clauseTypes, func(s *Type) *Type { + candidate := c.GetUnionType(core.Map(clauseTypes, func(s *Type) *Type { result := c.getConstituentTypeForKeyType(t, s) if result != nil { return result @@ -1275,7 +1275,7 @@ func (c *Checker) getTypeAtFlowBranchLabel(f *FlowState, flow *ast.FlowNode, ant // finalize all evolving array types. func (c *Checker) getUnionOrEvolvingArrayType(f *FlowState, types []*Type, subtypeReduction UnionReduction) *Type { if isEvolvingArrayTypeList(types) { - return c.getEvolvingArrayType(c.getUnionType(core.Map(types, c.getElementTypeOfEvolvingArrayType))) + return c.getEvolvingArrayType(c.GetUnionType(core.Map(types, c.getElementTypeOfEvolvingArrayType))) } result := c.recombineUnknownType(c.getUnionTypeEx(core.SameMap(types, c.finalizeEvolvingArrayType), subtypeReduction, nil, nil)) if result != f.declaredType && result.flags&f.declaredType.flags&TypeFlagsUnion != 0 && slices.Equal(result.AsUnionType().types, f.declaredType.AsUnionType().types) { @@ -1516,7 +1516,7 @@ func (c *Checker) addEvolvingArrayElementType(evolvingArrayType *Type, node *ast if c.isTypeSubsetOf(newElementType, elementType) { return evolvingArrayType } - return c.getEvolvingArrayType(c.getUnionType([]*Type{elementType, newElementType})) + return c.getEvolvingArrayType(c.GetUnionType([]*Type{elementType, newElementType})) } func (c *Checker) finalizeEvolvingArrayType(t *Type) *Type { @@ -2290,7 +2290,7 @@ func (c *Checker) getTypeOfDestructuredArrayElement(t *Type, index int) *Type { func (c *Checker) includeUndefinedInIndexSignature(t *Type) *Type { if c.compilerOptions.NoUncheckedIndexedAccess == core.TSTrue { - return c.getUnionType([]*Type{t, c.missingType}) + return c.GetUnionType([]*Type{t, c.missingType}) } return t } @@ -2337,7 +2337,7 @@ func (c *Checker) isDestructuringAssignmentTarget(parent *ast.Node) bool { func (c *Checker) getTypeWithDefault(t *Type, defaultExpression *ast.Node) *Type { if defaultExpression != nil { - return c.getUnionType([]*Type{c.getNonUndefinedType(t), c.getTypeOfExpression(defaultExpression)}) + return c.GetUnionType([]*Type{c.getNonUndefinedType(t), c.getTypeOfExpression(defaultExpression)}) } return t } diff --git a/internal/checker/inference.go b/internal/checker/inference.go index 80e465aada..e08a2b5264 100644 --- a/internal/checker/inference.go +++ b/internal/checker/inference.go @@ -108,7 +108,7 @@ func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type) if len(targets) == 0 { return } - target = c.getUnionType(targets) + target = c.GetUnionType(targets) if len(sources) == 0 { // All source constituents have been matched and there is nothing further to infer from. // However, simply making no inferences is undesirable because it could ultimately mean @@ -118,7 +118,7 @@ func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type) c.inferWithPriority(n, source, target, InferencePriorityNakedTypeVariable) return } - source = c.getUnionType(sources) + source = c.GetUnionType(sources) } else if target.flags&TypeFlagsIntersection != 0 && !core.Every(target.Types(), c.isNonGenericObjectType) { // We reduce intersection types unless they're simple combinations of object types. For example, // when inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and @@ -436,7 +436,7 @@ func (c *Checker) inferToMultipleTypes(n *InferenceState, source *Type, targets } } if len(unmatched) != 0 { - c.inferFromTypes(n, c.getUnionType(unmatched), nakedTypeVariable) + c.inferFromTypes(n, c.GetUnionType(unmatched), nakedTypeVariable) return } } @@ -848,7 +848,7 @@ func (c *Checker) inferFromIndexTypes(n *InferenceState, source *Type, target *T if c.isObjectTypeWithInferableIndex(source) { for _, targetInfo := range indexInfos { var propTypes []*Type - for _, prop := range c.getPropertiesOfType(source) { + for _, prop := range c.GetPropertiesOfType(source) { if c.isApplicableIndexType(c.getLiteralTypeFromProperty(prop, TypeFlagsStringOrNumberLiteralOrUnique, false), targetInfo.keyType) { propType := c.getTypeOfSymbol(prop) if prop.Flags&ast.SymbolFlagsOptional != 0 { @@ -863,7 +863,7 @@ func (c *Checker) inferFromIndexTypes(n *InferenceState, source *Type, target *T } } if len(propTypes) != 0 { - c.inferWithPriority(n, c.getUnionType(propTypes), targetInfo.valueType, priority) + c.inferWithPriority(n, c.GetUnionType(propTypes), targetInfo.valueType, priority) } } } @@ -914,14 +914,14 @@ func (c *Checker) inferToMappedType(n *InferenceState, source *Type, target *Typ } // If no inferences can be made to K's constraint, infer from a union of the property types // in the source to the template type X. - propTypes := core.Map(c.getPropertiesOfType(source), c.getTypeOfSymbol) + propTypes := core.Map(c.GetPropertiesOfType(source), c.getTypeOfSymbol) indexTypes := core.Map(c.getIndexInfosOfType(source), func(info *IndexInfo) *Type { if info != c.enumNumberIndexInfo { return info.valueType } return c.neverType }) - c.inferFromTypes(n, c.getUnionType(core.Concatenate(propTypes, indexTypes)), c.getTemplateTypeFromMappedType(target)) + c.inferFromTypes(n, c.GetUnionType(core.Concatenate(propTypes, indexTypes)), c.getTemplateTypeFromMappedType(target)) return true } return false @@ -944,7 +944,7 @@ func (c *Checker) inferTypeForHomomorphicMappedType(source *Type, target *Type, func (c *Checker) createReverseMappedType(source *Type, target *Type, constraint *Type) *Type { // We consider a source type reverse mappable if it has a string index signature or if // it has one or more properties and is of a partially inferable type. - if !(c.getIndexInfoOfType(source, c.stringType) != nil || len(c.getPropertiesOfType(source)) != 0 && c.isPartiallyInferableType(source)) { + if !(c.getIndexInfoOfType(source, c.stringType) != nil || len(c.GetPropertiesOfType(source)) != 0 && c.isPartiallyInferableType(source)) { return nil } // For arrays and tuples we infer new arrays and tuples where the reverse mapping has been @@ -988,7 +988,7 @@ func (c *Checker) createReverseMappedType(source *Type, target *Type, constraint // literal { a: 123, b: x => true } is marked non-inferable because it contains a context sensitive // arrow function, but is considered partially inferable because property 'a' has an inferable type. func (c *Checker) isPartiallyInferableType(t *Type) bool { - return t.objectFlags&ObjectFlagsNonInferrableType == 0 || isObjectLiteralType(t) && core.Some(c.getPropertiesOfType(t), func(prop *ast.Symbol) bool { + return t.objectFlags&ObjectFlagsNonInferrableType == 0 || isObjectLiteralType(t) && core.Some(c.GetPropertiesOfType(t), func(prop *ast.Symbol) bool { return c.isPartiallyInferableType(c.getTypeOfSymbol(prop)) }) || isTupleType(t) && core.Some(c.getElementTypes(t), c.isPartiallyInferableType) } @@ -1038,7 +1038,7 @@ func (c *Checker) resolveReverseMappedTypeMembers(t *Type) { } members := make(ast.SymbolTable) limitedConstraint := c.getLimitedConstraint(t) - for _, prop := range c.getPropertiesOfType(r.source) { + for _, prop := range c.GetPropertiesOfType(r.source) { // In case of a reverse mapped type with an intersection constraint, if we were able to // extract the filtering type literals we skip those properties that are not assignable to them, // because the extra properties wouldn't get through the application of the mapped type anyway @@ -1459,7 +1459,7 @@ func (c *Checker) getCommonSupertype(types []*Type) *Type { // right is a supertype. var supertype *Type if c.literalTypesWithSameBaseType(primaryTypes) { - supertype = c.getUnionType(primaryTypes) + supertype = c.GetUnionType(primaryTypes) } else { for _, t := range primaryTypes { if supertype == nil || c.isTypeSubtypeOf(supertype, t) { diff --git a/internal/checker/jsx.go b/internal/checker/jsx.go index 9bc8a5e131..42e70aaf7a 100644 --- a/internal/checker/jsx.go +++ b/internal/checker/jsx.go @@ -177,7 +177,7 @@ func (c *Checker) checkJsxReturnAssignableToAppropriateBound(refKind JsxReferenc if sfcReturnConstraint == nil || classConstraint == nil { return } - combined := c.getUnionType([]*Type{sfcReturnConstraint, classConstraint}) + combined := c.GetUnionType([]*Type{sfcReturnConstraint, classConstraint}) c.checkTypeRelatedToEx(elemInstanceType, combined, c.assignableRelation, openingLikeElement.TagName(), diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, &diags) } if len(diags) != 0 { @@ -246,7 +246,7 @@ func (c *Checker) getContextualTypeForChildJsxExpression(node *ast.Node, child * return childFieldType } return c.mapTypeEx(childFieldType, func(t *Type) *Type { - if c.isArrayLikeType(t) { + if c.IsArrayLikeType(t) { return c.getIndexedAccessType(t, c.getNumberLiteralType(jsnum.Number(childIndex))) } return t @@ -267,7 +267,7 @@ func (c *Checker) discriminateContextualTypeByJSXAttributes(node *ast.Node, cont initializer := p.Initializer() return (initializer == nil || c.isPossiblyDiscriminantValue(initializer)) && c.isDiscriminantProperty(contextualType, symbol.Name) }) - discriminantMembers := core.Filter(c.getPropertiesOfType(contextualType), func(s *ast.Symbol) bool { + discriminantMembers := core.Filter(c.GetPropertiesOfType(contextualType), func(s *ast.Symbol) bool { if s.Flags&ast.SymbolFlagsOptional == 0 || node.Symbol() == nil || len(node.Symbol().Members) == 0 { return false } @@ -418,7 +418,7 @@ func (c *Checker) elaborateIterableOrArrayLikeTargetElementwise(iterator iter.Se } if targetIndexedPropType != nil && targetIndexedPropType.flags&TypeFlagsIndexedAccess == 0 { if iterationType != nil { - targetPropType = c.getUnionType([]*Type{iterationType, targetIndexedPropType}) + targetPropType = c.GetUnionType([]*Type{iterationType, targetIndexedPropType}) } else { targetPropType = targetIndexedPropType } @@ -461,7 +461,7 @@ func (c *Checker) elaborateIterableOrArrayLikeTargetElementwise(iterator iter.Se } func (c *Checker) getSuggestedSymbolForNonexistentJSXAttribute(name string, containingType *Type) *ast.Symbol { - properties := c.getPropertiesOfType(containingType) + properties := c.GetPropertiesOfType(containingType) var jsxSpecific *ast.Symbol switch name { case "for": @@ -726,7 +726,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme case childrenContextualType != nil && someType(childrenContextualType, c.isTupleLikeType): links.resolvedType = c.createTupleType(childTypes) default: - links.resolvedType = c.createArrayType(c.getUnionType(childTypes)) + links.resolvedType = c.createArrayType(c.GetUnionType(childTypes)) } // Fake up a property declaration for the children childrenPropSymbol.ValueDeclaration = c.factory.NewPropertySignatureDeclaration(nil, c.factory.NewIdentifier(jsxChildrenPropertyName), nil /*postfixToken*/, nil /*type*/, nil /*initializer*/) @@ -989,7 +989,7 @@ func (c *Checker) getNameFromJsxElementAttributesContainer(nameOfAttribPropConta jsxElementAttribPropInterfaceSym := c.getSymbol(jsxNamespace.Exports, nameOfAttribPropContainer, ast.SymbolFlagsType) if jsxElementAttribPropInterfaceSym != nil { jsxElementAttribPropInterfaceType := c.getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym) - propertiesOfJsxElementAttribPropInterface := c.getPropertiesOfType(jsxElementAttribPropInterfaceType) + propertiesOfJsxElementAttribPropInterface := c.GetPropertiesOfType(jsxElementAttribPropInterfaceType) // Element Attributes has zero properties, so the element attributes type will be the class instance type if len(propertiesOfJsxElementAttribPropInterface) == 0 { return "" @@ -1151,7 +1151,7 @@ func (c *Checker) getJsxStatelessElementTypeAt(location *ast.Node) *Type { if jsxElementType == nil { return nil } - return c.getUnionType([]*Type{jsxElementType, c.nullType}) + return c.GetUnionType([]*Type{jsxElementType, c.nullType}) } func (c *Checker) getJsxElementClassTypeAt(location *ast.Node) *Type { diff --git a/internal/checker/relater.go b/internal/checker/relater.go index 52239e034a..770349d084 100644 --- a/internal/checker/relater.go +++ b/internal/checker/relater.go @@ -294,7 +294,7 @@ func (c *Checker) isEnumTypeRelatedTo(source *ast.Symbol, target *ast.Symbol, er return entry&RelationComparisonResultSucceeded != 0 } targetEnumType := c.getTypeOfSymbol(targetSymbol) - for _, sourceProperty := range c.getPropertiesOfType(c.getTypeOfSymbol(sourceSymbol)) { + for _, sourceProperty := range c.GetPropertiesOfType(c.getTypeOfSymbol(sourceSymbol)) { if sourceProperty.Flags&ast.SymbolFlagsEnumMember != 0 { targetProperty := c.getPropertyOfType(targetEnumType, sourceProperty.Name) if targetProperty == nil || targetProperty.Flags&ast.SymbolFlagsEnumMember == 0 { @@ -645,7 +645,7 @@ func (c *Checker) elaborateArrowFunction(node *ast.Node, source *Type, target *T } returnExpression := node.Body() sourceReturn := c.getReturnTypeOfSignature(sourceSig) - targetReturn := c.getUnionType(core.Map(targetSignatures, c.getReturnTypeOfSignature)) + targetReturn := c.GetUnionType(core.Map(targetSignatures, c.getReturnTypeOfSignature)) if c.checkTypeRelatedTo(sourceReturn, targetReturn, relation, nil /*errorNode*/) { return false } @@ -687,7 +687,7 @@ func (c *Checker) isWeakType(t *Type) bool { } func (c *Checker) hasCommonProperties(source *Type, target *Type, isComparingJsxAttributes bool) bool { - for _, prop := range c.getPropertiesOfType(source) { + for _, prop := range c.GetPropertiesOfType(source) { if c.isKnownProperty(target, prop.Name, isComparingJsxAttributes) { return true } @@ -940,8 +940,8 @@ func (c *Checker) findMostOverlappyType(source *Type, unionTarget *Type) *Type { } func (c *Checker) findBestTypeForObjectLiteral(source *Type, unionTarget *Type) *Type { - if source.objectFlags&ObjectFlagsObjectLiteral != 0 && someType(unionTarget, c.isArrayLikeType) { - return core.Find(unionTarget.Types(), func(t *Type) bool { return !c.isArrayLikeType(t) }) + if source.objectFlags&ObjectFlagsObjectLiteral != 0 && someType(unionTarget, c.IsArrayLikeType) { + return core.Find(unionTarget.Types(), func(t *Type) bool { return !c.IsArrayLikeType(t) }) } return nil } @@ -972,7 +972,7 @@ func (c *Checker) getUnmatchedProperties(source *Type, target *Type, requireOpti } func (c *Checker) getUnmatchedPropertiesWorker(source *Type, target *Type, requireOptionalProperties bool, matchDiscriminantProperties bool, propsOut *[]*ast.Symbol) *ast.Symbol { - properties := c.getPropertiesOfType(target) + properties := c.GetPropertiesOfType(target) for _, targetProp := range properties { // TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass if isStaticPrivateIdentifierProperty(targetProp) { @@ -1054,7 +1054,7 @@ func (c *Checker) findMatchingDiscriminantType(source *Type, target *Type, isRel if match := c.getMatchingUnionConstituentForType(target, source); match != nil { return match } - discriminantProperties := c.findDiscriminantProperties(c.getPropertiesOfType(source), target) + discriminantProperties := c.findDiscriminantProperties(c.GetPropertiesOfType(source), target) discriminator := &TypeDiscriminator{c: c, props: discriminantProperties, isRelatedTo: isRelatedTo} discriminated := c.discriminateTypeByDiscriminableItems(target, discriminator) if discriminated != target { @@ -1149,7 +1149,7 @@ func isObjectOrInstantiableNonPrimitive(t *Type) bool { func (c *Checker) getKeyPropertyCandidateName(types []*Type) string { for _, t := range types { if t.flags&(TypeFlagsObject|TypeFlagsInstantiableNonPrimitive) != 0 { - for _, p := range c.getPropertiesOfType(t) { + for _, p := range c.GetPropertiesOfType(t) { if isUnitType(c.getTypeOfSymbol(p)) { return p.Name } @@ -1871,7 +1871,7 @@ func (c *Checker) getKnownKeysOfTupleType(t *Type) *Type { keys[i] = c.getStringLiteralType(strconv.Itoa(i)) } keys[fixedLength] = c.getIndexType(core.IfElse(t.TargetTupleType().readonly, c.globalReadonlyArrayType, c.globalArrayType)) - return c.getUnionType(keys) + return c.GetUnionType(keys) } func (c *Checker) getRestArrayTypeOfTupleType(t *Type) *Type { @@ -2627,7 +2627,7 @@ func (r *Relater) isRelatedToEx(originalSource *Type, originalTarget *Type, recu isPerformingCommonPropertyChecks := (r.relation != r.c.comparableRelation || isUnitType(source)) && intersectionState&IntersectionStateTarget == 0 && source.flags&(TypeFlagsPrimitive|TypeFlagsObject|TypeFlagsIntersection) != 0 && source != r.c.globalObjectType && - target.flags&(TypeFlagsObject|TypeFlagsIntersection) != 0 && r.c.isWeakType(target) && (len(r.c.getPropertiesOfType(source)) > 0 || r.c.typeHasCallOrConstructSignatures(source)) + target.flags&(TypeFlagsObject|TypeFlagsIntersection) != 0 && r.c.isWeakType(target) && (len(r.c.GetPropertiesOfType(source)) > 0 || r.c.TypeHasCallOrConstructSignatures(source)) isComparingJsxAttributes := source.objectFlags&ObjectFlagsJsxAttributes != 0 if isPerformingCommonPropertyChecks && !r.c.hasCommonProperties(source, target, isComparingJsxAttributes) { if reportErrors { @@ -2680,7 +2680,7 @@ func (r *Relater) hasExcessProperties(source *Type, target *Type, reportErrors b } checkTypes = reducedTarget.Distributed() } - for _, prop := range r.c.getPropertiesOfType(source) { + for _, prop := range r.c.GetPropertiesOfType(source) { if shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop) { if !r.c.isKnownProperty(reducedTarget, prop.Name, isComparingJsxAttributes) { if reportErrors { @@ -2749,7 +2749,7 @@ func (c *Checker) getTypeOfPropertyInTypes(types []*Type, name string) *Type { for _, t := range types { propTypes = append(propTypes, c.getTypeOfPropertyInType(t, name)) } - return c.getUnionType(propTypes) + return c.GetUnionType(propTypes) } func (c *Checker) getTypeOfPropertyInType(t *Type, name string) *Type { @@ -3459,7 +3459,7 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo // missing from the `constraintType` which will otherwise be mapped in the object mappedKeys := r.c.getApparentMappedTypeKeys(nameType, targetType) // We still need to include the non-apparent (and thus still generic) keys in the target side of the comparison (in case they're in the source side) - targetKeys = r.c.getUnionType([]*Type{mappedKeys, nameType}) + targetKeys = r.c.GetUnionType([]*Type{mappedKeys, nameType}) } else if nameType != nil { targetKeys = nameType } else { @@ -3923,7 +3923,7 @@ func (r *Relater) typeRelatedToDiscriminatedType(source *Type, target *Type) Ter // // NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts // for examples. - sourceProperties := r.c.getPropertiesOfType(source) + sourceProperties := r.c.GetPropertiesOfType(source) sourcePropertiesFiltered := r.c.findDiscriminantProperties(sourceProperties, target) if len(sourcePropertiesFiltered) == 0 { return TernaryFalse @@ -4152,7 +4152,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b return TernaryFalse } if isObjectLiteralType(target) { - for _, sourceProp := range excludeProperties(r.c.getPropertiesOfType(source), excludedProperties) { + for _, sourceProp := range excludeProperties(r.c.GetPropertiesOfType(source), excludedProperties) { if r.c.getPropertyOfObjectType(target, sourceProp.Name) == nil { sourceType := r.c.getTypeOfSymbol(sourceProp) if sourceType.flags&TypeFlagsUndefined == 0 { @@ -4166,7 +4166,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b } // We only call this for union target types when we're attempting to do excess property checking - in those cases, we want to get _all possible props_ // from the target union, across all members - properties := r.c.getPropertiesOfType(target) + properties := r.c.GetPropertiesOfType(target) numericNamesOnly := isTupleType(source) && isTupleType(target) for _, targetProp := range excludeProperties(properties, excludedProperties) { name := targetProp.Name @@ -4185,8 +4185,8 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b } func (r *Relater) propertyRelatedTo(source *Type, target *Type, sourceProp *ast.Symbol, targetProp *ast.Symbol, getTypeOfSourceProperty func(sym *ast.Symbol) *Type, reportErrors bool, intersectionState IntersectionState, skipOptional bool) Ternary { - sourcePropFlags := getDeclarationModifierFlagsFromSymbol(sourceProp) - targetPropFlags := getDeclarationModifierFlagsFromSymbol(targetProp) + sourcePropFlags := GetDeclarationModifierFlagsFromSymbol(sourceProp) + targetPropFlags := GetDeclarationModifierFlagsFromSymbol(targetProp) switch { case sourcePropFlags&ast.ModifierFlagsPrivate != 0 || targetPropFlags&ast.ModifierFlagsPrivate != 0: if sourceProp.ValueDeclaration != targetProp.ValueDeclaration { @@ -4537,7 +4537,7 @@ func (c *Checker) isObjectTypeWithInferableIndex(t *Type) bool { return core.Every(t.Types(), c.isObjectTypeWithInferableIndex) } return t.symbol != nil && t.symbol.Flags&(ast.SymbolFlagsObjectLiteral|ast.SymbolFlagsTypeLiteral|ast.SymbolFlagsEnum|ast.SymbolFlagsValueModule) != 0 && - t.symbol.Flags&ast.SymbolFlagsClass == 0 && !c.typeHasCallOrConstructSignatures(t) || + t.symbol.Flags&ast.SymbolFlagsClass == 0 && !c.TypeHasCallOrConstructSignatures(t) || t.objectFlags&ObjectFlagsObjectRestType != 0 || t.objectFlags&ObjectFlagsReverseMapped != 0 && c.isObjectTypeWithInferableIndex(t.AsReverseMappedType().source) } diff --git a/internal/checker/services.go b/internal/checker/services.go index 5484e35197..576be91d5c 100644 --- a/internal/checker/services.go +++ b/internal/checker/services.go @@ -143,7 +143,7 @@ func (c *Checker) isValidPropertyAccessWithType(node *ast.Node, isSuper bool, pr } prop := c.getPropertyOfType(t, propertyName) - return prop != nil && c.isPropertyAccessible(node, isSuper, false /*isWrite*/, t, prop) + return prop != nil && c.IsPropertyAccessible(node, isSuper, false /*isWrite*/, t, prop) } // Checks if an existing property access is valid for completions purposes. @@ -155,7 +155,7 @@ func (c *Checker) isValidPropertyAccessWithType(node *ast.Node, isSuper bool, pr // type: the type whose property we are checking. // property: the accessed property's symbol. func (c *Checker) IsValidPropertyAccessForCompletions(node *ast.Node, t *Type, property *ast.Symbol) bool { - return c.isPropertyAccessible( + return c.IsPropertyAccessible( node, node.Kind == ast.KindPropertyAccessExpression && node.Expression().Kind == ast.KindSuperKeyword, false, /*isWrite*/ @@ -166,7 +166,7 @@ func (c *Checker) IsValidPropertyAccessForCompletions(node *ast.Node, t *Type, p } func (c *Checker) GetAllPossiblePropertiesOfTypes(types []*Type) []*ast.Symbol { - unionType := c.getUnionType(types) + unionType := c.GetUnionType(types) if unionType.flags&TypeFlagsUnion == 0 { return c.getAugmentedPropertiesOfType(unionType) } @@ -226,7 +226,7 @@ func (c *Checker) GetApparentProperties(t *Type) []*ast.Symbol { func (c *Checker) getAugmentedPropertiesOfType(t *Type) []*ast.Symbol { t = c.getApparentType(t) - propsByName := createSymbolTable(c.getPropertiesOfType(t)) + propsByName := createSymbolTable(c.GetPropertiesOfType(t)) var functionType *Type if len(c.getSignaturesOfType(t, SignatureKindCall)) > 0 { functionType = c.globalCallableFunctionType @@ -235,7 +235,7 @@ func (c *Checker) getAugmentedPropertiesOfType(t *Type) []*ast.Symbol { } if functionType != nil { - for _, p := range c.getPropertiesOfType(functionType) { + for _, p := range c.GetPropertiesOfType(functionType) { if _, ok := propsByName[p.Name]; !ok { propsByName[p.Name] = p } @@ -427,3 +427,44 @@ func (c *Checker) getTypeArgumentConstraint(node *ast.Node) *Type { } return nil } + +func (c *Checker) IsTypeInvalidDueToUnionDiscriminant(contextualType *Type, obj *ast.Node) bool { + properties := obj.Properties() + return core.Some(properties, func(property *ast.Node) bool { + var nameType *Type + propertyName := property.Name() + if propertyName != nil { + if ast.IsJsxNamespacedName(propertyName) { + nameType = c.getStringLiteralType(propertyName.Text()) + } else { + nameType = c.getLiteralTypeFromPropertyName(propertyName) + } + } + var name string + if nameType != nil && isTypeUsableAsPropertyName(nameType) { + name = getPropertyNameFromType(nameType) + } + var expected *Type + if name != "" { + expected = c.getTypeOfPropertyOfType(contextualType, name) + } + return expected != nil && isLiteralType(expected) && !c.isTypeAssignableTo(c.getTypeOfNode(property), expected) + }) +} + +// Unlike `getExportsOfModule`, this includes properties of an `export =` value. +func (c *Checker) GetExportsAndPropertiesOfModule(moduleSymbol *ast.Symbol) []*ast.Symbol { + exports := c.getExportsOfModuleAsArray(moduleSymbol) + exportEquals := c.resolveExternalModuleSymbol(moduleSymbol, false /*dontResolveAlias*/) + if exportEquals != moduleSymbol { + t := c.getTypeOfSymbol(exportEquals) + if c.shouldTreatPropertiesOfExternalModuleAsExports(t) { + exports = append(exports, c.GetPropertiesOfType(t)...) + } + } + return exports +} + +func (c *Checker) getExportsOfModuleAsArray(moduleSymbol *ast.Symbol) []*ast.Symbol { + return symbolsToArray(c.getExportsOfModule(moduleSymbol)) +} diff --git a/internal/checker/types.go b/internal/checker/types.go index 767abf2438..3783c781a8 100644 --- a/internal/checker/types.go +++ b/internal/checker/types.go @@ -675,6 +675,10 @@ func (t *Type) IsStringLike() bool { return t.flags&TypeFlagsStringLike != 0 } +func (t *Type) IsClass() bool { + return t.objectFlags&ObjectFlagsClass != 0 +} + // TypeData type TypeData interface { @@ -760,6 +764,10 @@ func (t *StructuredType) ConstructSignatures() []*Signature { return slices.Clip(t.signatures[t.callSignatureCount:]) } +func (t *StructuredType) Properties() []*ast.Symbol { + return t.properties +} + // Except for tuple type references and reverse mapped types, all object types have an associated symbol. // Possible object type instances are listed in the following. diff --git a/internal/checker/utilities.go b/internal/checker/utilities.go index 8d2651c970..d5c3582297 100644 --- a/internal/checker/utilities.go +++ b/internal/checker/utilities.go @@ -869,7 +869,7 @@ func compareTypeMappers(m1, m2 *TypeMapper) int { return 0 } -func getDeclarationModifierFlagsFromSymbol(s *ast.Symbol) ast.ModifierFlags { +func GetDeclarationModifierFlagsFromSymbol(s *ast.Symbol) ast.ModifierFlags { return getDeclarationModifierFlagsFromSymbolEx(s, false /*isWrite*/) } @@ -1068,7 +1068,7 @@ func isNumericLiteralName(name string) bool { return jsnum.FromString(name).String() == name } -func getPropertyNameForPropertyNameNode(name *ast.Node) string { +func GetPropertyNameForPropertyNameNode(name *ast.Node) string { switch name.Kind { case ast.KindIdentifier, ast.KindPrivateIdentifier, ast.KindStringLiteral, ast.KindNoSubstitutionTemplateLiteral, ast.KindNumericLiteral, ast.KindBigIntLiteral, ast.KindJsxNamespacedName: @@ -1328,15 +1328,6 @@ func isInAmbientOrTypeNode(node *ast.Node) bool { }) != nil } -func isVariableLike(node *ast.Node) bool { - switch node.Kind { - case ast.KindBindingElement, ast.KindEnumMember, ast.KindParameter, ast.KindPropertyAssignment, ast.KindPropertyDeclaration, - ast.KindPropertySignature, ast.KindShorthandPropertyAssignment, ast.KindVariableDeclaration: - return true - } - return false -} - func getAncestor(node *ast.Node, kind ast.Kind) *ast.Node { for node != nil && node.Kind != kind { node = node.Parent @@ -1958,7 +1949,7 @@ func tryGetPropertyAccessOrIdentifierToString(expr *ast.Node) string { case ast.IsElementAccessExpression(expr): baseStr := tryGetPropertyAccessOrIdentifierToString(expr.Expression()) if baseStr != "" && ast.IsPropertyName(expr.AsElementAccessExpression().ArgumentExpression) { - return baseStr + "." + getPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression) + return baseStr + "." + GetPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression) } case ast.IsIdentifier(expr): return expr.Text() diff --git a/internal/ls/completions.go b/internal/ls/completions.go index c6cc9ffb3b..cce21d95d2 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -206,6 +206,10 @@ type symbolOriginInfoTypeOnlyAlias struct { declaration *ast.TypeOnlyImportDeclaration } +type symbolOriginInfoComputedPropertyName struct { + symbolName string +} + // Special values for `CompletionInfo['source']` used to disambiguate // completion items with the same `name`. (Each completion item must // have a unique name/source combination, because those two fields @@ -319,7 +323,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position // The decision to provide completion depends on the contextToken, which is determined through the previousToken. // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file - // isJSOnlyLocation := !insideJsDocTagTypeExpression && !insideJsDocImportTag && ast.IsSourceFileJS(file) + isJSOnlyLocation := !insideJsDocTagTypeExpression && !insideJsDocImportTag && ast.IsSourceFileJS(file) previousToken, contextToken := getRelevantTokens(position, file) // Find the node where completion is requested on. @@ -777,7 +781,424 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position return globalsSearchContinue } - return globalsSearchContinue // !!! + // We're looking up possible property names from contextual/inferred/declared type. + completionKind = CompletionKindObjectPropertyDeclaration + + var typeMembers []*ast.Symbol + var existingMembers []*ast.Declaration + + if objectLikeContainer.Kind == ast.KindObjectLiteralExpression { + instantiatedType := tryGetObjectLiteralContextualType(objectLikeContainer, typeChecker) + + // Check completions for Object property value shorthand + if instantiatedType == nil { + if objectLikeContainer.Flags&ast.NodeFlagsInWithStatement != 0 { + return globalsSearchFail + } + return globalsSearchContinue + } + completionsType := typeChecker.GetContextualType(objectLikeContainer, checker.ContextFlagsCompletions) + t := core.IfElse(completionsType != nil, completionsType, instantiatedType) + stringIndexType := typeChecker.GetStringIndexType(t) + numberIndexType := typeChecker.GetNumberIndexType(t) + isNewIdentifierLocation = stringIndexType != nil || numberIndexType != nil + typeMembers = getPropertiesForObjectExpression(instantiatedType, completionsType, objectLikeContainer, typeChecker) + properties := objectLikeContainer.AsObjectLiteralExpression().Properties + if properties != nil { + existingMembers = properties.Nodes + } + + if len(typeMembers) == 0 { + // Edge case: If NumberIndexType exists + if numberIndexType == nil { + return globalsSearchContinue + } + } + } else { + if objectLikeContainer.Kind != ast.KindObjectBindingPattern { + panic("Expected 'objectLikeContainer' to be an object binding pattern.") + } + // We are *only* completing on properties from the type being destructured. + isNewIdentifierLocation = false + rootDeclaration := ast.GetRootDeclaration(objectLikeContainer.Parent) + if !ast.IsVariableLike(rootDeclaration) { + panic("Root declaration is not variable-like.") + } + + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function. + canGetType := ast.HasInitializer(rootDeclaration) || + ast.GetTypeAnnotationNode(rootDeclaration) != nil || + rootDeclaration.Parent.Parent.Kind == ast.KindForOfStatement + if !canGetType && rootDeclaration.Kind == ast.KindParameter { + if ast.IsExpression(rootDeclaration.Parent) { + canGetType = typeChecker.GetContextualType(rootDeclaration.Parent, checker.ContextFlagsNone) != nil + } else if rootDeclaration.Parent.Kind == ast.KindMethodDeclaration || + rootDeclaration.Parent.Kind == ast.KindSetAccessor { + canGetType = ast.IsExpression(rootDeclaration.Parent.Parent) && + typeChecker.GetContextualType(rootDeclaration.Parent.Parent, checker.ContextFlagsNone) != nil + } + } + if canGetType { + typeForObject := typeChecker.GetTypeAtLocation(objectLikeContainer) + if typeForObject == nil { + return globalsSearchFail + } + typeMembers = core.Filter( + typeChecker.GetPropertiesOfType(typeForObject), + func(propertySymbol *ast.Symbol) bool { + return typeChecker.IsPropertyAccessible( + objectLikeContainer, + false, /*isSuper*/ + false, /*isWrite*/ + typeForObject, + propertySymbol, + ) + }, + ) + elements := objectLikeContainer.AsBindingPattern().Elements + if elements != nil { + existingMembers = elements.Nodes + } + } + } + + if len(typeMembers) > 0 { + // Add filtered items to the completion list. + filteredMembers, spreadMemberNames := filterObjectMembersList( + typeMembers, + core.CheckEachDefined(existingMembers, "object like properties or elements should all be defined"), + file, + position, + typeChecker, + ) + symbols = append(symbols, filteredMembers...) + + // Set sort texts. + transformObjectLiteralMembers := ptrIsTrue(preferences.IncludeCompletionsWithObjectLiteralMethodSnippets) && + objectLikeContainer.Kind == ast.KindObjectLiteralExpression + for _, member := range filteredMembers { + symbolId := ast.GetSymbolId(member) + if spreadMemberNames.Has(member.Name) { + symbolToSortTextMap[symbolId] = SortTextMemberDeclaredBySpreadAssignment + } + if member.Flags&ast.SymbolFlagsOptional != 0 { + _, ok := symbolToSortTextMap[symbolId] + if !ok { + symbolToSortTextMap[symbolId] = SortTextOptionalMember + } + } + if transformObjectLiteralMembers { + // !!! object literal member snippet completions + } + } + } + + return globalsSearchSuccess + } + + tryGetImportCompletionSymbols := func() globalsSearch { + if importStatementCompletion == nil { + return globalsSearchContinue + } + isNewIdentifierLocation = true + // !!! auto imports + // collectAutoImports() + return globalsSearchSuccess + } + + // Aggregates relevant symbols for completion in import clauses and export clauses + // whose declarations have a module specifier; for instance, symbols will be aggregated for + // + // import { | } from "moduleName"; + // export { a as foo, | } from "moduleName"; + // + // but not for + // + // export { | }; + // + // Relevant symbols are stored in the captured 'symbols' variable. + tryGetImportOrExportClauseCompletionSymbols := func() globalsSearch { + if contextToken == nil { + return globalsSearchContinue + } + + // `import { |` or `import { a as 0, | }` or `import { type | }` + var namedImportsOrExports *ast.NamedImportsOrExports + if contextToken.Kind == ast.KindOpenBraceToken || contextToken.Kind == ast.KindCommaToken { + namedImportsOrExports = core.IfElse(isNamedImportsOrExports(contextToken.Parent), contextToken.Parent, nil) + } else if isTypeKeywordTokenOrIdentifier(contextToken) { + namedImportsOrExports = core.IfElse( + isNamedImportsOrExports(contextToken.Parent.Parent), + contextToken.Parent.Parent, + nil, + ) + } + + if namedImportsOrExports == nil { + return globalsSearchContinue + } + + // We can at least offer `type` at `import { |` + if !isTypeKeywordTokenOrIdentifier(contextToken) { + keywordFilters = KeywordCompletionFiltersTypeKeyword + } + + // try to show exported member for imported/re-exported module + moduleSpecifier := core.IfElse( + namedImportsOrExports.Kind == ast.KindNamedImports, + namedImportsOrExports.Parent.Parent, + namedImportsOrExports.Parent).ModuleSpecifier() + if moduleSpecifier == nil { + isNewIdentifierLocation = true + if namedImportsOrExports.Kind == ast.KindNamedImports { + return globalsSearchFail + } + return globalsSearchContinue + } + + moduleSpecifierSymbol := typeChecker.GetSymbolAtLocation(moduleSpecifier) + if moduleSpecifierSymbol == nil { + isNewIdentifierLocation = true + return globalsSearchFail + } + + completionKind = CompletionKindMemberLike + isNewIdentifierLocation = false + exports := typeChecker.GetExportsAndPropertiesOfModule(moduleSpecifierSymbol) + + existing := core.Set[string]{} + for _, element := range namedImportsOrExports.Elements() { + if isCurrentlyEditingNode(element, file, position) { + continue + } + existing.Add(element.PropertyNameOrName().Text()) + } + uniques := core.Filter(exports, func(symbol *ast.Symbol) bool { + return symbol.Name != ast.InternalSymbolNameDefault && !existing.Has(symbol.Name) + }) + + symbols = append(symbols, uniques...) + if len(uniques) == 0 { + // If there's nothing else to import, don't offer `type` either. + keywordFilters = KeywordCompletionFiltersNone + } + return globalsSearchSuccess + } + + // import { x } from "foo" with { | } + tryGetImportAttributesCompletionSymbols := func() globalsSearch { + if contextToken == nil { + return globalsSearchContinue + } + + var importAttributes *ast.ImportAttributesNode + if contextToken.Kind == ast.KindOpenBraceToken || contextToken.Kind == ast.KindCommaToken { + importAttributes = core.IfElse(ast.IsImportAttributes(contextToken.Parent), contextToken.Parent, nil) + } else if contextToken.Kind == ast.KindColonToken { + importAttributes = core.IfElse(ast.IsImportAttributes(contextToken.Parent.Parent), contextToken.Parent.Parent, nil) + } + + if importAttributes == nil { + return globalsSearchContinue + } + + existing := core.NewSetFromItems(core.Map(importAttributes.Elements(), (*ast.Node).Text)...) + uniques := core.Filter( + typeChecker.GetApparentProperties(typeChecker.GetTypeAtLocation(importAttributes)), + func(symbol *ast.Symbol) bool { + return !existing.Has(symbol.Name) + }) + symbols = append(symbols, uniques...) + return globalsSearchSuccess + } + + // Adds local declarations for completions in named exports: + // export { | }; + // Does not check for the absence of a module specifier (`export {} from "./other"`) + // because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that, + // preventing this function from running. + tryGetLocalNamedExportCompletionSymbols := func() globalsSearch { + if contextToken == nil { + return globalsSearchContinue + } + var namedExports *ast.NamedExportsNode + if contextToken.Kind == ast.KindOpenBraceToken || contextToken.Kind == ast.KindCommaToken { + namedExports = core.IfElse(ast.IsNamedExports(contextToken.Parent), contextToken.Parent, nil) + } + + if namedExports == nil { + return globalsSearchContinue + } + + localsContainer := ast.FindAncestor(namedExports, func(node *ast.Node) bool { + return ast.IsSourceFile(node) || ast.IsModuleDeclaration(node) + }) + completionKind = CompletionKindNone + isNewIdentifierLocation = false + localSymbol := localsContainer.Symbol() + var localExports ast.SymbolTable + if localSymbol != nil { + localExports = localSymbol.Exports + } + for name, symbol := range localsContainer.Locals() { + symbols = append(symbols, symbol) + if _, ok := localExports[name]; ok { + symbolId := ast.GetSymbolId(symbol) + symbolToSortTextMap[symbolId] = SortTextOptionalMember + } + } + + return globalsSearchSuccess + } + + tryGetConstructorCompletion := func() globalsSearch { + if tryGetConstructorLikeCompletionContainer(contextToken) == nil { + return globalsSearchContinue + } + + // no members, only keywords + completionKind = CompletionKindNone + // Declaring new property/method/accessor + isNewIdentifierLocation = true + // Has keywords for constructor parameter + keywordFilters = KeywordCompletionFiltersConstructorParameterKeywords + return globalsSearchSuccess + } + + // Aggregates relevant symbols for completion in class declaration + // Relevant symbols are stored in the captured 'symbols' variable. + tryGetClassLikeCompletionSymbols := func() globalsSearch { + decl := tryGetObjectTypeDeclarationCompletionContainer(file, contextToken, location, position) + if decl == nil { + return globalsSearchContinue + } + + // We're looking up possible property names from parent type. + completionKind = CompletionKindMemberLike + // Declaring new property/method/accessor + isNewIdentifierLocation = true + if contextToken.Kind == ast.KindAsteriskToken { + keywordFilters = KeywordCompletionFiltersNone + } else if ast.IsClassLike(decl) { + keywordFilters = KeywordCompletionFiltersClassElementKeywords + } else { + keywordFilters = KeywordCompletionFiltersInterfaceElementKeywords + } + + // If you're in an interface you don't want to repeat things from super-interface. So just stop here. + if !ast.IsClassLike(decl) { + return globalsSearchSuccess + } + + var classElement *ast.Node + if contextToken.Kind == ast.KindSemicolonToken { + classElement = contextToken.Parent.Parent + } else { + classElement = contextToken.Parent + } + var classElementModifierFlags ast.ModifierFlags + if ast.IsClassElement(classElement) { + classElementModifierFlags = classElement.ModifierFlags() + } + // If this is context token is not something we are editing now, consider if this would lead to be modifier. + if contextToken.Kind == ast.KindIdentifier && !isCurrentlyEditingNode(contextToken, file, position) { + switch contextToken.Text() { + case "private": + classElementModifierFlags |= ast.ModifierFlagsPrivate + case "static": + classElementModifierFlags |= ast.ModifierFlagsStatic + case "override": + classElementModifierFlags |= ast.ModifierFlagsOverride + } + } + if ast.IsClassStaticBlockDeclaration(classElement) { + classElementModifierFlags |= ast.ModifierFlagsStatic + } + + // No member list for private methods + if classElementModifierFlags&ast.ModifierFlagsPrivate == 0 { + // List of property symbols of base type that are not private and already implemented + var baseTypeNodes []*ast.Node + if ast.IsClassLike(decl) && classElementModifierFlags&ast.ModifierFlagsOverride != 0 { + baseTypeNodes = []*ast.Node{ast.GetClassExtendsHeritageElement(decl)} + } else { + baseTypeNodes = getAllSuperTypeNodes(decl) + } + var baseSymbols []*ast.Symbol + for _, baseTypeNode := range baseTypeNodes { + t := typeChecker.GetTypeAtLocation(baseTypeNode) + if classElementModifierFlags&ast.ModifierFlagsStatic != 0 { + if t.Symbol() != nil { + baseSymbols = append( + baseSymbols, + typeChecker.GetPropertiesOfType(typeChecker.GetTypeOfSymbolAtLocation(t.Symbol(), decl))...) + } + } else if t != nil { + baseSymbols = append(baseSymbols, typeChecker.GetPropertiesOfType(t)...) + } + } + + symbols = append(symbols, + filterClassMembersList(baseSymbols, decl.Members(), classElementModifierFlags, file, position)...) + for _, symbol := range symbols { + declaration := symbol.ValueDeclaration + if declaration != nil && ast.IsClassElement(declaration) && + declaration.Name() != nil && + ast.IsComputedPropertyName(declaration.Name()) { + symbolId := ast.GetSymbolId(symbol) + origin := &symbolOriginInfo{ + kind: symbolOriginInfoKindComputedPropertyName, + data: &symbolOriginInfoComputedPropertyName{symbolName: typeChecker.SymbolToString(symbol)}, + } + symbolToOriginInfoMap[symbolId] = origin + } + } + } + + return globalsSearchSuccess + } + + tryGetJsxCompletionSymbols := func() globalsSearch { + jsxContainer := tryGetContainingJsxElement(contextToken, file) + if jsxContainer == nil { + return globalsSearchContinue + } + // Cursor is inside a JSX self-closing element or opening element. + attrsType := typeChecker.GetContextualType(jsxContainer.Attributes(), checker.ContextFlagsNone) + if attrsType == nil { + return globalsSearchContinue + } + completionsType := typeChecker.GetContextualType(jsxContainer.Attributes(), checker.ContextFlagsCompletions) + filteredSymbols, spreadMemberNames := filterJsxAttributes( + getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.Attributes(), typeChecker), + jsxContainer.Attributes().Properties(), + file, + position, + typeChecker, + ) + + symbols = append(symbols, filteredSymbols...) + // Set sort texts. + for _, symbol := range filteredSymbols { + symbolId := ast.GetSymbolId(symbol) + if spreadMemberNames.Has(symbol.Name) { + symbolToSortTextMap[symbolId] = SortTextMemberDeclaredBySpreadAssignment + } + if symbol.Flags&ast.SymbolFlagsOptional != 0 { + _, ok := symbolToSortTextMap[symbolId] + if !ok { + symbolToSortTextMap[symbolId] = SortTextOptionalMember + } + } + } + + completionKind = CompletionKindMemberLike + isNewIdentifierLocation = false + return globalsSearchSuccess } getGlobalCompletions := func() globalsSearch { @@ -893,16 +1314,15 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position tryGetGlobalSymbols := func() bool { var result globalsSearch globalSearchFuncs := []func() globalsSearch{ - // !!! tryGetObjectTypeLiteralInTypeArgumentCompletionSymbols, - // tryGetObjectLikeCompletionSymbols, - // tryGetImportCompletionSymbols, - // tryGetImportOrExportClauseCompletionSymbols, - // tryGetImportAttributesCompletionSymbols, - // tryGetLocalNamedExportCompletionSymbols, - // tryGetConstructorCompletion, - // tryGetClassLikeCompletionSymbols, - // tryGetJsxCompletionSymbols, + tryGetObjectLikeCompletionSymbols, + tryGetImportCompletionSymbols, + tryGetImportOrExportClauseCompletionSymbols, + tryGetImportAttributesCompletionSymbols, + tryGetLocalNamedExportCompletionSymbols, + tryGetConstructorCompletion, + tryGetClassLikeCompletionSymbols, + tryGetJsxCompletionSymbols, getGlobalCompletions, } for _, globalSearchFunc := range globalSearchFuncs { @@ -924,7 +1344,12 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position // For JavaScript or TypeScript, if we're not after a dot, then just try to get the // global symbols in scope. These results should be valid for either language as // the set of symbols that can be referenced from this location. - // !!! global completions + if !tryGetGlobalSymbols() { + if keywordFilters != KeywordCompletionFiltersNone { + return keywordCompletionData(keywordFilters, isJSOnlyLocation, isNewIdentifierLocation) + } + return nil + } } var contextualType *checker.Type @@ -986,6 +1411,14 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position } } +func keywordCompletionData( + keywordFilters KeywordCompletionFilters, + filterOutTSOnlyKeywords bool, + isNewIdentifierLocation bool, +) *completionData { + return nil // !!! +} + func getDefaultCommitCharacters(isNewIdentifierLocation bool) []string { if isNewIdentifierLocation { return []string{} @@ -2734,7 +3167,8 @@ func tryGetFunctionLikeBodyCompletionContainer(contextToken *ast.Node) *ast.Node func computeCommitCharactersAndIsNewIdentifier( contextToken *ast.Node, file *ast.SourceFile, - position int) (isNewIdentifierLocation bool, defaultCommitCharacters []string) { + position int, +) (isNewIdentifierLocation bool, defaultCommitCharacters []string) { if contextToken == nil { return false, allCommitCharacters } @@ -3007,3 +3441,435 @@ func tryGetObjectLikeCompletionContainer(contextToken *ast.Node, position int, f return nil } + +func tryGetObjectLiteralContextualType(node *ast.ObjectLiteralExpressionNode, typeChecker *checker.Checker) *checker.Type { + t := typeChecker.GetContextualType(node, checker.ContextFlagsNone) + if t != nil { + return t + } + + parent := ast.WalkUpParenthesizedExpressions(node.Parent) + if ast.IsBinaryExpression(parent) && + parent.AsBinaryExpression().OperatorToken.Kind == ast.KindEqualsToken && + node == parent.AsBinaryExpression().Left { + // Object literal is assignment pattern: ({ | } = x) + return typeChecker.GetTypeAtLocation(parent) + } + if ast.IsExpression(parent) { + // f(() => (({ | }))); + return typeChecker.GetContextualType(parent, checker.ContextFlagsNone) + } + + return nil +} + +func getPropertiesForObjectExpression( + contextualType *checker.Type, + completionsType *checker.Type, + obj *ast.Node, + typeChecker *checker.Checker, +) []*ast.Symbol { + hasCompletionsType := completionsType != nil && completionsType != contextualType + var types []*checker.Type + if contextualType.IsUnion() { + types = contextualType.Types() + } else { + types = []*checker.Type{contextualType} + } + promiseFilteredContextualType := typeChecker.GetUnionType(core.Filter(types, func(t *checker.Type) bool { + return typeChecker.GetPromisedTypeOfPromise(t) == nil + })) + + var t *checker.Type + if hasCompletionsType && completionsType.Flags()&checker.TypeFlagsAnyOrUnknown == 0 { + t = typeChecker.GetUnionType([]*checker.Type{promiseFilteredContextualType, completionsType}) + } else { + t = promiseFilteredContextualType + } + + // Filter out members whose only declaration is the object literal itself to avoid + // self-fulfilling completions like: + // + // function f(x: T) {} + // f({ abc/**/: "" }) // `abc` is a member of `T` but only because it declares itself + hasDeclarationOtherThanSelf := func(member *ast.Symbol) bool { + if len(member.Declarations) == 0 { + return true + } + return core.Some(member.Declarations, func(decl *ast.Declaration) bool { return decl.Parent != obj }) + } + + properties := getApparentProperties(t, obj, typeChecker) + if t.IsClass() && containsNonPublicProperties(properties) { + return nil + } else if hasCompletionsType { + return core.Filter(properties, hasDeclarationOtherThanSelf) + } else { + return properties + } +} + +func getApparentProperties(t *checker.Type, node *ast.Node, typeChecker *checker.Checker) []*ast.Symbol { + if !t.IsUnion() { + return typeChecker.GetApparentProperties(t) + } + return typeChecker.GetAllPossiblePropertiesOfTypes(core.Filter(t.Types(), func(memberType *checker.Type) bool { + return !(memberType.Flags()&checker.TypeFlagsPrimitive != 0 || + typeChecker.IsArrayLikeType(memberType) || + typeChecker.IsTypeInvalidDueToUnionDiscriminant(memberType, node) || + typeChecker.TypeHasCallOrConstructSignatures(memberType) || + memberType.IsClass() && containsNonPublicProperties(typeChecker.GetApparentProperties(memberType))) + })) +} + +func containsNonPublicProperties(props []*ast.Symbol) bool { + return core.Some(props, func(p *ast.Symbol) bool { + return checker.GetDeclarationModifierFlagsFromSymbol(p)&ast.ModifierFlagsNonPublicAccessibilityModifier != 0 + }) +} + +// Filters out members that are already declared in the object literal or binding pattern. +// Also computes the set of existing members declared by spread assignment. +func filterObjectMembersList( + contextualMemberSymbols []*ast.Symbol, + existingMembers []*ast.Declaration, + file *ast.SourceFile, + position int, + typeChecker *checker.Checker, +) (filteredMembers []*ast.Symbol, spreadMemberNames *core.Set[string]) { + if len(existingMembers) == 0 { + return contextualMemberSymbols, nil + } + + membersDeclaredBySpreadAssignment := core.Set[string]{} + existingMemberNames := core.Set[string]{} + for _, member := range existingMembers { + // Ignore omitted expressions for missing members. + if member.Kind != ast.KindPropertyAssignment && + member.Kind != ast.KindShorthandPropertyAssignment && + member.Kind != ast.KindBindingElement && + member.Kind != ast.KindMethodDeclaration && + member.Kind != ast.KindGetAccessor && + member.Kind != ast.KindSetAccessor && + member.Kind != ast.KindSpreadAssignment { + continue + } + + // If this is the current item we are editing right now, do not filter it out. + if isCurrentlyEditingNode(member, file, position) { + continue + } + + var existingName string + + if ast.IsSpreadAssignment(member) { + setMemberDeclaredBySpreadAssignment(member, &membersDeclaredBySpreadAssignment, typeChecker) + } else if ast.IsBindingElement(member) && member.AsBindingElement().PropertyName != nil { + // include only identifiers in completion list + if member.AsBindingElement().PropertyName.Kind == ast.KindIdentifier { + existingName = member.AsBindingElement().PropertyName.Text() + } + } else { + // TODO: Account for computed property name + // NOTE: if one only performs this step when m.name is an identifier, + // things like '__proto__' are not filtered out. + name := ast.GetNameOfDeclaration(member) + if name != nil && ast.IsPropertyNameLiteral(name) { + existingName = name.Text() + } + } + + if existingName != "" { + existingMemberNames.Add(existingName) + } + } + + filteredSymbols := core.Filter(contextualMemberSymbols, func(m *ast.Symbol) bool { + return !existingMemberNames.Has(m.Name) + }) + + return filteredSymbols, &membersDeclaredBySpreadAssignment +} + +func isCurrentlyEditingNode(node *ast.Node, file *ast.SourceFile, position int) bool { + start := astnav.GetStartOfNode(node, file, false /*includeJSDoc*/) + return start <= position && position <= node.End() +} + +func setMemberDeclaredBySpreadAssignment(declaration *ast.Node, members *core.Set[string], typeChecker *checker.Checker) { + expression := declaration.Expression() + symbol := typeChecker.GetSymbolAtLocation(expression) + var t *checker.Type + if symbol != nil { + t = typeChecker.GetTypeOfSymbolAtLocation(symbol, expression) + } + properties := t.AsStructuredType().Properties() + for _, property := range properties { + members.Add(property.Name) + } +} + +// Returns the immediate owning class declaration of a context token, +// on the condition that one exists and that the context implies completion should be given. +func tryGetConstructorLikeCompletionContainer(contextToken *ast.Node) *ast.ConstructorDeclarationNode { + if contextToken == nil { + return nil + } + + parent := contextToken.Parent + switch contextToken.Kind { + case ast.KindOpenParenToken, ast.KindCommaToken: + if ast.IsConstructorDeclaration(parent) { + return parent + } + return nil + default: + if isConstructorParameterCompletion(contextToken) { + return parent.Parent + } + } + return nil +} + +func isConstructorParameterCompletion(node *ast.Node) bool { + return node.Parent != nil && ast.IsParameter(node.Parent) && ast.IsConstructorDeclaration(node.Parent.Parent) && + (ast.IsParameterPropertyModifier(node.Kind) || ast.IsDeclarationName(node)) +} + +// Returns the immediate owning class declaration of a context token, +// on the condition that one exists and that the context implies completion should be given. +func tryGetObjectTypeDeclarationCompletionContainer( + file *ast.SourceFile, + contextToken *ast.Node, + location *ast.Node, + position int, +) *ast.ObjectTypeDeclaration { + // class c { method() { } | method2() { } } + switch location.Kind { + case ast.KindSyntaxList: + if ast.IsObjectTypeDeclaration(location.Parent) { + return location.Parent + } + return nil + // !!! we don't include EOF token anymore, verify what we should do in this case. + case ast.KindEndOfFile: + stmtList := location.Parent.AsSourceFile().Statements + if stmtList != nil && len(stmtList.Nodes) > 0 && ast.IsObjectTypeDeclaration(stmtList.Nodes[len(stmtList.Nodes)-1]) { + cls := stmtList.Nodes[len(stmtList.Nodes)-1] + if findChildOfKind(cls, ast.KindCloseBraceToken, file) == nil { + return cls + } + } + case ast.KindPrivateIdentifier: + if ast.IsPropertyDeclaration(location.Parent) { + return ast.FindAncestor(location, ast.IsClassLike) + } + case ast.KindIdentifier: + originalKeywordKind := scanner.IdentifierToKeywordKind(location.AsIdentifier()) + if originalKeywordKind != ast.KindUnknown { + return nil + } + // class c { public prop = c| } + if ast.IsPropertyDeclaration(location.Parent) && location.Parent.Initializer() == location { + return nil + } + // class c extends React.Component { a: () => 1\n compon| } + if isFromObjectTypeDeclaration(location) { + return ast.FindAncestor(location, ast.IsObjectTypeDeclaration) + } + } + + if contextToken == nil { + return nil + } + + // class C { blah; constructor/**/ } + // or + // class C { blah \n constructor/**/ } + if location.Kind == ast.KindConstructorKeyword || + (ast.IsIdentifier(contextToken) && ast.IsPropertyDeclaration(contextToken.Parent) && ast.IsClassLike(location)) { + return ast.FindAncestor(contextToken, ast.IsClassLike) + } + + switch contextToken.Kind { + // class c { public prop = | /* global completions */ } + case ast.KindEqualsToken: + return nil + // class c {getValue(): number; | } + // class c { method() { } | } + case ast.KindSemicolonToken, ast.KindCloseBraceToken: + // class c { method() { } b| } + if isFromObjectTypeDeclaration(location) && location.Parent.Name() == location { + return location.Parent.Parent + } + if ast.IsObjectTypeDeclaration(location) { + return location + } + return nil + // class c { | + // class c {getValue(): number, | } + case ast.KindOpenBraceToken, ast.KindCommaToken: + if ast.IsObjectTypeDeclaration(contextToken.Parent) { + return contextToken.Parent + } + return nil + default: + if ast.IsObjectTypeDeclaration(location) { + // class C extends React.Component { a: () => 1\n| } + // class C { prop = ""\n | } + if getLineOfPosition(file, contextToken.End()) != getLineOfPosition(file, position) { + return location + } + isValidKeyword := core.IfElse( + ast.IsClassLike(contextToken.Parent.Parent), + isClassMemberCompletionKeyword, + isInterfaceOrTypeLiteralCompletionKeyword, + ) + + if isValidKeyword(contextToken.Kind) || contextToken.Kind == ast.KindAsteriskToken || + ast.IsIdentifier(contextToken) && isValidKeyword(scanner.IdentifierToKeywordKind(contextToken.AsIdentifier())) { + return contextToken.Parent.Parent + } + } + + return nil + } +} + +func isFromObjectTypeDeclaration(node *ast.Node) bool { + return node.Parent != nil && ast.IsClassOrTypeElement(node.Parent) && ast.IsObjectTypeDeclaration(node.Parent.Parent) +} + +// Filters out completion suggestions for class elements. +func filterClassMembersList( + baseSymbols []*ast.Symbol, + existingMembers []*ast.ClassElement, + classElementModifierFlags ast.ModifierFlags, + file *ast.SourceFile, + position int, +) []*ast.Symbol { + existingMemberNames := core.Set[string]{} + for _, member := range existingMembers { + // Ignore omitted expressions for missing members. + if member.Kind != ast.KindPropertyDeclaration && + member.Kind != ast.KindMethodDeclaration && + member.Kind != ast.KindGetAccessor && + member.Kind != ast.KindSetAccessor { + continue + } + + // If this is the current item we are editing right now, do not filter it out + if isCurrentlyEditingNode(member, file, position) { + continue + } + + // Don't filter member even if the name matches if it is declared private in the list. + if member.ModifierFlags()&ast.ModifierFlagsPrivate != 0 { + continue + } + + // Do not filter it out if the static presence doesn't match. + if ast.IsStatic(member) != (classElementModifierFlags&ast.ModifierFlagsStatic != 0) { + continue + } + + existingName := checker.GetPropertyNameForPropertyNameNode(member.Name()) + if existingName != "" { + existingMemberNames.Add(existingName) + } + } + + return core.Filter(baseSymbols, func(propertySymbol *ast.Symbol) bool { + return !existingMemberNames.Has(propertySymbol.Name) && + len(propertySymbol.Declarations) > 0 && + checker.GetDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsPrivate == 0 && + !(propertySymbol.ValueDeclaration != nil && ast.IsPrivateIdentifierClassElementDeclaration(propertySymbol.ValueDeclaration)) + }) +} + +func tryGetContainingJsxElement(contextToken *ast.Node, file *ast.SourceFile) *ast.JsxOpeningLikeElement { + if contextToken == nil { + return nil + } + + parent := contextToken.Parent + switch contextToken.Kind { + case ast.KindGreaterThanToken, ast.KindLessThanSlashToken, ast.KindSlashToken, ast.KindIdentifier, + ast.KindPropertyAccessExpression, ast.KindJsxAttributes, ast.KindJsxAttribute, ast.KindJsxSpreadAttribute: + if parent != nil && (parent.Kind == ast.KindJsxSelfClosingElement || parent.Kind == ast.KindJsxOpeningElement) { + if contextToken.Kind == ast.KindGreaterThanToken { + precedingToken := astnav.FindPrecedingToken(file, contextToken.Pos()) + if len(parent.TypeArguments()) == 0 || + precedingToken != nil && precedingToken.Kind == ast.KindSlashToken { + return nil + } + } + return parent + } + // The context token is the closing } or " of an attribute, which means + // its parent is a JsxExpression, whose parent is a JsxAttribute, + // whose parent is a JsxOpeningLikeElement + case ast.KindStringLiteral: + if parent != nil && (parent.Kind == ast.KindJsxAttribute || parent.Kind == ast.KindJsxSpreadAttribute) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray + return parent.Parent.Parent + } + case ast.KindCloseBraceToken: + if parent != nil && parent.Kind == ast.KindJsxExpression && + parent.Parent != nil && parent.Parent.Kind == ast.KindJsxAttribute { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray + // each JsxAttribute can have initializer as JsxExpression + return parent.Parent.Parent.Parent + } + if parent != nil && parent.Kind == ast.KindJsxSpreadAttribute { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray + return parent.Parent.Parent + } + } + + return nil +} + +// Filters out completion suggestions from 'symbols' according to existing JSX attributes. +// @returns Symbols to be suggested in a JSX element, barring those whose attributes +// +// do not occur at the current position and have not otherwise been typed. +func filterJsxAttributes( + symbols []*ast.Symbol, + attributes []*ast.JsxAttributeLike, + file *ast.SourceFile, + position int, + typeChecker *checker.Checker, +) (filteredMembers []*ast.Symbol, spreadMemberNames *core.Set[string]) { + existingNames := core.Set[string]{} + membersDeclaredBySpreadAssignment := core.Set[string]{} + for _, attr := range attributes { + // If this is the item we are editing right now, do not filter it out. + if isCurrentlyEditingNode(attr, file, position) { + continue + } + + if attr.Kind == ast.KindJsxAttribute { + existingNames.Add(attr.Name().Text()) + } else if ast.IsJsxSpreadAttribute(attr) { + setMemberDeclaredBySpreadAssignment(attr, &membersDeclaredBySpreadAssignment, typeChecker) + } + } + + return core.Filter(symbols, func(a *ast.Symbol) bool { return !existingNames.Has(a.Name) }), + &membersDeclaredBySpreadAssignment +} + +func isTypeKeywordTokenOrIdentifier(node *ast.Node) bool { + return ast.IsTypeKeywordToken(node) || + ast.IsIdentifier(node) && scanner.IdentifierToKeywordKind(node.AsIdentifier()) == ast.KindTypeKeyword +} diff --git a/internal/ls/utilities.go b/internal/ls/utilities.go index 8fbd46e536..759edc00ae 100644 --- a/internal/ls/utilities.go +++ b/internal/ls/utilities.go @@ -610,3 +610,17 @@ func nodeEndsWith(n *ast.Node, expectedLastToken ast.Kind, sourceFile *ast.Sourc } return false } + +// Returns the node in an `extends` or `implements` clause of a class or interface. +func getAllSuperTypeNodes(node *ast.Node) []*ast.TypeNode { + if ast.IsInterfaceDeclaration(node) { + return ast.GetHeritageElements(node, ast.KindExtendsKeyword) + } + if ast.IsClassLike(node) { + return append( + []*ast.Node{ast.GetClassExtendsHeritageElement(node)}, + ast.GetImplementsTypeNodes(node)..., + ) + } + return nil +} From 1e72412423498e338ba3654dbc89309fa69ef436 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Fri, 2 May 2025 10:32:39 -0700 Subject: [PATCH 03/16] kewyord completion data --- internal/ls/completions.go | 137 ++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 41 deletions(-) diff --git a/internal/ls/completions.go b/internal/ls/completions.go index cce21d95d2..007f6e1438 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -32,9 +32,10 @@ func (l *LanguageService) ProvideCompletion( return l.getCompletionsAtPosition(program, file, position, context, preferences, clientOptions) } -// !!! figure out other kinds of completion data return -type completionData struct { - // !!! +// *completionDataData | *completionDataKeyword +type completionData = any + +type completionDataData struct { symbols []*ast.Symbol completionKind CompletionKind isInSnippetScope bool @@ -62,6 +63,11 @@ type completionData struct { defaultCommitCharacters []string } +type completionDataKeyword struct { + keywordCompletions []*lsproto.CompletionItem + isNewIdentifierLocation bool +} + type importStatementCompletionInfo struct { // !!! } @@ -285,28 +291,32 @@ func (l *LanguageService) getCompletionsAtPosition( // !!! label completions - completionData := getCompletionData(program, file, position, preferences) - if completionData == nil { + data := getCompletionData(program, file, position, preferences) + if data == nil { return nil } - // switch completionData.Kind // !!! other data cases - // !!! transform data into completion list - - response := l.completionInfoFromData( - file, - program, - compilerOptions, - completionData, - preferences, - position, - clientOptions, - ) - // !!! check if response is incomplete - return response + switch data := data.(type) { + case *completionDataData: + response := l.completionInfoFromData( + file, + program, + compilerOptions, + data, + preferences, + position, + clientOptions, + ) + // !!! check if response is incomplete + return response + case *completionDataKeyword: + return specificKeywordCompletionInfo(clientOptions, data.keywordCompletions, data.isNewIdentifierLocation) + default: + panic("getCompletionData() returned unexpected type: " + fmt.Sprintf("%T", data)) + } } -func getCompletionData(program *compiler.Program, file *ast.SourceFile, position int, preferences *UserPreferences) *completionData { +func getCompletionData(program *compiler.Program, file *ast.SourceFile, position int, preferences *UserPreferences) completionData { typeChecker := program.GetTypeChecker() inCheckedFile := isCheckedFile(file, program.GetCompilerOptions()) @@ -1385,7 +1395,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position defaultCommitCharacters = getDefaultCommitCharacters(isNewIdentifierLocation) } - return &completionData{ + return &completionDataData{ symbols: symbols, completionKind: completionKind, isInSnippetScope: isInSnippetScope, @@ -1415,8 +1425,11 @@ func keywordCompletionData( keywordFilters KeywordCompletionFilters, filterOutTSOnlyKeywords bool, isNewIdentifierLocation bool, -) *completionData { - return nil // !!! +) *completionDataKeyword { + return &completionDataKeyword{ + keywordCompletions: getKeywordCompletions(keywordFilters, filterOutTSOnlyKeywords), + isNewIdentifierLocation: isNewIdentifierLocation, + } } func getDefaultCommitCharacters(isNewIdentifierLocation bool) []string { @@ -1430,7 +1443,7 @@ func (l *LanguageService) completionInfoFromData( file *ast.SourceFile, program *compiler.Program, compilerOptions *core.CompilerOptions, - data *completionData, + data *completionDataData, preferences *UserPreferences, position int, clientOptions *lsproto.CompletionClientCapabilities, @@ -1512,17 +1525,8 @@ func (l *LanguageService) completionInfoFromData( // !!! exhaustive case completions - var defaultCommitCharacters *[]string - if supportsDefaultCommitCharacters(clientOptions) && ptrIsTrue(clientOptions.CompletionItem.CommitCharactersSupport) { - defaultCommitCharacters = &data.defaultCommitCharacters - } - - var itemDefaults *lsproto.CompletionItemDefaults - if defaultCommitCharacters != nil { - itemDefaults = &lsproto.CompletionItemDefaults{ - CommitCharacters: defaultCommitCharacters, - } - } + itemDefaults := + setCommitCharacters(clientOptions, sortedEntries, &data.defaultCommitCharacters) // !!! port behavior of other strada fields of CompletionInfo that are non-LSP return &lsproto.CompletionList{ @@ -1533,7 +1537,7 @@ func (l *LanguageService) completionInfoFromData( } func (l *LanguageService) getCompletionEntriesFromSymbols( - data *completionData, + data *completionDataData, replacementToken *ast.Node, position int, file *ast.SourceFile, @@ -1655,7 +1659,7 @@ func (l *LanguageService) createCompletionItem( symbol *ast.Symbol, sortText sortText, replacementToken *ast.Node, - data *completionData, + data *completionDataData, position int, file *ast.SourceFile, program *compiler.Program, @@ -2202,7 +2206,7 @@ func symbolAppearsToBeTypeOnly(symbol *ast.Symbol, typeChecker *checker.Checker) func shouldIncludeSymbol( symbol *ast.Symbol, - data *completionData, + data *completionDataData, closestSymbolDeclaration *ast.Declaration, file *ast.SourceFile, typeChecker *checker.Checker, @@ -2975,14 +2979,23 @@ var ( }) ) +func cloneItems(items []*lsproto.CompletionItem) []*lsproto.CompletionItem { + result := make([]*lsproto.CompletionItem, len(items)) + for i, item := range items { + itemClone := *item + result[i] = &itemClone + } + return result +} + func getKeywordCompletions(keywordFilter KeywordCompletionFilters, filterOutTsOnlyKeywords bool) []*lsproto.CompletionItem { if !filterOutTsOnlyKeywords { - return getTypescriptKeywordCompletions(keywordFilter) + return cloneItems(getTypescriptKeywordCompletions(keywordFilter)) } index := keywordFilter + KeywordCompletionFiltersLast + 1 if cached, ok := keywordCompletionsCache.Load(index); ok { - return cached + return cloneItems(cached) } result := core.Filter( getTypescriptKeywordCompletions(keywordFilter), @@ -2990,7 +3003,7 @@ func getKeywordCompletions(keywordFilter KeywordCompletionFilters, filterOutTsOn return !isTypeScriptOnlyKeyword(scanner.StringToToken(ci.Label)) }) keywordCompletionsCache.Store(index, result) - return result + return cloneItems(result) } func getTypescriptKeywordCompletions(keywordFilter KeywordCompletionFilters) []*lsproto.CompletionItem { @@ -3873,3 +3886,45 @@ func isTypeKeywordTokenOrIdentifier(node *ast.Node) bool { return ast.IsTypeKeywordToken(node) || ast.IsIdentifier(node) && scanner.IdentifierToKeywordKind(node.AsIdentifier()) == ast.KindTypeKeyword } + +// Returns the default commit characters for completion items, if that capability is supported. +// Otherwise, if item commit characters are supported, sets the commit characters on each item. +func setCommitCharacters( + clientOptions *lsproto.CompletionClientCapabilities, + items []*lsproto.CompletionItem, + defaultCommitCharacters *[]string, +) *lsproto.CompletionItemDefaults { + var itemDefaults *lsproto.CompletionItemDefaults + supportsItemCommitCharacters := ptrIsTrue(clientOptions.CompletionItem.CommitCharactersSupport) + if supportsDefaultCommitCharacters(clientOptions) && supportsItemCommitCharacters { + itemDefaults = &lsproto.CompletionItemDefaults{ + CommitCharacters: defaultCommitCharacters, + } + } else if supportsItemCommitCharacters { + for _, item := range items { + if item.CommitCharacters == nil { + item.CommitCharacters = defaultCommitCharacters + } + } + } + + return itemDefaults +} + +func specificKeywordCompletionInfo( + clientOptions *lsproto.CompletionClientCapabilities, + items []*lsproto.CompletionItem, + isNewIdentifierLocation bool, +) *lsproto.CompletionList { + defaultCommitCharacters := getDefaultCommitCharacters(isNewIdentifierLocation) + itemDefaults := setCommitCharacters( + clientOptions, + items, + &defaultCommitCharacters, + ) + return &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: items, + } +} From 459236eecec1040bda6239f7e640be497950043d Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Fri, 2 May 2025 14:03:14 -0700 Subject: [PATCH 04/16] implement get first and last token --- internal/ast/utilities.go | 9 +++ internal/astnav/tokens.go | 17 ++--- internal/ls/completions.go | 41 +++++++++-- internal/ls/utilities.go | 137 ++++++++++++++++++++++++++++++++----- 4 files changed, 169 insertions(+), 35 deletions(-) diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index c64c400419..4545fb8c0f 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -2866,3 +2866,12 @@ func GetImplementsTypeNodes(node *Node) []*ExpressionWithTypeArgumentsNode { func IsTypeKeywordToken(node *Node) bool { return node.Kind == KindTypeKeyword } + +// If node is a single comment JSDoc, we do not visit the comment node list. +func IsJSDocSingleCommentNodeList(parent *Node, nodeList *NodeList) bool { + return IsJSDocSingleCommentNode(parent) && nodeList == parent.AsJSDoc().Comment +} + +func IsJSDocSingleCommentNode(node *Node) bool { + return node.Kind == KindJSDoc && node.AsJSDoc().Comment != nil && len(node.AsJSDoc().Comment.Nodes) == 1 +} diff --git a/internal/astnav/tokens.go b/internal/astnav/tokens.go index b70f2de7f9..ad9aa6f785 100644 --- a/internal/astnav/tokens.go +++ b/internal/astnav/tokens.go @@ -134,7 +134,7 @@ func getTokenAtPosition( }) for { - visitEachChildAndJSDoc(current, sourceFile, nodeVisitor) + VisitEachChildAndJSDoc(current, sourceFile, nodeVisitor) // If prevSubtree was set on the last iteration, it ends at the target position. // Check if the rightmost token of prevSubtree should be returned based on the // `includePrecedingTokenAtEndPosition` callback. @@ -234,7 +234,7 @@ func findRightmostNode(node *ast.Node) *ast.Node { } } -func visitEachChildAndJSDoc(node *ast.Node, sourceFile *ast.SourceFile, visitor *ast.NodeVisitor) { +func VisitEachChildAndJSDoc(node *ast.Node, sourceFile *ast.SourceFile, visitor *ast.NodeVisitor) { if node.Flags&ast.NodeFlagsHasJSDoc != 0 { for _, jsdoc := range node.JSDoc(sourceFile) { if visitor.Hooks.VisitNode != nil { @@ -292,7 +292,7 @@ func FindPrecedingTokenEx(sourceFile *ast.SourceFile, position int, startNode *a } if nodeList != nil && len(nodeList.Nodes) > 0 { nodes := nodeList.Nodes - if isJSDocSingleCommentNodeList(n, nodeList) { + if ast.IsJSDocSingleCommentNodeList(n, nodeList) { return nodeList } index, match := core.BinarySearchUniqueFunc(nodes, func(middle int, _ *ast.Node) int { @@ -336,7 +336,7 @@ func FindPrecedingTokenEx(sourceFile *ast.SourceFile, position int, startNode *a return modifiers }, }) - visitEachChildAndJSDoc(n, sourceFile, nodeVisitor) + VisitEachChildAndJSDoc(n, sourceFile, nodeVisitor) if foundChild != nil { // Note that the span of a node's tokens is [getStartOfNode(node, ...), node.end). @@ -407,11 +407,6 @@ func GetStartOfNode(node *ast.Node, file *ast.SourceFile, includeJSDoc bool) int return scanner.GetTokenPosOfNode(node, file, includeJSDoc) } -// If this is a single comment JSDoc, we do not visit the comment node. -func isJSDocSingleCommentNodeList(parent *ast.Node, nodeList *ast.NodeList) bool { - return parent.Kind == ast.KindJSDoc && nodeList == parent.AsJSDoc().Comment && nodeList != nil && len(nodeList.Nodes) == 1 -} - // Looks for rightmost valid token in the range [startPos, endPos). // If position is >= 0, looks for rightmost valid token that precedes or touches that position. func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingNode *ast.Node, position int, excludeJSDoc bool) *ast.Node { @@ -452,7 +447,7 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN } visitNodes := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList { if nodeList != nil && len(nodeList.Nodes) > 0 { - if isJSDocSingleCommentNodeList(n, nodeList) { + if ast.IsJSDocSingleCommentNodeList(n, nodeList) { return nodeList } hasChildren = true @@ -493,7 +488,7 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN return modifiers }, }) - visitEachChildAndJSDoc(n, sourceFile, nodeVisitor) + VisitEachChildAndJSDoc(n, sourceFile, nodeVisitor) // Three cases: // 1. The answer is a token of `rightmostValidNode`. diff --git a/internal/ls/completions.go b/internal/ls/completions.go index 007f6e1438..e613b4cc12 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -272,12 +272,8 @@ func (l *LanguageService) getCompletionsAtPosition( if context.TriggerCharacter != nil && *context.TriggerCharacter == " " { // `isValidTrigger` ensures we are at `import |` if ptrIsTrue(preferences.IncludeCompletionsForImportStatements) { - // !!! isMemberCompletion return &lsproto.CompletionList{ IsIncomplete: true, - ItemDefaults: &lsproto.CompletionItemDefaults{ // !!! do we need this if no entries? also, check if client supports item defaults - CommitCharacters: ptrTo(getDefaultCommitCharacters(true /*isNewIdentifierLocation*/)), - }, } } return nil @@ -311,6 +307,7 @@ func (l *LanguageService) getCompletionsAtPosition( return response case *completionDataKeyword: return specificKeywordCompletionInfo(clientOptions, data.keywordCompletions, data.isNewIdentifierLocation) + // !!! jsdoc completion data cases default: panic("getCompletionData() returned unexpected type: " + fmt.Sprintf("%T", data)) } @@ -1525,8 +1522,7 @@ func (l *LanguageService) completionInfoFromData( // !!! exhaustive case completions - itemDefaults := - setCommitCharacters(clientOptions, sortedEntries, &data.defaultCommitCharacters) + itemDefaults := setCommitCharacters(clientOptions, sortedEntries, &data.defaultCommitCharacters) // !!! port behavior of other strada fields of CompletionInfo that are non-LSP return &lsproto.CompletionList{ @@ -3047,7 +3043,38 @@ func getTypescriptKeywordCompletions(keywordFilter KeywordCompletionFilters) []* } func isTypeScriptOnlyKeyword(kind ast.Kind) bool { - return false // !!! here + switch kind { + case ast.KindAbstractKeyword, + ast.KindAnyKeyword, + ast.KindBigIntKeyword, + ast.KindBooleanKeyword, + ast.KindDeclareKeyword, + ast.KindEnumKeyword, + ast.KindGlobalKeyword, + ast.KindImplementsKeyword, + ast.KindInferKeyword, + ast.KindInterfaceKeyword, + ast.KindIsKeyword, + ast.KindKeyOfKeyword, + ast.KindModuleKeyword, + ast.KindNamespaceKeyword, + ast.KindNeverKeyword, + ast.KindNumberKeyword, + ast.KindObjectKeyword, + ast.KindOverrideKeyword, + ast.KindPrivateKeyword, + ast.KindProtectedKeyword, + ast.KindPublicKeyword, + ast.KindReadonlyKeyword, + ast.KindStringKeyword, + ast.KindSymbolKeyword, + ast.KindTypeKeyword, + ast.KindUniqueKeyword, + ast.KindUnknownKeyword: + return true + default: + return false + } } func isFunctionLikeBodyKeyword(kind ast.Kind) bool { diff --git a/internal/ls/utilities.go b/internal/ls/utilities.go index 759edc00ae..d9d1435a9d 100644 --- a/internal/ls/utilities.go +++ b/internal/ls/utilities.go @@ -46,10 +46,29 @@ func isInComment(file *ast.SourceFile, position int, tokenAtPosition *ast.Node) return nil } -// !!! // Replaces last(node.getChildren(sourceFile)) func getLastChild(node *ast.Node, sourceFile *ast.SourceFile) *ast.Node { - return nil + lastChildNode := getLastVisitedChild(node, sourceFile) + if ast.IsJSDocSingleCommentNode(node) { + return nil + } + var tokenStartPos int + if lastChildNode != nil { + tokenStartPos = lastChildNode.End() + } else { + tokenStartPos = node.Pos() + } + var lastToken *ast.Node + scanner := scanner.GetScannerForSourceFile(sourceFile, tokenStartPos) + for startPos := tokenStartPos; startPos < node.End(); { + tokenKind := scanner.Token() + tokenFullStart := scanner.TokenFullStart() + tokenEnd := scanner.TokenEnd() + lastToken = sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, node) + startPos = tokenEnd + scanner.Scan() + } + return core.IfElse(lastToken != nil, lastToken, lastChildNode) } func getLastToken(node *ast.Node, sourceFile *ast.SourceFile) *ast.Node { @@ -57,6 +76,10 @@ func getLastToken(node *ast.Node, sourceFile *ast.SourceFile) *ast.Node { return nil } + if ast.IsTokenKind(node.Kind) || ast.IsIdentifier(node) { + return nil + } + assertHasRealPosition(node) lastChild := getLastChild(node, sourceFile) @@ -71,9 +94,84 @@ func getLastToken(node *ast.Node, sourceFile *ast.SourceFile) *ast.Node { } } -// !!! +// Gets the last visited child of the given node. +// NOTE: This doesn't include unvisited tokens; for this, use `getLastChild` or `getLastToken`. +func getLastVisitedChild(node *ast.Node, sourceFile *ast.SourceFile) *ast.Node { + var lastChild *ast.Node + + visitNode := func(n *ast.Node, _ *ast.NodeVisitor) *ast.Node { + if !(n == nil || node.Flags&ast.NodeFlagsReparsed != 0) { + lastChild = n + } + return n + } + visitNodeList := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList { + if nodeList != nil && len(nodeList.Nodes) > 0 && !ast.IsJSDocSingleCommentNodeList(node, nodeList) { + for i := len(nodeList.Nodes) - 1; i >= 0; i-- { + if nodeList.Nodes[i].Flags&ast.NodeFlagsReparsed == 0 { + lastChild = nodeList.Nodes[i] + break + } + } + } + return nodeList + } + + nodeVisitor := ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{ + VisitNode: visitNode, + VisitToken: visitNode, + VisitNodes: visitNodeList, + VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList { + if modifiers != nil { + visitNodeList(&modifiers.NodeList, visitor) + } + return modifiers + }, + }) + + astnav.VisitEachChildAndJSDoc(node, sourceFile, nodeVisitor) + return lastChild +} + func getFirstToken(node *ast.Node, sourceFile *ast.SourceFile) *ast.Node { - return nil + if ast.IsIdentifier(node) || ast.IsTokenKind(node.Kind) { + return nil + } + assertHasRealPosition(node) + var firstChild *ast.Node + node.ForEachChild(func(n *ast.Node) bool { + if n == nil || node.Flags&ast.NodeFlagsReparsed != 0 { + return false + } + firstChild = n + return true + }) + + var tokenEndPosition int + if firstChild != nil { + tokenEndPosition = firstChild.Pos() + } else { + tokenEndPosition = node.End() + } + scanner := scanner.GetScannerForSourceFile(sourceFile, node.Pos()) + var firstToken *ast.Node + if node.Pos() < tokenEndPosition { + tokenKind := scanner.Token() + tokenFullStart := scanner.TokenFullStart() + tokenEnd := scanner.TokenEnd() + firstToken = sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, node) + } + + if firstToken != nil { + return firstToken + } + if firstChild == nil { + return nil + } + if firstChild.Kind < ast.KindFirstNode { + return firstChild + } + return getFirstToken(firstChild, sourceFile) } func assertHasRealPosition(node *ast.Node) { @@ -349,6 +447,9 @@ func probablyUsesSemicolons(file *ast.SourceFile) bool { } // If even 2/5 places have a semicolon, the user probably wants semicolons + if withoutSemicolon == 0 { + return true + } return withSemicolon/withoutSemicolon > 1/nStatementsToObserve } @@ -582,25 +683,27 @@ func isCompletedNode(n *ast.Node, sourceFile *ast.SourceFile) bool { // Checks if node ends with 'expectedLastToken'. // If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'. func nodeEndsWith(n *ast.Node, expectedLastToken ast.Kind, sourceFile *ast.SourceFile) bool { - var lastChildNode *ast.Node - ast.ForEachChildAndJSDoc(n, sourceFile, func(node *ast.Node) bool { // !!! This can be extracted into its own `findLastChildNode` function. - if node == nil || node.Flags&ast.NodeFlagsReparsed != 0 { - return false - } - lastChildNode = node - return false - }) - if lastChildNode == nil { - return false + lastChildNode := getLastVisitedChild(n, sourceFile) + var lastNodeAndTokens []*ast.Node + var tokenStartPos int + if lastChildNode != nil { + lastNodeAndTokens = []*ast.Node{lastChildNode} + tokenStartPos = lastChildNode.End() + } else { + tokenStartPos = n.Pos() } - lastNodeAndTokens := []*ast.Node{lastChildNode} - scanner := scanner.GetScannerForSourceFile(sourceFile, lastChildNode.End()) - for startPos := lastChildNode.End(); startPos < n.End(); { + scanner := scanner.GetScannerForSourceFile(sourceFile, tokenStartPos) + for startPos := tokenStartPos; startPos < n.End(); { tokenKind := scanner.Token() tokenFullStart := scanner.TokenFullStart() tokenEnd := scanner.TokenEnd() token := sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, n) lastNodeAndTokens = append(lastNodeAndTokens, token) + tokenStartPos = tokenEnd + scanner.Scan() + } + if len(lastNodeAndTokens) == 0 { + return false } lastChild := lastNodeAndTokens[len(lastNodeAndTokens)-1] if lastChild.Kind == expectedLastToken { From 113f523f60c3ba7c126927dc6460b8a0991c46a8 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 7 May 2025 09:07:42 -0700 Subject: [PATCH 05/16] findNextToken --- internal/astnav/tokens.go | 146 ++++++++++++++++++++++++-------------- internal/ls/utilities.go | 2 +- 2 files changed, 93 insertions(+), 55 deletions(-) diff --git a/internal/astnav/tokens.go b/internal/astnav/tokens.go index ad9aa6f785..0910afac65 100644 --- a/internal/astnav/tokens.go +++ b/internal/astnav/tokens.go @@ -121,17 +121,7 @@ func getTokenAtPosition( return nodeList } - nodeVisitor := ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{ - VisitNode: visitNode, - VisitToken: visitNode, - VisitNodes: visitNodeList, - VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList { - if modifiers != nil { - visitNodeList(&modifiers.NodeList, visitor) - } - return modifiers - }, - }) + nodeVisitor := getNodeVisitor(visitNode, visitNodeList) for { VisitEachChildAndJSDoc(current, sourceFile, nodeVisitor) @@ -203,26 +193,15 @@ func findRightmostNode(node *ast.Node) *ast.Node { } return node } - visitor := ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{ - VisitNode: visitNode, - VisitToken: visitNode, - VisitNodes: func(nodeList *ast.NodeList, visitor *ast.NodeVisitor) *ast.NodeList { - if nodeList != nil { - if rightmost := ast.FindLastVisibleNode(nodeList.Nodes); rightmost != nil { - next = rightmost - } + visitNodes := func(nodeList *ast.NodeList, visitor *ast.NodeVisitor) *ast.NodeList { + if nodeList != nil { + if rightmost := ast.FindLastVisibleNode(nodeList.Nodes); rightmost != nil { + next = rightmost } - return nodeList - }, - VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList { - if modifiers != nil { - if rightmost := ast.FindLastVisibleNode(modifiers.Nodes); rightmost != nil { - next = rightmost - } - } - return modifiers - }, - }) + } + return nodeList + } + visitor := getNodeVisitor(visitNode, visitNodes) for { current.VisitEachChild(visitor) @@ -325,17 +304,7 @@ func FindPrecedingTokenEx(sourceFile *ast.SourceFile, position int, startNode *a } return nodeList } - nodeVisitor := ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{ - VisitNode: visitNode, - VisitToken: visitNode, - VisitNodes: visitNodes, - VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList { - if modifiers != nil { - visitNodes(&modifiers.NodeList, visitor) - } - return modifiers - }, - }) + nodeVisitor := getNodeVisitor(visitNode, visitNodes) VisitEachChildAndJSDoc(n, sourceFile, nodeVisitor) if foundChild != nil { @@ -477,17 +446,7 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN } return nodeList } - nodeVisitor := ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{ - VisitNode: visitNode, - VisitToken: visitNode, - VisitNodes: visitNodes, - VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList { - if modifiers != nil { - visitNodes(&modifiers.NodeList, visitor) - } - return modifiers - }, - }) + nodeVisitor := getNodeVisitor(visitNode, visitNodes) VisitEachChildAndJSDoc(n, sourceFile, nodeVisitor) // Three cases: @@ -559,7 +518,86 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN return find(containingNode, endPos) } -// !!! func FindNextToken(previousToken *ast.Node, parent *ast.Node, file *ast.SourceFile) *ast.Node { - return nil + var find func(n *ast.Node) *ast.Node + find = func(n *ast.Node) *ast.Node { + if ast.IsTokenKind(n.Kind) && n.Pos() == previousToken.End() { + // this is token that starts at the end of previous token - return it + return n + } + // Node that contains `previousToken` or occurs immediately after it. + var foundNode *ast.Node + visitNode := func(node *ast.Node, _ *ast.NodeVisitor) *ast.Node { + if node != nil && node.Flags&ast.NodeFlagsReparsed == 0 && + node.Pos() <= previousToken.End() && node.End() > previousToken.End() { + foundNode = node + } + return node + } + visitNodes := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList { + if nodeList != nil && len(nodeList.Nodes) > 0 && foundNode == nil { + nodes := nodeList.Nodes + index, match := core.BinarySearchUniqueFunc(nodes, func(_ int, node *ast.Node) int { + if node.Flags&ast.NodeFlagsReparsed != 0 { + return comparisonLessThan + } + if node.Pos() > previousToken.End() { + return comparisonGreaterThan + } + if node.End() <= previousToken.Pos() { + return comparisonLessThan + } + return comparisonEqualTo + }) + if match { + foundNode = nodes[index] + } + } + return nodeList + } + nodeVisitor := getNodeVisitor(visitNode, visitNodes) + VisitEachChildAndJSDoc(n, file, nodeVisitor) + // Cases: + // 1. no answer exists + // 2. answer is an unvisited token + // 3. answer is in the visited found node + + // Case 3: look for the next token inside the found node. + if foundNode != nil { + return find(foundNode) + } + startPos := previousToken.End() + // Case 2: look for the next token directly. + if startPos >= n.Pos() && startPos < n.End() { + scanner := scanner.GetScannerForSourceFile(file, startPos) + token := scanner.Token() + tokenFullStart := scanner.TokenFullStart() + tokenStart := scanner.TokenStart() + tokenEnd := scanner.TokenEnd() + if tokenStart == previousToken.End() { + return file.GetOrCreateToken(token, tokenFullStart, tokenEnd, n) + } + panic(fmt.Sprintf("Expected to find next token at %d, got token %s at %d", previousToken.End(), token, tokenStart)) + } + // Case 3: no answer. + return nil + } + return find(parent) +} + +func getNodeVisitor( + visitNode func(*ast.Node, *ast.NodeVisitor) *ast.Node, + visitNodes func(*ast.NodeList, *ast.NodeVisitor) *ast.NodeList, +) *ast.NodeVisitor { + return ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{ + VisitNode: visitNode, + VisitToken: visitNode, + VisitNodes: visitNodes, + VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList { + if modifiers != nil { + visitNodes(&modifiers.NodeList, visitor) + } + return modifiers + }, + }) } diff --git a/internal/ls/utilities.go b/internal/ls/utilities.go index d9d1435a9d..5e4f4bd742 100644 --- a/internal/ls/utilities.go +++ b/internal/ls/utilities.go @@ -699,7 +699,7 @@ func nodeEndsWith(n *ast.Node, expectedLastToken ast.Kind, sourceFile *ast.Sourc tokenEnd := scanner.TokenEnd() token := sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, n) lastNodeAndTokens = append(lastNodeAndTokens, token) - tokenStartPos = tokenEnd + startPos = tokenEnd scanner.Scan() } if len(lastNodeAndTokens) == 0 { From bcaa7e08418fff9fbfcb15e3dbfffbc49a3a1037 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Thu, 8 May 2025 08:30:22 -0700 Subject: [PATCH 06/16] add first global test + fixes --- internal/checker/services.go | 2 +- internal/ls/completions_test.go | 954 +++++++++++++++++--------------- internal/ls/symbol_display.go | 11 +- 3 files changed, 519 insertions(+), 448 deletions(-) diff --git a/internal/checker/services.go b/internal/checker/services.go index 576be91d5c..0181c074ad 100644 --- a/internal/checker/services.go +++ b/internal/checker/services.go @@ -18,7 +18,7 @@ func (c *Checker) getSymbolsInScope(location *ast.Node, meaning ast.SymbolFlags) return nil } - symbols := createSymbolTable(nil) + symbols := make(ast.SymbolTable) isStaticSymbol := false // Copy the given symbol into symbol tables if the symbol has the given meaning diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 31675cbf43..9588fe3d13 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1,8 +1,10 @@ package ls_test import ( + "slices" "testing" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/microsoft/typescript-go/internal/bundled" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/ls" @@ -15,9 +17,14 @@ import ( var defaultCommitCharacters = []string{".", ",", ";"} type testCase struct { - name string - files map[string]string - expected map[string]*lsproto.CompletionList + name string + files map[string]string + expectedResult map[string]*testCaseResult +} + +type testCaseResult struct { + list *lsproto.CompletionList + isIncludes bool } const mainFileName = "/index.ts" @@ -41,6 +48,7 @@ func TestCompletions(t *testing.T) { methodKind := ptrTo(lsproto.CompletionItemKindMethod) functionKind := ptrTo(lsproto.CompletionItemKindFunction) variableKind := ptrTo(lsproto.CompletionItemKindVariable) + classKind := ptrTo(lsproto.CompletionItemKindClass) stringMembers := []*lsproto.CompletionItem{ {Label: "charAt", Kind: methodKind, SortText: sortTextLocationPriority, InsertTextFormat: insertTextFormatPlainText}, @@ -103,52 +111,55 @@ interface Point { declare const p: Point; p./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "x", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 6, Character: 2}, - End: lsproto.Position{Line: 6, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 6, Character: 2}, - End: lsproto.Position{Line: 6, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 2}, + End: lsproto.Position{Line: 6, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 2}, + End: lsproto.Position{Line: 6, Character: 2}, + }, }, }, }, - }, - { - Label: "y", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".y"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "y", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 6, Character: 2}, - End: lsproto.Position{Line: 6, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 6, Character: 2}, - End: lsproto.Position{Line: 6, Character: 2}, + { + Label: "y", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".y"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "y", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 2}, + End: lsproto.Position{Line: 6, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 2}, + End: lsproto.Position{Line: 6, Character: 2}, + }, }, }, }, }, }, + isIncludes: false, }, }, }, @@ -164,41 +175,43 @@ interface Point { declare const p: Point | undefined; p./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "x", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".?.x"), - InsertText: ptrTo("?.x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "?.x", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 6, Character: 1}, - End: lsproto.Position{Line: 6, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".?.x"), + InsertText: ptrTo("?.x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "?.x", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 1}, + End: lsproto.Position{Line: 6, Character: 2}, + }, }, }, }, - }, - { - Label: "y", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".?.y"), - InsertText: ptrTo("?.y"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "?.y", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 6, Character: 1}, - End: lsproto.Position{Line: 6, Character: 2}, + { + Label: "y", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".?.y"), + InsertText: ptrTo("?.y"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "?.y", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 1}, + End: lsproto.Position{Line: 6, Character: 2}, + }, }, }, }, @@ -214,27 +227,29 @@ p./*a*/`, let x = { foo: 123 }; x./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "foo", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".foo"), - InsertTextFormat: ptrTo(lsproto.InsertTextFormatPlainText), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "foo", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 2, Character: 2}, - End: lsproto.Position{Line: 2, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 2, Character: 2}, - End: lsproto.Position{Line: 2, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "foo", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".foo"), + InsertTextFormat: ptrTo(lsproto.InsertTextFormatPlainText), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "foo", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 2, Character: 2}, + End: lsproto.Position{Line: 2, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 2, Character: 2}, + End: lsproto.Position{Line: 2, Character: 2}, + }, }, }, }, @@ -252,47 +267,49 @@ class n { } var t = new n(0, 1, '');t./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "x", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, }, }, }, - }, - { - Label: "y", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".y"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "y", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, + { + Label: "y", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".y"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "y", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, }, }, }, @@ -326,247 +343,249 @@ class D extends A { D./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ // !!! `funcionMembersPlus` - { - Label: "bar", - Kind: methodKind, - SortText: sortTextLocalDeclarationPriority, - FilterText: ptrTo(".bar"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bar", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ // !!! `funcionMembersPlus` + { + Label: "bar", + Kind: methodKind, + SortText: sortTextLocalDeclarationPriority, + FilterText: ptrTo(".bar"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bar", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "bar2", - Kind: methodKind, - SortText: sortTextLocalDeclarationPriority, - FilterText: ptrTo(".bar2"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bar2", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "bar2", + Kind: methodKind, + SortText: sortTextLocalDeclarationPriority, + FilterText: ptrTo(".bar2"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bar2", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "apply", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".apply"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "apply", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "apply", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".apply"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "apply", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "arguments", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".arguments"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "arguments", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "arguments", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".arguments"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "arguments", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "baz", - Kind: functionKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".baz"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "baz", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "baz", + Kind: functionKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".baz"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "baz", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "bind", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".bind"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bind", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "bind", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".bind"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bind", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "call", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".call"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "call", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "call", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".call"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "call", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "caller", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".caller"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "caller", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "caller", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".caller"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "caller", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "length", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".length"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "length", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "length", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".length"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "length", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "prototype", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".prototype"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "prototype", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "prototype", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".prototype"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "prototype", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "toString", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".toString"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "toString", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "toString", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".toString"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "toString", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "x", - Kind: variableKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "x", + Kind: variableKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, @@ -587,47 +606,49 @@ D./*a*/`, } }`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "a", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".a"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "a", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "a", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".a"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "a", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, }, }, }, - }, - { - Label: "b", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".b"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "b", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, + { + Label: "b", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".b"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "b", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, }, }, }, @@ -642,28 +663,30 @@ D./*a*/`, mainFileName: `var x: string[] = []; x.forEach(function (y) { y./*1*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "1": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: core.Map(stringMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { - item := *basicItem - item.FilterText = ptrTo("." + item.Label) - item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: item.Label, - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 27}, - End: lsproto.Position{Line: 1, Character: 27}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 27}, - End: lsproto.Position{Line: 1, Character: 27}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: core.Map(stringMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { + item := *basicItem + item.FilterText = ptrTo("." + item.Label) + item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: item.Label, + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 27}, + End: lsproto.Position{Line: 1, Character: 27}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 27}, + End: lsproto.Position{Line: 1, Character: 27}, + }, }, - }, - } - return &item - }), + } + return &item + }), + }, }, }, }, @@ -673,63 +696,90 @@ x.forEach(function (y) { y./*1*/`, mainFileName: `declare const x: [number, number]; x./**/;`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: append([]*lsproto.CompletionItem{ - { - Label: "0", - Kind: fieldKind, - SortText: sortTextLocationPriority, - InsertText: ptrTo("[0]"), - InsertTextFormat: insertTextFormatPlainText, - FilterText: ptrTo(".[0]"), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "[0]", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 1}, - End: lsproto.Position{Line: 1, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: append([]*lsproto.CompletionItem{ + { + Label: "0", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertText: ptrTo("[0]"), + InsertTextFormat: insertTextFormatPlainText, + FilterText: ptrTo(".[0]"), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "[0]", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 1}, + End: lsproto.Position{Line: 1, Character: 2}, + }, }, }, }, - }, - { - Label: "1", - Kind: fieldKind, - SortText: sortTextLocationPriority, - InsertText: ptrTo("[1]"), - InsertTextFormat: insertTextFormatPlainText, - FilterText: ptrTo(".[1]"), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "[1]", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 1}, - End: lsproto.Position{Line: 1, Character: 2}, + { + Label: "1", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertText: ptrTo("[1]"), + InsertTextFormat: insertTextFormatPlainText, + FilterText: ptrTo(".[1]"), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "[1]", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 1}, + End: lsproto.Position{Line: 1, Character: 2}, + }, }, }, }, - }, - }, core.Map(arrayMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { - item := *basicItem - item.FilterText = ptrTo("." + item.Label) - item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: item.Label, - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 2}, - End: lsproto.Position{Line: 1, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 2}, - End: lsproto.Position{Line: 1, Character: 2}, + }, core.Map(arrayMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { + item := *basicItem + item.FilterText = ptrTo("." + item.Label) + item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: item.Label, + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 2}, + End: lsproto.Position{Line: 1, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 2}, + End: lsproto.Position{Line: 1, Character: 2}, + }, }, + } + return &item + })...), + }, + }, + }, + }, + { + name: "augmentedTypesClass3Fourslash", + files: map[string]string{ + mainFileName: `class c5b { public foo() { } } +namespace c5b { export var y = 2; } // should be ok +/*3*/`, + }, + expectedResult: map[string]*testCaseResult{ + "3": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "c5b", + Kind: classKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, }, - } - return &item - })...), + }, + }, + isIncludes: true, }, }, }, @@ -737,12 +787,12 @@ x./**/;`, for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - runTest(t, testCase.files, testCase.expected) + runTest(t, testCase.files, testCase.expectedResult) }) } } -func runTest(t *testing.T, files map[string]string, expected map[string]*lsproto.CompletionList) { +func runTest(t *testing.T, files map[string]string, expected map[string]*testCaseResult) { parsedFiles := make(map[string]string) var markerPositions map[string]*lstestutil.Marker for fileName, content := range files { @@ -784,8 +834,26 @@ func runTest(t *testing.T, files map[string]string, expected map[string]*lsproto context, capabilities, preferences) - assert.DeepEqual(t, completionList, expectedResult) + if expectedResult.isIncludes { + assertIncludesItem(t, completionList, expectedResult.list) + } else { + assert.DeepEqual(t, completionList, expectedResult.list) + } + } +} + +func assertIncludesItem(t *testing.T, actual *lsproto.CompletionList, expected *lsproto.CompletionList) bool { + assert.DeepEqual(t, actual, expected, cmpopts.IgnoreFields(lsproto.CompletionList{}, "Items")) + for _, item := range expected.Items { + index := slices.IndexFunc(actual.Items, func(actualItem *lsproto.CompletionItem) bool { + return actualItem.Label == item.Label + }) + if index == -1 { + t.Fatalf("Label %s not found in actual items. Actual items: %v", item.Label, actual.Items) + } + assert.DeepEqual(t, actual.Items[index], item) } + return false } func createLanguageService(fileName string, files map[string]string) *ls.LanguageService { diff --git a/internal/ls/symbol_display.go b/internal/ls/symbol_display.go index 777eea8614..b800044c90 100644 --- a/internal/ls/symbol_display.go +++ b/internal/ls/symbol_display.go @@ -288,15 +288,18 @@ func isLocalVariableOrFunction(symbol *ast.Symbol) bool { } // If the parent is not source file or module block, it is a local variable. - for parent := decl.Parent; !ast.IsFunctionBlock(parent); parent = parent.Parent { + parent := decl.Parent + for ; !ast.IsFunctionBlock(parent); parent = parent.Parent { // Reached source file or module block if parent.Kind == ast.KindSourceFile || parent.Kind == ast.KindModuleBlock { - continue + break } } - // Parent is in function block. - return true + if ast.IsFunctionBlock(parent) { + // Parent is in function block. + return true + } } return false } From d55312a5a473ae3d52f5ab6cb0e472e4aa36542a Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Fri, 9 May 2025 08:39:00 -0700 Subject: [PATCH 07/16] more fixes and tests --- internal/ls/completions.go | 26 +- internal/ls/completions_test.go | 478 +++++++++++++++++++++++++++++++- internal/scanner/scanner.go | 2 + 3 files changed, 481 insertions(+), 25 deletions(-) diff --git a/internal/ls/completions.go b/internal/ls/completions.go index e613b4cc12..992ce7f457 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -51,7 +51,7 @@ type completionDataData struct { previousToken *ast.Node contextToken *ast.Node jsxInitializer jsxInitializer - insideJsDocTagTypeExpression bool + insideJSDocTagTypeExpression bool isTypeOnlyLocation bool // In JSX tag name and attribute names, identifiers like "my-tag" or "aria-name" is valid identifier. isJsxIdentifierExpected bool @@ -321,7 +321,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position insideComment := isInComment(file, position, currentToken) - insideJsDocTagTypeExpression := false + insideJSDocTagTypeExpression := false insideJsDocImportTag := false isInSnippetScope := false if insideComment != nil { @@ -330,7 +330,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position // The decision to provide completion depends on the contextToken, which is determined through the previousToken. // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file - isJSOnlyLocation := !insideJsDocTagTypeExpression && !insideJsDocImportTag && ast.IsSourceFileJS(file) + isJSOnlyLocation := !insideJSDocTagTypeExpression && !insideJsDocImportTag && ast.IsSourceFileJS(file) previousToken, contextToken := getRelevantTokens(position, file) // Find the node where completion is requested on. @@ -470,7 +470,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position symbolToSortTextMap := map[ast.SymbolId]sortText{} // var importSpecifierResolver any // !!! import var seenPropertySymbols core.Set[ast.SymbolId] - isTypeOnlyLocation := insideJsDocTagTypeExpression || insideJsDocImportTag || + isTypeOnlyLocation := insideJSDocTagTypeExpression || insideJsDocImportTag || importStatementCompletion != nil && ast.IsTypeOnlyImportOrExportDeclaration(location.Parent) || !isContextTokenValueLocation(contextToken) && (isPossiblyTypeArgumentPosition(contextToken, file, typeChecker) || @@ -672,7 +672,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position } else if isRhsOfImportDeclaration { // Any kind is allowed when dotting off namespace in internal import equals declaration isValidAccess = isValidTypeAccess(exportedSymbol) || isValidValueAccess(exportedSymbol) - } else if isTypeLocation || insideJsDocTagTypeExpression { + } else if isTypeLocation || insideJSDocTagTypeExpression { isValidAccess = isValidTypeAccess(exportedSymbol) } else { isValidAccess = isValidValueAccess(exportedSymbol) @@ -683,7 +683,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position } // If the module is merged with a value, we must get the type of the class and add its properties (for inherited static methods). - if !isTypeLocation && !insideJsDocTagTypeExpression && + if !isTypeLocation && !insideJSDocTagTypeExpression && core.Some( symbol.Declarations, func(decl *ast.Declaration) bool { @@ -1013,7 +1013,11 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position return globalsSearchContinue } - existing := core.NewSetFromItems(core.Map(importAttributes.Elements(), (*ast.Node).Text)...) + var elements []*ast.Node + if importAttributes.AsImportAttributes().Attributes != nil { + elements = importAttributes.AsImportAttributes().Attributes.Nodes + } + existing := core.NewSetFromItems(core.Map(elements, (*ast.Node).Text)...) uniques := core.Filter( typeChecker.GetApparentProperties(typeChecker.GetTypeAtLocation(importAttributes)), func(symbol *ast.Symbol) bool { @@ -1407,7 +1411,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position previousToken: previousToken, contextToken: contextToken, jsxInitializer: jsxInitializer, - insideJsDocTagTypeExpression: insideJsDocTagTypeExpression, + insideJSDocTagTypeExpression: insideJSDocTagTypeExpression, isTypeOnlyLocation: isTypeOnlyLocation, isJsxIdentifierExpected: isJsxIdentifierExpected, isRightOfOpenTag: isRightOfOpenTag, @@ -1486,7 +1490,7 @@ func (l *LanguageService) completionInfoFromData( if data.keywordFilters != KeywordCompletionFiltersNone { keywordCompletions := getKeywordCompletions( data.keywordFilters, - !data.insideJsDocTagTypeExpression && ast.IsSourceFileJS(file)) + !data.insideJSDocTagTypeExpression && ast.IsSourceFileJS(file)) for _, keywordEntry := range keywordCompletions { if data.isTypeOnlyLocation && isTypeKeyword(scanner.StringToToken(keywordEntry.Label)) || !data.isTypeOnlyLocation && isContextualKeywordInAutoImportableExpressionSpace(keywordEntry.Label) || @@ -2050,7 +2054,7 @@ func getWordRange(sourceFile *ast.SourceFile, position int) (wordRange *core.Tex text := sourceFile.Text()[:position] totalSize := 0 var firstRune rune - for r, size := utf8.DecodeLastRuneInString(text); size != 0; r, size = utf8.DecodeLastRuneInString(text[:len(text)-size]) { + for r, size := utf8.DecodeLastRuneInString(text); size != 0; r, size = utf8.DecodeLastRuneInString(text[:len(text)-totalSize]) { if wordSeparators.Has(r) || unicode.IsSpace(r) { break } @@ -3578,7 +3582,7 @@ func filterObjectMembersList( typeChecker *checker.Checker, ) (filteredMembers []*ast.Symbol, spreadMemberNames *core.Set[string]) { if len(existingMembers) == 0 { - return contextualMemberSymbols, nil + return contextualMemberSymbols, &core.Set[string]{} } membersDeclaredBySpreadAssignment := core.Set[string]{} diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 9588fe3d13..a0820a0fd9 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -20,6 +20,7 @@ type testCase struct { name string files map[string]string expectedResult map[string]*testCaseResult + mainFileName string } type testCaseResult struct { @@ -27,7 +28,7 @@ type testCaseResult struct { isIncludes bool } -const mainFileName = "/index.ts" +const defaultMainFileName = "/index.ts" func TestCompletions(t *testing.T) { t.Parallel() @@ -44,11 +45,13 @@ func TestCompletions(t *testing.T) { sortTextLocationPriority := ptrTo(string(ls.SortTextLocationPriority)) sortTextLocalDeclarationPriority := ptrTo(string(ls.SortTextLocalDeclarationPriority)) sortTextDeprecatedLocationPriority := ptrTo(string(ls.DeprecateSortText(ls.SortTextLocationPriority))) + sortTextGlobalsOrKeywords := ptrTo(string(ls.SortTextGlobalsOrKeywords)) fieldKind := ptrTo(lsproto.CompletionItemKindField) methodKind := ptrTo(lsproto.CompletionItemKindMethod) functionKind := ptrTo(lsproto.CompletionItemKindFunction) variableKind := ptrTo(lsproto.CompletionItemKindVariable) classKind := ptrTo(lsproto.CompletionItemKindClass) + keywordKind := ptrTo(lsproto.CompletionItemKindKeyword) stringMembers := []*lsproto.CompletionItem{ {Label: "charAt", Kind: methodKind, SortText: sortTextLocationPriority, InsertTextFormat: insertTextFormatPlainText}, @@ -103,7 +106,7 @@ func TestCompletions(t *testing.T) { { name: "basicInterfaceMembers", files: map[string]string{ - mainFileName: `export {}; + defaultMainFileName: `export {}; interface Point { x: number; y: number; @@ -167,7 +170,7 @@ p./*a*/`, name: "basicInterfaceMembersOptional", files: map[string]string{ "/tsconfig.json": `{ "compilerOptions": { "strict": true } }`, - mainFileName: `export {}; + defaultMainFileName: `export {}; interface Point { x: number; y: number; @@ -223,7 +226,7 @@ p./*a*/`, { name: "objectLiteralType", files: map[string]string{ - mainFileName: `export {}; + defaultMainFileName: `export {}; let x = { foo: 123 }; x./*a*/`, }, @@ -261,7 +264,7 @@ x./*a*/`, { name: "basicClassMembers", files: map[string]string{ - mainFileName: ` + defaultMainFileName: ` class n { constructor (public x: number, public y: number, private z: string) { } } @@ -321,7 +324,7 @@ var t = new n(0, 1, '');t./*a*/`, { name: "cloduleAsBaseClass", files: map[string]string{ - mainFileName: ` + defaultMainFileName: ` class A { constructor(x: number) { } foo() { } @@ -597,7 +600,7 @@ D./*a*/`, { name: "lambdaThisMembers", files: map[string]string{ - mainFileName: `class Foo { + defaultMainFileName: `class Foo { a: number; b() { var x = () => { @@ -660,7 +663,7 @@ D./*a*/`, { name: "memberCompletionInForEach1", files: map[string]string{ - mainFileName: `var x: string[] = []; + defaultMainFileName: `var x: string[] = []; x.forEach(function (y) { y./*1*/`, }, expectedResult: map[string]*testCaseResult{ @@ -693,7 +696,7 @@ x.forEach(function (y) { y./*1*/`, { name: "completionsTuple", files: map[string]string{ - mainFileName: `declare const x: [number, number]; + defaultMainFileName: `declare const x: [number, number]; x./**/;`, }, expectedResult: map[string]*testCaseResult{ @@ -761,7 +764,7 @@ x./**/;`, { name: "augmentedTypesClass3Fourslash", files: map[string]string{ - mainFileName: `class c5b { public foo() { } } + defaultMainFileName: `class c5b { public foo() { } } namespace c5b { export var y = 2; } // should be ok /*3*/`, }, @@ -783,23 +786,470 @@ namespace c5b { export var y = 2; } // should be ok }, }, }, + { + name: "objectLiteralBindingInParameter", + files: map[string]string{ + defaultMainFileName: `interface I { x1: number; x2: string } +function f(cb: (ev: I) => any) { } +f(({/*1*/}) => 0); + +[null].reduce(({/*2*/}, b) => b); + +interface Foo { + m(x: { x1: number, x2: number }): void; + prop: I; +} +let x: Foo = { + m({ /*3*/ }) { + }, + get prop(): I { return undefined; }, + set prop({ /*4*/ }) { + } +};`, + }, + expectedResult: map[string]*testCaseResult{ + "1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x1", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "x2", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + }, + }, + }, + "2": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x1", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "x2", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + }, + }, + }, + "3": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x1", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "x2", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + }, + }, + }, + }, + }, + { + name: "completionListInTypeLiteralInTypeParameter3", + files: map[string]string{ + defaultMainFileName: `interface Foo { + one: string; + two: number; +} + +interface Bar { + foo: T; +} + +var foobar: Bar<{ one: string, /**/`, + }, + expectedResult: map[string]*testCaseResult{ + "": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: &lsproto.CompletionItemDefaults{ + CommitCharacters: &[]string{}, + }, + Items: []*lsproto.CompletionItem{ + { + Label: "two", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + }, + }, + }, + }, + }, + { + name: "completionListInImportClause04", + files: map[string]string{ + defaultMainFileName: `import {/*1*/} from './foo';`, + "/foo.d.ts": `declare class Foo { + static prop1(x: number): number; + static prop1(x: string): string; + static prop2(x: boolean): boolean; +} +export = Foo;`, + }, + expectedResult: map[string]*testCaseResult{ + "1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "prop1", + Kind: methodKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "prop2", + Kind: methodKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "prototype", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "type", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + }, + }, + }, + }, + }, + { + name: "completionListForImportAttributes", + files: map[string]string{ + defaultMainFileName: `declare global { + interface ImportAttributes { + type: "json", + "resolution-mode": "import" + } +} +const str = "hello"; + +import * as t1 from "./a" with { /*1*/ }; +import * as t3 from "./a" with { type: "json", /*3*/ }; +import * as t4 from "./a" with { type: /*4*/ };`, + "/a.ts": `export default {};`, + "/tsconfig.json": `{ "compilerOptions": { "module": "esnext", "target": "esnext" } }`, + }, + expectedResult: map[string]*testCaseResult{ + "1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "resolution-mode", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "type", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + }, + }, + }, + }, + }, + { + name: "completionsInExport_invalid", + files: map[string]string{ + defaultMainFileName: `function topLevel() {} +if (!!true) { + const blockScoped = 0; + export { /**/ }; +}`, + }, + expectedResult: map[string]*testCaseResult{ + "": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "topLevel", + Kind: functionKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + }, + { + Label: "type", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + }, + }, + }, + }, + }, + { + name: "completionListAtIdentifierDefinitionLocations_parameters", + files: map[string]string{ + defaultMainFileName: `var aa = 1; +class bar5{ constructor(public /*constructorParameter1*/`, + }, + expectedResult: map[string]*testCaseResult{ + "constructorParameter1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: &lsproto.CompletionItemDefaults{ + CommitCharacters: &[]string{}, + }, + Items: []*lsproto.CompletionItem{ + { + Label: "override", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "private", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "protected", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "public", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "readonly", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + }, + }, + }, + }, + }, + { + name: "completionEntryForClassMembers_StaticWhenBaseTypeIsNotResolved", + files: map[string]string{ + defaultMainFileName: `import React from 'react' +class Slider extends React.Component { + static defau/**/ltProps = { + onMouseDown: () => { }, + onMouseUp: () => { }, + unit: 'px', + } + handleChange = () => 10; +}`, + "/node_modules/@types/react/index.d.ts": `export = React; +export as namespace React; +declare namespace React { + function createElement(): any; + interface Component

{ } + class Component { + static contextType?: any; + context: any; + constructor(props: Readonly

); + setState( + state: ((prevState: Readonly, props: Readonly

) => (Pick | S | null)) | (Pick | S | null), + callback?: () => void + ): void; + } +}`, + }, + expectedResult: map[string]*testCaseResult{ + "": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: &lsproto.CompletionItemDefaults{ + CommitCharacters: &[]string{}, + }, + Items: []*lsproto.CompletionItem{ + { + Label: "contextType?", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo("contextType"), + InsertText: ptrTo("contextType"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "contextType", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 2, Character: 11}, + End: lsproto.Position{Line: 2, Character: 16}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 2, Character: 11}, + End: lsproto.Position{Line: 2, Character: 23}, + }, + }, + }, + }, + { + Label: "abstract", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "accessor", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "async", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "constructor", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "declare", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "get", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "override", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "private", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "protected", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "public", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "readonly", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "set", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + { + Label: "static", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + }, + }, + }, + }, + }, + { + name: "completionsInJsxTag", + mainFileName: "/index.tsx", + files: map[string]string{ + "/index.tsx": `declare namespace JSX { + interface Element {} + interface IntrinsicElements { + div: { + /** Doc */ + foo: string + /** Label docs */ + "aria-label": string + } + } +} +class Foo { + render() { +

; +
+ } +}`, + "/tsconfig.json": `{ "compilerOptions": { "jsx": "preserve" } }`, + }, + expectedResult: map[string]*testCaseResult{ + "1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{}, + }, + }, + "2": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{}, + }, + }, + }, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - runTest(t, testCase.files, testCase.expectedResult) + runTest(t, testCase.files, testCase.expectedResult, testCase.mainFileName) }) } } -func runTest(t *testing.T, files map[string]string, expected map[string]*testCaseResult) { +func runTest(t *testing.T, files map[string]string, expected map[string]*testCaseResult, mainFileName string) { + if mainFileName == "" { + mainFileName = defaultMainFileName + } parsedFiles := make(map[string]string) var markerPositions map[string]*lstestutil.Marker for fileName, content := range files { if fileName == mainFileName { testData := lstestutil.ParseTestData("", content, fileName) markerPositions = testData.MarkerPositions - parsedFiles[fileName] = testData.Files[0].Content // !!! Assumes no usage of @filename + parsedFiles[fileName] = testData.Files[0].Content // !!! Assumes no usage of @filename, markers only on main file } else { parsedFiles[fileName] = content } @@ -829,7 +1279,7 @@ func runTest(t *testing.T, files map[string]string, expected map[string]*testCas t.Fatalf("No marker found for '%s'", markerName) } completionList := languageService.ProvideCompletion( - "/index.ts", + mainFileName, marker.Position, context, capabilities, diff --git a/internal/scanner/scanner.go b/internal/scanner/scanner.go index cc546e7418..44c1e065fd 100644 --- a/internal/scanner/scanner.go +++ b/internal/scanner/scanner.go @@ -3,6 +3,7 @@ package scanner import ( "fmt" "iter" + "maps" "strconv" "strings" "unicode" @@ -2020,6 +2021,7 @@ func init() { for text, key := range textToToken { tokenToText[key] = text } + maps.Copy(textToToken, textToKeyword) } func TokenToString(token ast.Kind) string { From ac2f853d86549d874c863ce3895f20c1b4f9ab26 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 30 Apr 2025 09:46:39 -0700 Subject: [PATCH 08/16] Port more of member completions + tests (#833) --- internal/ls/completions_test.go | 490 ++++++++++++++++++++++++++++++++ 1 file changed, 490 insertions(+) diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index a0820a0fd9..548918f06e 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1230,6 +1230,496 @@ class Foo { }, }, }, + { + name: "basicClassMembers", + files: map[string]string{ + mainFileName: ` +class n { + constructor (public x: number, public y: number, private z: string) { } +} +var t = new n(0, 1, '');t./*a*/`, + }, + expected: map[string]*lsproto.CompletionList{ + "a": { + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + }, + }, + }, + { + Label: "y", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".y"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "y", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "cloduleAsBaseClass", + files: map[string]string{ + mainFileName: ` +class A { + constructor(x: number) { } + foo() { } + static bar() { } +} + +module A { + export var x = 1; + export function baz() { } +} + +class D extends A { + constructor() { + super(1); + } + foo2() { } + static bar2() { } +} + +D./*a*/`, + }, + expected: map[string]*lsproto.CompletionList{ + "a": { + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ // !!! `funcionMembersPlus` + { + Label: "bar", + Kind: methodKind, + SortText: sortTextLocalDeclarationPriority, + FilterText: ptrTo(".bar"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bar", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "bar2", + Kind: methodKind, + SortText: sortTextLocalDeclarationPriority, + FilterText: ptrTo(".bar2"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bar2", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "apply", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".apply"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "apply", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "arguments", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".arguments"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "arguments", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "baz", + Kind: functionKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".baz"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "baz", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "bind", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".bind"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bind", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "call", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".call"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "call", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "caller", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".caller"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "caller", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "length", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".length"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "length", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "prototype", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".prototype"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "prototype", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "toString", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".toString"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "toString", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + { + Label: "x", + Kind: variableKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "lambdaThisMembers", + files: map[string]string{ + mainFileName: `class Foo { + a: number; + b() { + var x = () => { + this./**/; + } + } +}`, + }, + expected: map[string]*lsproto.CompletionList{ + "": { + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "a", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".a"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "a", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + }, + }, + }, + { + Label: "b", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".b"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "b", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "memberCompletionInForEach1", + files: map[string]string{ + mainFileName: `var x: string[] = []; +x.forEach(function (y) { y./*1*/`, + }, + expected: map[string]*lsproto.CompletionList{ + "1": { + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: core.Map(stringMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { + item := *basicItem + item.FilterText = ptrTo("." + item.Label) + item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: item.Label, + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 27}, + End: lsproto.Position{Line: 1, Character: 27}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 27}, + End: lsproto.Position{Line: 1, Character: 27}, + }, + }, + } + return &item + }), + }, + }, + }, + { + name: "completionsTuple", + files: map[string]string{ + mainFileName: `declare const x: [number, number]; +x./**/;`, + }, + expected: map[string]*lsproto.CompletionList{ + "": { + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: append([]*lsproto.CompletionItem{ + { + Label: "0", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertText: ptrTo("[0]"), + InsertTextFormat: insertTextFormatPlainText, + FilterText: ptrTo(".[0]"), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "[0]", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 1}, + End: lsproto.Position{Line: 1, Character: 2}, + }, + }, + }, + }, + { + Label: "1", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertText: ptrTo("[1]"), + InsertTextFormat: insertTextFormatPlainText, + FilterText: ptrTo(".[1]"), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "[1]", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 1}, + End: lsproto.Position{Line: 1, Character: 2}, + }, + }, + }, + }, + }, core.Map(arrayMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { + item := *basicItem + item.FilterText = ptrTo("." + item.Label) + item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: item.Label, + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 2}, + End: lsproto.Position{Line: 1, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 2}, + End: lsproto.Position{Line: 1, Character: 2}, + }, + }, + } + return &item + })...), + }, + }, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { From 818d26bf6740705020bfbc0c2215525e0950cb91 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Fri, 9 May 2025 13:34:31 -0700 Subject: [PATCH 09/16] tests, fix scanner usage in findPrecedingToken --- internal/ast/ast.go | 2 +- internal/astnav/tokens.go | 1 + internal/ls/completions_test.go | 64 +++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 79b0d27c64..5e9217dbc3 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -799,7 +799,7 @@ func (n *Node) PropertyList() *NodeList { switch n.Kind { case KindObjectLiteralExpression: return n.AsObjectLiteralExpression().Properties - case KindJsxAttribute: + case KindJsxAttributes: return n.AsJsxAttributes().Properties } panic("Unhandled case in Node.PropertyList: " + n.Kind.String()) diff --git a/internal/astnav/tokens.go b/internal/astnav/tokens.go index 0910afac65..e332874f2c 100644 --- a/internal/astnav/tokens.go +++ b/internal/astnav/tokens.go @@ -480,6 +480,7 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN } startPos = visitedNode.End() scanner.ResetPos(startPos) + scanner.Scan() } // Trailing tokens after last visited node. for startPos < min(endPos, position) { diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 548918f06e..7084bb1035 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -26,6 +26,7 @@ type testCase struct { type testCaseResult struct { list *lsproto.CompletionList isIncludes bool + excludes []string } const defaultMainFileName = "/index.ts" @@ -1215,18 +1216,10 @@ class Foo { }, expectedResult: map[string]*testCaseResult{ "1": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{}, - }, + list: nil, // !!! jsx }, "2": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{}, - }, + list: nil, // !!! jsx }, }, }, @@ -1720,6 +1713,50 @@ x./**/;`, }, }, }, + { + name: "completionsDotDotDotInObjectLiteral1", + files: map[string]string{ + defaultMainFileName: `const foo = { b: 100 }; +const bar: { + a: number; + b: number; +} = { + a: 42, + .../*1*/ +};`, + }, + expectedResult: map[string]*testCaseResult{ + "1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "foo", + Kind: variableKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "foo", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 5}, + End: lsproto.Position{Line: 6, Character: 5}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 6, Character: 5}, + End: lsproto.Position{Line: 6, Character: 5}, + }, + }, + }, + }, + }, + }, + isIncludes: true, + excludes: []string{"b"}, + }, + }, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { @@ -1779,6 +1816,13 @@ func runTest(t *testing.T, files map[string]string, expected map[string]*testCas } else { assert.DeepEqual(t, completionList, expectedResult.list) } + for _, excludedLabel := range expectedResult.excludes { + for _, item := range completionList.Items { + if item.Label == excludedLabel { + t.Fatalf("Label %s should not be included in completion list", excludedLabel) + } + } + } } } From 94476b9cf4fab7ea922d0369d2fa58ca60459e39 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Fri, 9 May 2025 14:40:28 -0700 Subject: [PATCH 10/16] fix relevant tokens order --- internal/ls/completions.go | 4 ++-- internal/ls/completions_test.go | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/internal/ls/completions.go b/internal/ls/completions.go index 992ce7f457..bb1e24e4d6 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -264,7 +264,7 @@ func (l *LanguageService) getCompletionsAtPosition( preferences *UserPreferences, clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionList { - previousToken, _ := getRelevantTokens(position, file) + _, previousToken := getRelevantTokens(position, file) if context.TriggerCharacter != nil && !isInString(file, position, previousToken) && !isValidTrigger(file, *context.TriggerCharacter, previousToken, position) { return nil } @@ -331,7 +331,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position // The decision to provide completion depends on the contextToken, which is determined through the previousToken. // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file isJSOnlyLocation := !insideJSDocTagTypeExpression && !insideJsDocImportTag && ast.IsSourceFileJS(file) - previousToken, contextToken := getRelevantTokens(position, file) + contextToken, previousToken := getRelevantTokens(position, file) // Find the node where completion is requested on. // Also determine whether we are trying to complete with members of that node diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 7084bb1035..a3d42822d3 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1757,6 +1757,43 @@ const bar: { }, }, }, + { + name: "extendsKeywordCompletion2", + files: map[string]string{ + defaultMainFileName: `function f1() {} +function f2() {}`, + }, + expectedResult: map[string]*testCaseResult{ + // "1": { + // list: &lsproto.CompletionList{ + // IsIncomplete: false, + // ItemDefaults: itemDefaults, + // Items: []*lsproto.CompletionItem{ + // { + // Label: "extends", + // Kind: keywordKind, + // SortText: sortTextGlobalsOrKeywords, + // }, + // }, + // }, + // isIncludes: true, + // }, + "2": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "extends", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + }, + }, + isIncludes: true, + }, + }, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { From a101a6e3f40ba9795a4dc61668a51dcf8d7d55e5 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Mon, 12 May 2025 09:11:31 -0700 Subject: [PATCH 11/16] fix test after rebase --- internal/ls/completions_test.go | 721 ++++++++++++++++---------------- 1 file changed, 365 insertions(+), 356 deletions(-) diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index a3d42822d3..5e6bcbdc0d 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -163,7 +163,6 @@ p./*a*/`, }, }, }, - isIncludes: false, }, }, }, @@ -1226,53 +1225,55 @@ class Foo { { name: "basicClassMembers", files: map[string]string{ - mainFileName: ` + defaultMainFileName: ` class n { constructor (public x: number, public y: number, private z: string) { } } var t = new n(0, 1, '');t./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "x", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "x", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, }, }, }, - }, - { - Label: "y", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".y"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "y", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, + { + Label: "y", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".y"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "y", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 3, Character: 26}, + End: lsproto.Position{Line: 3, Character: 26}, + }, }, }, }, @@ -1284,7 +1285,7 @@ var t = new n(0, 1, '');t./*a*/`, { name: "cloduleAsBaseClass", files: map[string]string{ - mainFileName: ` + defaultMainFileName: ` class A { constructor(x: number) { } foo() { } @@ -1306,247 +1307,249 @@ class D extends A { D./*a*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "a": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ // !!! `funcionMembersPlus` - { - Label: "bar", - Kind: methodKind, - SortText: sortTextLocalDeclarationPriority, - FilterText: ptrTo(".bar"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bar", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ // !!! `funcionMembersPlus` + { + Label: "bar", + Kind: methodKind, + SortText: sortTextLocalDeclarationPriority, + FilterText: ptrTo(".bar"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bar", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "bar2", - Kind: methodKind, - SortText: sortTextLocalDeclarationPriority, - FilterText: ptrTo(".bar2"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bar2", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "bar2", + Kind: methodKind, + SortText: sortTextLocalDeclarationPriority, + FilterText: ptrTo(".bar2"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bar2", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "apply", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".apply"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "apply", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "apply", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".apply"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "apply", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "arguments", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".arguments"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "arguments", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "arguments", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".arguments"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "arguments", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "baz", - Kind: functionKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".baz"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "baz", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "baz", + Kind: functionKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".baz"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "baz", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "bind", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".bind"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bind", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "bind", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".bind"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "bind", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "call", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".call"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "call", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "call", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".call"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "call", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "caller", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".caller"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "caller", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "caller", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".caller"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "caller", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "length", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".length"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "length", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "length", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".length"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "length", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "prototype", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".prototype"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "prototype", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "prototype", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".prototype"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "prototype", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "toString", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".toString"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "toString", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "toString", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".toString"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "toString", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, - }, - { - Label: "x", - Kind: variableKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, + { + Label: "x", + Kind: variableKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".x"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "x", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 19, Character: 2}, + End: lsproto.Position{Line: 19, Character: 2}, + }, }, }, }, @@ -1558,7 +1561,7 @@ D./*a*/`, { name: "lambdaThisMembers", files: map[string]string{ - mainFileName: `class Foo { + defaultMainFileName: `class Foo { a: number; b() { var x = () => { @@ -1567,47 +1570,49 @@ D./*a*/`, } }`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "a", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".a"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "a", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "a", + Kind: fieldKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".a"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "a", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, }, }, }, - }, - { - Label: "b", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".b"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "b", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, + { + Label: "b", + Kind: methodKind, + SortText: sortTextLocationPriority, + FilterText: ptrTo(".b"), + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "b", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 4, Character: 17}, + End: lsproto.Position{Line: 4, Character: 17}, + }, }, }, }, @@ -1619,97 +1624,101 @@ D./*a*/`, { name: "memberCompletionInForEach1", files: map[string]string{ - mainFileName: `var x: string[] = []; + defaultMainFileName: `var x: string[] = []; x.forEach(function (y) { y./*1*/`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "1": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: core.Map(stringMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { - item := *basicItem - item.FilterText = ptrTo("." + item.Label) - item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: item.Label, - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 27}, - End: lsproto.Position{Line: 1, Character: 27}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 27}, - End: lsproto.Position{Line: 1, Character: 27}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: core.Map(stringMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { + item := *basicItem + item.FilterText = ptrTo("." + item.Label) + item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: item.Label, + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 27}, + End: lsproto.Position{Line: 1, Character: 27}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 27}, + End: lsproto.Position{Line: 1, Character: 27}, + }, }, - }, - } - return &item - }), + } + return &item + }), + }, }, }, }, { name: "completionsTuple", files: map[string]string{ - mainFileName: `declare const x: [number, number]; + defaultMainFileName: `declare const x: [number, number]; x./**/;`, }, - expected: map[string]*lsproto.CompletionList{ + expectedResult: map[string]*testCaseResult{ "": { - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: append([]*lsproto.CompletionItem{ - { - Label: "0", - Kind: fieldKind, - SortText: sortTextLocationPriority, - InsertText: ptrTo("[0]"), - InsertTextFormat: insertTextFormatPlainText, - FilterText: ptrTo(".[0]"), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "[0]", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 1}, - End: lsproto.Position{Line: 1, Character: 2}, + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: append([]*lsproto.CompletionItem{ + { + Label: "0", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertText: ptrTo("[0]"), + InsertTextFormat: insertTextFormatPlainText, + FilterText: ptrTo(".[0]"), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "[0]", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 1}, + End: lsproto.Position{Line: 1, Character: 2}, + }, }, }, }, - }, - { - Label: "1", - Kind: fieldKind, - SortText: sortTextLocationPriority, - InsertText: ptrTo("[1]"), - InsertTextFormat: insertTextFormatPlainText, - FilterText: ptrTo(".[1]"), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "[1]", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 1}, - End: lsproto.Position{Line: 1, Character: 2}, + { + Label: "1", + Kind: fieldKind, + SortText: sortTextLocationPriority, + InsertText: ptrTo("[1]"), + InsertTextFormat: insertTextFormatPlainText, + FilterText: ptrTo(".[1]"), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{ + NewText: "[1]", + Range: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 1}, + End: lsproto.Position{Line: 1, Character: 2}, + }, }, }, }, - }, - }, core.Map(arrayMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { - item := *basicItem - item.FilterText = ptrTo("." + item.Label) - item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: item.Label, - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 2}, - End: lsproto.Position{Line: 1, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 2}, - End: lsproto.Position{Line: 1, Character: 2}, + }, core.Map(arrayMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { + item := *basicItem + item.FilterText = ptrTo("." + item.Label) + item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: item.Label, + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 2}, + End: lsproto.Position{Line: 1, Character: 2}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 1, Character: 2}, + End: lsproto.Position{Line: 1, Character: 2}, + }, }, - }, - } - return &item - })...), + } + return &item + })...), + }, }, }, }, From 97503241c5d09ad719039a12d73db52ee467cc86 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Mon, 12 May 2025 09:29:22 -0700 Subject: [PATCH 12/16] tiny fixes --- internal/ls/completions.go | 5 ++--- internal/ls/completions_test.go | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/internal/ls/completions.go b/internal/ls/completions.go index bb1e24e4d6..f6918fa99c 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -2133,7 +2133,7 @@ func getFilterText( func getDotAccessorContext(file *ast.SourceFile, position int) (acessorRange *core.TextRange, accessorText string) { text := file.Text()[:position] totalSize := 0 - for r, size := utf8.DecodeLastRuneInString(text); size != 0; r, size = utf8.DecodeLastRuneInString(text[:len(text)-size]) { + for r, size := utf8.DecodeLastRuneInString(text); size != 0; r, size = utf8.DecodeLastRuneInString(text[:len(text)-totalSize]) { if !unicode.IsSpace(r) { break } @@ -3885,8 +3885,7 @@ func tryGetContainingJsxElement(contextToken *ast.Node, file *ast.SourceFile) *a // Filters out completion suggestions from 'symbols' according to existing JSX attributes. // @returns Symbols to be suggested in a JSX element, barring those whose attributes -// -// do not occur at the current position and have not otherwise been typed. +// do not occur at the current position and have not otherwise been typed. func filterJsxAttributes( symbols []*ast.Symbol, attributes []*ast.JsxAttributeLike, diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 5e6bcbdc0d..7fb7e312a6 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1773,20 +1773,20 @@ const bar: { function f2() {}`, }, expectedResult: map[string]*testCaseResult{ - // "1": { - // list: &lsproto.CompletionList{ - // IsIncomplete: false, - // ItemDefaults: itemDefaults, - // Items: []*lsproto.CompletionItem{ - // { - // Label: "extends", - // Kind: keywordKind, - // SortText: sortTextGlobalsOrKeywords, - // }, - // }, - // }, - // isIncludes: true, - // }, + "1": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "extends", + Kind: keywordKind, + SortText: sortTextGlobalsOrKeywords, + }, + }, + }, + isIncludes: true, + }, "2": { list: &lsproto.CompletionList{ IsIncomplete: false, From caac7787e5e236dca7791e8d8ae8980845b6699d Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Mon, 12 May 2025 13:11:18 -0700 Subject: [PATCH 13/16] remove repeated tests --- internal/ls/completions_test.go | 500 -------------------------------- 1 file changed, 500 deletions(-) diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 7fb7e312a6..0d387bad49 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1222,506 +1222,6 @@ class Foo { }, }, }, - { - name: "basicClassMembers", - files: map[string]string{ - defaultMainFileName: ` -class n { - constructor (public x: number, public y: number, private z: string) { } -} -var t = new n(0, 1, '');t./*a*/`, - }, - expectedResult: map[string]*testCaseResult{ - "a": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "x", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - }, - }, - }, - { - Label: "y", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".y"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "y", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 3, Character: 26}, - End: lsproto.Position{Line: 3, Character: 26}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "cloduleAsBaseClass", - files: map[string]string{ - defaultMainFileName: ` -class A { - constructor(x: number) { } - foo() { } - static bar() { } -} - -module A { - export var x = 1; - export function baz() { } -} - -class D extends A { - constructor() { - super(1); - } - foo2() { } - static bar2() { } -} - -D./*a*/`, - }, - expectedResult: map[string]*testCaseResult{ - "a": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ // !!! `funcionMembersPlus` - { - Label: "bar", - Kind: methodKind, - SortText: sortTextLocalDeclarationPriority, - FilterText: ptrTo(".bar"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bar", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "bar2", - Kind: methodKind, - SortText: sortTextLocalDeclarationPriority, - FilterText: ptrTo(".bar2"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bar2", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "apply", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".apply"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "apply", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "arguments", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".arguments"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "arguments", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "baz", - Kind: functionKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".baz"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "baz", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "bind", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".bind"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "bind", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "call", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".call"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "call", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "caller", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".caller"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "caller", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "length", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".length"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "length", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "prototype", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".prototype"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "prototype", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "toString", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".toString"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "toString", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - { - Label: "x", - Kind: variableKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".x"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "x", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 19, Character: 2}, - End: lsproto.Position{Line: 19, Character: 2}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "lambdaThisMembers", - files: map[string]string{ - defaultMainFileName: `class Foo { - a: number; - b() { - var x = () => { - this./**/; - } - } -}`, - }, - expectedResult: map[string]*testCaseResult{ - "": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: []*lsproto.CompletionItem{ - { - Label: "a", - Kind: fieldKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".a"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "a", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - }, - }, - }, - { - Label: "b", - Kind: methodKind, - SortText: sortTextLocationPriority, - FilterText: ptrTo(".b"), - InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: "b", - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 4, Character: 17}, - End: lsproto.Position{Line: 4, Character: 17}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "memberCompletionInForEach1", - files: map[string]string{ - defaultMainFileName: `var x: string[] = []; -x.forEach(function (y) { y./*1*/`, - }, - expectedResult: map[string]*testCaseResult{ - "1": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: core.Map(stringMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { - item := *basicItem - item.FilterText = ptrTo("." + item.Label) - item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: item.Label, - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 27}, - End: lsproto.Position{Line: 1, Character: 27}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 27}, - End: lsproto.Position{Line: 1, Character: 27}, - }, - }, - } - return &item - }), - }, - }, - }, - }, - { - name: "completionsTuple", - files: map[string]string{ - defaultMainFileName: `declare const x: [number, number]; -x./**/;`, - }, - expectedResult: map[string]*testCaseResult{ - "": { - list: &lsproto.CompletionList{ - IsIncomplete: false, - ItemDefaults: itemDefaults, - Items: append([]*lsproto.CompletionItem{ - { - Label: "0", - Kind: fieldKind, - SortText: sortTextLocationPriority, - InsertText: ptrTo("[0]"), - InsertTextFormat: insertTextFormatPlainText, - FilterText: ptrTo(".[0]"), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "[0]", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 1}, - End: lsproto.Position{Line: 1, Character: 2}, - }, - }, - }, - }, - { - Label: "1", - Kind: fieldKind, - SortText: sortTextLocationPriority, - InsertText: ptrTo("[1]"), - InsertTextFormat: insertTextFormatPlainText, - FilterText: ptrTo(".[1]"), - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ - TextEdit: &lsproto.TextEdit{ - NewText: "[1]", - Range: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 1}, - End: lsproto.Position{Line: 1, Character: 2}, - }, - }, - }, - }, - }, core.Map(arrayMembers, func(basicItem *lsproto.CompletionItem) *lsproto.CompletionItem { - item := *basicItem - item.FilterText = ptrTo("." + item.Label) - item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ - InsertReplaceEdit: &lsproto.InsertReplaceEdit{ - NewText: item.Label, - Insert: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 2}, - End: lsproto.Position{Line: 1, Character: 2}, - }, - Replace: lsproto.Range{ - Start: lsproto.Position{Line: 1, Character: 2}, - End: lsproto.Position{Line: 1, Character: 2}, - }, - }, - } - return &item - })...), - }, - }, - }, - }, { name: "completionsDotDotDotInObjectLiteral1", files: map[string]string{ From 917e79b6ee5097b8f75f8914e0cfb438d7c0442b Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 14 May 2025 09:34:04 -0700 Subject: [PATCH 14/16] some CR feedback, test for lsp position --- internal/ls/completions_test.go | 68 ++++++++++++++++ internal/scanner/scanner.go | 136 ++++++++++++++++---------------- 2 files changed, 136 insertions(+), 68 deletions(-) diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 0d387bad49..5ae876f9a2 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1303,6 +1303,74 @@ function f2() {}`, }, }, }, + { + name: "paths.ts", + files: map[string]string{ + defaultMainFileName: `import { + CharacterCodes, + compareStringsCaseInsensitive, + compareStringsCaseSensitive, + compareValues, + Comparison, + Debug, + endsWith, + equateStringsCaseInsensitive, + equateStringsCaseSensitive, + GetCanonicalFileName, + getDeclarationFileExtension, + getStringComparer, + identity, + lastOrUndefined, + Path, + some, + startsWith, +} from "./_namespaces/ts.js"; + +/** + * Internally, we represent paths as strings with '/' as the directory separator. + * When we make system calls (eg: LanguageServiceHost.getDirectory()), + * we expect the host to correctly handle paths in our specified format. + * + * @internal + */ +export const directorySeparator = "/"; +/** @internal */ +export const altDirectorySeparator = "\\"; +const urlSchemeSeparator = "://"; +const backslashRegExp = /\\/g; + +b/*a*/ + +//// Path Tests + +/** + * Determines whether a charCode corresponds to '/' or '\'. + * + * @internal + */ +export function isAnyDirectorySeparator(charCode: number): boolean { + return charCode === CharacterCodes.slash || charCode === CharacterCodes.backslash; +}`, + }, + expectedResult: map[string]*testCaseResult{ + "a": { + list: &lsproto.CompletionList{ + IsIncomplete: false, + ItemDefaults: itemDefaults, + Items: []*lsproto.CompletionItem{ + { + Label: "CharacterCodes", + Kind: variableKind, + SortText: sortTextLocationPriority, + InsertTextFormat: insertTextFormatPlainText, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{}, + }, + }, + }, + isIncludes: true, + }, + }, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { diff --git a/internal/scanner/scanner.go b/internal/scanner/scanner.go index 44c1e065fd..bf8289c3f1 100644 --- a/internal/scanner/scanner.go +++ b/internal/scanner/scanner.go @@ -118,69 +118,73 @@ var textToKeyword = map[string]ast.Kind{ "of": ast.KindOfKeyword, } -var textToToken = map[string]ast.Kind{ - "{": ast.KindOpenBraceToken, - "}": ast.KindCloseBraceToken, - "(": ast.KindOpenParenToken, - ")": ast.KindCloseParenToken, - "[": ast.KindOpenBracketToken, - "]": ast.KindCloseBracketToken, - ".": ast.KindDotToken, - "...": ast.KindDotDotDotToken, - ";": ast.KindSemicolonToken, - ",": ast.KindCommaToken, - "<": ast.KindLessThanToken, - ">": ast.KindGreaterThanToken, - "<=": ast.KindLessThanEqualsToken, - ">=": ast.KindGreaterThanEqualsToken, - "==": ast.KindEqualsEqualsToken, - "!=": ast.KindExclamationEqualsToken, - "===": ast.KindEqualsEqualsEqualsToken, - "!==": ast.KindExclamationEqualsEqualsToken, - "=>": ast.KindEqualsGreaterThanToken, - "+": ast.KindPlusToken, - "-": ast.KindMinusToken, - "**": ast.KindAsteriskAsteriskToken, - "*": ast.KindAsteriskToken, - "/": ast.KindSlashToken, - "%": ast.KindPercentToken, - "++": ast.KindPlusPlusToken, - "--": ast.KindMinusMinusToken, - "<<": ast.KindLessThanLessThanToken, - ">": ast.KindGreaterThanGreaterThanToken, - ">>>": ast.KindGreaterThanGreaterThanGreaterThanToken, - "&": ast.KindAmpersandToken, - "|": ast.KindBarToken, - "^": ast.KindCaretToken, - "!": ast.KindExclamationToken, - "~": ast.KindTildeToken, - "&&": ast.KindAmpersandAmpersandToken, - "||": ast.KindBarBarToken, - "?": ast.KindQuestionToken, - "??": ast.KindQuestionQuestionToken, - "?.": ast.KindQuestionDotToken, - ":": ast.KindColonToken, - "=": ast.KindEqualsToken, - "+=": ast.KindPlusEqualsToken, - "-=": ast.KindMinusEqualsToken, - "*=": ast.KindAsteriskEqualsToken, - "**=": ast.KindAsteriskAsteriskEqualsToken, - "/=": ast.KindSlashEqualsToken, - "%=": ast.KindPercentEqualsToken, - "<<=": ast.KindLessThanLessThanEqualsToken, - ">>=": ast.KindGreaterThanGreaterThanEqualsToken, - ">>>=": ast.KindGreaterThanGreaterThanGreaterThanEqualsToken, - "&=": ast.KindAmpersandEqualsToken, - "|=": ast.KindBarEqualsToken, - "^=": ast.KindCaretEqualsToken, - "||=": ast.KindBarBarEqualsToken, - "&&=": ast.KindAmpersandAmpersandEqualsToken, - "??=": ast.KindQuestionQuestionEqualsToken, - "@": ast.KindAtToken, - "#": ast.KindHashToken, - "`": ast.KindBacktickToken, -} +var textToToken = func() map[string]ast.Kind { + m := map[string]ast.Kind{ + "{": ast.KindOpenBraceToken, + "}": ast.KindCloseBraceToken, + "(": ast.KindOpenParenToken, + ")": ast.KindCloseParenToken, + "[": ast.KindOpenBracketToken, + "]": ast.KindCloseBracketToken, + ".": ast.KindDotToken, + "...": ast.KindDotDotDotToken, + ";": ast.KindSemicolonToken, + ",": ast.KindCommaToken, + "<": ast.KindLessThanToken, + ">": ast.KindGreaterThanToken, + "<=": ast.KindLessThanEqualsToken, + ">=": ast.KindGreaterThanEqualsToken, + "==": ast.KindEqualsEqualsToken, + "!=": ast.KindExclamationEqualsToken, + "===": ast.KindEqualsEqualsEqualsToken, + "!==": ast.KindExclamationEqualsEqualsToken, + "=>": ast.KindEqualsGreaterThanToken, + "+": ast.KindPlusToken, + "-": ast.KindMinusToken, + "**": ast.KindAsteriskAsteriskToken, + "*": ast.KindAsteriskToken, + "/": ast.KindSlashToken, + "%": ast.KindPercentToken, + "++": ast.KindPlusPlusToken, + "--": ast.KindMinusMinusToken, + "<<": ast.KindLessThanLessThanToken, + ">": ast.KindGreaterThanGreaterThanToken, + ">>>": ast.KindGreaterThanGreaterThanGreaterThanToken, + "&": ast.KindAmpersandToken, + "|": ast.KindBarToken, + "^": ast.KindCaretToken, + "!": ast.KindExclamationToken, + "~": ast.KindTildeToken, + "&&": ast.KindAmpersandAmpersandToken, + "||": ast.KindBarBarToken, + "?": ast.KindQuestionToken, + "??": ast.KindQuestionQuestionToken, + "?.": ast.KindQuestionDotToken, + ":": ast.KindColonToken, + "=": ast.KindEqualsToken, + "+=": ast.KindPlusEqualsToken, + "-=": ast.KindMinusEqualsToken, + "*=": ast.KindAsteriskEqualsToken, + "**=": ast.KindAsteriskAsteriskEqualsToken, + "/=": ast.KindSlashEqualsToken, + "%=": ast.KindPercentEqualsToken, + "<<=": ast.KindLessThanLessThanEqualsToken, + ">>=": ast.KindGreaterThanGreaterThanEqualsToken, + ">>>=": ast.KindGreaterThanGreaterThanGreaterThanEqualsToken, + "&=": ast.KindAmpersandEqualsToken, + "|=": ast.KindBarEqualsToken, + "^=": ast.KindCaretEqualsToken, + "||=": ast.KindBarBarEqualsToken, + "&&=": ast.KindAmpersandAmpersandEqualsToken, + "??=": ast.KindQuestionQuestionEqualsToken, + "@": ast.KindAtToken, + "#": ast.KindHashToken, + "`": ast.KindBacktickToken, + } + maps.Copy(m, textToKeyword) + return m +}() // As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers // IdentifierStart :: @@ -2014,14 +2018,10 @@ func isInUnicodeRanges(cp rune, ranges []rune) bool { var tokenToText map[ast.Kind]string func init() { - tokenToText = make(map[ast.Kind]string, len(textToKeyword)+len(textToToken)) - for text, key := range textToKeyword { - tokenToText[key] = text - } + tokenToText = make(map[ast.Kind]string, len(textToToken)) for text, key := range textToToken { tokenToText[key] = text } - maps.Copy(textToToken, textToKeyword) } func TokenToString(token ast.Kind) string { From 15e402f9ae2c742b6088c49dd45d18c8a4543445 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 14 May 2025 09:43:12 -0700 Subject: [PATCH 15/16] update test --- internal/ls/completions_test.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/ls/completions_test.go b/internal/ls/completions_test.go index 5ae876f9a2..a4dd1c056d 100644 --- a/internal/ls/completions_test.go +++ b/internal/ls/completions_test.go @@ -1363,7 +1363,19 @@ export function isAnyDirectorySeparator(charCode: number): boolean { Kind: variableKind, SortText: sortTextLocationPriority, InsertTextFormat: insertTextFormatPlainText, - TextEdit: &lsproto.TextEditOrInsertReplaceEdit{}, + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + InsertReplaceEdit: &lsproto.InsertReplaceEdit{ + NewText: "CharacterCodes", + Insert: lsproto.Range{ + Start: lsproto.Position{Line: 27, Character: 0}, + End: lsproto.Position{Line: 27, Character: 1}, + }, + Replace: lsproto.Range{ + Start: lsproto.Position{Line: 27, Character: 0}, + End: lsproto.Position{Line: 27, Character: 1}, + }, + }, + }, }, }, }, From d5a2a07d8294e0450a9a160b670d68cf59fd6def Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 14 May 2025 13:30:51 -0700 Subject: [PATCH 16/16] create public wrappers for checker methods --- internal/ast/utilities.go | 58 +++++ internal/checker/checker.go | 414 +++++++++++++++--------------- internal/checker/exports.go | 50 ++++ internal/checker/flow.go | 30 +-- internal/checker/grammarchecks.go | 2 +- internal/checker/inference.go | 22 +- internal/checker/jsx.go | 24 +- internal/checker/relater.go | 40 +-- internal/checker/services.go | 14 +- internal/checker/utilities.go | 62 +---- internal/ls/completions.go | 4 +- 11 files changed, 385 insertions(+), 335 deletions(-) create mode 100644 internal/checker/exports.go diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 8d62f4f26d..36cd8b764c 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -2867,3 +2867,61 @@ func IsJSDocSingleCommentNodeList(parent *Node, nodeList *NodeList) bool { func IsJSDocSingleCommentNode(node *Node) bool { return node.Kind == KindJSDoc && node.AsJSDoc().Comment != nil && len(node.AsJSDoc().Comment.Nodes) == 1 } + +func IsValidTypeOnlyAliasUseSite(useSite *Node) bool { + return useSite.Flags&NodeFlagsAmbient != 0 || + IsPartOfTypeQuery(useSite) || + isIdentifierInNonEmittingHeritageClause(useSite) || + isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) || + !(IsExpressionNode(useSite) || isShorthandPropertyNameUseSite(useSite)) +} + +func isIdentifierInNonEmittingHeritageClause(node *Node) bool { + if !IsIdentifier(node) { + return false + } + parent := node.Parent + for IsPropertyAccessExpression(parent) || IsExpressionWithTypeArguments(parent) { + parent = parent.Parent + } + return IsHeritageClause(parent) && (parent.AsHeritageClause().Token == KindImplementsKeyword || IsInterfaceDeclaration(parent.Parent)) +} + +func isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(node *Node) bool { + for NodeKindIs(node, KindIdentifier, KindPropertyAccessExpression) { + node = node.Parent + } + if node.Kind != KindComputedPropertyName { + return false + } + if HasSyntacticModifier(node.Parent, ModifierFlagsAbstract) { + return true + } + return NodeKindIs(node.Parent.Parent, KindInterfaceDeclaration, KindTypeLiteral) +} + +func isShorthandPropertyNameUseSite(useSite *Node) bool { + return IsIdentifier(useSite) && IsShorthandPropertyAssignment(useSite.Parent) && useSite.Parent.AsShorthandPropertyAssignment().Name() == useSite +} + +func GetPropertyNameForPropertyNameNode(name *Node) string { + switch name.Kind { + case KindIdentifier, KindPrivateIdentifier, KindStringLiteral, KindNoSubstitutionTemplateLiteral, + KindNumericLiteral, KindBigIntLiteral, KindJsxNamespacedName: + return name.Text() + case KindComputedPropertyName: + nameExpression := name.AsComputedPropertyName().Expression + if IsStringOrNumericLiteralLike(nameExpression) { + return nameExpression.Text() + } + if IsSignedNumericLiteral(nameExpression) { + text := nameExpression.AsPrefixUnaryExpression().Operand.Text() + if nameExpression.AsPrefixUnaryExpression().Operator == KindMinusToken { + text = "-" + text + } + return text + } + return InternalSymbolNameMissing + } + panic("Unhandled case in getPropertyNameForPropertyNameNode") +} diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 777eda8474..993804de3d 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -926,7 +926,7 @@ func NewChecker(program Program) *Checker { c.trueType = c.newLiteralType(TypeFlagsBooleanLiteral, true, c.regularTrueType) c.regularTrueType.AsLiteralType().freshType = c.trueType c.trueType.AsLiteralType().freshType = c.trueType - c.booleanType = c.GetUnionType([]*Type{c.regularFalseType, c.regularTrueType}) + c.booleanType = c.getUnionType([]*Type{c.regularFalseType, c.regularTrueType}) c.esSymbolType = c.newIntrinsicType(TypeFlagsESSymbol, "symbol") c.voidType = c.newIntrinsicType(TypeFlagsVoid, "void") c.neverType = c.newIntrinsicType(TypeFlagsNever, "never") @@ -934,11 +934,11 @@ func NewChecker(program Program) *Checker { c.implicitNeverType = c.newIntrinsicType(TypeFlagsNever, "never") c.unreachableNeverType = c.newIntrinsicType(TypeFlagsNever, "never") c.nonPrimitiveType = c.newIntrinsicType(TypeFlagsNonPrimitive, "object") - c.stringOrNumberType = c.GetUnionType([]*Type{c.stringType, c.numberType}) - c.stringNumberSymbolType = c.GetUnionType([]*Type{c.stringType, c.numberType, c.esSymbolType}) - c.numberOrBigIntType = c.GetUnionType([]*Type{c.numberType, c.bigintType}) + c.stringOrNumberType = c.getUnionType([]*Type{c.stringType, c.numberType}) + c.stringNumberSymbolType = c.getUnionType([]*Type{c.stringType, c.numberType, c.esSymbolType}) + c.numberOrBigIntType = c.getUnionType([]*Type{c.numberType, c.bigintType}) c.numericStringType = c.getTemplateLiteralType([]string{"", ""}, []*Type{c.numberType}) // The `${number}` type - c.templateConstraintType = c.GetUnionType([]*Type{c.stringType, c.numberType, c.booleanType, c.bigintType, c.nullType, c.undefinedType}) + c.templateConstraintType = c.getUnionType([]*Type{c.stringType, c.numberType, c.booleanType, c.bigintType, c.nullType, c.undefinedType}) c.uniqueLiteralType = c.newIntrinsicType(TypeFlagsNever, "never") // Special `never` flagged by union reduction to behave as a literal c.uniqueLiteralMapper = newFunctionTypeMapper(c.getUniqueLiteralTypeForTypeParameter) c.reportUnreliableMapper = newFunctionTypeMapper(c.reportUnreliableWorker) @@ -973,7 +973,7 @@ func NewChecker(program Program) *Checker { c.emptyStringType = c.getStringLiteralType("") c.zeroType = c.getNumberLiteralType(0) c.zeroBigIntType = c.getBigIntLiteralType(jsnum.PseudoBigInt{}) - c.typeofType = c.GetUnionType(core.Map(slices.Sorted(maps.Keys(typeofNEFacts)), c.getStringLiteralType)) + c.typeofType = c.getUnionType(core.Map(slices.Sorted(maps.Keys(typeofNEFacts)), c.getStringLiteralType)) c.flowLoopCache = make(map[FlowLoopKey]*Type) c.flowNodeReachable = make(map[*ast.FlowNode]bool) c.flowNodePostSuper = make(map[*ast.FlowNode]bool) @@ -1093,7 +1093,7 @@ func (c *Checker) getGlobalTypeAliasResolver(name string, arity int, reportError // Resolve to the global value symbol by the given name, or nil otherwise func (c *Checker) getGlobalValueSymbolResolver(name string, reportErrors bool) func() *ast.Symbol { return core.Memoize(func() *ast.Symbol { - return c.GetGlobalSymbol(name, ast.SymbolFlagsValue, core.IfElse(reportErrors, diagnostics.Cannot_find_global_value_0, nil)) + return c.getGlobalSymbol(name, ast.SymbolFlagsValue, core.IfElse(reportErrors, diagnostics.Cannot_find_global_value_0, nil)) }) } @@ -1106,7 +1106,7 @@ func (c *Checker) getGlobalTypesResolver(names []string, arity int, reportErrors } func (c *Checker) getGlobalTypeAliasSymbol(name string, arity int, reportErrors bool) *ast.Symbol { - symbol := c.GetGlobalSymbol(name, ast.SymbolFlagsTypeAlias, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) + symbol := c.getGlobalSymbol(name, ast.SymbolFlagsTypeAlias, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) if symbol == nil { return nil } @@ -1123,7 +1123,7 @@ func (c *Checker) getGlobalTypeAliasSymbol(name string, arity int, reportErrors } func (c *Checker) getGlobalType(name string, arity int, reportErrors bool) *Type { - symbol := c.GetGlobalSymbol(name, ast.SymbolFlagsType, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) + symbol := c.getGlobalSymbol(name, ast.SymbolFlagsType, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) if symbol != nil { if symbol.Flags&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface) != 0 { t := c.getDeclaredTypeOfSymbol(symbol) @@ -1153,7 +1153,7 @@ func getGlobalTypeDeclaration(symbol *ast.Symbol) *ast.Declaration { return nil } -func (c *Checker) GetGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { +func (c *Checker) getGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { // Don't track references for global symbols anyway, so value if `isReference` is arbitrary return c.resolveName(nil, name, meaning, diagnostic, false /*isUse*/, false /*excludeGlobals*/) } @@ -1711,7 +1711,7 @@ func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result * c.error(errorLocation, diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, scanner.DeclarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.Name()), scanner.DeclarationNameToString(errorLocation)) } } - if errorLocation != nil && meaning&ast.SymbolFlagsValue != 0 && result.Flags&ast.SymbolFlagsAlias != 0 && result.Flags&ast.SymbolFlagsValue == 0 && !IsValidTypeOnlyAliasUseSite(errorLocation) { + if errorLocation != nil && meaning&ast.SymbolFlagsValue != 0 && result.Flags&ast.SymbolFlagsAlias != 0 && result.Flags&ast.SymbolFlagsValue == 0 && !ast.IsValidTypeOnlyAliasUseSite(errorLocation) { typeOnlyDeclaration := c.getTypeOnlyAliasDeclarationEx(result, ast.SymbolFlagsValue) if typeOnlyDeclaration != nil { message := core.IfElse(ast.NodeKindIs(typeOnlyDeclaration, ast.KindExportSpecifier, ast.KindExportDeclaration, ast.KindNamespaceExport), @@ -2370,7 +2370,7 @@ func (c *Checker) checkJSDocTypeIsInJsFile(node *ast.Node) { message := core.IfElse(postfix, diagnostics.X_0_at_the_end_of_a_type_is_not_valid_TypeScript_syntax_Did_you_mean_to_write_1, diagnostics.X_0_at_the_start_of_a_type_is_not_valid_TypeScript_syntax_Did_you_mean_to_write_1) - t := c.GetTypeFromTypeNode(node.Type()) + t := c.getTypeFromTypeNode(node.Type()) if ast.IsJSDocNullableType(node) && t != c.neverType && t != c.voidType { t = c.getNullableType(t, core.IfElse(postfix, TypeFlagsUndefined, TypeFlagsNullable)) } @@ -2515,7 +2515,7 @@ func (c *Checker) checkSignatureDeclaration(node *ast.Node) { if returnTypeNode != nil { functionFlags := getFunctionFlags(node) if (functionFlags & (FunctionFlagsInvalid | FunctionFlagsGenerator)) == FunctionFlagsGenerator { - returnType := c.GetTypeFromTypeNode(returnTypeNode) + returnType := c.getTypeFromTypeNode(returnTypeNode) if returnType == c.voidType { c.error(returnTypeNode, diagnostics.A_generator_cannot_have_a_void_type_annotation) } else { @@ -2539,7 +2539,7 @@ func (c *Checker) checkSignatureDeclaration(node *ast.Node) { // that in turn supplies a `resolve` function as one of its arguments and results in an // object with a callable `then` signature. func (c *Checker) checkAsyncFunctionReturnType(node *ast.Node, returnTypeNode *ast.Node) { - returnType := c.GetTypeFromTypeNode(returnTypeNode) + returnType := c.getTypeFromTypeNode(returnTypeNode) if c.isErrorType(returnType) { return } @@ -2757,7 +2757,7 @@ func (c *Checker) checkTypeReferenceNode(node *ast.Node) { } func (c *Checker) checkTypeReferenceOrImport(node *ast.Node) { - t := c.GetTypeFromTypeNode(node) + t := c.getTypeFromTypeNode(node) if !c.isErrorType(t) { if len(node.TypeArguments()) != 0 { typeParameters := c.getTypeParametersForTypeReferenceOrImport(node) @@ -2988,8 +2988,8 @@ func (c *Checker) checkTupleType(node *ast.Node) { for _, e := range elements { flags := c.getTupleElementFlags(e) if flags&ElementFlagsVariadic != 0 { - t := c.GetTypeFromTypeNode(e.Type()) - if !c.IsArrayLikeType(t) { + t := c.getTypeFromTypeNode(e.Type()) + if !c.isArrayLikeType(t) { c.error(e, diagnostics.A_rest_element_type_must_be_an_array_type) break } @@ -3015,12 +3015,12 @@ func (c *Checker) checkTupleType(node *ast.Node) { } } c.checkSourceElements(elements) - c.GetTypeFromTypeNode(node) + c.getTypeFromTypeNode(node) } func (c *Checker) checkUnionOrIntersectionType(node *ast.Node) { node.ForEachChild(c.checkSourceElement) - c.GetTypeFromTypeNode(node) + c.getTypeFromTypeNode(node) } func (c *Checker) checkThisType(node *ast.Node) { @@ -3066,10 +3066,10 @@ func (c *Checker) checkInferType(node *ast.Node) { func (c *Checker) checkTemplateLiteralType(node *ast.Node) { for _, span := range node.AsTemplateLiteralTypeNode().TemplateSpans.Nodes { c.checkSourceElement(span.Type()) - t := c.GetTypeFromTypeNode(span.Type()) + t := c.getTypeFromTypeNode(span.Type()) c.checkTypeAssignableTo(t, c.templateConstraintType, span.Type(), nil) } - c.GetTypeFromTypeNode(node) + c.getTypeFromTypeNode(node) } func (c *Checker) checkImportType(node *ast.Node) { @@ -3129,7 +3129,7 @@ func (c *Checker) checkNamedTupleMember(node *ast.Node) { c.grammarErrorOnNode(tupleMember.Type, diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type) } c.checkSourceElement(node.Type()) - c.GetTypeFromTypeNode(node) + c.getTypeFromTypeNode(node) } func (c *Checker) checkIndexedAccessType(node *ast.Node) { @@ -3959,7 +3959,7 @@ func (c *Checker) checkCatchClause(node *ast.Node) { c.checkVariableLikeDeclaration(declaration) typeNode := declaration.Type() if typeNode != nil { - t := c.GetTypeFromTypeNode(typeNode) + t := c.getTypeFromTypeNode(typeNode) if t != nil && t.flags&TypeFlagsAnyOrUnknown == 0 { c.grammarErrorOnFirstToken(typeNode, diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified) } @@ -4071,7 +4071,7 @@ func (c *Checker) checkClassLikeDeclaration(node *ast.Node) { c.error(expr, diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments) } c.checkTypeReferenceNode(typeRefNode) - t := c.getReducedType(c.GetTypeFromTypeNode(typeRefNode)) + t := c.getReducedType(c.getTypeFromTypeNode(typeRefNode)) if !c.isErrorType(t) { if c.isValidBaseType(t) { genericDiag := core.IfElse(t.symbol != nil && t.symbol.Flags&ast.SymbolFlagsClass != 0, @@ -4143,14 +4143,14 @@ func (c *Checker) areTypeParametersIdentical(declarations []*ast.Node, targetPar targetConstraint := c.getConstraintOfTypeParameter(target) // relax check if later interface augmentation has no constraint, it's more broad and is OK to merge with // a more constrained interface (this could be generalized to a full hierarchy check, but that's maybe overkill) - if constraintNode != nil && targetConstraint != nil && !c.isTypeIdenticalTo(c.GetTypeFromTypeNode(constraintNode), targetConstraint) { + if constraintNode != nil && targetConstraint != nil && !c.isTypeIdenticalTo(c.getTypeFromTypeNode(constraintNode), targetConstraint) { return false } // If the type parameter node has a default and it is not identical to the default // for the type parameter at this position, we report an error. defaultNode := source.AsTypeParameter().DefaultType targetDefault := c.getDefaultFromTypeParameter(target) - if defaultNode != nil && targetDefault != nil && !c.isTypeIdenticalTo(c.GetTypeFromTypeNode(defaultNode), targetDefault) { + if defaultNode != nil && targetDefault != nil && !c.isTypeIdenticalTo(c.getTypeFromTypeNode(defaultNode), targetDefault) { return false } } @@ -4236,7 +4236,7 @@ func (c *Checker) checkKindsOfPropertyMemberOverrides(t *Type, baseType *Type) { } var notImplementedInfo map[*ast.Node]MemberInfo basePropertyCheck: - for _, baseProperty := range c.GetPropertiesOfType(baseType) { + for _, baseProperty := range c.getPropertiesOfType(baseType) { base := c.getTargetSymbol(baseProperty) if base.Flags&ast.SymbolFlagsPrototype != 0 { continue @@ -4246,7 +4246,7 @@ basePropertyCheck: continue } derived := c.getTargetSymbol(baseSymbol) - baseDeclarationFlags := GetDeclarationModifierFlagsFromSymbol(base) + baseDeclarationFlags := getDeclarationModifierFlagsFromSymbol(base) // In order to resolve whether the inherited method was overridden in the base class or not, // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated* // type declaration, derived and base resolve to the same symbol even in the case of generic classes. @@ -4285,7 +4285,7 @@ basePropertyCheck: } } else { // derived overrides base. - derivedDeclarationFlags := GetDeclarationModifierFlagsFromSymbol(derived) + derivedDeclarationFlags := getDeclarationModifierFlagsFromSymbol(derived) if baseDeclarationFlags&ast.ModifierFlagsPrivate != 0 || derivedDeclarationFlags&ast.ModifierFlagsPrivate != 0 { // either base or derived property is private - not override, skip it continue @@ -4456,7 +4456,7 @@ func (c *Checker) checkMemberForOverrideModifier(node *ast.Node, staticType *Typ } func (c *Checker) getSuggestedSymbolForNonexistentClassMember(name string, baseType *Type) *ast.Symbol { - return c.getSpellingSuggestionForName(name, c.GetPropertiesOfType(baseType), ast.SymbolFlagsClassMember) + return c.getSpellingSuggestionForName(name, c.getPropertiesOfType(baseType), ast.SymbolFlagsClassMember) } func (c *Checker) checkIndexConstraints(t *Type, symbol *ast.Symbol, isStaticIndex bool) { @@ -4590,7 +4590,7 @@ func (c *Checker) checkTypeForDuplicateIndexSignatures(node *ast.Node) { if ast.IsIndexSignatureDeclaration(declaration) { parameters := declaration.Parameters() if len(parameters) == 1 && parameters[0].Type() != nil { - for _, t := range c.GetTypeFromTypeNode(parameters[0].Type()).Distributed() { + for _, t := range c.getTypeFromTypeNode(parameters[0].Type()).Distributed() { indexSignatureMap[t] = append(indexSignatureMap[t], declaration) } } @@ -4717,7 +4717,7 @@ func (c *Checker) checkInheritedPropertiesAreIdentical(t *Type, typeNode *ast.No } identical := true for _, base := range baseTypes { - properties := c.GetPropertiesOfType(c.getTypeWithThisArgument(base, t.AsInterfaceType().thisType, false)) + properties := c.getPropertiesOfType(c.getTypeWithThisArgument(base, t.AsInterfaceType().thisType, false)) for _, prop := range properties { if existing, ok := seen[prop.Name]; !ok { seen[prop.Name] = InheritanceInfo{prop: prop, containingType: base} @@ -5513,14 +5513,14 @@ func (c *Checker) checkVariableLikeDeclaration(node *ast.Node) { globalAsyncDisposableType := c.getGlobalAsyncDisposableType() globalDisposableType := c.getGlobalDisposableType() if globalAsyncDisposableType != c.emptyObjectType && globalDisposableType != c.emptyObjectType { - optionalDisposableType := c.GetUnionType([]*Type{globalAsyncDisposableType, globalDisposableType, c.nullType, c.undefinedType}) + optionalDisposableType := c.getUnionType([]*Type{globalAsyncDisposableType, globalDisposableType, c.nullType, c.undefinedType}) c.checkTypeAssignableTo(c.widenTypeForVariableLikeDeclaration(initializerType, node, false), optionalDisposableType, initializer, diagnostics.The_initializer_of_an_await_using_declaration_must_be_either_an_object_with_a_Symbol_asyncDispose_or_Symbol_dispose_method_or_be_null_or_undefined) } } else if blockScopeKind == ast.NodeFlagsUsing { globalDisposableType := c.getGlobalDisposableType() if globalDisposableType != c.emptyObjectType { - optionalDisposableType := c.GetUnionType([]*Type{globalDisposableType, c.nullType, c.undefinedType}) + optionalDisposableType := c.getUnionType([]*Type{globalDisposableType, c.nullType, c.undefinedType}) c.checkTypeAssignableTo(c.widenTypeForVariableLikeDeclaration(initializerType, node, false), optionalDisposableType, initializer, diagnostics.The_initializer_of_a_using_declaration_must_be_either_an_object_with_a_Symbol_dispose_method_or_be_null_or_undefined) } @@ -5769,7 +5769,7 @@ func (c *Checker) getIteratedTypeOrElementType(use IterationUse, inputType *Type } } } - if !c.IsArrayLikeType(arrayType) { + if !c.isArrayLikeType(arrayType) { if errorNode != nil { // Which error we report depends on whether we allow strings or if there was a // string constituent. For example, if the input type is number | string, we @@ -5993,7 +5993,7 @@ func (c *Checker) getIterationTypeUnion(iterationTypes []IterationTypes, f func( if len(types) == 0 { return nil } - return c.GetUnionType(types) + return c.getUnionType(types) } func (c *Checker) getAsyncFromSyncIterationTypes(iterationTypes IterationTypes, errorNode *ast.Node) IterationTypes { @@ -6161,7 +6161,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes if methodName != "throw" { var methodParameterType *Type if methodParameterTypes != nil { - methodParameterType = c.GetUnionType(methodParameterTypes) + methodParameterType = c.getUnionType(methodParameterTypes) } else { methodParameterType = c.unknownType } @@ -6194,7 +6194,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes yieldType = iterationTypes.yieldType returnTypes = append(returnTypes, iterationTypes.returnType) } - return IterationTypes{yieldType, c.GetUnionType(returnTypes), nextType} + return IterationTypes{yieldType, c.getUnionType(returnTypes), nextType} } // Gets the *yield* and *return* types of an `IteratorResult`-like type. @@ -6885,7 +6885,7 @@ func (c *Checker) getQuickTypeOfExpression(node *ast.Node) *Type { } return c.getReturnTypeOfSingleNonGenericCallSignature(c.checkNonNullExpression(expr.Expression())) case ast.IsAssertionExpression(expr) && !ast.IsConstTypeReference(expr.Type()): - return c.GetTypeFromTypeNode(expr.Type()) + return c.getTypeFromTypeNode(expr.Type()) case ast.IsLiteralExpression(node) || ast.IsBooleanLiteral(node): return c.checkExpression(node) } @@ -7618,7 +7618,7 @@ func (c *Checker) checkArrayLiteral(node *ast.Node, checkMode CheckMode) *Type { case ast.IsSpreadElement(e): spreadType := c.checkExpressionEx(e.AsSpreadElement().Expression, checkMode) switch { - case c.IsArrayLikeType(spreadType): + case c.isArrayLikeType(spreadType): elementTypes[i] = spreadType elementInfos[i] = TupleElementInfo{flags: ElementFlagsVariadic} case inDestructuringPattern: @@ -7824,7 +7824,7 @@ func (c *Checker) checkIndexedAccessIndexType(t *Type, accessNode *ast.Node) *Ty propertyName := c.getPropertyNameFromIndex(indexType, accessNode) if propertyName != ast.InternalSymbolNameMissing { propertySymbol := c.getConstituentProperty(objectType, propertyName) - if propertySymbol != nil && GetDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsNonPublicAccessibilityModifier != 0 { + if propertySymbol != nil && getDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsNonPublicAccessibilityModifier != 0 { c.error(accessNode, diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, propertyName) return c.errorType } @@ -8380,7 +8380,7 @@ func (c *Checker) resolveInstanceofExpression(node *ast.Node, candidatesOutArray if len(callSignatures) != 0 { return c.resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlagsNone, nil) } - } else if !(c.TypeHasCallOrConstructSignatures(rightType) || c.isTypeSubtypeOf(rightType, c.globalFunctionType)) { + } else if !(c.typeHasCallOrConstructSignatures(rightType) || c.isTypeSubtypeOf(rightType, c.globalFunctionType)) { c.error(right, diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_either_of_type_any_a_class_function_or_other_type_assignable_to_the_Function_interface_type_or_an_object_type_with_a_Symbol_hasInstance_method) return c.resolveErrorCall(node) } @@ -8799,7 +8799,7 @@ func (c *Checker) hasCorrectTypeArgumentArity(signature *Signature, typeArgument func (c *Checker) checkTypeArguments(signature *Signature, typeArgumentNodes []*ast.Node, reportErrors bool, headMessage *diagnostics.Message) []*Type { typeParameters := signature.typeParameters - typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.GetTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) + typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) var mapper *TypeMapper for i := range typeArgumentNodes { // Debug.assert(typeParameters[i] != nil, "Should not call checkTypeArguments with too many type arguments") @@ -9138,7 +9138,7 @@ func (c *Checker) getTypeArgumentsFromNodes(typeArgumentNodes []*ast.Node, typeP if len(typeArgumentNodes) > len(typeParameters) { typeArgumentNodes = typeArgumentNodes[:len(typeParameters)] } - typeArguments := core.Map(typeArgumentNodes, c.GetTypeFromTypeNode) + typeArguments := core.Map(typeArgumentNodes, c.getTypeFromTypeNode) for len(typeArguments) < len(typeParameters) { t := c.getDefaultFromTypeParameter(typeParameters[len(typeArguments)]) if t == nil { @@ -9748,7 +9748,7 @@ func (c *Checker) inferFromAnnotatedParameters(sig *Signature, context *Signatur declaration := sig.parameters[i].ValueDeclaration typeNode := declaration.Type() if typeNode != nil { - source := c.addOptionalityEx(c.GetTypeFromTypeNode(typeNode), false /*isProperty*/, isOptionalDeclaration(declaration)) + source := c.addOptionalityEx(c.getTypeFromTypeNode(typeNode), false /*isProperty*/, isOptionalDeclaration(declaration)) target := c.getTypeAtPosition(context, i) c.inferTypes(inferenceContext.inferences, source, target, InferencePriorityNone, false) } @@ -10129,7 +10129,7 @@ func (c *Checker) checkSatisfiesExpression(node *ast.Node) *Type { func (c *Checker) checkSatisfiesExpressionWorker(expression *ast.Node, target *ast.Node, checkMode CheckMode) *Type { exprType := c.checkExpressionEx(expression, checkMode) - targetType := c.GetTypeFromTypeNode(target) + targetType := c.getTypeFromTypeNode(target) if c.isErrorType(targetType) { return targetType } @@ -10715,7 +10715,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l } propType = indexInfo.valueType if c.compilerOptions.NoUncheckedIndexedAccess == core.TSTrue && getAssignmentTargetKind(node) != AssignmentKindDefinite { - propType = c.GetUnionType([]*Type{propType, c.missingType}) + propType = c.getUnionType([]*Type{propType, c.missingType}) } if c.compilerOptions.NoPropertyAccessFromIndexSignature == core.TSTrue && ast.IsPropertyAccessExpression(node) { c.error(right, diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, right.Text()) @@ -10848,7 +10848,7 @@ func (c *Checker) getPrivateIdentifierPropertyOfType(leftType *Type, lexicallySc func (c *Checker) checkPrivateIdentifierPropertyAccess(leftType *Type, right *ast.Node, lexicallyScopedIdentifier *ast.Symbol) bool { // Either the identifier could not be looked up in the lexical scope OR the lexically scoped identifier did not exist on the type. // Find a private identifier with the same description on the type. - properties := c.GetPropertiesOfType(leftType) + properties := c.getPropertiesOfType(leftType) var propertyOnType *ast.Symbol for _, symbol := range properties { decl := symbol.ValueDeclaration @@ -10946,7 +10946,7 @@ func (c *Checker) getSuggestedLibForNonExistentProperty(missingProperty string, } func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, containingType *Type) *ast.Symbol { - props := c.GetPropertiesOfType(containingType) + props := c.getPropertiesOfType(containingType) parent := name.Parent if ast.IsPropertyAccessExpression(parent) { props = core.Filter(props, func(prop *ast.Symbol) bool { @@ -10965,7 +10965,7 @@ func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, conta // @param type the type whose property we are checking. // @param property the accessed property's symbol. func (c *Checker) isValidPropertyAccessForCompletions(node *ast.Node, t *Type, property *ast.Symbol) bool { - return c.IsPropertyAccessible(node, ast.IsPropertyAccessExpression(node) && node.Expression().Kind == ast.KindSuperKeyword, false /*isWrite*/, t, property) + return c.isPropertyAccessible(node, ast.IsPropertyAccessExpression(node) && node.Expression().Kind == ast.KindSuperKeyword, false /*isWrite*/, t, property) // Previously we validated the 'this' type of methods but this adversely affected performance. See #31377 for more context. } @@ -10977,7 +10977,7 @@ func (c *Checker) isValidPropertyAccessForCompletions(node *ast.Node, t *Type, p // @param isWrite whether this is a write access, e.g. `++foo.x`. // @param containingType type where the property comes from. // @param property property symbol. -func (c *Checker) IsPropertyAccessible(node *ast.Node, isSuper bool, isWrite bool, containingType *Type, property *ast.Symbol) bool { +func (c *Checker) isPropertyAccessible(node *ast.Node, isSuper bool, isWrite bool, containingType *Type, property *ast.Symbol) bool { // Short-circuiting for improved performance. if IsTypeAny(containingType) { return true @@ -11283,7 +11283,7 @@ func (c *Checker) getDeclaringClass(prop *ast.Symbol) *Type { // Return true if source property is a valid override of protected parts of target property. func (c *Checker) isValidOverrideOf(sourceProp *ast.Symbol, targetProp *ast.Symbol) bool { return !c.forEachProperty(targetProp, func(tp *ast.Symbol) bool { - if GetDeclarationModifierFlagsFromSymbol(tp)&ast.ModifierFlagsProtected != 0 { + if getDeclarationModifierFlagsFromSymbol(tp)&ast.ModifierFlagsProtected != 0 { return !c.isPropertyInClassDerivedFrom(sourceProp, c.getDeclaringClass(tp)) } return false @@ -11346,7 +11346,7 @@ func (c *Checker) getEnclosingClassFromThisParameter(node *ast.Node) *Type { thisParameter := getThisParameterFromNodeContext(node) var thisType *Type if thisParameter != nil && thisParameter.AsParameterDeclaration().Type != nil { - thisType = c.GetTypeFromTypeNode(thisParameter.AsParameterDeclaration().Type) + thisType = c.getTypeFromTypeNode(thisParameter.AsParameterDeclaration().Type) } if thisType != nil { // 2. The constraint of a type parameter used for an explicit 'this' parameter @@ -11636,12 +11636,12 @@ func (c *Checker) checkAssertion(node *ast.Node, checkMode CheckMode) *Type { links.exprType = exprType c.checkSourceElement(typeNode) c.checkNodeDeferred(node) - return c.GetTypeFromTypeNode(typeNode) + return c.getTypeFromTypeNode(typeNode) } func (c *Checker) checkAssertionDeferred(node *ast.Node) { exprType := c.getRegularTypeOfObjectLiteral(c.getBaseTypeOfLiteralType(c.assertionLinks.Get(node).exprType)) - targetType := c.GetTypeFromTypeNode(node.Type()) + targetType := c.getTypeFromTypeNode(node.Type()) if !c.isErrorType(targetType) { widenedType := c.getWidenedType(exprType) if !c.isTypeComparableTo(targetType, widenedType) { @@ -11820,7 +11820,7 @@ func (c *Checker) checkBinaryLikeExpression(left *ast.Node, operatorToken *ast.N if !c.strictNullChecks { t = c.getBaseTypeOfLiteralType(rightType) } - resultType = c.GetUnionType([]*Type{c.extractDefinitelyFalsyTypes(t), rightType}) + resultType = c.getUnionType([]*Type{c.extractDefinitelyFalsyTypes(t), rightType}) } if operator == ast.KindAmpersandAmpersandEqualsToken { c.checkAssignmentOperator(left, operator, right, leftType, rightType) @@ -11983,7 +11983,7 @@ func (c *Checker) checkArrayLiteralDestructuringElementAssignment(node *ast.Node if !ast.IsOmittedExpression(element) { if !ast.IsSpreadElement(element) { indexType := c.getNumberLiteralType(jsnum.Number(elementIndex)) - if c.IsArrayLikeType(sourceType) { + if c.isArrayLikeType(sourceType) { // We create a synthetic expression so that getIndexedAccessType doesn't get confused // when the element is a SyntaxKind.ElementAccessExpression. accessFlags := AccessFlagsExpressionPosition | core.IfElse(c.hasDefaultValue(element), AccessFlagsAllowMissing, 0) @@ -12395,7 +12395,7 @@ func (c *Checker) getExactOptionalUnassignableProperties(source *Type, target *T if isTupleType(source) && isTupleType(target) { return nil } - return core.Filter(c.GetPropertiesOfType(target), func(targetProp *ast.Symbol) bool { + return core.Filter(c.getPropertiesOfType(target), func(targetProp *ast.Symbol) bool { return c.isExactOptionalPropertyMismatch(c.getTypeOfPropertyOfType(source, targetProp.Name), c.getTypeOfSymbol(targetProp)) }) } @@ -12624,7 +12624,7 @@ func (c *Checker) checkObjectLiteral(node *ast.Node, checkMode CheckMode) *Type } func (c *Checker) checkSpreadPropOverrides(t *Type, props ast.SymbolTable, spread *ast.Node) { - for _, right := range c.GetPropertiesOfType(t) { + for _, right := range c.getPropertiesOfType(t) { if right.Flags&ast.SymbolFlagsOptional == 0 { if left := props[right.Name]; left != nil { diagnostic := c.error(left.ValueDeclaration, diagnostics.X_0_is_specified_more_than_once_so_this_usage_will_be_overwritten, left.Name) @@ -12699,15 +12699,15 @@ func (c *Checker) getSpreadType(left *Type, right *Type, symbol *ast.Symbol, obj } else { indexInfos = c.getUnionIndexInfos([]*Type{left, right}) } - for _, rightProp := range c.GetPropertiesOfType(right) { - if GetDeclarationModifierFlagsFromSymbol(rightProp)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { + for _, rightProp := range c.getPropertiesOfType(right) { + if getDeclarationModifierFlagsFromSymbol(rightProp)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { skippedPrivateMembers.Add(rightProp.Name) } else if c.isSpreadableProperty(rightProp) { members[rightProp.Name] = c.getSpreadSymbol(rightProp, readonly) } } - for _, leftProp := range c.GetPropertiesOfType(left) { + for _, leftProp := range c.getPropertiesOfType(left) { if skippedPrivateMembers.Has(leftProp.Name) || !c.isSpreadableProperty(leftProp) { continue } @@ -12768,7 +12768,7 @@ func (c *Checker) getUnionIndexInfos(types []*Type) []*IndexInfo { for _, info := range sourceInfos { indexType := info.keyType if core.Every(types, func(t *Type) bool { return c.getIndexInfoOfType(t, indexType) != nil }) { - valueType := c.GetUnionType(core.Map(types, func(t *Type) *Type { + valueType := c.getUnionType(core.Map(types, func(t *Type) *Type { return c.getIndexTypeOfType(t, indexType) })) isReadonly := core.Some(types, func(t *Type) bool { return c.getIndexInfoOfType(t, indexType).isReadonly }) @@ -12807,8 +12807,8 @@ func (c *Checker) tryMergeUnionOfObjectTypeAndEmptyObject(t *Type, readonly bool } // gets the type as if it had been spread, but where everything in the spread is made optional members := make(ast.SymbolTable) - for _, prop := range c.GetPropertiesOfType(firstType) { - if GetDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { + for _, prop := range c.getPropertiesOfType(firstType) { + if getDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { // do nothing, skip privates } else if c.isSpreadableProperty(prop) { isSetonlyAccessor := prop.Flags&ast.SymbolFlagsSetAccessor != 0 && prop.Flags&ast.SymbolFlagsGetAccessor == 0 @@ -13064,7 +13064,7 @@ func (c *Checker) isReadonlySymbol(symbol *ast.Symbol) bool { // Object.defineProperty assignments with writable false or no setter // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) return symbol.CheckFlags&ast.CheckFlagsReadonly != 0 || - symbol.Flags&ast.SymbolFlagsProperty != 0 && GetDeclarationModifierFlagsFromSymbol(symbol)&ast.ModifierFlagsReadonly != 0 || + symbol.Flags&ast.SymbolFlagsProperty != 0 && getDeclarationModifierFlagsFromSymbol(symbol)&ast.ModifierFlagsReadonly != 0 || symbol.Flags&ast.SymbolFlagsVariable != 0 && c.getDeclarationNodeFlagsFromSymbol(symbol)&ast.NodeFlagsConstant != 0 || symbol.Flags&ast.SymbolFlagsAccessor != 0 && symbol.Flags&ast.SymbolFlagsSetAccessor == 0 || symbol.Flags&ast.SymbolFlagsEnumMember != 0 @@ -13904,7 +13904,7 @@ func (c *Checker) getPropertyOfVariable(symbol *ast.Symbol, name string) *ast.Sy if symbol.Flags&ast.SymbolFlagsVariable != 0 { typeAnnotation := symbol.ValueDeclaration.AsVariableDeclaration().Type if typeAnnotation != nil { - return c.resolveSymbol(c.getPropertyOfType(c.GetTypeFromTypeNode(typeAnnotation), name)) + return c.resolveSymbol(c.getPropertyOfType(c.getTypeFromTypeNode(typeAnnotation), name)) } } return nil @@ -15117,7 +15117,7 @@ func (c *Checker) getTypeOfSymbolWithDeferredType(symbol *ast.Symbol) *Type { if links.resolvedType == nil { deferred := c.deferredSymbolLinks.Get(symbol) if deferred.parent.flags&TypeFlagsUnion != 0 { - links.resolvedType = c.GetUnionType(deferred.constituents) + links.resolvedType = c.getUnionType(deferred.constituents) } else { links.resolvedType = c.getIntersectionType(deferred.constituents) } @@ -15131,7 +15131,7 @@ func (c *Checker) getWriteTypeOfSymbolWithDeferredType(symbol *ast.Symbol) *Type deferred := c.deferredSymbolLinks.Get(symbol) if len(deferred.writeConstituents) != 0 { if deferred.parent.flags&TypeFlagsUnion != 0 { - links.writeType = c.GetUnionType(deferred.writeConstituents) + links.writeType = c.getUnionType(deferred.writeConstituents) } else { links.writeType = c.getIntersectionType(deferred.writeConstituents) } @@ -15727,7 +15727,7 @@ func (c *Checker) getConstraintFromTypeParameter(t *Type) *Type { } else { constraintDeclaration := c.getConstraintDeclaration(t) if constraintDeclaration != nil { - constraint = c.GetTypeFromTypeNode(constraintDeclaration) + constraint = c.getTypeFromTypeNode(constraintDeclaration) if constraint.flags&TypeFlagsAny != 0 && !c.isErrorType(constraint) { // use stringNumberSymbolType as the base constraint for mapped type key constraints (unknown isn;t assignable to that, but `any` was), // use unknown otherwise @@ -15813,11 +15813,11 @@ func (c *Checker) getInferredTypeParameterConstraint(t *Type, omitTypeReferences ast.IsMappedTypeNode(parent.Parent.AsConditionalTypeNode().CheckType) && parent.Parent.AsConditionalTypeNode().CheckType.AsMappedTypeNode().Type != nil: checkMappedType := parent.Parent.AsConditionalTypeNode().CheckType - nodeType := c.GetTypeFromTypeNode(checkMappedType.AsMappedTypeNode().Type) + nodeType := c.getTypeFromTypeNode(checkMappedType.AsMappedTypeNode().Type) checkMappedTypeParameter := checkMappedType.AsMappedTypeNode().TypeParameter mapper := newSimpleTypeMapper(c.getDeclaredTypeOfTypeParameter(c.getSymbolOfDeclaration(checkMappedTypeParameter)), core.IfElse(checkMappedTypeParameter.AsTypeParameter().Constraint != nil, - c.GetTypeFromTypeNode(checkMappedTypeParameter.AsTypeParameter().Constraint), + c.getTypeFromTypeNode(checkMappedTypeParameter.AsTypeParameter().Constraint), c.stringNumberSymbolType)) inferences = append(inferences, c.instantiateType(nodeType, mapper)) } @@ -15831,7 +15831,7 @@ func (c *Checker) getInferredTypeParameterConstraint(t *Type, omitTypeReferences } func (c *Checker) getTypeParametersForTypeReferenceOrImport(node *ast.Node) []*Type { - t := c.GetTypeFromTypeNode(node) + t := c.getTypeFromTypeNode(node) if !c.isErrorType(t) { symbol := c.getResolvedSymbolOrNil(node) if symbol != nil { @@ -15858,7 +15858,7 @@ func (c *Checker) getTypeParametersForTypeAndSymbol(t *Type, symbol *ast.Symbol) func (c *Checker) getEffectiveTypeArgumentAtIndex(node *ast.Node, typeParameters []*Type, index int) *Type { typeArguments := node.TypeArguments() if index < len(typeArguments) { - return c.GetTypeFromTypeNode(typeArguments[index]) + return c.getTypeFromTypeNode(typeArguments[index]) } return c.getEffectiveTypeArguments(node, typeParameters)[index] } @@ -15921,7 +15921,7 @@ func (c *Checker) getDefaultConstraintOfConditionalType(t *Type) *Type { case IsTypeAny(falseConstraint): d.resolvedDefaultConstraint = trueConstraint default: - d.resolvedDefaultConstraint = c.GetUnionType([]*Type{trueConstraint, falseConstraint}) + d.resolvedDefaultConstraint = c.getUnionType([]*Type{trueConstraint, falseConstraint}) } } return d.resolvedDefaultConstraint @@ -16425,7 +16425,7 @@ func (c *Checker) getBindingElementTypeFromParentType(declaration *ast.Node, par } else { t = c.createArrayType(elementType) } - } else if c.IsArrayLikeType(parentType) { + } else if c.isArrayLikeType(parentType) { indexType := c.getNumberLiteralType(jsnum.Number(index)) declaredType := core.OrElse(c.getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.Name(), nil), c.errorType) t = c.getFlowTypeOfDestructuring(declaration, declaredType) @@ -16459,12 +16459,12 @@ func (c *Checker) getRestType(source *Type, properties []*ast.Node, symbol *ast. return c.getRestType(t, properties, symbol) }) } - omitKeyType := c.GetUnionType(core.Map(properties, c.getLiteralTypeFromPropertyName)) + omitKeyType := c.getUnionType(core.Map(properties, c.getLiteralTypeFromPropertyName)) var spreadableProperties []*ast.Symbol var unspreadableToRestKeys []*Type - for _, prop := range c.GetPropertiesOfType(source) { + for _, prop := range c.getPropertiesOfType(source) { literalTypeFromProperty := c.getLiteralTypeFromProperty(prop, TypeFlagsStringOrNumberLiteralOrUnique, false) - if !c.isTypeAssignableTo(literalTypeFromProperty, omitKeyType) && GetDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) == 0 && c.isSpreadableProperty(prop) { + if !c.isTypeAssignableTo(literalTypeFromProperty, omitKeyType) && getDeclarationModifierFlagsFromSymbol(prop)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) == 0 && c.isSpreadableProperty(prop) { spreadableProperties = append(spreadableProperties, prop) } else { unspreadableToRestKeys = append(unspreadableToRestKeys, literalTypeFromProperty) @@ -16475,7 +16475,7 @@ func (c *Checker) getRestType(source *Type, properties []*ast.Node, symbol *ast. // If the type we're spreading from has properties that cannot // be spread into the rest type (e.g. getters, methods), ensure // they are explicitly omitted, as they would in the non-generic case. - omitKeyType = c.GetUnionType(append([]*Type{omitKeyType}, unspreadableToRestKeys...)) + omitKeyType = c.getUnionType(append([]*Type{omitKeyType}, unspreadableToRestKeys...)) } if omitKeyType.flags&TypeFlagsNever != 0 { return source @@ -16717,7 +16717,7 @@ func (c *Checker) getWidenedTypeForAssignmentDeclaration(symbol *ast.Symbol) *Ty types = core.AppendIfUnique(types, c.checkExpressionForMutableLocation(declaration.AsBinaryExpression().Right, CheckModeNormal)) } } - return c.getWidenedType(c.GetUnionType(types)) + return c.getWidenedType(c.getUnionType(types)) } func (c *Checker) widenTypeForVariableLikeDeclaration(t *Type, declaration *ast.Node, reportErrors bool) *Type { @@ -16907,7 +16907,7 @@ func (c *Checker) getPropertiesOfContext(context *WideningContext) []*ast.Symbol var names collections.OrderedMap[string, *ast.Symbol] for _, t := range c.getSiblingsOfContext(context) { if isObjectLiteralType(t) && t.objectFlags&ObjectFlagsContainsSpread == 0 { - for _, prop := range c.GetPropertiesOfType(t) { + for _, prop := range c.getPropertiesOfType(t) { names.Set(prop.Name, prop) } } @@ -17090,7 +17090,7 @@ func (c *Checker) getOptionalType(t *Type, isProperty bool) *Type { if t == missingOrUndefined || t.flags&TypeFlagsUnion != 0 && t.Types()[0] == missingOrUndefined { return t } - return c.GetUnionType([]*Type{t, missingOrUndefined}) + return c.getUnionType([]*Type{t, missingOrUndefined}) } // Add undefined or null or both to a type if they are missing. @@ -17100,11 +17100,11 @@ func (c *Checker) getNullableType(t *Type, flags TypeFlags) *Type { case missing == 0: return t case missing == TypeFlagsUndefined: - return c.GetUnionType([]*Type{t, c.undefinedType}) + return c.getUnionType([]*Type{t, c.undefinedType}) case missing == TypeFlagsNull: - return c.GetUnionType([]*Type{t, c.nullType}) + return c.getUnionType([]*Type{t, c.nullType}) } - return c.GetUnionType([]*Type{t, c.undefinedType, c.nullType}) + return c.getUnionType([]*Type{t, c.undefinedType, c.nullType}) } func (c *Checker) GetNonNullableType(t *Type) *Type { @@ -17148,7 +17148,7 @@ func (c *Checker) isVarConstLike(node *ast.Node) bool { } func (c *Checker) getEffectivePropertyNameForPropertyNameNode(node *ast.PropertyName) (string, bool) { - name := GetPropertyNameForPropertyNameNode(node) + name := ast.GetPropertyNameForPropertyNameNode(node) switch { case name != ast.InternalSymbolNameMissing: return name, true @@ -17279,7 +17279,7 @@ func (c *Checker) reportCircularityError(symbol *ast.Symbol) *Type { return c.anyType } -func (c *Checker) GetPropertiesOfType(t *Type) []*ast.Symbol { +func (c *Checker) getPropertiesOfType(t *Type) []*ast.Symbol { t = c.getReducedApparentType(t) if t.flags&TypeFlagsUnionOrIntersection != 0 { return c.getPropertiesOfUnionOrIntersectionType(t) @@ -17300,7 +17300,7 @@ func (c *Checker) getPropertiesOfUnionOrIntersectionType(t *Type) []*ast.Symbol var checked core.Set[string] props := []*ast.Symbol{} for _, current := range d.types { - for _, prop := range c.GetPropertiesOfType(current) { + for _, prop := range c.getPropertiesOfType(current) { if !checked.Has(prop.Name) { checked.Add(prop.Name) combinedProp := c.getPropertyOfUnionOrIntersectionType(t, prop.Name, t.flags&TypeFlagsIntersection != 0 /*skipObjectFunctionPropertyAugment*/) @@ -17572,7 +17572,7 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters if thisArgument != nil { instantiatedBaseType = c.getTypeWithThisArgument(c.instantiateType(baseType, mapper), thisArgument, false /*needsApparentType*/) } - members = c.addInheritedMembers(members, c.GetPropertiesOfType(instantiatedBaseType)) + members = c.addInheritedMembers(members, c.getPropertiesOfType(instantiatedBaseType)) callSignatures = core.Concatenate(callSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindCall)) constructSignatures = core.Concatenate(constructSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindConstruct)) var inheritedIndexInfos []*IndexInfo @@ -17640,7 +17640,7 @@ func (c *Checker) getTupleBaseType(t *Type) *Type { elementTypes[i] = tp } } - return c.createArrayTypeEx(c.GetUnionType(elementTypes), t.AsTupleType().readonly) + return c.createArrayTypeEx(c.getUnionType(elementTypes), t.AsTupleType().readonly) } func (c *Checker) resolveBaseTypesOfClass(t *Type) { @@ -17708,7 +17708,7 @@ func getBaseTypeNodeOfClass(t *Type) *ast.Node { func (c *Checker) getInstantiatedConstructorsForTypeArguments(t *Type, typeArgumentNodes []*ast.Node, location *ast.Node) []*Signature { signatures := c.getConstructorsForTypeArguments(t, typeArgumentNodes, location) - typeArguments := core.Map(typeArgumentNodes, c.GetTypeFromTypeNode) + typeArguments := core.Map(typeArgumentNodes, c.getTypeFromTypeNode) return core.SameMap(signatures, func(sig *Signature) *Signature { if len(sig.typeParameters) != 0 { return c.getSignatureInstantiation(sig, typeArguments, nil) @@ -17936,7 +17936,7 @@ func (c *Checker) resolveBaseTypesOfInterface(t *Type) { for _, declaration := range t.symbol.Declarations { if ast.IsInterfaceDeclaration(declaration) { for _, node := range ast.GetExtendsHeritageClauseElements(declaration) { - baseType := c.getReducedType(c.GetTypeFromTypeNode(node)) + baseType := c.getReducedType(c.getTypeFromTypeNode(node)) if !c.isErrorType(baseType) { if c.isValidBaseType(baseType) { if t != baseType && !c.hasBaseType(baseType, t) { @@ -18085,9 +18085,9 @@ func (c *Checker) getIndexInfosOfIndexSymbol(indexSymbol *ast.Symbol, siblingSym if typeNode != nil { valueType := c.anyType if returnTypeNode != nil { - valueType = c.GetTypeFromTypeNode(returnTypeNode) + valueType = c.getTypeFromTypeNode(returnTypeNode) } - forEachType(c.GetTypeFromTypeNode(typeNode), func(keyType *Type) { + forEachType(c.getTypeFromTypeNode(typeNode), func(keyType *Type) { if c.isValidIndexKeyType(keyType) && findIndexInfo(indexInfos, keyType) == nil { indexInfo := c.newIndexInfo(keyType, valueType, hasModifier(declaration, ast.ModifierFlagsReadonly), declaration) indexInfos = append(indexInfos, indexInfo) @@ -18469,7 +18469,7 @@ func (c *Checker) getReturnTypeFromAnnotation(declaration *ast.Node) *Type { } returnType := declaration.Type() if returnType != nil { - return c.GetTypeFromTypeNode(returnType) + return c.getTypeFromTypeNode(returnType) } if ast.IsGetAccessorDeclaration(declaration) && c.hasBindableName(declaration) { return c.getAnnotatedAccessorType(ast.GetDeclarationOfKind(c.getSymbolOfDeclaration(declaration), ast.KindSetAccessor)) @@ -18480,7 +18480,7 @@ func (c *Checker) getReturnTypeFromAnnotation(declaration *ast.Node) *Type { func (c *Checker) getAnnotatedAccessorType(accessor *ast.Node) *Type { node := c.getAnnotatedAccessorTypeNode(accessor) if node != nil { - return c.GetTypeFromTypeNode(node) + return c.getTypeFromTypeNode(node) } return nil } @@ -18988,7 +18988,7 @@ func (c *Checker) checkIfExpressionRefinesParameter(fn *ast.Node, expr *ast.Node func (c *Checker) addOptionalTypeMarker(t *Type) *Type { if c.strictNullChecks { - return c.GetUnionType([]*Type{t, c.optionalType}) + return c.getUnionType([]*Type{t, c.optionalType}) } return t } @@ -19068,7 +19068,7 @@ func (c *Checker) resolveAnonymousTypeMembers(t *Type) { baseConstructorType := c.getBaseConstructorTypeOfClass(classType) if baseConstructorType.flags&(TypeFlagsObject|TypeFlagsIntersection|TypeFlagsTypeVariable) != 0 { members = maps.Clone(members) - c.addInheritedMembers(members, c.GetPropertiesOfType(baseConstructorType)) + c.addInheritedMembers(members, c.getPropertiesOfType(baseConstructorType)) c.setStructuredTypeMembers(t, members, nil, nil, nil) } else if baseConstructorType == c.anyType { baseConstructorIndexInfo = &IndexInfo{keyType: c.stringType, valueType: c.anyType} @@ -19301,9 +19301,9 @@ func (c *Checker) resolveMappedTypeMembers(t *Type) { // property symbol's name type be the union of those enum member types. if existingProp := members[propName]; existingProp != nil { valueLinks := c.valueSymbolLinks.Get(existingProp) - valueLinks.nameType = c.GetUnionType([]*Type{valueLinks.nameType, propNameType}) + valueLinks.nameType = c.getUnionType([]*Type{valueLinks.nameType, propNameType}) mappedLinks := c.mappedSymbolLinks.Get(existingProp) - mappedLinks.keyType = c.GetUnionType([]*Type{mappedLinks.keyType, keyType}) + mappedLinks.keyType = c.getUnionType([]*Type{mappedLinks.keyType, keyType}) } else { var modifiersProp *ast.Symbol if isTypeUsableAsPropertyName(keyType) { @@ -19729,7 +19729,7 @@ func (c *Checker) appendIndexInfo(indexInfos []*IndexInfo, newInfo *IndexInfo, u var valueType *Type var isReadonly bool if union { - valueType = c.GetUnionType([]*Type{info.valueType, newInfo.valueType}) + valueType = c.getUnionType([]*Type{info.valueType, newInfo.valueType}) isReadonly = info.isReadonly || newInfo.isReadonly } else { valueType = c.getIntersectionType([]*Type{info.valueType, newInfo.valueType}) @@ -19849,7 +19849,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s prop := c.getPropertyOfTypeEx(t, name, skipObjectFunctionPropertyAugment, false) var modifiers ast.ModifierFlags if prop != nil { - modifiers = GetDeclarationModifierFlagsFromSymbol(prop) + modifiers = getDeclarationModifierFlagsFromSymbol(prop) if prop.Flags&ast.SymbolFlagsClassMember != 0 { if isUnion { optionalFlag |= prop.Flags & ast.SymbolFlagsOptional @@ -20014,13 +20014,13 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s return result } if isUnion { - links.resolvedType = c.GetUnionType(propTypes) + links.resolvedType = c.getUnionType(propTypes) } else { links.resolvedType = c.getIntersectionType(propTypes) } if writeTypes != nil { if isUnion { - links.writeType = c.GetUnionType(writeTypes) + links.writeType = c.getUnionType(writeTypes) } else { links.writeType = c.getIntersectionType(writeTypes) } @@ -20216,7 +20216,7 @@ func (c *Checker) getReducedUnionType(unionType *Type) *Type { if core.Same(reducedTypes, unionType.Types()) { return unionType } - reduced := c.GetUnionType(reducedTypes) + reduced := c.getUnionType(reducedTypes) if reduced.flags&TypeFlagsUnion != 0 { reduced.AsUnionType().resolvedReducedType = reduced } @@ -20324,9 +20324,9 @@ func (c *Checker) getTypeArguments(t *Type) []*Type { case ast.KindTypeReference: typeArguments = append(n.OuterTypeParameters(), c.getEffectiveTypeArguments(node, n.LocalTypeParameters())...) case ast.KindArrayType: - typeArguments = []*Type{c.GetTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} + typeArguments = []*Type{c.getTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} case ast.KindTupleType: - typeArguments = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.GetTypeFromTypeNode) + typeArguments = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.getTypeFromTypeNode) default: panic("Unhandled case in getTypeArguments") } @@ -20351,7 +20351,7 @@ func (c *Checker) getTypeArguments(t *Type) []*Type { } func (c *Checker) getEffectiveTypeArguments(node *ast.Node, typeParameters []*Type) []*Type { - return c.fillMissingTypeArguments(core.Map(node.TypeArguments(), c.GetTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) + return c.fillMissingTypeArguments(core.Map(node.TypeArguments(), c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters)) } // Gets the minimum number of type arguments needed to satisfy all non-optional type parameters. @@ -20430,7 +20430,7 @@ func (c *Checker) getResolvedTypeParameterDefault(t *Type) *Type { return nil }) if defaultDeclaration != nil { - defaultType = c.GetTypeFromTypeNode(defaultDeclaration) + defaultType = c.getTypeFromTypeNode(defaultDeclaration) } } if d.resolvedDefaultType == c.resolvingDefaultType { @@ -21019,7 +21019,7 @@ func (c *Checker) getNameTypeFromMappedType(t *Type) *Type { return nil } if m.nameType == nil { - m.nameType = c.instantiateType(c.GetTypeFromTypeNode(m.declaration.NameType), m.mapper) + m.nameType = c.instantiateType(c.getTypeFromTypeNode(m.declaration.NameType), m.mapper) } return m.nameType } @@ -21028,7 +21028,7 @@ func (c *Checker) getTemplateTypeFromMappedType(t *Type) *Type { m := t.AsMappedType() if m.templateType == nil { if m.declaration.Type != nil { - m.templateType = c.instantiateType(c.addOptionalityEx(c.GetTypeFromTypeNode(m.declaration.Type) /*isProperty*/, true, getMappedTypeModifiers(t)&MappedTypeModifiersIncludeOptional != 0), m.mapper) + m.templateType = c.instantiateType(c.addOptionalityEx(c.getTypeFromTypeNode(m.declaration.Type) /*isProperty*/, true, getMappedTypeModifiers(t)&MappedTypeModifiersIncludeOptional != 0), m.mapper) } else { m.templateType = c.errorType } @@ -21051,11 +21051,11 @@ func (c *Checker) getApparentMappedTypeKeys(nameType *Type, targetType *Type) *T c.forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlagsStringOrNumberLiteralOrUnique, false, func(t *Type) { mappedKeys = append(mappedKeys, c.instantiateType(nameType, appendTypeMapping(targetType.Mapper(), c.getTypeParameterFromMappedType(targetType), t))) }) - return c.GetUnionType(mappedKeys) + return c.getUnionType(mappedKeys) } func (c *Checker) forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(t *Type, include TypeFlags, stringsOnly bool, cb func(keyType *Type)) { - for _, prop := range c.GetPropertiesOfType(t) { + for _, prop := range c.getPropertiesOfType(t) { cb(c.getLiteralTypeFromProperty(prop, include, false)) } if t.flags&TypeFlagsAny != 0 { @@ -21129,12 +21129,12 @@ func instantiateList[T comparable](c *Checker, values []T, m *TypeMapper, instan func (c *Checker) tryGetTypeFromTypeNode(node *ast.Node) *Type { typeNode := node.Type() if typeNode != nil { - return c.GetTypeFromTypeNode(typeNode) + return c.getTypeFromTypeNode(typeNode) } return nil } -func (c *Checker) GetTypeFromTypeNode(node *ast.Node) *Type { +func (c *Checker) getTypeFromTypeNode(node *ast.Node) *Type { return c.getConditionalFlowTypeOfType(c.getTypeFromTypeNodeWorker(node), node) } @@ -21143,18 +21143,18 @@ func (c *Checker) getTypeFromTypeNodeWorker(node *ast.Node) *Type { case ast.KindAnyKeyword, ast.KindJSDocAllType: return c.anyType case ast.KindJSDocNonNullableType: - return c.GetTypeFromTypeNode(node.AsJSDocNonNullableType().Type) + return c.getTypeFromTypeNode(node.AsJSDocNonNullableType().Type) case ast.KindJSDocNullableType: - t := c.GetTypeFromTypeNode(node.AsJSDocNullableType().Type) + t := c.getTypeFromTypeNode(node.AsJSDocNullableType().Type) if c.strictNullChecks { return c.getNullableType(t, TypeFlagsNull) } else { return t } case ast.KindJSDocVariadicType: - return c.createArrayType(c.GetTypeFromTypeNode(node.AsJSDocVariadicType().Type)) + return c.createArrayType(c.getTypeFromTypeNode(node.AsJSDocVariadicType().Type)) case ast.KindJSDocOptionalType: - return c.addOptionality(c.GetTypeFromTypeNode(node.AsJSDocOptionalType().Type)) + return c.addOptionality(c.getTypeFromTypeNode(node.AsJSDocOptionalType().Type)) case ast.KindUnknownKeyword: return c.unknownType case ast.KindStringKeyword: @@ -21203,7 +21203,7 @@ func (c *Checker) getTypeFromTypeNodeWorker(node *ast.Node) *Type { case ast.KindNamedTupleMember: return c.getTypeFromNamedTupleTypeNode(node) case ast.KindParenthesizedType: - return c.GetTypeFromTypeNode(node.AsParenthesizedTypeNode().Type) + return c.getTypeFromTypeNode(node.AsParenthesizedTypeNode().Type) case ast.KindRestType: return c.getTypeFromRestTypeNode(node) case ast.KindFunctionType, ast.KindConstructorType, ast.KindTypeLiteral: @@ -21279,8 +21279,8 @@ func (c *Checker) getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node *as func (c *Checker) getTypeFromIndexedAccessTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { - objectType := c.GetTypeFromTypeNode(node.AsIndexedAccessTypeNode().ObjectType) - indexType := c.GetTypeFromTypeNode(node.AsIndexedAccessTypeNode().IndexType) + objectType := c.getTypeFromTypeNode(node.AsIndexedAccessTypeNode().ObjectType) + indexType := c.getTypeFromTypeNode(node.AsIndexedAccessTypeNode().IndexType) potentialAlias := c.getAliasForTypeNode(node) links.resolvedType = c.getIndexedAccessTypeEx(objectType, indexType, AccessFlagsNone, node, potentialAlias) } @@ -21293,7 +21293,7 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type { argType := node.AsTypeOperatorNode().Type switch node.AsTypeOperatorNode().Operator { case ast.KindKeyOfKeyword: - links.resolvedType = c.getIndexType(c.GetTypeFromTypeNode(argType)) + links.resolvedType = c.getIndexType(c.getTypeFromTypeNode(argType)) case ast.KindUniqueKeyword: if argType.Kind == ast.KindSymbolKeyword { links.resolvedType = c.getESSymbolLikeTypeForNode(ast.WalkUpParenthesizedTypes(node.Parent)) @@ -21301,7 +21301,7 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type { links.resolvedType = c.errorType } case ast.KindReadonlyKeyword: - links.resolvedType = c.GetTypeFromTypeNode(argType) + links.resolvedType = c.getTypeFromTypeNode(argType) default: panic("Unhandled case in getTypeFromTypeOperatorNode") } @@ -21472,7 +21472,7 @@ func (c *Checker) getTypeFromClassOrInterfaceReference(node *ast.Node, symbol *a } func (c *Checker) getTypeArgumentsFromNode(node *ast.Node) []*Type { - return core.Map(node.TypeArguments(), c.GetTypeFromTypeNode) + return core.Map(node.TypeArguments(), c.getTypeFromTypeNode) } func (c *Checker) checkNoTypeArguments(node *ast.Node, symbol *ast.Symbol) bool { @@ -21638,7 +21638,7 @@ func (n *TupleNormalizer) normalize(c *Checker, elementTypes []*Type, elementInf } else { // Treat everything else as an array type and create a rest element. var s *Type - if c.IsArrayLikeType(t) { + if c.isArrayLikeType(t) { s = c.getIndexTypeOfType(t, c.numberType) } if s == nil { @@ -21667,7 +21667,7 @@ func (n *TupleNormalizer) normalize(c *Checker, elementTypes []*Type, elementInf } types = append(types, t) } - n.types[n.firstRestIndex] = c.GetUnionType(types) + n.types[n.firstRestIndex] = c.getUnionType(types) n.types = slices.Delete(n.types, n.firstRestIndex+1, n.lastOptionalOrRestIndex+1) n.infos = slices.Delete(n.infos, n.firstRestIndex+1, n.lastOptionalOrRestIndex+1) } @@ -21764,7 +21764,7 @@ func (c *Checker) getElementTypeOfArrayType(t *Type) *Type { return nil } -func (c *Checker) IsArrayLikeType(t *Type) bool { +func (c *Checker) isArrayLikeType(t *Type) bool { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray return c.isArrayType(t) || t.flags&TypeFlagsNullable == 0 && c.isTypeAssignableTo(t, c.anyReadonlyArrayType) @@ -21792,7 +21792,7 @@ func (c *Checker) isTupleLikeType(t *Type) bool { if isTupleType(t) || c.getPropertyOfType(t, "0") != nil { return true } - if c.IsArrayLikeType(t) { + if c.isArrayLikeType(t) { if lengthType := c.getTypeOfPropertyOfType(t, "length"); lengthType != nil { return everyType(lengthType, func(t *Type) bool { return t.flags&TypeFlagsNumberLiteral != 0 }) } @@ -21801,7 +21801,7 @@ func (c *Checker) isTupleLikeType(t *Type) bool { } func (c *Checker) isArrayOrTupleLikeType(t *Type) bool { - return c.IsArrayLikeType(t) || c.isTupleLikeType(t) + return c.isArrayLikeType(t) || c.isTupleLikeType(t) } func (c *Checker) isArrayOrTupleOrIntersection(t *Type) bool { @@ -21827,7 +21827,7 @@ func (c *Checker) getTupleElementType(t *Type, index int) *Type { func (c *Checker) getTypeFromTypeAliasReference(node *ast.Node, symbol *ast.Symbol) *Type { typeArguments := node.TypeArguments() if symbol.CheckFlags&ast.CheckFlagsUnresolved != 0 { - alias := &TypeAlias{symbol: symbol, typeArguments: core.Map(typeArguments, c.GetTypeFromTypeNode)} + alias := &TypeAlias{symbol: symbol, typeArguments: core.Map(typeArguments, c.getTypeFromTypeNode)} key := getAliasKey(alias) errorType := c.errorTypes[key] if errorType == nil { @@ -22091,7 +22091,7 @@ func (c *Checker) getDeclaredTypeOfTypeAlias(symbol *ast.Symbol) *Type { } declaration := core.Find(symbol.Declarations, ast.IsTypeOrJSTypeAliasDeclaration) typeNode := declaration.AsTypeAliasDeclaration().Type - t := c.GetTypeFromTypeNode(typeNode) + t := c.getTypeFromTypeNode(typeNode) if c.popTypeResolution() { typeParameters := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) if len(typeParameters) != 0 { @@ -22273,7 +22273,7 @@ func (c *Checker) evaluateEntity(expr *ast.Node, location *ast.Node) evaluator.R return evaluator.NewResult(nil, false, false, false) } if expr.Kind == ast.KindIdentifier { - if isInfinityOrNaNString(expr.Text()) && (symbol == c.GetGlobalSymbol(expr.Text(), ast.SymbolFlagsValue, nil /*diagnostic*/)) { + if isInfinityOrNaNString(expr.Text()) && (symbol == c.getGlobalSymbol(expr.Text(), ast.SymbolFlagsValue, nil /*diagnostic*/)) { // Technically we resolved a global lib file here, but the decision to treat this as numeric // is more predicated on the fact that the single-file resolution *didn't* resolve to a // different meaning of `Infinity` or `NaN`. Transpilers handle this no problem. @@ -22372,9 +22372,9 @@ func (c *Checker) getTypeFromArrayOrTupleTypeNode(node *ast.Node) *Type { } else { var elementTypes []*Type if node.Kind == ast.KindArrayType { - elementTypes = []*Type{c.GetTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} + elementTypes = []*Type{c.getTypeFromTypeNode(node.AsArrayTypeNode().ElementType)} } else { - elementTypes = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.GetTypeFromTypeNode) + elementTypes = core.Map(node.AsTupleTypeNode().Elements.Nodes, c.getTypeFromTypeNode) } links.resolvedType = c.createNormalizedTypeReference(target, elementTypes) } @@ -22408,7 +22408,7 @@ func (c *Checker) getTypeFromNamedTupleTypeNode(node *ast.Node) *Type { if node.AsNamedTupleMember().DotDotDotToken != nil { links.resolvedType = c.getTypeFromRestTypeNode(node) } else { - links.resolvedType = c.addOptionalityEx(c.GetTypeFromTypeNode(node.Type()), true /*isProperty*/, node.AsNamedTupleMember().QuestionToken != nil) + links.resolvedType = c.addOptionalityEx(c.getTypeFromTypeNode(node.Type()), true /*isProperty*/, node.AsNamedTupleMember().QuestionToken != nil) } } return links.resolvedType @@ -22420,7 +22420,7 @@ func (c *Checker) getTypeFromRestTypeNode(node *ast.Node) *Type { if elementTypeNode != nil { typeNode = elementTypeNode } - return c.GetTypeFromTypeNode(typeNode) + return c.getTypeFromTypeNode(typeNode) } func (c *Checker) getArrayElementTypeNode(node *ast.Node) *ast.Node { @@ -22444,14 +22444,14 @@ func (c *Checker) getArrayElementTypeNode(node *ast.Node) *ast.Node { } func (c *Checker) getTypeFromOptionalTypeNode(node *ast.Node) *Type { - return c.addOptionalityEx(c.GetTypeFromTypeNode(node.AsOptionalTypeNode().Type), true /*isProperty*/, true /*isOptional*/) + return c.addOptionalityEx(c.getTypeFromTypeNode(node.AsOptionalTypeNode().Type), true /*isProperty*/, true /*isOptional*/) } func (c *Checker) getTypeFromUnionTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { alias := c.getAliasForTypeNode(node) - links.resolvedType = c.getUnionTypeEx(core.Map(node.AsUnionTypeNode().Types.Nodes, c.GetTypeFromTypeNode), UnionReductionLiteral, alias, nil /*origin*/) + links.resolvedType = c.getUnionTypeEx(core.Map(node.AsUnionTypeNode().Types.Nodes, c.getTypeFromTypeNode), UnionReductionLiteral, alias, nil /*origin*/) } return links.resolvedType } @@ -22460,7 +22460,7 @@ func (c *Checker) getTypeFromIntersectionTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { alias := c.getAliasForTypeNode(node) - types := core.Map(node.AsIntersectionTypeNode().Types.Nodes, c.GetTypeFromTypeNode) + types := core.Map(node.AsIntersectionTypeNode().Types.Nodes, c.getTypeFromTypeNode) // We perform no supertype reduction for X & {} or {} & X, where X is one of string, number, bigint, // or a pattern literal template type. This enables union types like "a" | "b" | string & {} or // "aa" | "ab" | `a${string}` which preserve the literal types for purposes of statement completion. @@ -22486,7 +22486,7 @@ func (c *Checker) getTypeFromTemplateTypeNode(node *ast.Node) *Type { texts[0] = node.AsTemplateLiteralTypeNode().Head.Text() for i, span := range spans.Nodes { texts[i+1] = span.AsTemplateLiteralTypeSpan().Literal.Text() - types[i] = c.GetTypeFromTypeNode(span.AsTemplateLiteralTypeSpan().Type) + types[i] = c.getTypeFromTypeNode(span.AsTemplateLiteralTypeSpan().Type) } links.resolvedType = c.getTemplateLiteralType(texts, types) } @@ -22510,7 +22510,7 @@ func (c *Checker) getTypeFromMappedTypeNode(node *ast.Node) *Type { func (c *Checker) getTypeFromConditionalTypeNode(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { - checkType := c.GetTypeFromTypeNode(node.AsConditionalTypeNode().CheckType) + checkType := c.getTypeFromTypeNode(node.AsConditionalTypeNode().CheckType) alias := c.getAliasForTypeNode(node) allOuterTypeParameters := c.getOuterTypeParameters(node, true /*includeThisTypes*/) var outerTypeParameters []*Type @@ -22522,7 +22522,7 @@ func (c *Checker) getTypeFromConditionalTypeNode(node *ast.Node) *Type { root := &ConditionalRoot{ node: node.AsConditionalTypeNode(), checkType: checkType, - extendsType: c.GetTypeFromTypeNode(node.AsConditionalTypeNode().ExtendsType), + extendsType: c.getTypeFromTypeNode(node.AsConditionalTypeNode().ExtendsType), isDistributive: checkType.flags&TypeFlagsTypeParameter != 0, inferTypeParameters: c.getInferTypeParameters(node), outerTypeParameters: outerTypeParameters, @@ -22624,11 +22624,11 @@ func (c *Checker) getConditionalType(root *ConditionalRoot, mapper *TypeMapper, if checkType.flags&TypeFlagsAny != 0 || forConstraint && inferredExtendsType.flags&TypeFlagsNever == 0 && someType(c.getPermissiveInstantiation(inferredExtendsType), func(t *Type) bool { return c.isTypeAssignableTo(t, c.getPermissiveInstantiation(checkType)) }) { - extraTypes = append(extraTypes, c.instantiateType(c.GetTypeFromTypeNode(root.node.TrueType), core.OrElse(combinedMapper, mapper))) + extraTypes = append(extraTypes, c.instantiateType(c.getTypeFromTypeNode(root.node.TrueType), core.OrElse(combinedMapper, mapper))) } // If falseType is an immediately nested conditional type that isn't distributive or has an // identical checkType, switch to that type and loop. - falseType := c.GetTypeFromTypeNode(root.node.FalseType) + falseType := c.getTypeFromTypeNode(root.node.FalseType) if falseType.flags&TypeFlagsConditional != 0 { newRoot := falseType.AsConditionalType().root if newRoot.node.Parent == root.node.AsNode() && (!newRoot.isDistributive || newRoot.checkType == root.checkType) { @@ -22654,7 +22654,7 @@ func (c *Checker) getConditionalType(root *ConditionalRoot, mapper *TypeMapper, // type Foo = T extends { x: string } ? string : number // doesn't immediately resolve to 'string' instead of being deferred. if inferredExtendsType.flags&TypeFlagsAnyOrUnknown != 0 || c.isTypeAssignableTo(c.getRestrictiveInstantiation(checkType), c.getRestrictiveInstantiation(inferredExtendsType)) { - trueType := c.GetTypeFromTypeNode(root.node.TrueType) + trueType := c.getTypeFromTypeNode(root.node.TrueType) trueMapper := core.OrElse(combinedMapper, mapper) if newRoot, newRootMapper := c.getTailRecursionRoot(trueType, trueMapper); newRoot != nil { root = newRoot @@ -22679,7 +22679,7 @@ func (c *Checker) getConditionalType(root *ConditionalRoot, mapper *TypeMapper, break } if extraTypes != nil { - return c.GetUnionType(append(extraTypes, result)) + return c.getUnionType(append(extraTypes, result)) } return result } @@ -22780,7 +22780,7 @@ func (c *Checker) permissiveMapperWorker(t *Type) *Type { func (c *Checker) getTrueTypeFromConditionalType(t *Type) *Type { d := t.AsConditionalType() if d.resolvedTrueType == nil { - d.resolvedTrueType = c.instantiateType(c.GetTypeFromTypeNode(d.root.node.TrueType), d.mapper) + d.resolvedTrueType = c.instantiateType(c.getTypeFromTypeNode(d.root.node.TrueType), d.mapper) } return d.resolvedTrueType } @@ -22788,7 +22788,7 @@ func (c *Checker) getTrueTypeFromConditionalType(t *Type) *Type { func (c *Checker) getFalseTypeFromConditionalType(t *Type) *Type { d := t.AsConditionalType() if d.resolvedFalseType == nil { - d.resolvedFalseType = c.instantiateType(c.GetTypeFromTypeNode(d.root.node.FalseType), d.mapper) + d.resolvedFalseType = c.instantiateType(c.getTypeFromTypeNode(d.root.node.FalseType), d.mapper) } return d.resolvedFalseType } @@ -22797,7 +22797,7 @@ func (c *Checker) getInferredTrueTypeFromConditionalType(t *Type) *Type { d := t.AsConditionalType() if d.resolvedInferredTrueType == nil { if d.combinedMapper != nil { - d.resolvedInferredTrueType = c.instantiateType(c.GetTypeFromTypeNode(d.root.node.TrueType), d.combinedMapper) + d.resolvedInferredTrueType = c.instantiateType(c.getTypeFromTypeNode(d.root.node.TrueType), d.combinedMapper) } else { d.resolvedInferredTrueType = c.getTrueTypeFromConditionalType(t) } @@ -23035,7 +23035,7 @@ func (c *Checker) createTupleTargetType(elementInfos []TupleElementInfo, readonl for i := minLength; i <= arity; i++ { literalTypes = append(literalTypes, c.getNumberLiteralType(jsnum.Number(i))) } - c.valueSymbolLinks.Get(lengthSymbol).resolvedType = c.GetUnionType(literalTypes) + c.valueSymbolLinks.Get(lengthSymbol).resolvedType = c.getUnionType(literalTypes) } members[lengthSymbol.Name] = lengthSymbol t := c.newObjectType(ObjectFlagsTuple|ObjectFlagsReference, nil) @@ -23090,7 +23090,7 @@ func (c *Checker) getTupleElementTypeOutOfStartCount(t *Type, index jsnum.Number return c.undefinedType } if undefinedLikeType != nil && index >= jsnum.Number(getTotalFixedElementCount(t.TargetTupleType())) { - return c.GetUnionType([]*Type{restType, undefinedLikeType}) + return c.getUnionType([]*Type{restType, undefinedLikeType}) } return restType }) @@ -23198,13 +23198,13 @@ func (c *Checker) getConditionalFlowTypeOfType(t *Type, node *ast.Node) *Type { constraints = append(constraints, constraint) } } else if t.flags&TypeFlagsTypeParameter != 0 && ast.IsMappedTypeNode(parent) && parent.AsMappedTypeNode().NameType == nil && node == parent.AsMappedTypeNode().Type { - mappedType := c.GetTypeFromTypeNode(parent) + mappedType := c.getTypeFromTypeNode(parent) if c.getTypeParameterFromMappedType(mappedType) == c.getActualTypeVariable(t) { typeParameter := c.getHomomorphicTypeVariable(mappedType) if typeParameter != nil { constraint := c.getConstraintOfTypeParameter(typeParameter) if constraint != nil && everyType(constraint, c.isArrayOrTupleType) { - constraints = append(constraints, c.GetUnionType([]*Type{c.numberType, c.numericStringType})) + constraints = append(constraints, c.getUnionType([]*Type{c.numberType, c.numericStringType})) } } } @@ -23221,8 +23221,8 @@ func (c *Checker) getImpliedConstraint(t *Type, checkNode *ast.Node, extendsNode switch { case isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode): return c.getImpliedConstraint(t, checkNode.AsTupleTypeNode().Elements.Nodes[0], extendsNode.AsTupleTypeNode().Elements.Nodes[0]) - case c.getActualTypeVariable(c.GetTypeFromTypeNode(checkNode)) == c.getActualTypeVariable(t): - return c.GetTypeFromTypeNode(extendsNode) + case c.getActualTypeVariable(c.getTypeFromTypeNode(checkNode)) == c.getActualTypeVariable(t): + return c.getTypeFromTypeNode(extendsNode) } return nil } @@ -23263,7 +23263,7 @@ func (c *Checker) createWideningType(nonWideningType *Type) *Type { func (c *Checker) createUnknownUnionType() *Type { if c.strictNullChecks { - return c.GetUnionType([]*Type{c.undefinedType, c.nullType, c.unknownEmptyObjectType}) + return c.getUnionType([]*Type{c.undefinedType, c.nullType, c.unknownEmptyObjectType}) } return c.unknownType } @@ -23819,7 +23819,7 @@ func (c *Checker) getUnionOrIntersectionType(types []*Type, isUnion bool, unionR return c.getIntersectionType(types) } -func (c *Checker) GetUnionType(types []*Type) *Type { +func (c *Checker) getUnionType(types []*Type) *Type { return c.getUnionTypeEx(types, UnionReductionLiteral, nil /*alias*/, nil /*origin*/) } @@ -24149,7 +24149,7 @@ func (c *Checker) removeSubtypes(types []*Type, hasObjectTypes bool) []*Type { // a subtype of just `A` or just `B`. When we encounter such a type parameter, we therefore check if the // type parameter is a subtype of a union of all the other types. if source.flags&TypeFlagsTypeParameter != 0 && c.getBaseConstraintOrType(source).flags&TypeFlagsUnion != 0 { - if c.isTypeRelatedTo(source, c.GetUnionType(core.Map(types, func(t *Type) *Type { + if c.isTypeRelatedTo(source, c.getUnionType(core.Map(types, func(t *Type) *Type { if t == source { return c.neverType } @@ -24165,7 +24165,7 @@ func (c *Checker) removeSubtypes(types []*Type, hasObjectTypes bool) []*Type { var keyProperty *ast.Symbol var keyPropertyType *Type if source.flags&(TypeFlagsObject|TypeFlagsIntersection|TypeFlagsInstantiableNonPrimitive) != 0 { - keyProperty = core.Find(c.GetPropertiesOfType(source), func(p *ast.Symbol) bool { + keyProperty = core.Find(c.getPropertiesOfType(source), func(p *ast.Symbol) bool { return isUnitType(c.getTypeOfSymbol(p)) }) } @@ -24844,7 +24844,7 @@ func (c *Checker) getIndexTypeEx(t *Type, indexFlags IndexFlags) *Type { case t.flags&TypeFlagsUnion != 0: return c.getIntersectionType(core.Map(t.Types(), func(t *Type) *Type { return c.getIndexTypeEx(t, indexFlags) })) case t.flags&TypeFlagsIntersection != 0: - return c.GetUnionType(core.Map(t.Types(), func(t *Type) *Type { return c.getIndexTypeEx(t, indexFlags) })) + return c.getUnionType(core.Map(t.Types(), func(t *Type) *Type { return c.getIndexTypeEx(t, indexFlags) })) case t.objectFlags&ObjectFlagsMapped != 0: return c.getIndexTypeForMappedType(t, indexFlags) case t == c.wildcardType: @@ -24873,7 +24873,7 @@ func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, inclu origin = c.newIndexType(t, IndexFlagsNone) } var types []*Type - for _, prop := range c.GetPropertiesOfType(t) { + for _, prop := range c.getPropertiesOfType(t) { types = append(types, c.getLiteralTypeFromProperty(prop, include, false)) } for _, info := range c.getIndexInfosOfType(t) { @@ -24889,7 +24889,7 @@ func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, inclu } func (c *Checker) getLiteralTypeFromProperty(prop *ast.Symbol, include TypeFlags, includeNonPublic bool) *Type { - if includeNonPublic || GetDeclarationModifierFlagsFromSymbol(prop)&ast.ModifierFlagsNonPublicAccessibilityModifier == 0 { + if includeNonPublic || getDeclarationModifierFlagsFromSymbol(prop)&ast.ModifierFlagsNonPublicAccessibilityModifier == 0 { t := c.valueSymbolLinks.Get(c.getLateBoundSymbol(prop)).nameType if t == nil { if prop.Name == ast.InternalSymbolNameDefault { @@ -24921,7 +24921,7 @@ func (c *Checker) getLiteralTypeFromPropertyName(name *ast.Node) *Type { if ast.IsComputedPropertyName(name) { return c.getRegularTypeOfLiteralType(c.checkComputedPropertyName(name)) } - propertyName := GetPropertyNameForPropertyNameNode(name) + propertyName := ast.GetPropertyNameForPropertyNameNode(name) if propertyName != ast.InternalSymbolNameMissing { return c.getStringLiteralType(propertyName) } @@ -25083,11 +25083,11 @@ func (c *Checker) getIndexTypeForMappedType(t *Type, indexFlags IndexFlags) *Typ // original constraintType, so we can return the union that preserves aliases/origin data if possible. var result *Type if indexFlags&IndexFlagsNoIndexSignatures != 0 { - result = c.filterType(c.GetUnionType(keyTypes), func(t *Type) bool { + result = c.filterType(c.getUnionType(keyTypes), func(t *Type) bool { return t.flags&(TypeFlagsAny|TypeFlagsString) == 0 }) } else { - result = c.GetUnionType(keyTypes) + result = c.getUnionType(keyTypes) } if result.flags&TypeFlagsUnion != 0 && constraintType.flags&TypeFlagsUnion != 0 && getTypeListKey(result.Types()) == getTypeListKey(constraintType.Types()) { return constraintType @@ -25186,7 +25186,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy } if hasPropName { if accessFlags&AccessFlagsContextual != 0 { - t := c.GetTypeOfPropertyOfContextualType(objectType, propName) + t := c.getTypeOfPropertyOfContextualType(objectType, propName) if t == nil { t = c.anyType } @@ -25222,7 +25222,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy case accessExpression != nil && getAssignmentTargetKind(accessExpression) != AssignmentKindDefinite: return c.getFlowTypeOfReference(accessExpression, propType) case accessNode != nil && ast.IsIndexedAccessTypeNode(accessNode) && c.containsMissingType(propType): - return c.GetUnionType([]*Type{propType, c.undefinedType}) + return c.getUnionType([]*Type{propType, c.undefinedType}) default: return propType } @@ -25274,7 +25274,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy indexNode := getIndexNodeForAccessExpression(accessNode) c.error(indexNode, diagnostics.Type_0_cannot_be_used_as_an_index_type, c.TypeToString(indexType)) if accessFlags&AccessFlagsIncludeUndefined != 0 { - return c.GetUnionType([]*Type{indexInfo.valueType, c.missingType}) + return c.getUnionType([]*Type{indexInfo.valueType, c.missingType}) } else { return indexInfo.valueType } @@ -25289,7 +25289,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy (indexType.symbol != nil && indexType.flags&TypeFlagsEnumLiteral != 0 && c.getParentOfSymbol(indexType.symbol) == objectType.symbol)) { - return c.GetUnionType([]*Type{indexInfo.valueType, c.missingType}) + return c.getUnionType([]*Type{indexInfo.valueType, c.missingType}) } return indexInfo.valueType } @@ -25305,7 +25305,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy types := core.Map(objectType.AsStructuredType().properties, func(prop *ast.Symbol) *Type { return c.getTypeOfSymbol(prop) }) - return c.GetUnionType(append(types, c.undefinedType)) + return c.getUnionType(append(types, c.undefinedType)) } } if objectType.symbol == c.globalThisSymbol && hasPropName && c.globalThisSymbol.Exports[propName] != nil && c.globalThisSymbol.Exports[propName].Flags&ast.SymbolFlagsBlockScoped != 0 { @@ -25384,7 +25384,7 @@ func (c *Checker) typeHasStaticProperty(propName string, containingType *Type) b } func (c *Checker) getSuggestionForNonexistentProperty(name string, containingType *Type) string { - symbol := c.getSpellingSuggestionForName(name, c.GetPropertiesOfType(containingType), ast.SymbolFlagsValue) + symbol := c.getSpellingSuggestionForName(name, c.getPropertiesOfType(containingType), ast.SymbolFlagsValue) if symbol != nil { return symbol.Name } @@ -25508,13 +25508,13 @@ func (c *Checker) getPropertyNameFromIndex(indexType *Type, accessNode *ast.Node return getPropertyNameFromType(indexType) } if accessNode != nil && ast.IsPropertyName(accessNode) { - return GetPropertyNameForPropertyNameNode(accessNode) + return ast.GetPropertyNameForPropertyNameNode(accessNode) } return ast.InternalSymbolNameMissing } func (c *Checker) isStringIndexSignatureOnlyTypeWorker(t *Type) bool { - return t.flags&TypeFlagsObject != 0 && !c.isGenericMappedType(t) && len(c.GetPropertiesOfType(t)) == 0 && len(c.getIndexInfosOfType(t)) == 1 && c.getIndexInfoOfType(t, c.stringType) != nil || + return t.flags&TypeFlagsObject != 0 && !c.isGenericMappedType(t) && len(c.getPropertiesOfType(t)) == 0 && len(c.getIndexInfosOfType(t)) == 1 && c.getIndexInfoOfType(t, c.stringType) != nil || t.flags&TypeFlagsUnionOrIntersection != 0 && core.Every(t.Types(), c.isStringIndexSignatureOnlyType) } @@ -25669,7 +25669,7 @@ func (c *Checker) computeBaseConstraint(t *Type, stack []RecursionId) *Type { } switch { case t.flags&TypeFlagsUnion != 0 && len(constraints) == len(types): - return c.GetUnionType(constraints) + return c.getUnionType(constraints) case t.flags&TypeFlagsIntersection != 0 && len(constraints) != 0: return c.getIntersectionType(constraints) } @@ -25818,8 +25818,8 @@ func (c *Checker) compareProperties(sourceProp *ast.Symbol, targetProp *ast.Symb if sourceProp == targetProp { return TernaryTrue } - sourcePropAccessibility := GetDeclarationModifierFlagsFromSymbol(sourceProp) & ast.ModifierFlagsNonPublicAccessibilityModifier - targetPropAccessibility := GetDeclarationModifierFlagsFromSymbol(targetProp) & ast.ModifierFlagsNonPublicAccessibilityModifier + sourcePropAccessibility := getDeclarationModifierFlagsFromSymbol(sourceProp) & ast.ModifierFlagsNonPublicAccessibilityModifier + targetPropAccessibility := getDeclarationModifierFlagsFromSymbol(targetProp) & ast.ModifierFlagsNonPublicAccessibilityModifier if sourcePropAccessibility != targetPropAccessibility { return TernaryFalse } @@ -25975,7 +25975,7 @@ func (c *Checker) containsUndefinedType(t *Type) bool { return t.flags&TypeFlagsUndefined != 0 } -func (c *Checker) TypeHasCallOrConstructSignatures(t *Type) bool { +func (c *Checker) typeHasCallOrConstructSignatures(t *Type) bool { return t.flags&TypeFlagsStructuredType != 0 && len(c.resolveStructuredTypeMembers(t).signatures) != 0 } @@ -26094,7 +26094,7 @@ func (c *Checker) distributeObjectOverIndexType(objectType *Type, indexType *Typ if writing { return c.getIntersectionType(types) } - return c.GetUnionType(types) + return c.getUnionType(types) } return nil } @@ -26110,7 +26110,7 @@ func (c *Checker) distributeIndexOverObjectType(objectType *Type, indexType *Typ if objectType.flags&TypeFlagsIntersection != 0 || writing { return c.getIntersectionType(types) } - return c.GetUnionType(types) + return c.getUnionType(types) } return nil } @@ -26139,7 +26139,7 @@ func (c *Checker) getSimplifiedConditionalType(t *Type, writing bool) *Type { // Invokes union simplification logic to determine if an intersection is considered empty as a union constituent func (c *Checker) isIntersectionEmpty(type1 *Type, type2 *Type) bool { - return c.GetUnionType([]*Type{c.intersectTypes(type1, type2), c.neverType}).flags&TypeFlagsNever != 0 + return c.getUnionType([]*Type{c.intersectTypes(type1, type2), c.neverType}).flags&TypeFlagsNever != 0 } func (c *Checker) getSimplifiedTypeOrConstraint(t *Type) *Type { @@ -26243,7 +26243,7 @@ func (c *Checker) getModifiersTypeFromMappedType(t *Type) *Type { // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves // 'keyof T' to a literal union type and we can't recover T from that type. - m.modifiersType = c.instantiateType(c.GetTypeFromTypeNode(c.getConstraintDeclarationForMappedType(t).AsTypeOperatorNode().Type), m.mapper) + m.modifiersType = c.instantiateType(c.getTypeFromTypeNode(c.getConstraintDeclarationForMappedType(t).AsTypeOperatorNode().Type), m.mapper) } else { // Otherwise, get the declared constraint type, and if the constraint type is a type parameter, // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T', @@ -26771,7 +26771,7 @@ func (c *Checker) getPromisedTypeOfPromiseEx(t *Type, errorNode *ast.Node, thisT } return nil } - onfulfilledParameterType := c.getTypeWithFacts(c.GetUnionType(core.Map(candidates, c.getTypeOfFirstParameterOfSignature)), TypeFactsNEUndefinedOrNull) + onfulfilledParameterType := c.getTypeWithFacts(c.getUnionType(core.Map(candidates, c.getTypeOfFirstParameterOfSignature)), TypeFactsNEUndefinedOrNull) if IsTypeAny(onfulfilledParameterType) { return nil } @@ -27095,7 +27095,7 @@ func (c *Checker) substituteIndexedMappedType(objectType *Type, index *Type) *Ty // Return true if an indexed access with the given object and index types could access an optional property. func (c *Checker) couldAccessOptionalProperty(objectType *Type, indexType *Type) bool { indexConstraint := c.getBaseConstraintOfType(indexType) - return indexConstraint != nil && core.Some(c.GetPropertiesOfType(objectType), func(p *ast.Symbol) bool { + return indexConstraint != nil && core.Some(c.getPropertiesOfType(objectType), func(p *ast.Symbol) bool { return p.Flags&ast.SymbolFlagsOptional != 0 && c.isTypeAssignableTo(c.getLiteralTypeFromProperty(p, TypeFlagsStringOrNumberLiteralOrUnique, false), indexConstraint) }) } @@ -27158,7 +27158,7 @@ func (c *Checker) getContextualType(node *ast.Node, contextFlags ContextFlags) * if isConstAssertion(parent) { return c.getContextualType(parent, contextFlags) } - return c.GetTypeFromTypeNode(getAssertedTypeNode(parent)) + return c.getTypeFromTypeNode(getAssertedTypeNode(parent)) case ast.KindBinaryExpression: return c.getContextualTypeForBinaryOperand(node, contextFlags) case ast.KindPropertyAssignment, @@ -27180,7 +27180,7 @@ func (c *Checker) getContextualType(node *ast.Node, contextFlags ContextFlags) * case ast.KindNonNullExpression: return c.getContextualType(parent, contextFlags) case ast.KindSatisfiesExpression: - return c.GetTypeFromTypeNode(parent.AsSatisfiesExpression().Type) + return c.getTypeFromTypeNode(parent.AsSatisfiesExpression().Type) case ast.KindExportAssignment: return c.tryGetTypeFromTypeNode(parent) case ast.KindJsxExpression: @@ -27224,7 +27224,7 @@ func (c *Checker) getContextualTypeForInitializerExpression(node *ast.Node, cont func (c *Checker) getContextualTypeForVariableLikeDeclaration(declaration *ast.Node, contextFlags ContextFlags) *Type { typeNode := declaration.Type() if typeNode != nil { - return c.GetTypeFromTypeNode(typeNode) + return c.getTypeFromTypeNode(typeNode) } switch declaration.Kind { case ast.KindParameter: @@ -27296,7 +27296,7 @@ func (c *Checker) getSpreadArgumentType(args []*ast.Node, index int, argCount in } else { spreadType = c.checkExpressionWithContextualType(arg.Expression(), restType, context, checkMode) } - if c.IsArrayLikeType(spreadType) { + if c.isArrayLikeType(spreadType) { return c.getMutableArrayOrTupleType(spreadType) } if ast.IsSpreadElement(arg) { @@ -27318,7 +27318,7 @@ func (c *Checker) getSpreadArgumentType(args []*ast.Node, index int, argCount in } else { spreadType = c.checkExpression(arg.Expression()) } - if c.IsArrayLikeType(spreadType) { + if c.isArrayLikeType(spreadType) { t = spreadType info.flags = ElementFlagsVariadic } else { @@ -27398,7 +27398,7 @@ func (c *Checker) getContextualTypeForBindingElement(declaration *ast.Node, cont func (c *Checker) getContextualTypeForStaticPropertyDeclaration(declaration *ast.Node, contextFlags ContextFlags) *Type { if ast.IsExpression(declaration.Parent) { if parentType := c.getContextualType(declaration.Parent, contextFlags); parentType != nil { - return c.GetTypeOfPropertyOfContextualType(parentType, c.getSymbolOfDeclaration(declaration).Name) + return c.getTypeOfPropertyOfContextualType(parentType, c.getSymbolOfDeclaration(declaration).Name) } } return nil @@ -27427,7 +27427,7 @@ func (c *Checker) getContextualTypeForReturnExpression(node *ast.Node, contextFl if functionFlags&FunctionFlagsAsync != 0 { // Get the awaited type without the `Awaited` alias contextualAwaitedType := c.mapType(contextualReturnType, c.getAwaitedTypeNoAlias) - return c.GetUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) + return c.getUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) } // Regular function or Generator function return contextualReturnType @@ -27520,7 +27520,7 @@ func (c *Checker) getContextualTypeForYieldOperand(node *ast.Node, contextFlags generatorType := c.createGeneratorType(yieldType, returnType, nextType, false /*isAsyncGenerator*/) if isAsyncGenerator { asyncGeneratorType := c.createGeneratorType(yieldType, returnType, nextType, true /*isAsyncGenerator*/) - return c.GetUnionType([]*Type{generatorType, asyncGeneratorType}) + return c.getUnionType([]*Type{generatorType, asyncGeneratorType}) } return generatorType } @@ -27535,7 +27535,7 @@ func (c *Checker) getContextualTypeForAwaitOperand(node *ast.Node, contextFlags if contextualType != nil { contextualAwaitedType := c.getAwaitedTypeNoAlias(contextualType) if contextualAwaitedType != nil { - return c.GetUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) + return c.getUnionType([]*Type{contextualAwaitedType, c.createPromiseLikeType(contextualAwaitedType)}) } } return nil @@ -27681,7 +27681,7 @@ func (c *Checker) getContextualTypeForObjectLiteralElement(element *ast.Node, co if name != nil && ast.IsComputedPropertyName(name) { exprType := c.checkExpression(name.Expression()) if isTypeUsableAsPropertyName(exprType) { - propType := c.GetTypeOfPropertyOfContextualType(t, getPropertyNameFromType(exprType)) + propType := c.getTypeOfPropertyOfContextualType(t, getPropertyNameFromType(exprType)) if propType != nil { return propType } @@ -27754,7 +27754,7 @@ func (c *Checker) getContextualTypeForElementExpression(t *Type, index int, leng // If element index is known and a contextual property with that name exists, return it. Otherwise return the // iterated or element type of the contextual type. if firstSpreadIndex < 0 || index < firstSpreadIndex { - propType := c.GetTypeOfPropertyOfContextualType(t, strconv.Itoa(index)) + propType := c.getTypeOfPropertyOfContextualType(t, strconv.Itoa(index)) if propType != nil { return propType } @@ -27780,7 +27780,7 @@ func (c *Checker) getContextualTypeForSubstitutionExpression(template *ast.Node, } func (c *Checker) getContextualImportAttributeType(node *ast.Node) *Type { - return c.GetTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().Text()) + return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().Text()) } // Returns the effective arguments for an expression that works like a function invocation. @@ -27912,7 +27912,7 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur // "static" or "constructor" side of the class). targetType := c.getTypeOfSymbol(c.getSymbolOfDeclaration(node)) targetParam := c.newParameter("target", targetType) - links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam}, c.GetUnionType([]*Type{targetType, c.voidType})) + links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam}, c.getUnionType([]*Type{targetType, c.voidType})) case ast.KindParameter: if !ast.IsConstructorDeclaration(node.Parent) && !(ast.IsMethodDeclaration(node.Parent) || ast.IsSetAccessorDeclaration(node.Parent) && ast.IsClassLike(node.Parent.Parent)) { break @@ -27956,9 +27956,9 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur if hasPropDesc { descriptorType := c.newTypedPropertyDescriptorType(c.getTypeOfNode(node)) descriptorParam := c.newParameter("descriptor", descriptorType) - links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam, descriptorParam}, c.GetUnionType([]*Type{returnType, c.voidType})) + links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam, descriptorParam}, c.getUnionType([]*Type{returnType, c.voidType})) } else { - links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam}, c.GetUnionType([]*Type{returnType, c.voidType})) + links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam}, c.getUnionType([]*Type{returnType, c.voidType})) } } } @@ -28237,7 +28237,7 @@ func (c *Checker) newClassFieldDecoratorInitializerMutatorType(thisType *Type, v func (c *Checker) newESDecoratorCallSignature(targetType *Type, contextType *Type, nonOptionalReturnType *Type) *Signature { targetParam := c.newParameter("target", targetType) contextParam := c.newParameter("context", contextType) - returnType := c.GetUnionType([]*Type{nonOptionalReturnType, c.voidType}) + returnType := c.getUnionType([]*Type{nonOptionalReturnType, c.voidType}) return c.newCallSignature(nil, nil /*thisParameter*/, []*ast.Symbol{targetParam, contextParam}, returnType) } @@ -28289,7 +28289,7 @@ func (c *Checker) getClassElementPropertyKeyType(element *ast.Node) *Type { panic("Unhandled case in getClassElementPropertyKeyType") } -func (c *Checker) GetTypeOfPropertyOfContextualType(t *Type, name string) *Type { +func (c *Checker) getTypeOfPropertyOfContextualType(t *Type, name string) *Type { return c.getTypeOfPropertyOfContextualTypeEx(t, name, nil) } @@ -28513,7 +28513,7 @@ func (c *Checker) discriminateContextualTypeByObjectMembers(node *ast.Node, cont } return false }) - discriminantMembers := core.Filter(c.GetPropertiesOfType(contextualType), func(s *ast.Symbol) bool { + discriminantMembers := core.Filter(c.getPropertiesOfType(contextualType), func(s *ast.Symbol) bool { return s.Flags&ast.SymbolFlagsOptional != 0 && node.Symbol().Members[s.Name] == nil && c.isDiscriminantProperty(contextualType, s.Name) }) discriminator := &ObjectLiteralDiscriminator{c: c, props: discriminantProperties, members: discriminantMembers} @@ -28908,7 +28908,7 @@ func (c *Checker) removeNullableByIntersection(t *Type, targetFacts TypeFacts, o return t } // By default we intersect with a union of {} and the opposite nullable. - emptyAndOtherUnion := c.GetUnionType([]*Type{c.emptyObjectType, otherType}) + emptyAndOtherUnion := c.getUnionType([]*Type{c.emptyObjectType, otherType}) // For each constituent type that can compare equal to the target nullable, intersect with the above union // if the type doesn't already include the opposite nullable and the constituent can compare equal to the // opposite nullable; otherwise, just intersect with {}. @@ -29425,7 +29425,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy objectType = c.getTypeOfExpression(parent.Expression()) } } else if ast.IsLiteralTypeNode(parent) && ast.IsIndexedAccessTypeNode(grandParent) { - objectType = c.GetTypeFromTypeNode(grandParent.AsIndexedAccessTypeNode().ObjectType) + objectType = c.getTypeFromTypeNode(grandParent.AsIndexedAccessTypeNode().ObjectType) } if objectType != nil { @@ -29504,7 +29504,7 @@ func (c *Checker) getSymbolOfNameOrPropertyAccessExpression(name *ast.Node) *ast if ast.IsEntityName(name) { possibleImportNode := isImportTypeQualifierPart(name) if possibleImportNode != nil { - c.GetTypeFromTypeNode(possibleImportNode) + c.getTypeFromTypeNode(possibleImportNode) sym := c.getResolvedSymbolOrNil(name) return core.IfElse(sym == c.unknownSymbol, nil, sym) } @@ -29632,7 +29632,7 @@ func (c *Checker) getTypeOfNode(node *ast.Node) *Type { } if ast.IsPartOfTypeNode(node) { - typeFromTypeNode := c.GetTypeFromTypeNode(node) + typeFromTypeNode := c.getTypeFromTypeNode(node) if classType != nil { return c.getTypeWithThisArgument( typeFromTypeNode, diff --git a/internal/checker/exports.go b/internal/checker/exports.go new file mode 100644 index 0000000000..4bf67fbba0 --- /dev/null +++ b/internal/checker/exports.go @@ -0,0 +1,50 @@ +package checker + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/diagnostics" +) + +func (c *Checker) GetUnionType(types []*Type) *Type { + return c.getUnionType(types) +} + +func (c *Checker) GetGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { + return c.getGlobalSymbol(name, meaning, diagnostic) +} + +func (c *Checker) GetTypeFromTypeNode(node *ast.Node) *Type { + return c.getTypeFromTypeNode(node) +} + +func (c *Checker) IsArrayLikeType(t *Type) bool { + return c.isArrayLikeType(t) +} + +func (c *Checker) GetPropertiesOfType(t *Type) []*ast.Symbol { + return c.getPropertiesOfType(t) +} + +func (c *Checker) TypeHasCallOrConstructSignatures(t *Type) bool { + return c.typeHasCallOrConstructSignatures(t) +} + +// Checks if a property can be accessed in a location. +// The location is given by the `node` parameter. +// The node does not need to be a property access. +// @param node location where to check property accessibility +// @param isSuper whether to consider this a `super` property access, e.g. `super.foo`. +// @param isWrite whether this is a write access, e.g. `++foo.x`. +// @param containingType type where the property comes from. +// @param property property symbol. +func (c *Checker) IsPropertyAccessible(node *ast.Node, isSuper bool, isWrite bool, containingType *Type, property *ast.Symbol) bool { + return c.isPropertyAccessible(node, isSuper, isWrite, containingType, property) +} + +func (c *Checker) GetTypeOfPropertyOfContextualType(t *Type, name string) *Type { + return c.getTypeOfPropertyOfContextualType(t, name) +} + +func GetDeclarationModifierFlagsFromSymbol(s *ast.Symbol) ast.ModifierFlags { + return getDeclarationModifierFlagsFromSymbol(s) +} diff --git a/internal/checker/flow.go b/internal/checker/flow.go index c816d11f82..58dcf30b9c 100644 --- a/internal/checker/flow.go +++ b/internal/checker/flow.go @@ -333,7 +333,7 @@ func (c *Checker) narrowTypeByAssertion(f *FlowState, t *Type, expr *ast.Node) * return c.narrowTypeByAssertion(f, c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Left), node.AsBinaryExpression().Right) } if node.AsBinaryExpression().OperatorToken.Kind == ast.KindBarBarToken { - return c.GetUnionType([]*Type{c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Left), c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Right)}) + return c.getUnionType([]*Type{c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Left), c.narrowTypeByAssertion(f, t, node.AsBinaryExpression().Right)}) } } return c.narrowType(f, t, node, true /*assumeTrue*/) @@ -531,10 +531,10 @@ func (c *Checker) narrowTypeByBinaryExpression(f *FlowState, t *Type, expr *ast. if assumeTrue { return c.narrowType(f, c.narrowType(f, t, expr.Left, true /*assumeTrue*/), expr.Right, true /*assumeTrue*/) } - return c.GetUnionType([]*Type{c.narrowType(f, t, expr.Left, false /*assumeTrue*/), c.narrowType(f, t, expr.Right, false /*assumeTrue*/)}) + return c.getUnionType([]*Type{c.narrowType(f, t, expr.Left, false /*assumeTrue*/), c.narrowType(f, t, expr.Right, false /*assumeTrue*/)}) case ast.KindBarBarToken: if assumeTrue { - return c.GetUnionType([]*Type{c.narrowType(f, t, expr.Left, true /*assumeTrue*/), c.narrowType(f, t, expr.Right, true /*assumeTrue*/)}) + return c.getUnionType([]*Type{c.narrowType(f, t, expr.Left, true /*assumeTrue*/), c.narrowType(f, t, expr.Right, true /*assumeTrue*/)}) } return c.narrowType(f, c.narrowType(f, t, expr.Left, false /*assumeTrue*/), expr.Right, false /*assumeTrue*/) } @@ -646,7 +646,7 @@ func (c *Checker) narrowTypeByTypeName(t *Type, typeName string) *Type { if t.flags&TypeFlagsAny != 0 { return t } - return c.GetUnionType([]*Type{c.narrowTypeByTypeFacts(t, c.nonPrimitiveType, TypeFactsTypeofEQObject), c.narrowTypeByTypeFacts(t, c.nullType, TypeFactsEQNull)}) + return c.getUnionType([]*Type{c.narrowTypeByTypeFacts(t, c.nonPrimitiveType, TypeFactsTypeofEQObject), c.narrowTypeByTypeFacts(t, c.nullType, TypeFactsEQNull)}) case "function": if t.flags&TypeFlagsAny != 0 { return t @@ -942,7 +942,7 @@ func (c *Checker) getInstanceType(constructorType *Type) *Type { } constructSignatures := c.getSignaturesOfType(constructorType, SignatureKindConstruct) if len(constructSignatures) != 0 { - return c.GetUnionType(core.Map(constructSignatures, func(signature *Signature) *Type { + return c.getUnionType(core.Map(constructSignatures, func(signature *Signature) *Type { return c.getReturnTypeOfSignature(c.getErasedSignature(signature)) })) } @@ -1087,9 +1087,9 @@ func (c *Checker) narrowTypeBySwitchOnDiscriminant(t *Type, data *ast.FlowSwitch return t } } - return c.GetUnionType(core.IfElse(groundClauseTypes == nil, clauseTypes, groundClauseTypes)) + return c.getUnionType(core.IfElse(groundClauseTypes == nil, clauseTypes, groundClauseTypes)) } - discriminantType := c.GetUnionType(clauseTypes) + discriminantType := c.getUnionType(clauseTypes) var caseType *Type if discriminantType.flags&TypeFlagsNever != 0 { caseType = c.neverType @@ -1113,7 +1113,7 @@ func (c *Checker) narrowTypeBySwitchOnDiscriminant(t *Type, data *ast.FlowSwitch if caseType.flags&TypeFlagsNever != 0 { return defaultType } - return c.GetUnionType([]*Type{caseType, defaultType}) + return c.getUnionType([]*Type{caseType, defaultType}) } func (c *Checker) narrowTypeBySwitchOnTypeOf(t *Type, data *ast.FlowSwitchClauseData) *Type { @@ -1138,7 +1138,7 @@ func (c *Checker) narrowTypeBySwitchOnTypeOf(t *Type, data *ast.FlowSwitchClause } // In the non-default cause we create a union of the type narrowed by each of the listed cases. clauseWitnesses := witnesses[clauseStart:clauseEnd] - return c.GetUnionType(core.Map(clauseWitnesses, func(text string) *Type { + return c.getUnionType(core.Map(clauseWitnesses, func(text string) *Type { if text != "" { return c.narrowTypeByTypeName(t, text) } @@ -1174,7 +1174,7 @@ func (c *Checker) narrowTypeBySwitchOnTrue(f *FlowState, t *Type, data *ast.Flow return t } // Now, narrow based on the cases in this set. - return c.GetUnionType(core.Map(clauses[clauseStart:clauseEnd], func(clause *ast.Node) *Type { + return c.getUnionType(core.Map(clauses[clauseStart:clauseEnd], func(clause *ast.Node) *Type { if clause.Kind == ast.KindCaseClause { return c.narrowType(f, t, clause.Expression(), true /*assumeTrue*/) } @@ -1195,7 +1195,7 @@ func (c *Checker) narrowTypeBySwitchOnDiscriminantProperty(t *Type, access *ast. accessedName, _ := c.getAccessedPropertyName(access) if accessedName != "" && c.getKeyPropertyName(t) == accessedName { clauseTypes := c.getSwitchClauseTypes(data.SwitchStatement)[data.ClauseStart:data.ClauseEnd] - candidate := c.GetUnionType(core.Map(clauseTypes, func(s *Type) *Type { + candidate := c.getUnionType(core.Map(clauseTypes, func(s *Type) *Type { result := c.getConstituentTypeForKeyType(t, s) if result != nil { return result @@ -1275,7 +1275,7 @@ func (c *Checker) getTypeAtFlowBranchLabel(f *FlowState, flow *ast.FlowNode, ant // finalize all evolving array types. func (c *Checker) getUnionOrEvolvingArrayType(f *FlowState, types []*Type, subtypeReduction UnionReduction) *Type { if isEvolvingArrayTypeList(types) { - return c.getEvolvingArrayType(c.GetUnionType(core.Map(types, c.getElementTypeOfEvolvingArrayType))) + return c.getEvolvingArrayType(c.getUnionType(core.Map(types, c.getElementTypeOfEvolvingArrayType))) } result := c.recombineUnknownType(c.getUnionTypeEx(core.SameMap(types, c.finalizeEvolvingArrayType), subtypeReduction, nil, nil)) if result != f.declaredType && result.flags&f.declaredType.flags&TypeFlagsUnion != 0 && slices.Equal(result.AsUnionType().types, f.declaredType.AsUnionType().types) { @@ -1516,7 +1516,7 @@ func (c *Checker) addEvolvingArrayElementType(evolvingArrayType *Type, node *ast if c.isTypeSubsetOf(newElementType, elementType) { return evolvingArrayType } - return c.getEvolvingArrayType(c.GetUnionType([]*Type{elementType, newElementType})) + return c.getEvolvingArrayType(c.getUnionType([]*Type{elementType, newElementType})) } func (c *Checker) finalizeEvolvingArrayType(t *Type) *Type { @@ -2290,7 +2290,7 @@ func (c *Checker) getTypeOfDestructuredArrayElement(t *Type, index int) *Type { func (c *Checker) includeUndefinedInIndexSignature(t *Type) *Type { if c.compilerOptions.NoUncheckedIndexedAccess == core.TSTrue { - return c.GetUnionType([]*Type{t, c.missingType}) + return c.getUnionType([]*Type{t, c.missingType}) } return t } @@ -2337,7 +2337,7 @@ func (c *Checker) isDestructuringAssignmentTarget(parent *ast.Node) bool { func (c *Checker) getTypeWithDefault(t *Type, defaultExpression *ast.Node) *Type { if defaultExpression != nil { - return c.GetUnionType([]*Type{c.getNonUndefinedType(t), c.getTypeOfExpression(defaultExpression)}) + return c.getUnionType([]*Type{c.getNonUndefinedType(t), c.getTypeOfExpression(defaultExpression)}) } return t } diff --git a/internal/checker/grammarchecks.go b/internal/checker/grammarchecks.go index 12cf378760..3a6363e567 100644 --- a/internal/checker/grammarchecks.go +++ b/internal/checker/grammarchecks.go @@ -835,7 +835,7 @@ func (c *Checker) checkGrammarIndexSignatureParameters(node *ast.IndexSignatureD if typeNode == nil { return c.grammarErrorOnNode(parameter.Name(), diagnostics.An_index_signature_parameter_must_have_a_type_annotation) } - t := c.GetTypeFromTypeNode(typeNode) + t := c.getTypeFromTypeNode(typeNode) if someType(t, func(t *Type) bool { return t.flags&TypeFlagsStringOrNumberLiteralOrUnique != 0 }) || c.isGenericType(t) { diff --git a/internal/checker/inference.go b/internal/checker/inference.go index e08a2b5264..80e465aada 100644 --- a/internal/checker/inference.go +++ b/internal/checker/inference.go @@ -108,7 +108,7 @@ func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type) if len(targets) == 0 { return } - target = c.GetUnionType(targets) + target = c.getUnionType(targets) if len(sources) == 0 { // All source constituents have been matched and there is nothing further to infer from. // However, simply making no inferences is undesirable because it could ultimately mean @@ -118,7 +118,7 @@ func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type) c.inferWithPriority(n, source, target, InferencePriorityNakedTypeVariable) return } - source = c.GetUnionType(sources) + source = c.getUnionType(sources) } else if target.flags&TypeFlagsIntersection != 0 && !core.Every(target.Types(), c.isNonGenericObjectType) { // We reduce intersection types unless they're simple combinations of object types. For example, // when inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and @@ -436,7 +436,7 @@ func (c *Checker) inferToMultipleTypes(n *InferenceState, source *Type, targets } } if len(unmatched) != 0 { - c.inferFromTypes(n, c.GetUnionType(unmatched), nakedTypeVariable) + c.inferFromTypes(n, c.getUnionType(unmatched), nakedTypeVariable) return } } @@ -848,7 +848,7 @@ func (c *Checker) inferFromIndexTypes(n *InferenceState, source *Type, target *T if c.isObjectTypeWithInferableIndex(source) { for _, targetInfo := range indexInfos { var propTypes []*Type - for _, prop := range c.GetPropertiesOfType(source) { + for _, prop := range c.getPropertiesOfType(source) { if c.isApplicableIndexType(c.getLiteralTypeFromProperty(prop, TypeFlagsStringOrNumberLiteralOrUnique, false), targetInfo.keyType) { propType := c.getTypeOfSymbol(prop) if prop.Flags&ast.SymbolFlagsOptional != 0 { @@ -863,7 +863,7 @@ func (c *Checker) inferFromIndexTypes(n *InferenceState, source *Type, target *T } } if len(propTypes) != 0 { - c.inferWithPriority(n, c.GetUnionType(propTypes), targetInfo.valueType, priority) + c.inferWithPriority(n, c.getUnionType(propTypes), targetInfo.valueType, priority) } } } @@ -914,14 +914,14 @@ func (c *Checker) inferToMappedType(n *InferenceState, source *Type, target *Typ } // If no inferences can be made to K's constraint, infer from a union of the property types // in the source to the template type X. - propTypes := core.Map(c.GetPropertiesOfType(source), c.getTypeOfSymbol) + propTypes := core.Map(c.getPropertiesOfType(source), c.getTypeOfSymbol) indexTypes := core.Map(c.getIndexInfosOfType(source), func(info *IndexInfo) *Type { if info != c.enumNumberIndexInfo { return info.valueType } return c.neverType }) - c.inferFromTypes(n, c.GetUnionType(core.Concatenate(propTypes, indexTypes)), c.getTemplateTypeFromMappedType(target)) + c.inferFromTypes(n, c.getUnionType(core.Concatenate(propTypes, indexTypes)), c.getTemplateTypeFromMappedType(target)) return true } return false @@ -944,7 +944,7 @@ func (c *Checker) inferTypeForHomomorphicMappedType(source *Type, target *Type, func (c *Checker) createReverseMappedType(source *Type, target *Type, constraint *Type) *Type { // We consider a source type reverse mappable if it has a string index signature or if // it has one or more properties and is of a partially inferable type. - if !(c.getIndexInfoOfType(source, c.stringType) != nil || len(c.GetPropertiesOfType(source)) != 0 && c.isPartiallyInferableType(source)) { + if !(c.getIndexInfoOfType(source, c.stringType) != nil || len(c.getPropertiesOfType(source)) != 0 && c.isPartiallyInferableType(source)) { return nil } // For arrays and tuples we infer new arrays and tuples where the reverse mapping has been @@ -988,7 +988,7 @@ func (c *Checker) createReverseMappedType(source *Type, target *Type, constraint // literal { a: 123, b: x => true } is marked non-inferable because it contains a context sensitive // arrow function, but is considered partially inferable because property 'a' has an inferable type. func (c *Checker) isPartiallyInferableType(t *Type) bool { - return t.objectFlags&ObjectFlagsNonInferrableType == 0 || isObjectLiteralType(t) && core.Some(c.GetPropertiesOfType(t), func(prop *ast.Symbol) bool { + return t.objectFlags&ObjectFlagsNonInferrableType == 0 || isObjectLiteralType(t) && core.Some(c.getPropertiesOfType(t), func(prop *ast.Symbol) bool { return c.isPartiallyInferableType(c.getTypeOfSymbol(prop)) }) || isTupleType(t) && core.Some(c.getElementTypes(t), c.isPartiallyInferableType) } @@ -1038,7 +1038,7 @@ func (c *Checker) resolveReverseMappedTypeMembers(t *Type) { } members := make(ast.SymbolTable) limitedConstraint := c.getLimitedConstraint(t) - for _, prop := range c.GetPropertiesOfType(r.source) { + for _, prop := range c.getPropertiesOfType(r.source) { // In case of a reverse mapped type with an intersection constraint, if we were able to // extract the filtering type literals we skip those properties that are not assignable to them, // because the extra properties wouldn't get through the application of the mapped type anyway @@ -1459,7 +1459,7 @@ func (c *Checker) getCommonSupertype(types []*Type) *Type { // right is a supertype. var supertype *Type if c.literalTypesWithSameBaseType(primaryTypes) { - supertype = c.GetUnionType(primaryTypes) + supertype = c.getUnionType(primaryTypes) } else { for _, t := range primaryTypes { if supertype == nil || c.isTypeSubtypeOf(supertype, t) { diff --git a/internal/checker/jsx.go b/internal/checker/jsx.go index 42e70aaf7a..10a172eec6 100644 --- a/internal/checker/jsx.go +++ b/internal/checker/jsx.go @@ -177,7 +177,7 @@ func (c *Checker) checkJsxReturnAssignableToAppropriateBound(refKind JsxReferenc if sfcReturnConstraint == nil || classConstraint == nil { return } - combined := c.GetUnionType([]*Type{sfcReturnConstraint, classConstraint}) + combined := c.getUnionType([]*Type{sfcReturnConstraint, classConstraint}) c.checkTypeRelatedToEx(elemInstanceType, combined, c.assignableRelation, openingLikeElement.TagName(), diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, &diags) } if len(diags) != 0 { @@ -211,7 +211,7 @@ func (c *Checker) getContextualTypeForJsxAttribute(attribute *ast.Node, contextF if attributesType == nil || IsTypeAny(attributesType) { return nil } - return c.GetTypeOfPropertyOfContextualType(attributesType, attribute.Name().Text()) + return c.getTypeOfPropertyOfContextualType(attributesType, attribute.Name().Text()) } return c.getContextualType(attribute.Parent, contextFlags) } @@ -238,7 +238,7 @@ func (c *Checker) getContextualTypeForChildJsxExpression(node *ast.Node, child * } realChildren := getSemanticJsxChildren(node.Children().Nodes) childIndex := slices.Index(realChildren, child) - childFieldType := c.GetTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) + childFieldType := c.getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) if childFieldType == nil { return nil } @@ -246,7 +246,7 @@ func (c *Checker) getContextualTypeForChildJsxExpression(node *ast.Node, child * return childFieldType } return c.mapTypeEx(childFieldType, func(t *Type) *Type { - if c.IsArrayLikeType(t) { + if c.isArrayLikeType(t) { return c.getIndexedAccessType(t, c.getNumberLiteralType(jsnum.Number(childIndex))) } return t @@ -267,7 +267,7 @@ func (c *Checker) discriminateContextualTypeByJSXAttributes(node *ast.Node, cont initializer := p.Initializer() return (initializer == nil || c.isPossiblyDiscriminantValue(initializer)) && c.isDiscriminantProperty(contextualType, symbol.Name) }) - discriminantMembers := core.Filter(c.GetPropertiesOfType(contextualType), func(s *ast.Symbol) bool { + discriminantMembers := core.Filter(c.getPropertiesOfType(contextualType), func(s *ast.Symbol) bool { if s.Flags&ast.SymbolFlagsOptional == 0 || node.Symbol() == nil || len(node.Symbol().Members) == 0 { return false } @@ -418,7 +418,7 @@ func (c *Checker) elaborateIterableOrArrayLikeTargetElementwise(iterator iter.Se } if targetIndexedPropType != nil && targetIndexedPropType.flags&TypeFlagsIndexedAccess == 0 { if iterationType != nil { - targetPropType = c.GetUnionType([]*Type{iterationType, targetIndexedPropType}) + targetPropType = c.getUnionType([]*Type{iterationType, targetIndexedPropType}) } else { targetPropType = targetIndexedPropType } @@ -461,7 +461,7 @@ func (c *Checker) elaborateIterableOrArrayLikeTargetElementwise(iterator iter.Se } func (c *Checker) getSuggestedSymbolForNonexistentJSXAttribute(name string, containingType *Type) *ast.Symbol { - properties := c.GetPropertiesOfType(containingType) + properties := c.getPropertiesOfType(containingType) var jsxSpecific *ast.Symbol switch name { case "for": @@ -715,7 +715,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme } var childrenContextualType *Type if contextualType := c.getApparentTypeOfContextualType(openingLikeElement.Attributes(), ContextFlagsNone); contextualType != nil { - childrenContextualType = c.GetTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName) + childrenContextualType = c.getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName) } // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process childrenPropSymbol := c.newSymbol(ast.SymbolFlagsProperty, jsxChildrenPropertyName) @@ -726,7 +726,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme case childrenContextualType != nil && someType(childrenContextualType, c.isTupleLikeType): links.resolvedType = c.createTupleType(childTypes) default: - links.resolvedType = c.createArrayType(c.GetUnionType(childTypes)) + links.resolvedType = c.createArrayType(c.getUnionType(childTypes)) } // Fake up a property declaration for the children childrenPropSymbol.ValueDeclaration = c.factory.NewPropertySignatureDeclaration(nil, c.factory.NewIdentifier(jsxChildrenPropertyName), nil /*postfixToken*/, nil /*type*/, nil /*initializer*/) @@ -989,7 +989,7 @@ func (c *Checker) getNameFromJsxElementAttributesContainer(nameOfAttribPropConta jsxElementAttribPropInterfaceSym := c.getSymbol(jsxNamespace.Exports, nameOfAttribPropContainer, ast.SymbolFlagsType) if jsxElementAttribPropInterfaceSym != nil { jsxElementAttribPropInterfaceType := c.getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym) - propertiesOfJsxElementAttribPropInterface := c.GetPropertiesOfType(jsxElementAttribPropInterfaceType) + propertiesOfJsxElementAttribPropInterface := c.getPropertiesOfType(jsxElementAttribPropInterfaceType) // Element Attributes has zero properties, so the element attributes type will be the class instance type if len(propertiesOfJsxElementAttribPropInterface) == 0 { return "" @@ -1151,7 +1151,7 @@ func (c *Checker) getJsxStatelessElementTypeAt(location *ast.Node) *Type { if jsxElementType == nil { return nil } - return c.GetUnionType([]*Type{jsxElementType, c.nullType}) + return c.getUnionType([]*Type{jsxElementType, c.nullType}) } func (c *Checker) getJsxElementClassTypeAt(location *ast.Node) *Type { @@ -1221,7 +1221,7 @@ func (c *Checker) getJsxNamespaceAt(location *ast.Node) *ast.Symbol { } } // JSX global fallback - s := c.resolveSymbol(c.GetGlobalSymbol(JsxNames.JSX, ast.SymbolFlagsNamespace, nil /*diagnostic*/)) + s := c.resolveSymbol(c.getGlobalSymbol(JsxNames.JSX, ast.SymbolFlagsNamespace, nil /*diagnostic*/)) if s == c.unknownSymbol { return nil } diff --git a/internal/checker/relater.go b/internal/checker/relater.go index 770349d084..56dfb8cdd8 100644 --- a/internal/checker/relater.go +++ b/internal/checker/relater.go @@ -294,7 +294,7 @@ func (c *Checker) isEnumTypeRelatedTo(source *ast.Symbol, target *ast.Symbol, er return entry&RelationComparisonResultSucceeded != 0 } targetEnumType := c.getTypeOfSymbol(targetSymbol) - for _, sourceProperty := range c.GetPropertiesOfType(c.getTypeOfSymbol(sourceSymbol)) { + for _, sourceProperty := range c.getPropertiesOfType(c.getTypeOfSymbol(sourceSymbol)) { if sourceProperty.Flags&ast.SymbolFlagsEnumMember != 0 { targetProperty := c.getPropertyOfType(targetEnumType, sourceProperty.Name) if targetProperty == nil || targetProperty.Flags&ast.SymbolFlagsEnumMember == 0 { @@ -645,7 +645,7 @@ func (c *Checker) elaborateArrowFunction(node *ast.Node, source *Type, target *T } returnExpression := node.Body() sourceReturn := c.getReturnTypeOfSignature(sourceSig) - targetReturn := c.GetUnionType(core.Map(targetSignatures, c.getReturnTypeOfSignature)) + targetReturn := c.getUnionType(core.Map(targetSignatures, c.getReturnTypeOfSignature)) if c.checkTypeRelatedTo(sourceReturn, targetReturn, relation, nil /*errorNode*/) { return false } @@ -687,7 +687,7 @@ func (c *Checker) isWeakType(t *Type) bool { } func (c *Checker) hasCommonProperties(source *Type, target *Type, isComparingJsxAttributes bool) bool { - for _, prop := range c.GetPropertiesOfType(source) { + for _, prop := range c.getPropertiesOfType(source) { if c.isKnownProperty(target, prop.Name, isComparingJsxAttributes) { return true } @@ -940,8 +940,8 @@ func (c *Checker) findMostOverlappyType(source *Type, unionTarget *Type) *Type { } func (c *Checker) findBestTypeForObjectLiteral(source *Type, unionTarget *Type) *Type { - if source.objectFlags&ObjectFlagsObjectLiteral != 0 && someType(unionTarget, c.IsArrayLikeType) { - return core.Find(unionTarget.Types(), func(t *Type) bool { return !c.IsArrayLikeType(t) }) + if source.objectFlags&ObjectFlagsObjectLiteral != 0 && someType(unionTarget, c.isArrayLikeType) { + return core.Find(unionTarget.Types(), func(t *Type) bool { return !c.isArrayLikeType(t) }) } return nil } @@ -972,7 +972,7 @@ func (c *Checker) getUnmatchedProperties(source *Type, target *Type, requireOpti } func (c *Checker) getUnmatchedPropertiesWorker(source *Type, target *Type, requireOptionalProperties bool, matchDiscriminantProperties bool, propsOut *[]*ast.Symbol) *ast.Symbol { - properties := c.GetPropertiesOfType(target) + properties := c.getPropertiesOfType(target) for _, targetProp := range properties { // TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass if isStaticPrivateIdentifierProperty(targetProp) { @@ -1054,7 +1054,7 @@ func (c *Checker) findMatchingDiscriminantType(source *Type, target *Type, isRel if match := c.getMatchingUnionConstituentForType(target, source); match != nil { return match } - discriminantProperties := c.findDiscriminantProperties(c.GetPropertiesOfType(source), target) + discriminantProperties := c.findDiscriminantProperties(c.getPropertiesOfType(source), target) discriminator := &TypeDiscriminator{c: c, props: discriminantProperties, isRelatedTo: isRelatedTo} discriminated := c.discriminateTypeByDiscriminableItems(target, discriminator) if discriminated != target { @@ -1149,7 +1149,7 @@ func isObjectOrInstantiableNonPrimitive(t *Type) bool { func (c *Checker) getKeyPropertyCandidateName(types []*Type) string { for _, t := range types { if t.flags&(TypeFlagsObject|TypeFlagsInstantiableNonPrimitive) != 0 { - for _, p := range c.GetPropertiesOfType(t) { + for _, p := range c.getPropertiesOfType(t) { if isUnitType(c.getTypeOfSymbol(p)) { return p.Name } @@ -1871,7 +1871,7 @@ func (c *Checker) getKnownKeysOfTupleType(t *Type) *Type { keys[i] = c.getStringLiteralType(strconv.Itoa(i)) } keys[fixedLength] = c.getIndexType(core.IfElse(t.TargetTupleType().readonly, c.globalReadonlyArrayType, c.globalArrayType)) - return c.GetUnionType(keys) + return c.getUnionType(keys) } func (c *Checker) getRestArrayTypeOfTupleType(t *Type) *Type { @@ -2055,7 +2055,7 @@ func (c *Checker) createTypePredicateFromTypePredicateNode(node *ast.Node, signa predicateNode := node.AsTypePredicateNode() var t *Type if predicateNode.Type != nil { - t = c.GetTypeFromTypeNode(predicateNode.Type) + t = c.getTypeFromTypeNode(predicateNode.Type) } if ast.IsThisTypeNode(predicateNode.ParameterName) { kind := core.IfElse(predicateNode.AssertsModifier != nil, TypePredicateKindAssertsThis, TypePredicateKindThis) @@ -2627,7 +2627,7 @@ func (r *Relater) isRelatedToEx(originalSource *Type, originalTarget *Type, recu isPerformingCommonPropertyChecks := (r.relation != r.c.comparableRelation || isUnitType(source)) && intersectionState&IntersectionStateTarget == 0 && source.flags&(TypeFlagsPrimitive|TypeFlagsObject|TypeFlagsIntersection) != 0 && source != r.c.globalObjectType && - target.flags&(TypeFlagsObject|TypeFlagsIntersection) != 0 && r.c.isWeakType(target) && (len(r.c.GetPropertiesOfType(source)) > 0 || r.c.TypeHasCallOrConstructSignatures(source)) + target.flags&(TypeFlagsObject|TypeFlagsIntersection) != 0 && r.c.isWeakType(target) && (len(r.c.getPropertiesOfType(source)) > 0 || r.c.typeHasCallOrConstructSignatures(source)) isComparingJsxAttributes := source.objectFlags&ObjectFlagsJsxAttributes != 0 if isPerformingCommonPropertyChecks && !r.c.hasCommonProperties(source, target, isComparingJsxAttributes) { if reportErrors { @@ -2680,7 +2680,7 @@ func (r *Relater) hasExcessProperties(source *Type, target *Type, reportErrors b } checkTypes = reducedTarget.Distributed() } - for _, prop := range r.c.GetPropertiesOfType(source) { + for _, prop := range r.c.getPropertiesOfType(source) { if shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop) { if !r.c.isKnownProperty(reducedTarget, prop.Name, isComparingJsxAttributes) { if reportErrors { @@ -2749,7 +2749,7 @@ func (c *Checker) getTypeOfPropertyInTypes(types []*Type, name string) *Type { for _, t := range types { propTypes = append(propTypes, c.getTypeOfPropertyInType(t, name)) } - return c.GetUnionType(propTypes) + return c.getUnionType(propTypes) } func (c *Checker) getTypeOfPropertyInType(t *Type, name string) *Type { @@ -3459,7 +3459,7 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo // missing from the `constraintType` which will otherwise be mapped in the object mappedKeys := r.c.getApparentMappedTypeKeys(nameType, targetType) // We still need to include the non-apparent (and thus still generic) keys in the target side of the comparison (in case they're in the source side) - targetKeys = r.c.GetUnionType([]*Type{mappedKeys, nameType}) + targetKeys = r.c.getUnionType([]*Type{mappedKeys, nameType}) } else if nameType != nil { targetKeys = nameType } else { @@ -3923,7 +3923,7 @@ func (r *Relater) typeRelatedToDiscriminatedType(source *Type, target *Type) Ter // // NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts // for examples. - sourceProperties := r.c.GetPropertiesOfType(source) + sourceProperties := r.c.getPropertiesOfType(source) sourcePropertiesFiltered := r.c.findDiscriminantProperties(sourceProperties, target) if len(sourcePropertiesFiltered) == 0 { return TernaryFalse @@ -4152,7 +4152,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b return TernaryFalse } if isObjectLiteralType(target) { - for _, sourceProp := range excludeProperties(r.c.GetPropertiesOfType(source), excludedProperties) { + for _, sourceProp := range excludeProperties(r.c.getPropertiesOfType(source), excludedProperties) { if r.c.getPropertyOfObjectType(target, sourceProp.Name) == nil { sourceType := r.c.getTypeOfSymbol(sourceProp) if sourceType.flags&TypeFlagsUndefined == 0 { @@ -4166,7 +4166,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b } // We only call this for union target types when we're attempting to do excess property checking - in those cases, we want to get _all possible props_ // from the target union, across all members - properties := r.c.GetPropertiesOfType(target) + properties := r.c.getPropertiesOfType(target) numericNamesOnly := isTupleType(source) && isTupleType(target) for _, targetProp := range excludeProperties(properties, excludedProperties) { name := targetProp.Name @@ -4185,8 +4185,8 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b } func (r *Relater) propertyRelatedTo(source *Type, target *Type, sourceProp *ast.Symbol, targetProp *ast.Symbol, getTypeOfSourceProperty func(sym *ast.Symbol) *Type, reportErrors bool, intersectionState IntersectionState, skipOptional bool) Ternary { - sourcePropFlags := GetDeclarationModifierFlagsFromSymbol(sourceProp) - targetPropFlags := GetDeclarationModifierFlagsFromSymbol(targetProp) + sourcePropFlags := getDeclarationModifierFlagsFromSymbol(sourceProp) + targetPropFlags := getDeclarationModifierFlagsFromSymbol(targetProp) switch { case sourcePropFlags&ast.ModifierFlagsPrivate != 0 || targetPropFlags&ast.ModifierFlagsPrivate != 0: if sourceProp.ValueDeclaration != targetProp.ValueDeclaration { @@ -4537,7 +4537,7 @@ func (c *Checker) isObjectTypeWithInferableIndex(t *Type) bool { return core.Every(t.Types(), c.isObjectTypeWithInferableIndex) } return t.symbol != nil && t.symbol.Flags&(ast.SymbolFlagsObjectLiteral|ast.SymbolFlagsTypeLiteral|ast.SymbolFlagsEnum|ast.SymbolFlagsValueModule) != 0 && - t.symbol.Flags&ast.SymbolFlagsClass == 0 && !c.TypeHasCallOrConstructSignatures(t) || + t.symbol.Flags&ast.SymbolFlagsClass == 0 && !c.typeHasCallOrConstructSignatures(t) || t.objectFlags&ObjectFlagsObjectRestType != 0 || t.objectFlags&ObjectFlagsReverseMapped != 0 && c.isObjectTypeWithInferableIndex(t.AsReverseMappedType().source) } diff --git a/internal/checker/services.go b/internal/checker/services.go index 0181c074ad..ea4394b498 100644 --- a/internal/checker/services.go +++ b/internal/checker/services.go @@ -131,7 +131,7 @@ func (c *Checker) isValidPropertyAccess(node *ast.Node, propertyName string) boo case ast.KindQualifiedName: return c.isValidPropertyAccessWithType(node, false /*isSuper*/, propertyName, c.getWidenedType(c.checkExpression(node.AsQualifiedName().Left))) case ast.KindImportType: - return c.isValidPropertyAccessWithType(node, false /*isSuper*/, propertyName, c.GetTypeFromTypeNode(node)) + return c.isValidPropertyAccessWithType(node, false /*isSuper*/, propertyName, c.getTypeFromTypeNode(node)) } panic("Unexpected node kind in isValidPropertyAccess: " + node.Kind.String()) } @@ -143,7 +143,7 @@ func (c *Checker) isValidPropertyAccessWithType(node *ast.Node, isSuper bool, pr } prop := c.getPropertyOfType(t, propertyName) - return prop != nil && c.IsPropertyAccessible(node, isSuper, false /*isWrite*/, t, prop) + return prop != nil && c.isPropertyAccessible(node, isSuper, false /*isWrite*/, t, prop) } // Checks if an existing property access is valid for completions purposes. @@ -155,7 +155,7 @@ func (c *Checker) isValidPropertyAccessWithType(node *ast.Node, isSuper bool, pr // type: the type whose property we are checking. // property: the accessed property's symbol. func (c *Checker) IsValidPropertyAccessForCompletions(node *ast.Node, t *Type, property *ast.Symbol) bool { - return c.IsPropertyAccessible( + return c.isPropertyAccessible( node, node.Kind == ast.KindPropertyAccessExpression && node.Expression().Kind == ast.KindSuperKeyword, false, /*isWrite*/ @@ -166,7 +166,7 @@ func (c *Checker) IsValidPropertyAccessForCompletions(node *ast.Node, t *Type, p } func (c *Checker) GetAllPossiblePropertiesOfTypes(types []*Type) []*ast.Symbol { - unionType := c.GetUnionType(types) + unionType := c.getUnionType(types) if unionType.flags&TypeFlagsUnion == 0 { return c.getAugmentedPropertiesOfType(unionType) } @@ -226,7 +226,7 @@ func (c *Checker) GetApparentProperties(t *Type) []*ast.Symbol { func (c *Checker) getAugmentedPropertiesOfType(t *Type) []*ast.Symbol { t = c.getApparentType(t) - propsByName := createSymbolTable(c.GetPropertiesOfType(t)) + propsByName := createSymbolTable(c.getPropertiesOfType(t)) var functionType *Type if len(c.getSignaturesOfType(t, SignatureKindCall)) > 0 { functionType = c.globalCallableFunctionType @@ -235,7 +235,7 @@ func (c *Checker) getAugmentedPropertiesOfType(t *Type) []*ast.Symbol { } if functionType != nil { - for _, p := range c.GetPropertiesOfType(functionType) { + for _, p := range c.getPropertiesOfType(functionType) { if _, ok := propsByName[p.Name]; !ok { propsByName[p.Name] = p } @@ -459,7 +459,7 @@ func (c *Checker) GetExportsAndPropertiesOfModule(moduleSymbol *ast.Symbol) []*a if exportEquals != moduleSymbol { t := c.getTypeOfSymbol(exportEquals) if c.shouldTreatPropertiesOfExternalModuleAsExports(t) { - exports = append(exports, c.GetPropertiesOfType(t)...) + exports = append(exports, c.getPropertiesOfType(t)...) } } return exports diff --git a/internal/checker/utilities.go b/internal/checker/utilities.go index d5c3582297..ca8704fc60 100644 --- a/internal/checker/utilities.go +++ b/internal/checker/utilities.go @@ -219,38 +219,6 @@ func getNameFromImportDeclaration(node *ast.Node) *ast.Node { return nil } -func IsValidTypeOnlyAliasUseSite(useSite *ast.Node) bool { - return useSite.Flags&ast.NodeFlagsAmbient != 0 || - ast.IsPartOfTypeQuery(useSite) || - isIdentifierInNonEmittingHeritageClause(useSite) || - isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) || - !(ast.IsExpressionNode(useSite) || isShorthandPropertyNameUseSite(useSite)) -} - -func isIdentifierInNonEmittingHeritageClause(node *ast.Node) bool { - if !ast.IsIdentifier(node) { - return false - } - parent := node.Parent - for ast.IsPropertyAccessExpression(parent) || ast.IsExpressionWithTypeArguments(parent) { - parent = parent.Parent - } - return ast.IsHeritageClause(parent) && (parent.AsHeritageClause().Token == ast.KindImplementsKeyword || ast.IsInterfaceDeclaration(parent.Parent)) -} - -func isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(node *ast.Node) bool { - for ast.NodeKindIs(node, ast.KindIdentifier, ast.KindPropertyAccessExpression) { - node = node.Parent - } - if node.Kind != ast.KindComputedPropertyName { - return false - } - if ast.HasSyntacticModifier(node.Parent, ast.ModifierFlagsAbstract) { - return true - } - return ast.NodeKindIs(node.Parent.Parent, ast.KindInterfaceDeclaration, ast.KindTypeLiteral) -} - func nodeCanBeDecorated(useLegacyDecorators bool, node *ast.Node, parent *ast.Node, grandparent *ast.Node) bool { // private names cannot be used with decorators yet if useLegacyDecorators && node.Name() != nil && ast.IsPrivateIdentifier(node.Name()) { @@ -285,10 +253,6 @@ func nodeCanBeDecorated(useLegacyDecorators bool, node *ast.Node, parent *ast.No return false } -func isShorthandPropertyNameUseSite(useSite *ast.Node) bool { - return ast.IsIdentifier(useSite) && ast.IsShorthandPropertyAssignment(useSite.Parent) && useSite.Parent.AsShorthandPropertyAssignment().Name() == useSite -} - func isTypeDeclaration(node *ast.Node) bool { switch node.Kind { case ast.KindTypeParameter, ast.KindClassDeclaration, ast.KindInterfaceDeclaration, ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindEnumDeclaration: @@ -869,7 +833,7 @@ func compareTypeMappers(m1, m2 *TypeMapper) int { return 0 } -func GetDeclarationModifierFlagsFromSymbol(s *ast.Symbol) ast.ModifierFlags { +func getDeclarationModifierFlagsFromSymbol(s *ast.Symbol) ast.ModifierFlags { return getDeclarationModifierFlagsFromSymbolEx(s, false /*isWrite*/) } @@ -1068,28 +1032,6 @@ func isNumericLiteralName(name string) bool { return jsnum.FromString(name).String() == name } -func GetPropertyNameForPropertyNameNode(name *ast.Node) string { - switch name.Kind { - case ast.KindIdentifier, ast.KindPrivateIdentifier, ast.KindStringLiteral, ast.KindNoSubstitutionTemplateLiteral, - ast.KindNumericLiteral, ast.KindBigIntLiteral, ast.KindJsxNamespacedName: - return name.Text() - case ast.KindComputedPropertyName: - nameExpression := name.AsComputedPropertyName().Expression - if ast.IsStringOrNumericLiteralLike(nameExpression) { - return nameExpression.Text() - } - if ast.IsSignedNumericLiteral(nameExpression) { - text := nameExpression.AsPrefixUnaryExpression().Operand.Text() - if nameExpression.AsPrefixUnaryExpression().Operator == ast.KindMinusToken { - text = "-" + text - } - return text - } - return ast.InternalSymbolNameMissing - } - panic("Unhandled case in getPropertyNameForPropertyNameNode") -} - func isThisProperty(node *ast.Node) bool { return (ast.IsPropertyAccessExpression(node) || ast.IsElementAccessExpression(node)) && node.Expression().Kind == ast.KindThisKeyword } @@ -1949,7 +1891,7 @@ func tryGetPropertyAccessOrIdentifierToString(expr *ast.Node) string { case ast.IsElementAccessExpression(expr): baseStr := tryGetPropertyAccessOrIdentifierToString(expr.Expression()) if baseStr != "" && ast.IsPropertyName(expr.AsElementAccessExpression().ArgumentExpression) { - return baseStr + "." + GetPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression) + return baseStr + "." + ast.GetPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression) } case ast.IsIdentifier(expr): return expr.Text() diff --git a/internal/ls/completions.go b/internal/ls/completions.go index f6918fa99c..3be923998d 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -1268,7 +1268,7 @@ func getCompletionData(program *compiler.Program, file *ast.SourceFile, position symbolMeanings := core.IfElse(isTypeOnlyLocation, ast.SymbolFlagsNone, ast.SymbolFlagsValue) | ast.SymbolFlagsType | ast.SymbolFlagsNamespace | ast.SymbolFlagsAlias - typeOnlyAliasNeedsPromotion := previousToken != nil && !checker.IsValidTypeOnlyAliasUseSite(previousToken) + typeOnlyAliasNeedsPromotion := previousToken != nil && !ast.IsValidTypeOnlyAliasUseSite(previousToken) symbols = append(symbols, typeChecker.GetSymbolsInScope(scopeNode, symbolMeanings)...) core.CheckEachDefined(symbols, "getSymbolsInScope() should all be defined") @@ -3817,7 +3817,7 @@ func filterClassMembersList( continue } - existingName := checker.GetPropertyNameForPropertyNameNode(member.Name()) + existingName := ast.GetPropertyNameForPropertyNameNode(member.Name()) if existingName != "" { existingMemberNames.Add(existingName) }