Skip to content
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

Allow allowJs and declaration to be used together #32372

Merged
merged 60 commits into from
Sep 26, 2019
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
78f04e5
Allow allowJs and declaration to be used together
weswigham Jul 3, 2019
f2a2a10
Add tests for various import/export forms, add notes on export as nam…
weswigham Jul 12, 2019
ccdff43
Tests & fixes for computed names
weswigham Jul 12, 2019
d18f1e3
Add test with current @enum tag behavior
weswigham Jul 12, 2019
7ed1331
fix declaration emit for jsdoc @enum tags
weswigham Jul 12, 2019
d44383e
Small adjustments to base class serialization to fix bugs in it
weswigham Jul 12, 2019
d7d37ab
Guard against type/type parameter confusion when using typeParameterT…
weswigham Jul 12, 2019
91c402e
Integrate feedback from PR
weswigham Jul 13, 2019
eb3b4cd
Fix issue with export= declarations visibility calculation and type d…
weswigham Jul 13, 2019
08c07cd
Only make one merged getCommonJsExportEquals symbol for a symbol
weswigham Jul 13, 2019
4d3a21d
Support preserving type reference directives in js declarations
weswigham Jul 13, 2019
11e9a06
Skip declare mdoifiers for namespace members in ambient contexts
weswigham Jul 15, 2019
02cc16b
FAKE ALIASES AND NAMESPACES EVERYWHERE
weswigham Jul 16, 2019
76f1e21
Dont do namespace sugar when type members contain keyword names
weswigham Jul 16, 2019
b4d6b2c
Fix json source file export modifier under new output
weswigham Jul 16, 2019
8d30a0c
Such clean nested aliasing, very wow
weswigham Jul 16, 2019
d369552
Fix lint
weswigham Jul 16, 2019
85d3008
Add visibility errors, reuse type nodes where possible
weswigham Jul 18, 2019
e6ef543
Suppoer having correctly named import types in bundled js declaration…
weswigham Jul 18, 2019
a0bf89e
Better support for module.exports = class expression
weswigham Jul 19, 2019
a68fd1d
Fix discovered crash bug
weswigham Jul 19, 2019
665afcf
Allow export assigned class expressions to be reachable symbols from …
weswigham Jul 22, 2019
b87e4d6
Add missing semicolon
weswigham Jul 22, 2019
114c4fd
Support @enum tag post-merge
weswigham Aug 2, 2019
5af190b
preserve comments on signatures and declarations where possible
weswigham Aug 2, 2019
6ea316e
Basic support for js classy functions
weswigham Aug 12, 2019
43d7965
Add example we should do better with
weswigham Aug 12, 2019
bebce37
Prototype assignments make things a bit wonky, but the example from t…
weswigham Aug 12, 2019
3961eae
Make a ton of changes to support the new way js classes are bound
weswigham Aug 28, 2019
6998296
Remove some old comments, fix import and export default names
weswigham Sep 10, 2019
799a4f4
Fix bug in object define handling and add tests for object define pro…
weswigham Sep 10, 2019
0e3894d
Fix organization nits from PR comments
weswigham Sep 10, 2019
94a64f7
Merge branch 'master' into symbolic-declaration-files
weswigham Sep 12, 2019
aa67e4c
Preserve comments from jsdoc declarations on properties and js declar…
weswigham Sep 12, 2019
14749ba
Merge export declarations with identical specifiers
weswigham Sep 12, 2019
d1a6da4
Remove completed TODO comment
weswigham Sep 12, 2019
733511d
Split lint
weswigham Sep 12, 2019
8de5d73
Merge branch 'master' into symbolic-declaration-files
weswigham Sep 23, 2019
a203b5f
Remove now-unused function
weswigham Sep 23, 2019
550b869
PR feedback
weswigham Sep 24, 2019
9d0cb15
Add some project references tests, remove some checks from project re…
weswigham Sep 24, 2019
87cbc15
Merge branch 'master' into symbolic-declaration-files
weswigham Sep 24, 2019
ff95ab5
Update project references tests again
weswigham Sep 24, 2019
bd9ac62
Merge branch 'master' into symbolic-declaration-files
weswigham Sep 25, 2019
649c9dd
Merge and update project references tests
weswigham Sep 25, 2019
cdcebc6
Rename case
weswigham Sep 25, 2019
16a332f
Update test to include declaration output
weswigham Sep 25, 2019
e055a9b
Remove yet another project refernces redirect extension check
weswigham Sep 25, 2019
08b105c
Update comment
weswigham Sep 25, 2019
adb773b
Add additional import ref to test
weswigham Sep 25, 2019
b8e2e91
Add shorthand prop to test
weswigham Sep 25, 2019
40a3540
Fix comment text
weswigham Sep 25, 2019
4741f40
Extract var to temp
weswigham Sep 25, 2019
59ddf20
Simplify function and add whitespace
weswigham Sep 25, 2019
8cad7b0
Merge branch 'master' into symbolic-declaration-files
weswigham Sep 25, 2019
861256f
Update project refs test to use incremental edit entry
weswigham Sep 25, 2019
0a2c6c8
Stylistic refactors in the symbol serializer
weswigham Sep 25, 2019
db2b1f9
Another round of PR feedback, mostly style, small bugfix with constru…
weswigham Sep 26, 2019
d7ef75b
Merge branch 'master' into symbolic-declaration-files
weswigham Sep 26, 2019
007b3d4
Use x instead of index
weswigham Sep 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 69 additions & 8 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,26 @@ namespace ts {
referenced: boolean;
}

