Ts-morph: How to identify an implicit global variable declaration ?

Created on 3 Mar 2020  路  4Comments  路  Source: dsherret/ts-morph

Implicit globals are variable that are declared without any keyword. There don't appear to be a VariableDeclaration node corresponding to implicit global variable declaration in the AST, just a BinaryExpression node. Is there a method to find out if an BinaryExpression node correspond to an implicit global variable declaration ?

Visualization of the issue :
https://ts-ast-viewer.com/#code/G4QwTgBKYPrQliARgGwKYQLwQC5gK5oDcAUCfALYAOK8AxvDjAOYoD2SIKc4iqG2PIVLQeYPuiwQAZlwDOxIA

Note that the line implicit global variable declaration is treated like a classic value-reassignment in the AST (line 3 and 4 in the code).

The implicit global variable declaration code is also underlined in red in the ast-viewer website: is this a simple warning or something else (were implicit globals disabled by a "use strict";)? As I understand it, typescript should be able to parse any valid JavaScript code. or ?

question

Most helpful comment

As I understand it, typescript should be able to parse any valid JavaScript code. or ?

Yes, TS will parse (almost) any valid JavaScript (there are some weird edge cases with << and >>, but you are unlikely to run into them in practice). That doesn't mean it won't produce errors when you do bad things, like these implicit globals.

I'm not aware of any way to check for implicit globals... but if by "implicit global" you can mean "undefined variable" you could simply check that checker.getSymbolAtLocation(node.left) returns undefined (also check that node.left is an identifier, or you will have false positives when destructuring... which could also include implicit declarations)

All 4 comments

As I understand it, typescript should be able to parse any valid JavaScript code. or ?

Yes, TS will parse (almost) any valid JavaScript (there are some weird edge cases with << and >>, but you are unlikely to run into them in practice). That doesn't mean it won't produce errors when you do bad things, like these implicit globals.

I'm not aware of any way to check for implicit globals... but if by "implicit global" you can mean "undefined variable" you could simply check that checker.getSymbolAtLocation(node.left) returns undefined (also check that node.left is an identifier, or you will have false positives when destructuring... which could also include implicit declarations)

node.left returns an error, node.getLeft() should be used instead. Otherwise the tests you proposed worked fine, thank you.

With this test it is possible to identify undefined variable involved in BinaryExpression nodes:
if (tsm.Node.isBinaryExpression(node) && checker.getSymbolAtLocation(node.getLeft()) == undefined && tsm.Node.isIdentifier(node.getLeft()))
Undefined variables involved in BinaryExpression include every possible implicit global declaration, but yields too many results since it also finds every case implicit globals variable reassignment.

The variables found have no references in the rest of the code, but I guess that must be expected if they are seen as undefined by the parser... I wonder if there is actually a way to really parse implicit global declarations, since those may be generated on the fly by JS when an undefined variable is accessed. It may therefore depends on flow of execution and hat would explain why they can't be parsed conventionally ?

That doesn't mean it won't produce errors when you do bad things, like these implicit globals.

I am working on a project I inherited and there just happens to be some in the source code, I don't plan to keep implicit globals variable in the future. But I'm looking to have a thorough approach when parsing the code (I am building a custom documentation tool), so identifying the particular case of implicit globals declaration would be nice.

@pierregallard I think maybe if the symbol for the left side returns undefined as @Gerrit0 mentioned.

Ideally though, a global declaration for that should be declared in a declaration file somewhere:

declare var implicit_global_variable: boolean;

Then getting the symbol would lead back to that global declaration.

Also thanks @Gerrit0 for responding! I've been too preoccuppied with dprint lately, but would like to get back to this project eventually.

Was this page helpful?
0 / 5 - 0 ratings