237 lines
7.8 KiB
Go
237 lines
7.8 KiB
Go
package declarations
|
|
|
|
import (
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/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.IsParameter(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) // || // !!! TODO: JSDoc support
|
|
/* ast.IsJSDocTypeAlias(node); */
|
|
}
|
|
|
|
func hasInferredType(node *ast.Node) bool {
|
|
// Debug.type<HasInferredType>(node); // !!!
|
|
switch node.Kind {
|
|
case ast.KindParameter,
|
|
ast.KindPropertySignature,
|
|
ast.KindPropertyDeclaration,
|
|
ast.KindBindingElement,
|
|
ast.KindPropertyAccessExpression,
|
|
ast.KindElementAccessExpression,
|
|
ast.KindBinaryExpression,
|
|
ast.KindVariableDeclaration,
|
|
ast.KindExportAssignment,
|
|
ast.KindJSExportAssignment,
|
|
ast.KindPropertyAssignment,
|
|
ast.KindShorthandPropertyAssignment,
|
|
ast.KindJSDocParameterTag,
|
|
ast.KindJSDocPropertyTag:
|
|
return true
|
|
default:
|
|
// assertType<never>(node); // !!!
|
|
return false
|
|
}
|
|
}
|
|
|
|
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.KindJSExportAssignment,
|
|
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().AsBindingPattern().Elements.Nodes {
|
|
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)
|
|
}
|
|
|
|
func isAlwaysType(node *ast.Node) bool {
|
|
if node.Kind == ast.KindInterfaceDeclaration {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func maskModifierFlags(host DeclarationEmitHost, node *ast.Node, modifierMask ast.ModifierFlags, modifierAdditions ast.ModifierFlags) ast.ModifierFlags {
|
|
flags := host.GetEffectiveDeclarationFlags(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 isPrimitiveLiteralValue(node *ast.Node, includeBigInt bool) bool {
|
|
// !!! Debug.type<PrimitiveLiteral>(node);
|
|
switch node.Kind {
|
|
case ast.KindTrueKeyword,
|
|
ast.KindFalseKeyword,
|
|
ast.KindNumericLiteral,
|
|
ast.KindStringLiteral,
|
|
ast.KindNoSubstitutionTemplateLiteral:
|
|
return true
|
|
case ast.KindBigIntLiteral:
|
|
return includeBigInt
|
|
case ast.KindPrefixUnaryExpression:
|
|
if node.AsPrefixUnaryExpression().Operator == ast.KindMinusToken {
|
|
return ast.IsNumericLiteral(node.AsPrefixUnaryExpression().Operand) || (includeBigInt && ast.IsBigIntLiteral(node.AsPrefixUnaryExpression().Operand))
|
|
}
|
|
if node.AsPrefixUnaryExpression().Operator == ast.KindPlusToken {
|
|
return ast.IsNumericLiteral(node.AsPrefixUnaryExpression().Operand)
|
|
}
|
|
return false
|
|
default:
|
|
// !!! assertType<never>(node);
|
|
return false
|
|
}
|
|
}
|
|
|
|
func isPrivateMethodTypeParameter(host DeclarationEmitHost, node *ast.TypeParameterDeclaration) bool {
|
|
return node.AsNode().Parent.Kind == ast.KindMethodDeclaration && host.GetEffectiveDeclarationFlags(node.AsNode().Parent, ast.ModifierFlagsPrivate) != 0
|
|
}
|
|
|
|
// If the ExpandoFunctionDeclaration have multiple overloads, then we only need to emit properties for the last one.
|
|
func shouldEmitFunctionProperties(input *ast.FunctionDeclaration) bool {
|
|
if input.Body != nil { // if it has an implementation, it must be the last one
|
|
return true
|
|
}
|
|
|
|
overloadSignatures := core.Filter(input.Symbol.Declarations, func(decl *ast.Node) bool {
|
|
return ast.IsFunctionDeclaration(decl)
|
|
})
|
|
|
|
return len(overloadSignatures) == 0 || overloadSignatures[len(overloadSignatures)-1] == input.AsNode()
|
|
}
|
|
|
|
func getFirstConstructorWithBody(node *ast.Node) *ast.Node {
|
|
for _, member := range node.Members() {
|
|
if ast.IsConstructorDeclaration(member) && ast.NodeIsPresent(member.Body()) {
|
|
return member
|
|
}
|
|
}
|
|
return 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)
|
|
}
|