-
Notifications
You must be signed in to change notification settings - Fork 582
Add basic CommonJS support #748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
93a5b2f
f329913
2dfca09
872ae19
29a1403
be697d6
c203acb
8b198fe
8ae9f66
3dc17ac
fc2a5d7
f01b883
2f19775
d3141dc
94cd60e
dda9a73
174be26
81286b4
288ca86
e2f23c5
15c1409
4985943
05a9e36
b77bdc1
dbd8b24
b2e0c0f
f9912a7
20f0198
7d428ac
7ff9d6e
9ec25a0
4c5c54e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -649,6 +649,7 @@ func isDeclarationStatementKind(kind Kind) bool { | |
KindImportEqualsDeclaration, | ||
KindExportDeclaration, | ||
KindExportAssignment, | ||
KindJSExportAssignment, | ||
KindNamespaceExportDeclaration: | ||
return true | ||
} | ||
|
@@ -1304,7 +1305,7 @@ func GetElementOrPropertyAccessArgumentExpressionOrName(node *Node) *Node { | |
} | ||
|
||
func GetElementOrPropertyAccessName(node *Node) string { | ||
name := getElementOrPropertyAccessArgumentExpressionOrName(node) | ||
name := GetElementOrPropertyAccessArgumentExpressionOrName(node) | ||
if name == nil { | ||
return "" | ||
} | ||
|
@@ -1351,10 +1352,10 @@ func GetNonAssignedNameOfDeclaration(declaration *Node) *Node { | |
switch declaration.Kind { | ||
case KindBinaryExpression: | ||
if IsFunctionPropertyAssignment(declaration) { | ||
return getElementOrPropertyAccessArgumentExpressionOrName(declaration.AsBinaryExpression().Left) | ||
return GetElementOrPropertyAccessArgumentExpressionOrName(declaration.AsBinaryExpression().Left) | ||
} | ||
return nil | ||
case KindExportAssignment: | ||
case KindExportAssignment, KindJSExportAssignment: | ||
expr := declaration.AsExportAssignment().Expression | ||
if IsIdentifier(expr) { | ||
return expr | ||
|
@@ -1414,22 +1415,6 @@ func IsFunctionPropertyAssignment(node *Node) bool { | |
return false | ||
} | ||
|
||
// Does not handle signed numeric names like `a[+0]` - handling those would require handling prefix unary expressions | ||
// throughout late binding handling as well, which is awkward (but ultimately probably doable if there is demand) | ||
func getElementOrPropertyAccessArgumentExpressionOrName(node *Node) *Node { | ||
switch node.Kind { | ||
case KindPropertyAccessExpression: | ||
return node.Name() | ||
case KindElementAccessExpression: | ||
arg := SkipParentheses(node.AsElementAccessExpression().ArgumentExpression) | ||
if IsStringOrNumericLiteralLike(arg) { | ||
return arg | ||
} | ||
return node | ||
} | ||
panic("Unhandled case in getElementOrPropertyAccessArgumentExpressionOrName") | ||
} | ||
|
||
/** | ||
* A declaration has a dynamic name if all of the following are true: | ||
* 1. The declaration has a computed property name. | ||
|
@@ -1495,10 +1480,6 @@ func IsEffectiveExternalModule(node *SourceFile, compilerOptions *core.CompilerO | |
return IsExternalModule(node) || (isCommonJSContainingModuleKind(compilerOptions.GetEmitModuleKind()) && node.CommonJSModuleIndicator != nil) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is unused |
||
|
||
func IsEffectiveExternalModuleWorker(node *SourceFile, moduleKind core.ModuleKind) bool { | ||
return IsExternalModule(node) || (isCommonJSContainingModuleKind(moduleKind) && node.CommonJSModuleIndicator != nil) | ||
} | ||
|
||
func isCommonJSContainingModuleKind(kind core.ModuleKind) bool { | ||
return kind == core.ModuleKindCommonJS || kind == core.ModuleKindNode16 || kind == core.ModuleKindNodeNext | ||
} | ||
|
@@ -1668,20 +1649,7 @@ func IsEnumConst(node *Node) bool { | |
} | ||
|
||
func ExportAssignmentIsAlias(node *Node) bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this was for syntactic |
||
return isAliasableExpression(getExportAssignmentExpression(node)) | ||
} | ||
|
||
func getExportAssignmentExpression(node *Node) *Node { | ||
switch node.Kind { | ||
case KindExportAssignment: | ||
return node.AsExportAssignment().Expression | ||
case KindBinaryExpression: | ||
return node.AsBinaryExpression().Right | ||
} | ||
panic("Unhandled case in getExportAssignmentExpression") | ||
} | ||
|
||
func isAliasableExpression(e *Node) bool { | ||
e := node.AsExportAssignment().Expression | ||
return IsEntityNameExpression(e) || IsClassExpression(e) | ||
} | ||
|
||
|
@@ -2086,6 +2054,7 @@ func GetMeaningFromDeclaration(node *Node) SemanticMeaning { | |
KindImportEqualsDeclaration, | ||
KindImportDeclaration, | ||
KindExportAssignment, | ||
KindJSExportAssignment, | ||
KindExportDeclaration: | ||
return SemanticMeaningAll | ||
|
||
|
@@ -2474,22 +2443,27 @@ func IsNonLocalAlias(symbol *Symbol, excludes SymbolFlags) bool { | |
// An alias symbol is created by one of the following declarations: | ||
// | ||
// import <symbol> = ... | ||
// const <symbol> = ... (JS only) | ||
// const { <symbol>, ... } = ... (JS only) | ||
// import <symbol> from ... | ||
// import * as <symbol> from ... | ||
// import { x as <symbol> } from ... | ||
// export { x as <symbol> } from ... | ||
// export * as ns <symbol> from ... | ||
// export = <EntityNameExpression> | ||
// export default <EntityNameExpression> | ||
// module.exports = <EntityNameExpression> (JS only) | ||
func IsAliasSymbolDeclaration(node *Node) bool { | ||
switch node.Kind { | ||
case KindImportEqualsDeclaration, KindNamespaceExportDeclaration, KindNamespaceImport, KindNamespaceExport, | ||
KindImportSpecifier, KindExportSpecifier: | ||
return true | ||
case KindImportClause: | ||
return node.AsImportClause().Name() != nil | ||
case KindExportAssignment: | ||
case KindExportAssignment, KindJSExportAssignment: | ||
return ExportAssignmentIsAlias(node) | ||
case KindVariableDeclaration, KindBindingElement: | ||
return IsVariableDeclarationInitializedToRequire(node) | ||
} | ||
return false | ||
} | ||
|
@@ -2568,7 +2542,7 @@ func ForEachDynamicImportOrRequireCall( | |
lastIndex, size := findImportOrRequire(file.Text(), 0) | ||
for lastIndex >= 0 { | ||
node := GetNodeAtPosition(file, lastIndex, isJavaScriptFile && includeTypeSpaceImports) | ||
if isJavaScriptFile && IsRequireCall(node, requireStringLiteralLikeArgument) { | ||
if isJavaScriptFile && IsRequireCall(node) { | ||
if cb(node, node.Arguments()[0]) { | ||
return true | ||
} | ||
|
@@ -2595,7 +2569,8 @@ func ForEachDynamicImportOrRequireCall( | |
return false | ||
} | ||
|
||
func IsRequireCall(node *Node, requireStringLiteralLikeArgument bool) bool { | ||
// IsVariableDeclarationInitializedToRequire should be used wherever parent pointers are set | ||
func IsRequireCall(node *Node) bool { | ||
if !IsCallExpression(node) { | ||
return false | ||
} | ||
|
@@ -2606,7 +2581,7 @@ func IsRequireCall(node *Node, requireStringLiteralLikeArgument bool) bool { | |
if len(call.Arguments.Nodes) != 1 { | ||
return false | ||
} | ||
return !requireStringLiteralLikeArgument || IsStringLiteralLike(call.Arguments.Nodes[0]) | ||
return IsStringLiteralLike(call.Arguments.Nodes[0]) | ||
} | ||
|
||
func IsUnterminatedLiteral(node *Node) bool { | ||
|
@@ -2664,6 +2639,36 @@ func GetPragmaArgument(pragma *Pragma, name string) string { | |
return "" | ||
} | ||
|
||
// Of the form: `const x = require("x")` or `const { x } = require("x")` or with `var` or `let` | ||
// The variable must not be exported and must not have a type annotation, even a jsdoc one. | ||
// The initializer must be a call to `require` with a string literal or a string literal-like argument. | ||
func IsVariableDeclarationInitializedToRequire(node *Node) bool { | ||
if !IsInJSFile(node) { | ||
return false | ||
} | ||
if node.Kind == KindBindingElement { | ||
node = node.Parent.Parent | ||
} | ||
if node.Kind != KindVariableDeclaration { | ||
return false | ||
} | ||
|
||
return node.Parent.Parent.ModifierFlags()&ModifierFlagsExport == 0 && | ||
node.AsVariableDeclaration().Initializer != nil && | ||
node.Type() == nil && | ||
IsRequireCall(node.AsVariableDeclaration().Initializer) | ||
} | ||
|
||
func IsModuleExportsAccessExpression(node *Node) bool { | ||
return (IsPropertyAccessExpression(node) || isLiteralLikeElementAccess(node)) && | ||
IsModuleIdentifier(node.Expression()) && | ||
GetElementOrPropertyAccessName(node) == "exports" | ||
} | ||
|
||
func isLiteralLikeElementAccess(node *Node) bool { | ||
return node.Kind == KindElementAccessExpression && IsStringOrNumericLiteralLike(node.AsElementAccessExpression().ArgumentExpression) | ||
} | ||
|
||
func IsCheckJSEnabledForFile(sourceFile *SourceFile, compilerOptions *core.CompilerOptions) bool { | ||
if sourceFile.CheckJsDirective != nil { | ||
return sourceFile.CheckJsDirective.Enabled | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have a private and public duplicate of this function so I deleted the private one