vendor tsgo
This commit is contained in:
735
tools/tsgo/internal/transformers/declarations/diagnostics.go
Normal file
735
tools/tsgo/internal/transformers/declarations/diagnostics.go
Normal file
@@ -0,0 +1,735 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
252
tools/tsgo/internal/transformers/declarations/tracker.go
Normal file
252
tools/tsgo/internal/transformers/declarations/tracker.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package declarations
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/checker"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/diagnostics"
|
||||
"github.com/microsoft/typescript-go/internal/printer"
|
||||
"github.com/microsoft/typescript-go/internal/scanner"
|
||||
)
|
||||
|
||||
type SymbolTrackerImpl struct {
|
||||
resolver printer.EmitResolver
|
||||
state *SymbolTrackerSharedState
|
||||
host DeclarationEmitHost
|
||||
fallbackStack []*ast.Node
|
||||
|
||||
// For detecting class expression self-references during member serialization.
|
||||
// When set, TrackSymbol will record usage without reporting accessibility errors.
|
||||
watchedClassSymbol *ast.Symbol
|
||||
classSymbolTracked bool
|
||||
|
||||
getIsolatedDeclarationError func(node *ast.Node) *ast.Diagnostic
|
||||
}
|
||||
|
||||
// PopErrorFallbackNode implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) PopErrorFallbackNode() {
|
||||
s.fallbackStack = s.fallbackStack[:len(s.fallbackStack)-1]
|
||||
}
|
||||
|
||||
// PushErrorFallbackNode implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) PushErrorFallbackNode(node *ast.Node) {
|
||||
s.fallbackStack = append(s.fallbackStack, node)
|
||||
}
|
||||
|
||||
// ReportCyclicStructureError implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportCyclicStructureError() {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_inferred_type_of_0_references_a_type_with_a_cyclic_structure_which_cannot_be_trivially_serialized_A_type_annotation_is_necessary, s.errorDeclarationNameWithFallback()))
|
||||
}
|
||||
}
|
||||
|
||||
// ReportInaccessibleThisError implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportInaccessibleThisError() {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, s.errorDeclarationNameWithFallback(), "this"))
|
||||
}
|
||||
}
|
||||
|
||||
// ReportInaccessibleUniqueSymbolError implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportInaccessibleUniqueSymbolError() {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, s.errorDeclarationNameWithFallback(), "unique symbol"))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerImpl) isBoundExpando(node *ast.Node) bool {
|
||||
if !(ast.IsExpandoPropertyDeclaration(node) && ast.IsPropertyAccessExpression(node.AsBinaryExpression().Left)) {
|
||||
return false
|
||||
}
|
||||
ref := s.resolver.GetReferencedValueDeclarationUnsafe(ast.GetLeftmostExpression(node.AsBinaryExpression().Left, true))
|
||||
if ref == nil {
|
||||
return false
|
||||
}
|
||||
return s.resolver.IsExpandoFunctionDeclarationUnsafe(ref)
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerImpl) isChildOfBoundExpando(node *ast.Node) bool {
|
||||
return ast.FindAncestorOrQuit(node, func(n *ast.Node) ast.FindAncestorResult {
|
||||
if ast.IsSourceFile(n) || ast.IsBlock(n) {
|
||||
return ast.FindAncestorQuit
|
||||
}
|
||||
return ast.ToFindAncestorResult(s.isBoundExpando(n))
|
||||
}) != nil
|
||||
}
|
||||
|
||||
// ReportInferenceFallback implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportInferenceFallback(node *ast.Node) {
|
||||
if !s.state.isolatedDeclarations {
|
||||
return
|
||||
}
|
||||
if ast.GetSourceFileOfNode(node) != s.state.currentSourceFile {
|
||||
return // Nested error on a declaration in another file - ignore, will be reemitted if file is in the output file set
|
||||
}
|
||||
if s.state.resolver.IsExpandoFunctionDeclarationUnsafe(node) { // within a node builder call that should already lock the checker, use the unsafe call
|
||||
s.state.reportExpandoFunctionErrors(node)
|
||||
}
|
||||
if !s.isChildOfBoundExpando(node) { // expando props get an error when their host is visited by the above, this prevents a follow-on error on a non-inferrable expression
|
||||
s.state.addDiagnostic(s.getIsolatedDeclarationError(node))
|
||||
}
|
||||
}
|
||||
|
||||
// ReportLikelyUnsafeImportRequiredError implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportLikelyUnsafeImportRequiredError(specifier string, symbolName string) {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
if symbolName != "" {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_2_from_1_This_is_likely_not_portable_A_type_annotation_is_necessary, s.errorDeclarationNameWithFallback(), specifier, symbolName))
|
||||
} else {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary, s.errorDeclarationNameWithFallback(), specifier))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReportNonSerializableProperty implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportNonSerializableProperty(propertyName string) {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_type_of_this_node_cannot_be_serialized_because_its_property_0_cannot_be_serialized, propertyName))
|
||||
}
|
||||
}
|
||||
|
||||
// ReportNonlocalAugmentation implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportNonlocalAugmentation(containingFile *ast.SourceFile, parentSymbol *ast.Symbol, augmentingSymbol *ast.Symbol) {
|
||||
primaryDeclaration := core.Find(parentSymbol.Declarations, func(d *ast.Node) bool { return ast.GetSourceFileOfNode(d) == containingFile })
|
||||
augmentingDeclarations := core.Filter(augmentingSymbol.Declarations, func(d *ast.Node) bool { return ast.GetSourceFileOfNode(d) != containingFile })
|
||||
if primaryDeclaration != nil && len(augmentingDeclarations) > 0 {
|
||||
for _, augmentations := range augmentingDeclarations {
|
||||
diag := createDiagnosticForNode(augmentations, diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized)
|
||||
related := createDiagnosticForNode(primaryDeclaration, diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file)
|
||||
diag.AddRelatedInfo(related)
|
||||
s.state.addDiagnostic(diag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReportPrivateInBaseOfClassExpression implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportPrivateInBaseOfClassExpression(propertyName string) {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
diag := createDiagnosticForNode(location, diagnostics.Property_0_of_exported_anonymous_class_type_may_not_be_private_or_protected, propertyName)
|
||||
if ast.IsVariableDeclaration(location.Parent) {
|
||||
related := createDiagnosticForNode(location, diagnostics.Add_a_type_annotation_to_the_variable_0, s.errorDeclarationNameWithFallback())
|
||||
diag.AddRelatedInfo(related)
|
||||
}
|
||||
s.state.addDiagnostic(diag)
|
||||
}
|
||||
}
|
||||
|
||||
// ReportTruncationError implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) ReportTruncationError() {
|
||||
location := s.errorLocation()
|
||||
if location != nil {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(location, diagnostics.The_inferred_type_of_this_node_exceeds_the_maximum_length_the_compiler_will_serialize_An_explicit_type_annotation_is_needed))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerImpl) errorFallbackNode() *ast.Node {
|
||||
if len(s.fallbackStack) >= 1 {
|
||||
return s.fallbackStack[len(s.fallbackStack)-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerImpl) errorLocation() *ast.Node {
|
||||
location := s.state.errorNameNode
|
||||
if location == nil {
|
||||
location = s.errorFallbackNode()
|
||||
}
|
||||
return location
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerImpl) errorDeclarationNameWithFallback() string {
|
||||
if s.state.errorNameNode != nil {
|
||||
return scanner.DeclarationNameToString(s.state.errorNameNode)
|
||||
}
|
||||
if s.errorFallbackNode() != nil && ast.GetNameOfDeclaration(s.errorFallbackNode()) != nil {
|
||||
return scanner.DeclarationNameToString(ast.GetNameOfDeclaration(s.errorFallbackNode()))
|
||||
}
|
||||
if s.errorFallbackNode() != nil && ast.IsExportAssignment(s.errorFallbackNode()) {
|
||||
if s.errorFallbackNode().AsExportAssignment().IsExportEquals {
|
||||
return "export="
|
||||
}
|
||||
return "default"
|
||||
}
|
||||
return "(Missing)" // same fallback declarationNameToString uses when node is zero-width (ie, nameless)
|
||||
}
|
||||
|
||||
// TrackSymbol implements checker.SymbolTracker.
|
||||
func (s *SymbolTrackerImpl) TrackSymbol(symbol *ast.Symbol, enclosingDeclaration *ast.Node, meaning ast.SymbolFlags) bool {
|
||||
if symbol.Flags&ast.SymbolFlagsTypeParameter != 0 {
|
||||
return false
|
||||
}
|
||||
// When watching for a class expression symbol, record its usage without
|
||||
// reporting accessibility errors — the caller will handle visibility by
|
||||
// wrapping the class in a namespace.
|
||||
if s.watchedClassSymbol != nil && symbol == s.watchedClassSymbol {
|
||||
s.classSymbolTracked = true
|
||||
return false
|
||||
}
|
||||
issuedDiagnostic := s.handleSymbolAccessibilityError(s.resolver.IsSymbolAccessible(symbol, enclosingDeclaration, meaning /*shouldComputeAliasToMarkVisible*/, true))
|
||||
return issuedDiagnostic
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerImpl) handleSymbolAccessibilityError(symbolAccessibilityResult printer.SymbolAccessibilityResult) bool {
|
||||
if symbolAccessibilityResult.Accessibility == printer.SymbolAccessibilityAccessible {
|
||||
// Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info
|
||||
if len(symbolAccessibilityResult.AliasesToMakeVisible) > 0 {
|
||||
for _, ref := range symbolAccessibilityResult.AliasesToMakeVisible {
|
||||
s.state.lateMarkedStatements = core.AppendIfUnique(s.state.lateMarkedStatements, ref)
|
||||
}
|
||||
}
|
||||
// TODO: Do all these accessibility checks inside/after the first pass in the checker when declarations are enabled, if possible
|
||||
|
||||
// The checker should issue errors on unresolvable names, skip the declaration emit error for using a private/unreachable name for those
|
||||
} else if symbolAccessibilityResult.Accessibility != printer.SymbolAccessibilityNotResolved {
|
||||
// Report error
|
||||
errorInfo := s.state.getSymbolAccessibilityDiagnostic(symbolAccessibilityResult)
|
||||
if errorInfo != nil {
|
||||
info := *errorInfo
|
||||
diagNode := symbolAccessibilityResult.ErrorNode
|
||||
if diagNode == nil {
|
||||
diagNode = errorInfo.errorNode
|
||||
}
|
||||
if info.typeName != nil {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(diagNode, info.diagnosticMessage, scanner.GetTextOfNode(info.typeName), symbolAccessibilityResult.ErrorSymbolName, symbolAccessibilityResult.ErrorModuleName))
|
||||
} else {
|
||||
s.state.addDiagnostic(createDiagnosticForNode(diagNode, info.diagnosticMessage, symbolAccessibilityResult.ErrorSymbolName, symbolAccessibilityResult.ErrorModuleName))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func createDiagnosticForNode(node *ast.Node, message *diagnostics.Message, args ...any) *ast.Diagnostic {
|
||||
return checker.NewDiagnosticForNode(node, message, args...)
|
||||
}
|
||||
|
||||
type SymbolTrackerSharedState struct {
|
||||
lateMarkedStatements []*ast.Node
|
||||
diagnostics []*ast.Diagnostic
|
||||
getSymbolAccessibilityDiagnostic GetSymbolAccessibilityDiagnostic
|
||||
errorNameNode *ast.Node
|
||||
isolatedDeclarations bool
|
||||
stripInternal bool
|
||||
currentSourceFile *ast.SourceFile
|
||||
resolver printer.EmitResolver
|
||||
reportExpandoFunctionErrors func(node *ast.Node)
|
||||
}
|
||||
|
||||
func (s *SymbolTrackerSharedState) addDiagnostic(diag *ast.Diagnostic) {
|
||||
s.diagnostics = append(s.diagnostics, diag)
|
||||
}
|
||||
|
||||
func NewSymbolTracker(host DeclarationEmitHost, resolver printer.EmitResolver, state *SymbolTrackerSharedState) *SymbolTrackerImpl {
|
||||
tracker := &SymbolTrackerImpl{host: host, resolver: resolver, state: state, getIsolatedDeclarationError: createGetIsolatedDeclarationErrors(resolver)}
|
||||
return tracker
|
||||
}
|
||||
2957
tools/tsgo/internal/transformers/declarations/transform.go
Normal file
2957
tools/tsgo/internal/transformers/declarations/transform.go
Normal file
File diff suppressed because it is too large
Load Diff
186
tools/tsgo/internal/transformers/declarations/util.go
Normal file
186
tools/tsgo/internal/transformers/declarations/util.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package declarations
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/printer"
|
||||
)
|
||||
|
||||
func needsScopeMarker(result *ast.Node) bool {
|
||||
return !ast.IsAnyImportOrReExport(result) && !ast.IsExportAssignment(result) && !ast.HasSyntacticModifier(result, ast.ModifierFlagsExport) && !ast.IsAmbientModule(result)
|
||||
}
|
||||
|
||||
func canHaveLiteralInitializer(host DeclarationEmitHost, node *ast.Node) bool {
|
||||
switch node.Kind {
|
||||
case ast.KindPropertyDeclaration,
|
||||
ast.KindPropertySignature:
|
||||
return host.GetEffectiveDeclarationFlags(node, ast.ModifierFlagsPrivate) == 0
|
||||
case ast.KindParameter,
|
||||
ast.KindVariableDeclaration:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func canProduceDiagnostics(node *ast.Node) bool {
|
||||
return ast.IsVariableDeclaration(node) ||
|
||||
ast.IsPropertyDeclaration(node) ||
|
||||
ast.IsPropertySignatureDeclaration(node) ||
|
||||
ast.IsBindingElement(node) ||
|
||||
ast.IsSetAccessorDeclaration(node) ||
|
||||
ast.IsGetAccessorDeclaration(node) ||
|
||||
ast.IsConstructSignatureDeclaration(node) ||
|
||||
ast.IsCallSignatureDeclaration(node) ||
|
||||
ast.IsMethodDeclaration(node) ||
|
||||
ast.IsMethodSignatureDeclaration(node) ||
|
||||
ast.IsFunctionDeclaration(node) ||
|
||||
ast.IsParameterDeclaration(node) ||
|
||||
ast.IsTypeParameterDeclaration(node) ||
|
||||
ast.IsExpressionWithTypeArguments(node) ||
|
||||
ast.IsImportEqualsDeclaration(node) ||
|
||||
ast.IsTypeAliasDeclaration(node) ||
|
||||
ast.IsJSTypeAliasDeclaration(node) ||
|
||||
ast.IsConstructorDeclaration(node) ||
|
||||
ast.IsIndexSignatureDeclaration(node) ||
|
||||
ast.IsPropertyAccessExpression(node) ||
|
||||
ast.IsElementAccessExpression(node) ||
|
||||
ast.IsBinaryExpression(node) ||
|
||||
ast.IsCallExpression(node) // || // !!! TODO: JSDoc support
|
||||
/* ast.IsJSDocTypeAlias(node); */
|
||||
}
|
||||
|
||||
func canReuseModifierNodes(nodes []*ast.Node) bool {
|
||||
for _, node := range nodes {
|
||||
if ast.IsModifier(node) && node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isDeclarationAndNotVisible(emitContext *printer.EmitContext, resolver printer.EmitResolver, node *ast.Node) bool {
|
||||
node = emitContext.ParseNode(node)
|
||||
switch node.Kind {
|
||||
case ast.KindFunctionDeclaration,
|
||||
ast.KindModuleDeclaration,
|
||||
ast.KindInterfaceDeclaration,
|
||||
ast.KindClassDeclaration,
|
||||
ast.KindTypeAliasDeclaration,
|
||||
ast.KindJSTypeAliasDeclaration,
|
||||
ast.KindEnumDeclaration:
|
||||
return !resolver.IsDeclarationVisible(node)
|
||||
// The following should be doing their own visibility checks based on filtering their members
|
||||
case ast.KindVariableDeclaration:
|
||||
return !getBindingNameVisible(resolver, node)
|
||||
case ast.KindImportEqualsDeclaration,
|
||||
ast.KindImportDeclaration,
|
||||
ast.KindJSImportDeclaration,
|
||||
ast.KindExportDeclaration,
|
||||
ast.KindExportAssignment:
|
||||
return false
|
||||
case ast.KindClassStaticBlockDeclaration:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getBindingNameVisible(resolver printer.EmitResolver, elem *ast.Node) bool {
|
||||
if ast.IsOmittedExpression(elem) {
|
||||
return false
|
||||
}
|
||||
// TODO: parseArrayBindingElement _never_ parses out an OmittedExpression anymore, instead producing a nameless binding element
|
||||
// Audit if OmittedExpression should be removed
|
||||
if elem.Name() == nil {
|
||||
return false
|
||||
}
|
||||
if ast.IsBindingPattern(elem.Name()) {
|
||||
// If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible
|
||||
for _, elem := range elem.Name().Elements() {
|
||||
if getBindingNameVisible(resolver, elem) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
} else {
|
||||
return resolver.IsDeclarationVisible(elem)
|
||||
}
|
||||
}
|
||||
|
||||
func isEnclosingDeclaration(node *ast.Node) bool {
|
||||
return ast.IsSourceFile(node) ||
|
||||
ast.IsTypeAliasDeclaration(node) ||
|
||||
ast.IsJSTypeAliasDeclaration(node) ||
|
||||
ast.IsModuleDeclaration(node) ||
|
||||
ast.IsClassDeclaration(node) ||
|
||||
ast.IsInterfaceDeclaration(node) ||
|
||||
ast.IsFunctionLike(node) ||
|
||||
ast.IsIndexSignatureDeclaration(node) ||
|
||||
ast.IsMappedTypeNode(node) ||
|
||||
ast.IsVariableDeclaration(node)
|
||||
}
|
||||
|
||||
func isAlwaysType(node *ast.Node) bool {
|
||||
if node.Kind == ast.KindInterfaceDeclaration {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func maskModifierFlags(node *ast.Node, modifierMask ast.ModifierFlags, modifierAdditions ast.ModifierFlags) ast.ModifierFlags {
|
||||
flags := (ast.GetCombinedModifierFlags(node) & modifierMask) | modifierAdditions
|
||||
if flags&ast.ModifierFlagsDefault != 0 && (flags&ast.ModifierFlagsExport == 0) {
|
||||
// A non-exported default is a nonsequitor - we usually try to remove all export modifiers
|
||||
// from statements in ambient declarations; but a default export must retain its export modifier to be syntactically valid
|
||||
flags ^= ast.ModifierFlagsExport
|
||||
}
|
||||
if flags&ast.ModifierFlagsDefault != 0 && flags&ast.ModifierFlagsAmbient != 0 {
|
||||
flags ^= ast.ModifierFlagsAmbient // `declare` is never required alongside `default` (and would be an error if printed)
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func unwrapParenthesizedExpression(o *ast.Node) *ast.Node {
|
||||
for o.Kind == ast.KindParenthesizedExpression {
|
||||
o = o.Expression()
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func isPrivateMethodTypeParameter(host DeclarationEmitHost, node *ast.TypeParameterDeclaration) bool {
|
||||
return node.AsNode().Parent.Kind == ast.KindMethodDeclaration && host.GetEffectiveDeclarationFlags(node.AsNode().Parent, ast.ModifierFlagsPrivate) != 0
|
||||
}
|
||||
|
||||
// Returns true if expando properties should be emitted for this function.
|
||||
// Properties are emitted if any overload in the symbol has a body (implementation).
|
||||
func shouldEmitFunctionProperties(input *ast.FunctionDeclaration) bool {
|
||||
if input.Body != nil {
|
||||
return true
|
||||
}
|
||||
return !core.Every(input.Symbol.Declarations, func(decl *ast.Node) bool {
|
||||
return !ast.IsFunctionDeclaration(decl) || decl.AsFunctionDeclaration().Body == nil
|
||||
})
|
||||
}
|
||||
|
||||
func getEffectiveBaseTypeNode(node *ast.Node) *ast.Node {
|
||||
baseType := ast.GetClassExtendsHeritageElement(node)
|
||||
// !!! TODO: JSDoc support
|
||||
// if (baseType && isInJSFile(node)) {
|
||||
// // Prefer an @augments tag because it may have type parameters.
|
||||
// const tag = getJSDocAugmentsTag(node);
|
||||
// if (tag) {
|
||||
// return tag.class;
|
||||
// }
|
||||
// }
|
||||
return baseType
|
||||
}
|
||||
|
||||
func isScopeMarker(node *ast.Node) bool {
|
||||
return ast.IsExportAssignment(node) || ast.IsExportDeclaration(node)
|
||||
}
|
||||
|
||||
func hasScopeMarker(statements *ast.StatementList) bool {
|
||||
if statements == nil {
|
||||
return false
|
||||
}
|
||||
return core.Some(statements.Nodes, isScopeMarker)
|
||||
}
|
||||
Reference in New Issue
Block a user