export function getModuleInstanceState(node: ModuleDeclaration): ModuleInstanceState {
return node.body ? getModuleInstanceStateWorker(node.body) : ModuleInstanceState.Instantiated;
export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
if (node.body && !node.body.parent) {
// getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already
setParentPointers(node, node.body);
}
return node.body ? getModuleInstanceStateCached(node.body, visited) : ModuleInstanceState.Instantiated;
}

function getModuleInstanceStateWorker(node: Node): ModuleInstanceState {
function getModuleInstanceStateCached(node: Node, visited = createMap<ModuleInstanceState | undefined>()) {
const nodeId = "" + getNodeId(node);
if (visited.has(nodeId)) {
return visited.get(nodeId) || ModuleInstanceState.NonInstantiated;
}
visited.set(nodeId, undefined);
const result = getModuleInstanceStateWorker(node, visited);
visited.set(nodeId, result);
return result;
}

function getModuleInstanceStateWorker(node: Node, visited: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
// A module is uninstantiated if it contains only
switch (node.kind) {
// 1. interface declarations, type alias declarations
Expand All @@ -37,11 +52,27 @@ namespace ts {
return ModuleInstanceState.NonInstantiated;
}
break;
// 4. other uninstantiated module declarations.
// 4. Export alias declarations pointing at only uninstantiated modules or things uninstantiated modules contain
case SyntaxKind.ExportDeclaration:
if (!(node as ExportDeclaration).moduleSpecifier && !!(node as ExportDeclaration).exportClause) {
let state = ModuleInstanceState.NonInstantiated;
for (const specifier of (node as ExportDeclaration).exportClause!.elements) {
const specifierState = getModuleInstanceStateForAliasTarget(specifier, visited);
if (specifierState > state) {
state = specifierState;
}
if (state === ModuleInstanceState.Instantiated) {
return state;
}
}
return state;
}
break;
// 5. other uninstantiated module declarations.
case SyntaxKind.ModuleBlock: {
let state = ModuleInstanceState.NonInstantiated;
forEachChild(node, n => {
const childState = getModuleInstanceStateWorker(n);
const childState = getModuleInstanceStateCached(n, visited);
switch (childState) {
case ModuleInstanceState.NonInstantiated:
// child is non-instantiated - continue searching
Expand All @@ -61,7 +92,7 @@ namespace ts {
return state;
}
case SyntaxKind.ModuleDeclaration:
return getModuleInstanceState(node as ModuleDeclaration);
return getModuleInstanceState(node as ModuleDeclaration, visited);
case SyntaxKind.Identifier:
// Only jsdoc typedef definition can exist in jsdoc namespace, and it should
// be considered the same as type alias
Expand All @@ -72,6 +103,36 @@ namespace ts {
return ModuleInstanceState.Instantiated;
}

function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: Map<ModuleInstanceState | undefined>) {
const name = specifier.propertyName || specifier.name;
let p: Node | undefined = specifier.parent;
while (p) {
if (isBlock(p) || isModuleBlock(p) || isSourceFile(p)) {
const statements = p.statements;
let found: ModuleInstanceState | undefined;
for (const statement of statements) {
if (nodeHasName(statement, name)) {
if (!statement.parent) {
setParentPointers(p, statement);
}
const state = getModuleInstanceStateCached(statement, visited);
if (found === undefined || state > found) {
found = state;
}
if (found === ModuleInstanceState.Instantiated) {
return found;
}
}
}
if (found !== undefined) {
return found;
}
}
p = p.parent;
}
return ModuleInstanceState.Instantiated; // Couldn't locate, assume could refer to a value
}

const enum ContainerFlags {
// The current node is not a container, and no container manipulation should happen before
// recursing into it.
Expand Down Expand Up @@ -2561,7 +2622,7 @@ namespace ts {
// Declare a 'member' if the container is an ES5 class or ES6 constructor
constructorSymbol.members = constructorSymbol.members || createSymbolTable();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class);
}
break;
Expand All @@ -2575,7 +2636,7 @@ namespace ts {
// Bind this property to the containing class
const containingClass = thisContainer.parent;
const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!;
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this very likely obsoletes some syntactic code in the checker. But are you sure it doesn't cause these symbols to take incorrect code paths in the checker sometimes? I guess tests would fail if it did.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yah, definitely seemed like the symbol was missing an Assignment flag.

break;
case SyntaxKind.SourceFile:
// this.property = assignment in a source file -- declare symbol in exports for a module, in locals for a script
Expand Down
Loading