package declarations import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/scanner" ) type GetSymbolAccessibilityDiagnostic = func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic type SymbolAccessibilityDiagnostic struct { errorNode *ast.Node diagnosticMessage *diagnostics.Message typeName *ast.Node } func wrapSimpleDiagnosticSelector(node *ast.Node, selector func(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message) GetSymbolAccessibilityDiagnostic { return func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { diagnosticMessage := selector(node, symbolAccessibilityResult) if diagnosticMessage == nil { return nil } return &SymbolAccessibilityDiagnostic{ errorNode: node, diagnosticMessage: diagnosticMessage, typeName: ast.GetNameOfDeclaration(node), } } } func wrapNamedDiagnosticSelector(node *ast.Node, selector func(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message) GetSymbolAccessibilityDiagnostic { return func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { diagnosticMessage := selector(node, symbolAccessibilityResult) if diagnosticMessage == nil { return nil } name := ast.GetNameOfDeclaration(node) return &SymbolAccessibilityDiagnostic{ errorNode: name, diagnosticMessage: diagnosticMessage, typeName: name, } } } func wrapFallbackErrorDiagnosticSelector(node *ast.Node, selector func(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message) GetSymbolAccessibilityDiagnostic { return func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { diagnosticMessage := selector(node, symbolAccessibilityResult) if diagnosticMessage == nil { return nil } errorNode := ast.GetNameOfDeclaration(node) if errorNode == nil { errorNode = node } return &SymbolAccessibilityDiagnostic{ errorNode: errorNode, diagnosticMessage: diagnosticMessage, } } } func selectDiagnosticBasedOnModuleName(symbolAccessibilityResult printer.SymbolAccessibilityResult, moduleNotNameable *diagnostics.Message, privateModule *diagnostics.Message, nonModule *diagnostics.Message) *diagnostics.Message { if len(symbolAccessibilityResult.ErrorModuleName) > 0 { if symbolAccessibilityResult.Accessibility == printer.SymbolAccessibilityCannotBeNamed { return moduleNotNameable } return privateModule } return nonModule } func selectDiagnosticBasedOnModuleNameNoNameCheck(symbolAccessibilityResult printer.SymbolAccessibilityResult, privateModule *diagnostics.Message, nonModule *diagnostics.Message) *diagnostics.Message { if len(symbolAccessibilityResult.ErrorModuleName) > 0 { return privateModule } return nonModule } func createGetSymbolAccessibilityDiagnosticForNodeName(node *ast.Node) GetSymbolAccessibilityDiagnostic { if ast.IsSetAccessorDeclaration(node) || ast.IsGetAccessorDeclaration(node) { return wrapSimpleDiagnosticSelector(node, getAccessorNameVisibilityDiagnosticMessage) } else if ast.IsMethodDeclaration(node) || ast.IsMethodSignatureDeclaration(node) { return wrapSimpleDiagnosticSelector(node, getMethodNameVisibilityDiagnosticMessage) } else { return createGetSymbolAccessibilityDiagnosticForNode(node) } } func getAccessorNameVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { if ast.IsStatic(node) { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1, ) } else if node.Parent.Kind == ast.KindClassDeclaration { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1, ) } else { return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1, ) } } func getMethodNameVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { if ast.IsStatic(node) { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1, ) } else if node.Parent.Kind == ast.KindClassDeclaration { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1, ) } else { return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Method_0_of_exported_interface_has_or_is_using_private_name_1, ) } } func createGetSymbolAccessibilityDiagnosticForNode(node *ast.Node) GetSymbolAccessibilityDiagnostic { if ast.IsVariableDeclaration(node) || ast.IsPropertyDeclaration(node) || ast.IsPropertySignatureDeclaration(node) || ast.IsPropertyAccessExpression(node) || ast.IsElementAccessExpression(node) || ast.IsBinaryExpression(node) || ast.IsBindingElement(node) || ast.IsConstructorDeclaration(node) { return wrapSimpleDiagnosticSelector(node, getVariableDeclarationTypeVisibilityDiagnosticMessage) } else if ast.IsSetAccessorDeclaration(node) || ast.IsGetAccessorDeclaration(node) { return wrapNamedDiagnosticSelector(node, getAccessorDeclarationTypeVisibilityDiagnosticMessage) } else if ast.IsConstructSignatureDeclaration(node) || ast.IsCallSignatureDeclaration(node) || ast.IsMethodDeclaration(node) || ast.IsMethodSignatureDeclaration(node) || ast.IsFunctionDeclaration(node) || ast.IsIndexSignatureDeclaration(node) { return wrapFallbackErrorDiagnosticSelector(node, getReturnTypeVisibilityDiagnosticMessage) } else if ast.IsParameterDeclaration(node) { if ast.IsParameterPropertyDeclaration(node, node.Parent) && ast.HasSyntacticModifier(node.Parent, ast.ModifierFlagsPrivate) { return wrapSimpleDiagnosticSelector(node, getVariableDeclarationTypeVisibilityDiagnosticMessage) } return wrapSimpleDiagnosticSelector(node, getParameterDeclarationTypeVisibilityDiagnosticMessage) } else if ast.IsTypeParameterDeclaration(node) { return wrapSimpleDiagnosticSelector(node, getTypeParameterConstraintVisibilityDiagnosticMessage) } else if ast.IsExpressionWithTypeArguments(node) { // unique node selection behavior, inline closure return func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { var diagnosticMessage *diagnostics.Message // Heritage clause is written by user so it can always be named if ast.IsClassDeclaration(node.Parent.Parent) { // Class or Interface implemented/extended is inaccessible if ast.IsHeritageClause(node.Parent) && node.Parent.AsHeritageClause().Token == ast.KindImplementsKeyword { diagnosticMessage = diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 } else { if node.Parent.Parent.Name() != nil { diagnosticMessage = diagnostics.X_extends_clause_of_exported_class_0_has_or_is_using_private_name_1 } else { diagnosticMessage = diagnostics.X_extends_clause_of_exported_class_has_or_is_using_private_name_0 } } } else { // interface is inaccessible diagnosticMessage = diagnostics.X_extends_clause_of_exported_interface_0_has_or_is_using_private_name_1 } return &SymbolAccessibilityDiagnostic{ diagnosticMessage: diagnosticMessage, errorNode: node, typeName: ast.GetNameOfDeclaration(node.Parent.Parent), } } } else if ast.IsImportEqualsDeclaration(node) { return wrapSimpleDiagnosticSelector(node, func(_ *ast.Node, _ printer.SymbolAccessibilityResult) *diagnostics.Message { return diagnostics.Import_declaration_0_is_using_private_name_1 }) } else if ast.IsTypeAliasDeclaration(node) || ast.IsJSTypeAliasDeclaration(node) { // unique node selection behavior, inline closure return func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { diagnosticMessage := selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1_from_module_2, diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, ) errorNode := node.Type() typeName := node.Name() return &SymbolAccessibilityDiagnostic{ errorNode: errorNode, diagnosticMessage: diagnosticMessage, typeName: typeName, } } } else if ast.IsCallExpression(node) { // JS object.defineProperty call // unique node selection behavior, inline closure return func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { diagnosticMessage := selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2, diagnostics.Exported_variable_0_has_or_is_using_private_name_1, ) errorNode := node.Arguments()[1] typeName := node.Arguments()[1] return &SymbolAccessibilityDiagnostic{ errorNode: errorNode, diagnosticMessage: diagnosticMessage, typeName: typeName, } } } else { panic("Attempted to set a declaration diagnostic context for unhandled node kind: " + node.Kind.String()) } } func getVariableDeclarationTypeVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { if node.Kind == ast.KindVariableDeclaration || node.Kind == ast.KindBindingElement { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2, diagnostics.Exported_variable_0_has_or_is_using_private_name_1, ) // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit // The only exception here is if the constructor was marked as private. we are not emitting the constructor parameters at all. } else if node.Kind == ast.KindPropertyDeclaration || node.Kind == ast.KindPropertyAccessExpression || node.Kind == ast.KindElementAccessExpression || node.Kind == ast.KindBinaryExpression || node.Kind == ast.KindPropertySignature || (node.Kind == ast.KindParameter && ast.HasSyntacticModifier(node.Parent, ast.ModifierFlagsPrivate)) { // TODO(jfreeman): Deal with computed properties in error reporting. if ast.IsStatic(node) { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1, ) } else if node.Parent.Kind == ast.KindClassDeclaration || node.Kind == ast.KindParameter { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1, ) } else { // Interfaces cannot have types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1, ) } } return nil // TODO: Audit behavior - should this panic? potentially silent error state in strada } func getAccessorDeclarationTypeVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { if node.Kind == ast.KindSetAccessor { // Getters can infer the return type from the returned expression, but setters cannot, so the // "_from_external_module_1_but_cannot_be_named" case cannot occur. if ast.IsStatic(node) { return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1, ) } else { return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_private_name_1, ) } } else { if ast.IsStatic(node) { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1, ) } else { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1, ) } } } func getReturnTypeVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { switch node.Kind { case ast.KindConstructSignature: // Interfaces cannot have return types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0, ) case ast.KindCallSignature: // Interfaces cannot have return types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0, ) case ast.KindIndexSignature: // Interfaces cannot have return types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0, ) case ast.KindMethodDeclaration, ast.KindMethodSignature: if ast.IsStatic(node) { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named, diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0, ) } else if node.Parent.Kind == ast.KindClassDeclaration { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named, diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0, ) } else { // Interfaces cannot have return types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0, ) } case ast.KindFunctionDeclaration: return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named, diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1, diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0, ) default: panic("This is unknown kind for signature: " + node.Kind.String()) } } func getParameterDeclarationTypeVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { switch node.Parent.Kind { case ast.KindConstructor: return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1, ) case ast.KindConstructSignature, ast.KindConstructorType: // Interfaces cannot have parameter types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1, ) case ast.KindCallSignature: // Interfaces cannot have parameter types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1, ) case ast.KindIndexSignature: // Interfaces cannot have parameter types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1, ) case ast.KindMethodDeclaration, ast.KindMethodSignature: if ast.IsStatic(node.Parent) { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1, ) } else if node.Parent.Parent.Kind == ast.KindClassDeclaration { return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1, ) } else { // Interfaces cannot have parameter types that cannot be named return selectDiagnosticBasedOnModuleNameNoNameCheck( symbolAccessibilityResult, diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1, ) } case ast.KindFunctionDeclaration, ast.KindFunctionType: return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1, ) case ast.KindSetAccessor, ast.KindGetAccessor: return selectDiagnosticBasedOnModuleName( symbolAccessibilityResult, diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named, diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_private_module_2, diagnostics.Parameter_0_of_accessor_has_or_is_using_private_name_1, ) default: panic("Unknown parent for parameter: " + node.Parent.Kind.String()) } } func getTypeParameterConstraintVisibilityDiagnosticMessage(node *ast.Node, symbolAccessibilityResult printer.SymbolAccessibilityResult) *diagnostics.Message { // Type parameter constraints are named by user so we should always be able to name it switch node.Parent.Kind { case ast.KindClassDeclaration: return diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1 case ast.KindInterfaceDeclaration: return diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1 case ast.KindMappedType: return diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1 case ast.KindConstructorType, ast.KindConstructSignature: return diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1 case ast.KindCallSignature: return diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1 case ast.KindMethodDeclaration, ast.KindMethodSignature: if ast.IsStatic(node.Parent) { return diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1 } else if node.Parent.Parent.Kind == ast.KindClassDeclaration { return diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1 } else { return diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1 } case ast.KindFunctionType, ast.KindFunctionDeclaration: return diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1 case ast.KindInferType: return diagnostics.Extends_clause_for_inferred_type_0_has_or_is_using_private_name_1 case ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration: return diagnostics.Type_parameter_0_of_exported_type_alias_has_or_is_using_private_name_1 default: panic("This is unknown parent for type parameter: " + node.Parent.Kind.String()) } } func getRelatedSuggestionByDeclarationKind(kind ast.Kind) *diagnostics.Message { switch kind { case ast.KindArrowFunction: return diagnostics.Add_a_return_type_to_the_function_expression case ast.KindFunctionExpression: return diagnostics.Add_a_return_type_to_the_function_expression case ast.KindMethodDeclaration: return diagnostics.Add_a_return_type_to_the_method case ast.KindGetAccessor: return diagnostics.Add_a_return_type_to_the_get_accessor_declaration case ast.KindSetAccessor: return diagnostics.Add_a_type_to_parameter_of_the_set_accessor_declaration case ast.KindFunctionDeclaration: return diagnostics.Add_a_return_type_to_the_function_declaration case ast.KindConstructSignature: return diagnostics.Add_a_return_type_to_the_function_declaration case ast.KindParameter: return diagnostics.Add_a_type_annotation_to_the_parameter_0 case ast.KindVariableDeclaration: return diagnostics.Add_a_type_annotation_to_the_variable_0 case ast.KindPropertyDeclaration: return diagnostics.Add_a_type_annotation_to_the_property_0 case ast.KindPropertySignature: return diagnostics.Add_a_type_annotation_to_the_property_0 case ast.KindExportAssignment: return diagnostics.Move_the_expression_in_default_export_to_a_variable_and_add_a_type_annotation_to_it default: return nil } } func getErrorByDeclarationKind(kind ast.Kind) *diagnostics.Message { switch kind { case ast.KindFunctionExpression: return diagnostics.Function_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations case ast.KindFunctionDeclaration: return diagnostics.Function_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations case ast.KindArrowFunction: return diagnostics.Function_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations case ast.KindMethodDeclaration: return diagnostics.Method_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations case ast.KindConstructSignature: return diagnostics.Method_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations case ast.KindGetAccessor: return diagnostics.At_least_one_accessor_must_have_an_explicit_type_annotation_with_isolatedDeclarations case ast.KindSetAccessor: return diagnostics.At_least_one_accessor_must_have_an_explicit_type_annotation_with_isolatedDeclarations case ast.KindParameter: return diagnostics.Parameter_must_have_an_explicit_type_annotation_with_isolatedDeclarations case ast.KindVariableDeclaration: return diagnostics.Variable_must_have_an_explicit_type_annotation_with_isolatedDeclarations case ast.KindPropertyDeclaration: return diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations case ast.KindPropertySignature: return diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations case ast.KindComputedPropertyName: return diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations case ast.KindSpreadAssignment: return diagnostics.Objects_that_contain_spread_assignments_can_t_be_inferred_with_isolatedDeclarations case ast.KindShorthandPropertyAssignment: return diagnostics.Objects_that_contain_shorthand_properties_can_t_be_inferred_with_isolatedDeclarations case ast.KindArrayLiteralExpression: return diagnostics.Only_const_arrays_can_be_inferred_with_isolatedDeclarations case ast.KindExportAssignment: return diagnostics.Default_exports_can_t_be_inferred_with_isolatedDeclarations case ast.KindSpreadElement: return diagnostics.Arrays_with_spread_elements_can_t_inferred_with_isolatedDeclarations default: return nil } } func isDeclarationEnoughForErrors(node *ast.Node) bool { return ast.IsExportAssignment(node) || ast.IsStatement(node) || ast.IsVariableDeclaration(node) || ast.IsPropertyDeclaration(node) || ast.IsParameterDeclaration(node) } func isFunctionLikeAndNotConstructor(node *ast.Node) bool { return ast.IsFunctionLikeDeclaration(node) && !ast.IsConstructorDeclaration(node) } func findNearestDeclaration(node *ast.Node) *ast.Node { result := ast.FindAncestor(node, isDeclarationEnoughForErrors) if result == nil { return nil } if ast.IsExportAssignment(result) { return result } if ast.IsReturnStatement(result) { return ast.FindAncestor(result, isFunctionLikeAndNotConstructor) } if ast.IsStatement(result) { return nil } return result } func createEntityInTypeNodeError(node *ast.Node) *ast.Diagnostic { diag := createDiagnosticForNode(node, diagnostics.Type_containing_private_name_0_can_t_be_used_with_isolatedDeclarations, scanner.GetTextOfNode(node)) addParentDeclarationRelatedInfo(node, diag) return diag } func addParentDeclarationRelatedInfo(node *ast.Node, diag *ast.Diagnostic) { parentDeclaration := findNearestDeclaration(node) if parentDeclaration == nil { return } targetStr := "" if !ast.IsExportAssignment(parentDeclaration) && parentDeclaration.Name() != nil { targetStr = scanner.GetTextOfNode(parentDeclaration.Name()) } diag.AddRelatedInfo(createDiagnosticForNode(parentDeclaration, getRelatedSuggestionByDeclarationKind(parentDeclaration.Kind), targetStr)) } func createAccessorTypeError(node *ast.Node) *ast.Diagnostic { allDeclarations := ast.GetAllAccessorDeclarationsForDeclaration(node, node.Symbol().Declarations) getAccessor := allDeclarations.GetAccessor setAccessor := allDeclarations.SetAccessor targetNode := node if ast.IsSetAccessorDeclaration(node) && len(node.Parameters()) > 0 { targetNode = node.Parameters()[0] } diag := createDiagnosticForNode(targetNode, getErrorByDeclarationKind(node.Kind)) if setAccessor != nil { diag.AddRelatedInfo(createDiagnosticForNode(setAccessor.AsNode(), getRelatedSuggestionByDeclarationKind(setAccessor.Kind))) } if getAccessor != nil { diag.AddRelatedInfo(createDiagnosticForNode(getAccessor.AsNode(), getRelatedSuggestionByDeclarationKind(getAccessor.Kind))) } return diag } func createObjectLiteralError(node *ast.Node) *ast.Diagnostic { diag := createDiagnosticForNode(node, getErrorByDeclarationKind(node.Kind)) addParentDeclarationRelatedInfo(node, diag) return diag } func createArrayLiteralError(node *ast.Node) *ast.Diagnostic { diag := createDiagnosticForNode(node, getErrorByDeclarationKind(node.Kind)) addParentDeclarationRelatedInfo(node, diag) return diag } func createReturnTypeError(node *ast.Node) *ast.Diagnostic { diag := createDiagnosticForNode(node, getErrorByDeclarationKind(node.Kind)) addParentDeclarationRelatedInfo(node, diag) diag.AddRelatedInfo(createDiagnosticForNode(node, getRelatedSuggestionByDeclarationKind(node.Kind))) return diag } func createBindingElementError(node *ast.Node) *ast.Diagnostic { return createDiagnosticForNode(node, diagnostics.Binding_elements_can_t_be_exported_directly_with_isolatedDeclarations) } func createVariableOrPropertyError(node *ast.Node) *ast.Diagnostic { diag := createDiagnosticForNode(node, getErrorByDeclarationKind(node.Kind)) diag.AddRelatedInfo(createDiagnosticForNode(node, getRelatedSuggestionByDeclarationKind(node.Kind), scanner.GetTextOfNode(node.Name()))) return diag } func createExpressionError(node *ast.Node) *ast.Diagnostic { return createExpressionErrorEx(node, nil) } func createClassExpressionError(node *ast.Node) *ast.Diagnostic { return createExpressionErrorEx(node, diagnostics.Inference_from_class_expressions_is_not_supported_with_isolatedDeclarations) } func isParentForIDDIagnostic(node *ast.Node) ast.FindAncestorResult { if ast.IsExportAssignment(node) { return ast.FindAncestorTrue } if ast.IsStatement(node) { return ast.FindAncestorQuit } return ast.ToFindAncestorResult(!ast.IsParenthesizedExpression(node) && !ast.IsAssertionExpression(node)) } func createExpressionErrorEx(node *ast.Node, diagnosticMessage *diagnostics.Message) *ast.Diagnostic { parentDeclaration := findNearestDeclaration(node) if parentDeclaration == nil { if diagnosticMessage == nil { diagnosticMessage = diagnostics.Expression_type_can_t_be_inferred_with_isolatedDeclarations } return createDiagnosticForNode(node, diagnosticMessage) } targetStr := "" if !ast.IsExportAssignment(parentDeclaration) && parentDeclaration.Name() != nil { targetStr = scanner.GetTextOfNode(parentDeclaration.Name()) } parent := ast.FindAncestorOrQuit(node.Parent, isParentForIDDIagnostic) if parentDeclaration == parent { if diagnosticMessage == nil { diagnosticMessage = getErrorByDeclarationKind(parentDeclaration.Kind) } diag := createDiagnosticForNode(node, diagnosticMessage) diag.AddRelatedInfo(createDiagnosticForNode(parentDeclaration, getRelatedSuggestionByDeclarationKind(parentDeclaration.Kind), targetStr)) return diag } if diagnosticMessage == nil { diagnosticMessage = diagnostics.Expression_type_can_t_be_inferred_with_isolatedDeclarations } diag := createDiagnosticForNode(node, diagnosticMessage) diag.AddRelatedInfo(createDiagnosticForNode(parentDeclaration, getRelatedSuggestionByDeclarationKind(parentDeclaration.Kind), targetStr)) diag.AddRelatedInfo(createDiagnosticForNode(node, diagnostics.Add_satisfies_and_a_type_assertion_to_this_expression_satisfies_T_as_T_to_make_the_type_explicit)) return diag } func createGetIsolatedDeclarationErrors(resolver printer.EmitResolver) func(node *ast.Node) *ast.Diagnostic { createParameterError := func(node *ast.Node) *ast.Diagnostic { if ast.IsSetAccessorDeclaration(node.Parent) { return createAccessorTypeError(node.Parent) } addUndefined := resolver.RequiresAddingImplicitUndefinedUnsafe(node, nil, nil) // skip checker lock - node builder will already have one if !addUndefined && node.Initializer() != nil { return createExpressionError(node.Initializer()) } message := getErrorByDeclarationKind(node.Kind) if addUndefined { message = diagnostics.Declaration_emit_for_this_parameter_requires_implicitly_adding_undefined_to_its_type_This_is_not_supported_with_isolatedDeclarations } diag := createDiagnosticForNode(node, message) targetStr := scanner.GetTextOfNode(node.Name()) diag.AddRelatedInfo(createDiagnosticForNode(node, getRelatedSuggestionByDeclarationKind(node.Kind), targetStr)) return diag } return func(node *ast.Node) *ast.Diagnostic { heritageClause := ast.FindAncestor(node, ast.IsHeritageClause) if heritageClause != nil { return createDiagnosticForNode(node, diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations) } if ast.IsPartOfTypeNode(node) || ast.IsTypeQueryNode(node) { return createEntityInTypeNodeError(node) } if ast.IsEntityName(node) || ast.IsEntityNameExpression(node) { return createEntityInTypeNodeError(node) } switch node.Kind { case ast.KindGetAccessor, ast.KindSetAccessor: return createAccessorTypeError(node) case ast.KindComputedPropertyName, ast.KindShorthandPropertyAssignment, ast.KindSpreadAssignment: return createObjectLiteralError(node) case ast.KindArrayLiteralExpression, ast.KindSpreadElement: return createArrayLiteralError(node) case ast.KindMethodDeclaration, ast.KindConstructSignature, ast.KindFunctionExpression, ast.KindArrowFunction, ast.KindFunctionDeclaration: return createReturnTypeError(node) case ast.KindBindingElement: return createBindingElementError(node) case ast.KindPropertyDeclaration, ast.KindVariableDeclaration: return createVariableOrPropertyError(node) case ast.KindParameter: return createParameterError(node) case ast.KindPropertyAssignment: return createExpressionError(node.Initializer()) case ast.KindClassExpression: return createClassExpressionError(node) default: return createExpressionError(node) } } }