From 1577110c8dd038461e454d126eb50c5b1c5ea3d7 Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Sat, 23 May 2020 16:36:42 -0700 Subject: [PATCH] feat: add package scope-manager --- .cspell.json | 6 +- .eslintrc.js | 5 + .github/workflows/ci.yml | 14 +- .prettierignore | 1 + .vscode/extensions.json | 5 +- .vscode/launch.json | 44 +- .vscode/settings.json | 17 + .../eslint-plugin-internal/jest.config.js | 2 + packages/eslint-plugin-tslint/jest.config.js | 2 + packages/eslint-plugin/jest.config.js | 2 + packages/experimental-utils/jest.config.js | 2 + packages/scope-manager/LICENSE | 21 + packages/scope-manager/README.md | 16 + packages/scope-manager/jest.config.js | 24 + packages/scope-manager/package.json | 63 + packages/scope-manager/src/ID.ts | 20 + packages/scope-manager/src/ScopeManager.ts | 247 ++++ packages/scope-manager/src/Variable.ts | 80 ++ packages/scope-manager/src/analyze.ts | 58 + packages/scope-manager/src/assert.ts | 8 + .../src/definition/CatchClauseDefinition.ts | 19 + .../src/definition/ClassNameDefinition.ts | 19 + .../src/definition/Definition.ts | 26 + .../src/definition/DefinitionBase.ts | 60 + .../src/definition/DefinitionType.ts | 16 + .../src/definition/FunctionNameDefinition.ts | 22 + .../ImplicitGlobalVariableDefinition.ts | 22 + .../src/definition/ImportBindingDefinition.ts | 44 + .../src/definition/ParameterDefinition.ts | 37 + .../src/definition/TSEnumMemberDefinition.ts | 22 + .../src/definition/TSEnumNameDefinition.ts | 19 + .../src/definition/TSModuleNameDefinition.ts | 19 + .../src/definition/TypeDefinition.ts | 21 + .../src/definition/VariableDefinition.ts | 23 + .../scope-manager/src/definition/index.ts | 13 + packages/scope-manager/src/index.ts | 12 + .../src/referencer/ExportVisitor.ts | 72 + .../src/referencer/ImportVisitor.ts | 59 + .../src/referencer/PatternVisitor.ts | 142 ++ .../scope-manager/src/referencer/Reference.ts | 148 +++ .../src/referencer/Referencer.ts | 745 +++++++++++ .../src/referencer/TypeVisitor.ts | 199 +++ .../scope-manager/src/referencer/Visitor.ts | 44 + .../src/referencer/VisitorBase.ts | 79 ++ .../scope-manager/src/referencer/index.ts | 1 + .../scope-manager/src/scope/BlockScope.ts | 21 + .../scope-manager/src/scope/CatchScope.ts | 21 + .../scope-manager/src/scope/ClassScope.ts | 21 + .../src/scope/ConditionalTypeScope.ts | 21 + packages/scope-manager/src/scope/ForScope.ts | 21 + .../src/scope/FunctionExpressionNameScope.ts | 36 + .../scope-manager/src/scope/FunctionScope.ts | 65 + .../src/scope/FunctionTypeScope.ts | 25 + .../scope-manager/src/scope/GlobalScope.ts | 64 + .../src/scope/MappedTypeScope.ts | 21 + .../scope-manager/src/scope/ModuleScope.ts | 17 + packages/scope-manager/src/scope/Scope.ts | 36 + packages/scope-manager/src/scope/ScopeBase.ts | 495 +++++++ packages/scope-manager/src/scope/ScopeType.ts | 20 + .../scope-manager/src/scope/SwitchScope.ts | 21 + .../scope-manager/src/scope/TSEnumScope.ts | 21 + .../scope-manager/src/scope/TSModuleScope.ts | 21 + packages/scope-manager/src/scope/TypeScope.ts | 21 + packages/scope-manager/src/scope/WithScope.ts | 34 + packages/scope-manager/src/scope/index.ts | 18 + .../tests/eslint-scope/README.md | 13 + .../tests/eslint-scope/arguments.test.ts | 29 + .../tests/eslint-scope/catch-scope.test.ts | 48 + .../eslint-scope/child-visitor-keys.test.ts | 54 + .../es6-arrow-function-expression.test.ts | 118 ++ .../eslint-scope/es6-block-scope.test.ts | 149 +++ .../tests/eslint-scope/es6-catch.test.ts | 64 + .../tests/eslint-scope/es6-class.test.ts | 171 +++ .../es6-default-parameters.test.ts | 338 +++++ .../es6-destructuring-assignments.test.ts | 1179 +++++++++++++++++ .../tests/eslint-scope/es6-export.test.ts | 193 +++ .../tests/eslint-scope/es6-import.test.ts | 134 ++ .../eslint-scope/es6-iteration-scope.test.ts | 180 +++ .../tests/eslint-scope/es6-new-target.test.ts | 25 + .../tests/eslint-scope/es6-object.test.ts | 66 + .../tests/eslint-scope/es6-rest-args.test.ts | 36 + .../tests/eslint-scope/es6-super.test.ts | 49 + .../tests/eslint-scope/es6-switch.test.ts | 47 + .../eslint-scope/es6-template-literal.test.ts | 46 + .../function-expression-name.test.ts | 39 + .../get-declared-variables.test.ts | 228 ++++ .../eslint-scope/global-increment.test.ts | 15 + .../tests/eslint-scope/global-return.test.ts | 67 + .../implicit-global-reference.test.ts | 148 +++ .../tests/eslint-scope/implied-strict.test.ts | 124 ++ .../tests/eslint-scope/label.test.ts | 61 + .../tests/eslint-scope/references.test.ts | 512 +++++++ .../tests/eslint-scope/typescript.test.ts | 43 + .../tests/eslint-scope/with-scope.test.ts | 48 + packages/scope-manager/tests/fixtures.test.ts | 153 +++ .../tests/fixtures/block/inherited-scope.ts | 5 + .../fixtures/block/inherited-scope.ts.shot | 63 + .../tests/fixtures/block/scope.ts | 7 + .../tests/fixtures/block/scope.ts.shot | 93 ++ .../call-expression/call-expression.ts | 5 + .../call-expression/call-expression.ts.shot | 107 ++ .../call-expression/type-parameters1.ts | 2 + .../call-expression/type-parameters1.ts.shot | 50 + .../call-expression/type-parameters2.ts | 2 + .../call-expression/type-parameters2.ts.shot | 58 + .../tests/fixtures/catch/inherited-scope.ts | 5 + .../fixtures/catch/inherited-scope.ts.shot | 97 ++ .../tests/fixtures/catch/scope.ts | 8 + .../tests/fixtures/catch/scope.ts.shot | 160 +++ .../fixtures/class/declaration/abstract.ts | 4 + .../class/declaration/abstract.ts.shot | 108 ++ .../class/declaration/computed-member.ts | 6 + .../class/declaration/computed-member.ts.shot | 144 ++ .../class/declaration/extends-generic.ts | 3 + .../class/declaration/extends-generic.ts.shot | 145 ++ .../fixtures/class/declaration/extends.ts | 2 + .../class/declaration/extends.ts.shot | 108 ++ .../class/declaration/generic-ref-extends.ts | 1 + .../declaration/generic-ref-extends.ts.shot | 90 ++ .../declaration/generic-ref-implements.ts | 1 + .../generic-ref-implements.ts.shot | 89 ++ .../fixtures/class/declaration/generic.ts | 3 + .../class/declaration/generic.ts.shot | 95 ++ .../class/declaration/implements-generic.ts | 3 + .../declaration/implements-generic.ts.shot | 130 ++ .../fixtures/class/declaration/implements.ts | 2 + .../class/declaration/implements.ts.shot | 83 ++ .../fixtures/class/declaration/method.ts | 8 + .../fixtures/class/declaration/method.ts.shot | 261 ++++ .../tests/fixtures/class/declaration/new.ts | 2 + .../fixtures/class/declaration/new.ts.shot | 69 + .../class/declaration/parameter-properties.ts | 16 + .../declaration/parameter-properties.ts.shot | 294 ++++ .../declaration/properties-type-annotation.ts | 4 + .../properties-type-annotation.ts.shot | 83 ++ .../fixtures/class/declaration/properties.ts | 5 + .../class/declaration/properties.ts.shot | 91 ++ .../class/declaration/type-reference.ts | 5 + .../class/declaration/type-reference.ts.shot | 135 ++ .../class/expression/computed-member.ts | 6 + .../class/expression/computed-member.ts.shot | 138 ++ .../fixtures/class/expression/extends.ts | 2 + .../fixtures/class/expression/extends.ts.shot | 102 ++ .../tests/fixtures/class/expression/method.ts | 8 + .../fixtures/class/expression/method.ts.shot | 255 ++++ .../tests/fixtures/class/expression/new.ts | 2 + .../fixtures/class/expression/new.ts.shot | 62 + .../class/expression/parameter-properties.ts | 16 + .../expression/parameter-properties.ts.shot | 288 ++++ .../fixtures/class/expression/properties.ts | 5 + .../class/expression/properties.ts.shot | 85 ++ .../tests/fixtures/decorators/accessor.ts | 9 + .../fixtures/decorators/accessor.ts.shot | 150 +++ .../fixtures/decorators/class-property.ts | 5 + .../decorators/class-property.ts.shot | 103 ++ .../tests/fixtures/decorators/class.ts | 3 + .../tests/fixtures/decorators/class.ts.shot | 103 ++ .../tests/fixtures/decorators/method.ts | 5 + .../tests/fixtures/decorators/method.ts.shot | 123 ++ .../fixtures/decorators/parameter-property.ts | 4 + .../decorators/parameter-property.ts.shot | 168 +++ .../tests/fixtures/decorators/parameter.ts | 7 + .../fixtures/decorators/parameter.ts.shot | 185 +++ .../destructuring/array-assignment.ts | 3 + .../destructuring/array-assignment.ts.shot | 101 ++ .../tests/fixtures/destructuring/array.ts | 1 + .../fixtures/destructuring/array.ts.shot | 214 +++ .../destructuring/object-assignment.ts | 6 + .../destructuring/object-assignment.ts.shot | 75 ++ .../tests/fixtures/destructuring/object.ts | 6 + .../fixtures/destructuring/object.ts.shot | 196 +++ .../tests/fixtures/export/all.ts | 4 + .../tests/fixtures/export/all.ts.shot | 27 + .../tests/fixtures/export/default-type.ts | 4 + .../fixtures/export/default-type.ts.shot | 53 + .../tests/fixtures/export/default1.ts | 3 + .../tests/fixtures/export/default1.ts.shot | 64 + .../tests/fixtures/export/default2.ts | 4 + .../tests/fixtures/export/default2.ts.shot | 62 + .../tests/fixtures/export/default3.ts | 3 + .../tests/fixtures/export/default3.ts.shot | 27 + .../tests/fixtures/export/default4.ts | 3 + .../tests/fixtures/export/default4.ts.shot | 48 + .../tests/fixtures/export/equals1.ts | 4 + .../tests/fixtures/export/equals1.ts.shot | 62 + .../tests/fixtures/export/equals2.ts | 3 + .../tests/fixtures/export/equals2.ts.shot | 27 + .../tests/fixtures/export/named-dual.ts | 3 + .../tests/fixtures/export/named-dual.ts.shot | 57 + .../tests/fixtures/export/named-source1.ts | 3 + .../fixtures/export/named-source1.ts.shot | 27 + .../tests/fixtures/export/named-source2.ts | 3 + .../fixtures/export/named-source2.ts.shot | 27 + .../tests/fixtures/export/named-type1.ts | 3 + .../tests/fixtures/export/named-type1.ts.shot | 44 + .../tests/fixtures/export/named1.ts | 3 + .../tests/fixtures/export/named1.ts.shot | 55 + .../tests/fixtures/export/named2-type.ts | 4 + .../tests/fixtures/export/named2-type.ts.shot | 53 + .../tests/fixtures/export/named2.ts | 4 + .../tests/fixtures/export/named2.ts.shot | 62 + .../tests/fixtures/export/named3-type.ts | 4 + .../tests/fixtures/export/named3-type.ts.shot | 53 + .../tests/fixtures/export/named3.ts | 4 + .../tests/fixtures/export/named3.ts.shot | 62 + .../tests/fixtures/export/type.ts | 5 + .../tests/fixtures/export/type.ts.shot | 66 + .../readable-ref-body-shadow.ts | 5 + .../readable-ref-body-shadow.ts.shot | 118 ++ .../default-params/readable-ref-const.ts | 2 + .../default-params/readable-ref-const.ts.shot | 113 ++ .../arrow/default-params/readable-ref-let.ts | 2 + .../default-params/readable-ref-let.ts.shot | 104 ++ .../readable-ref-nested-body-shadow.ts | 8 + .../readable-ref-nested-body-shadow.ts.shot | 139 ++ .../default-params/readable-ref-nested.ts | 6 + .../readable-ref-nested.ts.shot | 125 ++ .../readable-ref-param-shadow.ts | 3 + .../readable-ref-param-shadow.ts.shot | 118 ++ .../default-params/readable-ref-partial.ts | 2 + .../readable-ref-partial.ts.shot | 104 ++ .../arrow/default-params/writable-ref.ts | 1 + .../arrow/default-params/writable-ref.ts.shot | 96 ++ .../functions/arrow/inherited-scope.ts | 5 + .../functions/arrow/inherited-scope.ts.shot | 63 + .../tests/fixtures/functions/arrow/no-body.ts | 1 + .../fixtures/functions/arrow/no-body.ts.shot | 53 + .../tests/fixtures/functions/arrow/params.ts | 6 + .../fixtures/functions/arrow/params.ts.shot | 238 ++++ .../tests/fixtures/functions/arrow/scope.ts | 8 + .../fixtures/functions/arrow/scope.ts.shot | 143 ++ .../arrow/type-parameters/body-reference.ts | 3 + .../type-parameters/body-reference.ts.shot | 94 ++ .../arrow/type-parameters/param-reference.ts | 1 + .../type-parameters/param-reference.ts.shot | 94 ++ .../type-parameters/return-value-reference.ts | 1 + .../return-value-reference.ts.shot | 80 ++ .../type-parameters/type-param-reference.ts | 1 + .../type-param-reference.ts.shot | 94 ++ .../type-parameter-declaration.ts | 3 + .../type-parameter-declaration.ts.shot | 91 ++ .../readable-ref-body-shadow.ts | 5 + .../readable-ref-body-shadow.ts.shot | 116 ++ .../default-params/readable-ref-const.ts | 2 + .../default-params/readable-ref-const.ts.shot | 112 ++ .../default-params/readable-ref-let.ts | 2 + .../default-params/readable-ref-let.ts.shot | 102 ++ .../readable-ref-nested-body-shadow.ts | 8 + .../readable-ref-nested-body-shadow.ts.shot | 137 ++ .../default-params/readable-ref-nested.ts | 6 + .../readable-ref-nested.ts.shot | 123 ++ .../readable-ref-param-shadow.ts | 3 + .../readable-ref-param-shadow.ts.shot | 116 ++ .../default-params/readable-ref-partial.ts | 2 + .../readable-ref-partial.ts.shot | 102 ++ .../default-params/writable-ref.ts | 1 + .../default-params/writable-ref.ts.shot | 94 ++ .../function-declaration/inherited-scope.ts | 5 + .../inherited-scope.ts.shot | 88 ++ .../function-declaration/overload.ts | 4 + .../function-declaration/overload.ts.shot | 144 ++ .../functions/function-declaration/params.ts | 6 + .../function-declaration/params.ts.shot | 261 ++++ .../functions/function-declaration/scope.ts | 8 + .../function-declaration/scope.ts.shot | 142 ++ .../type-parameters/body-reference.ts | 3 + .../type-parameters/body-reference.ts.shot | 92 ++ .../type-parameters/param-reference.ts | 1 + .../type-parameters/param-reference.ts.shot | 92 ++ .../type-parameters/return-value-reference.ts | 1 + .../return-value-reference.ts.shot | 78 ++ .../type-parameters/type-param-reference.ts | 1 + .../type-param-reference.ts.shot | 92 ++ .../type-parameter-declaration.ts | 3 + .../type-parameter-declaration.ts.shot | 90 ++ .../function-expression/anonymous.ts | 1 + .../function-expression/anonymous.ts.shot | 66 + .../readable-ref-body-shadow.ts | 5 + .../readable-ref-body-shadow.ts.shot | 127 ++ .../default-params/readable-ref-const.ts | 2 + .../default-params/readable-ref-const.ts.shot | 122 ++ .../default-params/readable-ref-let.ts | 2 + .../default-params/readable-ref-let.ts.shot | 113 ++ .../readable-ref-nested-body-shadow.ts | 8 + .../readable-ref-nested-body-shadow.ts.shot | 148 +++ .../default-params/readable-ref-nested.ts | 6 + .../readable-ref-nested.ts.shot | 134 ++ .../readable-ref-param-shadow.ts | 3 + .../readable-ref-param-shadow.ts.shot | 127 ++ .../default-params/readable-ref-partial.ts | 2 + .../readable-ref-partial.ts.shot | 113 ++ .../default-params/writable-ref.ts | 1 + .../default-params/writable-ref.ts.shot | 105 ++ .../function-expression/inherited-scope.ts | 5 + .../inherited-scope.ts.shot | 98 ++ .../functions/function-expression/params.ts | 6 + .../function-expression/params.ts.shot | 271 ++++ .../functions/function-expression/scope.ts | 8 + .../function-expression/scope.ts.shot | 152 +++ .../type-parameters/body-reference.ts | 3 + .../type-parameters/body-reference.ts.shot | 103 ++ .../type-parameters/param-reference.ts | 1 + .../type-parameters/param-reference.ts.shot | 103 ++ .../type-parameters/return-value-reference.ts | 1 + .../return-value-reference.ts.shot | 89 ++ .../type-parameters/type-param-reference.ts | 1 + .../type-param-reference.ts.shot | 103 ++ .../type-parameter-declaration.ts | 3 + .../type-parameter-declaration.ts.shot | 100 ++ .../global-resolution/module/class.ts | 3 + .../global-resolution/module/class.ts.shot | 78 ++ .../global-resolution/module/function.ts | 3 + .../global-resolution/module/function.ts.shot | 73 + .../module/variable-decl-const.ts | 3 + .../module/variable-decl-const.ts.shot | 71 + .../module/variable-decl-let.ts | 3 + .../module/variable-decl-let.ts.shot | 71 + .../module/variable-decl-var.ts | 3 + .../module/variable-decl-var.ts.shot | 71 + .../global-resolution/script/class.ts | 3 + .../global-resolution/script/class.ts.shot | 69 + .../global-resolution/script/function.ts | 3 + .../global-resolution/script/function.ts.shot | 64 + .../script/variable-decl-const.ts | 3 + .../script/variable-decl-const.ts.shot | 62 + .../script/variable-decl-let.ts | 3 + .../script/variable-decl-let.ts.shot | 62 + .../script/variable-decl-var.ts | 3 + .../script/variable-decl-var.ts.shot | 59 + .../tests/fixtures/implicit/implicit1.ts | 1 + .../tests/fixtures/implicit/implicit1.ts.shot | 52 + .../tests/fixtures/import/default.ts | 6 + .../tests/fixtures/import/default.ts.shot | 74 ++ .../tests/fixtures/import/equals1.ts | 5 + .../tests/fixtures/import/equals1.ts.shot | 53 + .../tests/fixtures/import/equals2.ts | 4 + .../tests/fixtures/import/equals2.ts.shot | 76 ++ .../tests/fixtures/import/named-alias.ts | 6 + .../tests/fixtures/import/named-alias.ts.shot | 74 ++ .../tests/fixtures/import/named.ts | 6 + .../tests/fixtures/import/named.ts.shot | 74 ++ .../tests/fixtures/import/namespace.ts | 6 + .../tests/fixtures/import/namespace.ts.shot | 74 ++ .../tests/fixtures/import/type-default.ts | 6 + .../fixtures/import/type-default.ts.shot | 97 ++ .../tests/fixtures/import/type-named.ts | 6 + .../tests/fixtures/import/type-named.ts.shot | 97 ++ .../member-expression/member-expression.ts | 7 + .../member-expression.ts.shot | 81 ++ .../tests/fixtures/ts-enum/external-ref.ts | 5 + .../fixtures/ts-enum/external-ref.ts.shot | 83 ++ .../fixtures/ts-enum/literal-member-ref.ts | 4 + .../ts-enum/literal-member-ref.ts.shot | 97 ++ .../tests/fixtures/ts-enum/literal-member.ts | 3 + .../fixtures/ts-enum/literal-member.ts.shot | 74 ++ .../tests/fixtures/ts-enum/member-ref.ts | 4 + .../tests/fixtures/ts-enum/member-ref.ts.shot | 97 ++ .../tests/fixtures/ts-enum/scope.ts | 5 + .../tests/fixtures/ts-enum/scope.ts.shot | 105 ++ .../tests/fixtures/ts-enum/self-ref.ts | 4 + .../tests/fixtures/ts-enum/self-ref.ts.shot | 97 ++ .../tests/fixtures/ts-module/external-ref.ts | 5 + .../fixtures/ts-module/external-ref.ts.shot | 94 ++ .../tests/fixtures/ts-module/import.ts | 5 + .../tests/fixtures/ts-module/import.ts.shot | 53 + .../tests/fixtures/ts-module/namespace.ts | 7 + .../fixtures/ts-module/namespace.ts.shot | 132 ++ .../tests/fixtures/ts-module/scope.ts | 5 + .../tests/fixtures/ts-module/scope.ts.shot | 116 ++ .../tests/fixtures/ts-module/self-ref.ts | 4 + .../tests/fixtures/ts-module/self-ref.ts.shot | 93 ++ .../parameter-array-destructure.ts | 2 + .../parameter-array-destructure.ts.shot | 92 ++ .../type-annotation/parameter-default.ts | 2 + .../type-annotation/parameter-default.ts.shot | 102 ++ .../parameter-object-destructure.ts | 2 + .../parameter-object-destructure.ts.shot | 92 ++ .../type-annotation/parameter-rest.ts | 2 + .../type-annotation/parameter-rest.ts.shot | 92 ++ .../fixtures/type-annotation/parameter.ts | 2 + .../type-annotation/parameter.ts.shot | 92 ++ .../variable-array-destructure.ts | 2 + .../variable-array-destructure.ts.shot | 68 + .../type-annotation/variable-const.ts | 2 + .../type-annotation/variable-const.ts.shot | 68 + .../fixtures/type-annotation/variable-let.ts | 2 + .../type-annotation/variable-let.ts.shot | 58 + .../variable-object-destructure.ts | 2 + .../variable-object-destructure.ts.shot | 68 + .../fixtures/type-annotation/variable-var.ts | 2 + .../type-annotation/variable-var.ts.shot | 58 + .../fixtures/type-assertion/angle-bracket.ts | 4 + .../type-assertion/angle-bracket.ts.shot | 75 ++ .../tests/fixtures/type-assertion/as.ts | 4 + .../tests/fixtures/type-assertion/as.ts.shot | 75 ++ .../fixtures/type-declaration/conditional1.ts | 3 + .../type-declaration/conditional1.ts.shot | 123 ++ .../fixtures/type-declaration/conditional2.ts | 3 + .../type-declaration/conditional2.ts.shot | 90 ++ .../type-declaration/dual-type-value.ts | 5 + .../type-declaration/dual-type-value.ts.shot | 102 ++ .../function/constructor-generics1.ts | 2 + .../function/constructor-generics1.ts.shot | 116 ++ .../function/constructor-generics2.ts | 2 + .../function/constructor-generics2.ts.shot | 105 ++ .../type-declaration/function/constructor.ts | 2 + .../function/constructor.ts.shot | 90 ++ .../function/function-generics1.ts | 2 + .../function/function-generics1.ts.shot | 116 ++ .../function/function-generics2.ts | 2 + .../function/function-generics2.ts.shot | 105 ++ .../type-declaration/function/function1.ts | 2 + .../function/function1.ts.shot | 90 ++ .../type-declaration/function/function2.ts | 3 + .../function/function2.ts.shot | 94 ++ .../type-declaration/index-access1.ts | 2 + .../type-declaration/index-access1.ts.shot | 58 + .../type-declaration/index-access2.ts | 3 + .../type-declaration/index-access2.ts.shot | 80 ++ .../type-declaration/index-access3.ts | 3 + .../type-declaration/index-access3.ts.shot | 89 ++ .../type-declaration/interface-heritage1.ts | 2 + .../interface-heritage1.ts.shot | 58 + .../type-declaration/interface-heritage2.ts | 5 + .../interface-heritage2.ts.shot | 111 ++ .../fixtures/type-declaration/interface1.ts | 3 + .../type-declaration/interface1.ts.shot | 35 + .../fixtures/type-declaration/interface2.ts | 2 + .../type-declaration/interface2.ts.shot | 58 + .../tests/fixtures/type-declaration/mapped.ts | 2 + .../fixtures/type-declaration/mapped.ts.shot | 98 ++ .../type-declaration/qualified-name.ts | 2 + .../type-declaration/qualified-name.ts.shot | 58 + .../signatures/call-generics.ts | 4 + .../signatures/call-generics.ts.shot | 105 ++ .../type-declaration/signatures/call.ts | 4 + .../type-declaration/signatures/call.ts.shot | 90 ++ .../signatures/construct-generics.ts | 4 + .../signatures/construct-generics.ts.shot | 105 ++ .../type-declaration/signatures/construct.ts | 4 + .../signatures/construct.ts.shot | 90 ++ .../type-declaration/signatures/index-sig.ts | 2 + .../signatures/index-sig.ts.shot | 58 + .../signatures/method-computed-name.ts | 5 + .../signatures/method-computed-name.ts.shot | 122 ++ .../signatures/method-generics.ts | 4 + .../signatures/method-generics.ts.shot | 105 ++ .../type-declaration/signatures/method.ts | 4 + .../signatures/method.ts.shot | 90 ++ .../signatures/property-computed-name.ts | 5 + .../signatures/property-computed-name.ts.shot | 89 ++ .../type-declaration/signatures/property.ts | 4 + .../signatures/property.ts.shot | 58 + .../fixtures/type-declaration/tuple-rest.ts | 2 + .../type-declaration/tuple-rest.ts.shot | 58 + .../tests/fixtures/type-declaration/tuple.ts | 2 + .../fixtures/type-declaration/tuple.ts.shot | 58 + .../interface/body-reference.ts | 3 + .../interface/body-reference.ts.shot | 69 + .../interface/extends-reference.ts | 2 + .../interface/extends-reference.ts.shot | 116 ++ .../interface/type-param-reference.ts | 1 + .../interface/type-param-reference.ts.shot | 83 ++ .../type-parameter-declaration-extends.ts | 1 + ...type-parameter-declaration-extends.ts.shot | 83 ++ .../interface/type-parameter-declaration.ts | 3 + .../type-parameter-declaration.ts.shot | 81 ++ .../type-decl/body-reference.ts | 1 + .../type-decl/body-reference.ts.shot | 69 + .../type-decl/type-param-reference.ts | 1 + .../type-decl/type-param-reference.ts.shot | 83 ++ .../type-parameter-declaration-extends.ts | 1 + ...type-parameter-declaration-extends.ts.shot | 83 ++ .../type-decl/type-parameter-declaration.ts | 3 + .../type-parameter-declaration.ts.shot | 81 ++ .../fixtures/type-declaration/type-query.ts | 3 + .../type-declaration/type-query.ts.shot | 87 ++ .../tests/fixtures/type-declaration/type1.ts | 1 + .../fixtures/type-declaration/type1.ts.shot | 35 + .../tests/fixtures/type-declaration/type2.ts | 2 + .../fixtures/type-declaration/type2.ts.shot | 58 + .../tests/fixtures/type-declaration/type3.ts | 5 + .../fixtures/type-declaration/type3.ts.shot | 58 + .../tests/types/reference-type.test.ts | 196 +++ .../tests/types/variable-definition.test.ts | 109 ++ packages/scope-manager/tests/util/expect.ts | 138 ++ .../tests/util/getSpecificNode.ts | 52 + packages/scope-manager/tests/util/index.ts | 3 + packages/scope-manager/tests/util/parse.ts | 30 + .../tests/util/serializers/DefinitionBase.ts | 20 + .../tests/util/serializers/Reference.ts | 13 + .../tests/util/serializers/ScopeBase.ts | 22 + .../tests/util/serializers/ScopeManager.ts | 10 + .../tests/util/serializers/TSESTreeNode.ts | 50 + .../tests/util/serializers/Variable.ts | 13 + .../tests/util/serializers/baseSerializer.ts | 78 ++ .../tests/util/serializers/index.ts | 28 + packages/scope-manager/tsconfig.build.json | 16 + packages/scope-manager/tsconfig.json | 8 + packages/types/src/ts-estree.ts | 35 +- packages/typescript-estree/src/convert.ts | 4 +- packages/typescript-estree/src/index.ts | 2 +- .../typescript-estree/src/parser-options.ts | 17 + .../typescript-estree/src/simple-traverse.ts | 46 +- tests/integration/docker-compose.yml | 12 + tests/integration/fixtures/eslint-v6/test.sh | 1 + tests/integration/fixtures/markdown/test.sh | 1 + .../test.sh | 1 + .../test.sh | 1 + tests/integration/fixtures/vue-jsx/test.sh | 1 + tests/integration/fixtures/vue-sfc/test.sh | 1 + yarn.lock | 34 +- 512 files changed, 28327 insertions(+), 45 deletions(-) create mode 100644 packages/scope-manager/LICENSE create mode 100644 packages/scope-manager/README.md create mode 100644 packages/scope-manager/jest.config.js create mode 100644 packages/scope-manager/package.json create mode 100644 packages/scope-manager/src/ID.ts create mode 100644 packages/scope-manager/src/ScopeManager.ts create mode 100644 packages/scope-manager/src/Variable.ts create mode 100644 packages/scope-manager/src/analyze.ts create mode 100644 packages/scope-manager/src/assert.ts create mode 100644 packages/scope-manager/src/definition/CatchClauseDefinition.ts create mode 100644 packages/scope-manager/src/definition/ClassNameDefinition.ts create mode 100644 packages/scope-manager/src/definition/Definition.ts create mode 100644 packages/scope-manager/src/definition/DefinitionBase.ts create mode 100644 packages/scope-manager/src/definition/DefinitionType.ts create mode 100644 packages/scope-manager/src/definition/FunctionNameDefinition.ts create mode 100644 packages/scope-manager/src/definition/ImplicitGlobalVariableDefinition.ts create mode 100644 packages/scope-manager/src/definition/ImportBindingDefinition.ts create mode 100644 packages/scope-manager/src/definition/ParameterDefinition.ts create mode 100644 packages/scope-manager/src/definition/TSEnumMemberDefinition.ts create mode 100644 packages/scope-manager/src/definition/TSEnumNameDefinition.ts create mode 100644 packages/scope-manager/src/definition/TSModuleNameDefinition.ts create mode 100644 packages/scope-manager/src/definition/TypeDefinition.ts create mode 100644 packages/scope-manager/src/definition/VariableDefinition.ts create mode 100644 packages/scope-manager/src/definition/index.ts create mode 100644 packages/scope-manager/src/index.ts create mode 100644 packages/scope-manager/src/referencer/ExportVisitor.ts create mode 100644 packages/scope-manager/src/referencer/ImportVisitor.ts create mode 100644 packages/scope-manager/src/referencer/PatternVisitor.ts create mode 100644 packages/scope-manager/src/referencer/Reference.ts create mode 100644 packages/scope-manager/src/referencer/Referencer.ts create mode 100644 packages/scope-manager/src/referencer/TypeVisitor.ts create mode 100644 packages/scope-manager/src/referencer/Visitor.ts create mode 100644 packages/scope-manager/src/referencer/VisitorBase.ts create mode 100644 packages/scope-manager/src/referencer/index.ts create mode 100644 packages/scope-manager/src/scope/BlockScope.ts create mode 100644 packages/scope-manager/src/scope/CatchScope.ts create mode 100644 packages/scope-manager/src/scope/ClassScope.ts create mode 100644 packages/scope-manager/src/scope/ConditionalTypeScope.ts create mode 100644 packages/scope-manager/src/scope/ForScope.ts create mode 100644 packages/scope-manager/src/scope/FunctionExpressionNameScope.ts create mode 100644 packages/scope-manager/src/scope/FunctionScope.ts create mode 100644 packages/scope-manager/src/scope/FunctionTypeScope.ts create mode 100644 packages/scope-manager/src/scope/GlobalScope.ts create mode 100644 packages/scope-manager/src/scope/MappedTypeScope.ts create mode 100644 packages/scope-manager/src/scope/ModuleScope.ts create mode 100644 packages/scope-manager/src/scope/Scope.ts create mode 100644 packages/scope-manager/src/scope/ScopeBase.ts create mode 100644 packages/scope-manager/src/scope/ScopeType.ts create mode 100644 packages/scope-manager/src/scope/SwitchScope.ts create mode 100644 packages/scope-manager/src/scope/TSEnumScope.ts create mode 100644 packages/scope-manager/src/scope/TSModuleScope.ts create mode 100644 packages/scope-manager/src/scope/TypeScope.ts create mode 100644 packages/scope-manager/src/scope/WithScope.ts create mode 100644 packages/scope-manager/src/scope/index.ts create mode 100644 packages/scope-manager/tests/eslint-scope/README.md create mode 100644 packages/scope-manager/tests/eslint-scope/arguments.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/catch-scope.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/child-visitor-keys.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-arrow-function-expression.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-block-scope.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-catch.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-class.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-default-parameters.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-destructuring-assignments.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-export.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-import.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-iteration-scope.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-new-target.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-object.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-rest-args.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-super.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-switch.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/es6-template-literal.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/function-expression-name.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/get-declared-variables.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/global-increment.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/global-return.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/implicit-global-reference.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/implied-strict.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/label.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/references.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/typescript.test.ts create mode 100644 packages/scope-manager/tests/eslint-scope/with-scope.test.ts create mode 100644 packages/scope-manager/tests/fixtures.test.ts create mode 100644 packages/scope-manager/tests/fixtures/block/inherited-scope.ts create mode 100644 packages/scope-manager/tests/fixtures/block/inherited-scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/block/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/block/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/call-expression/call-expression.ts create mode 100644 packages/scope-manager/tests/fixtures/call-expression/call-expression.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts create mode 100644 packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts create mode 100644 packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/catch/inherited-scope.ts create mode 100644 packages/scope-manager/tests/fixtures/catch/inherited-scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/catch/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/catch/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/abstract.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/abstract.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/extends.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/extends.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/generic.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/generic.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/implements.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/implements.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/method.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/method.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/new.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/new.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/properties.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/properties.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/expression/computed-member.ts create mode 100644 packages/scope-manager/tests/fixtures/class/expression/computed-member.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/expression/extends.ts create mode 100644 packages/scope-manager/tests/fixtures/class/expression/extends.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/expression/method.ts create mode 100644 packages/scope-manager/tests/fixtures/class/expression/method.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/expression/new.ts create mode 100644 packages/scope-manager/tests/fixtures/class/expression/new.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts create mode 100644 packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/class/expression/properties.ts create mode 100644 packages/scope-manager/tests/fixtures/class/expression/properties.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/decorators/accessor.ts create mode 100644 packages/scope-manager/tests/fixtures/decorators/accessor.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/decorators/class-property.ts create mode 100644 packages/scope-manager/tests/fixtures/decorators/class-property.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/decorators/class.ts create mode 100644 packages/scope-manager/tests/fixtures/decorators/class.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/decorators/method.ts create mode 100644 packages/scope-manager/tests/fixtures/decorators/method.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/decorators/parameter-property.ts create mode 100644 packages/scope-manager/tests/fixtures/decorators/parameter-property.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/decorators/parameter.ts create mode 100644 packages/scope-manager/tests/fixtures/decorators/parameter.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts create mode 100644 packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/destructuring/array.ts create mode 100644 packages/scope-manager/tests/fixtures/destructuring/array.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts create mode 100644 packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/destructuring/object.ts create mode 100644 packages/scope-manager/tests/fixtures/destructuring/object.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/all.ts create mode 100644 packages/scope-manager/tests/fixtures/export/all.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/default-type.ts create mode 100644 packages/scope-manager/tests/fixtures/export/default-type.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/default1.ts create mode 100644 packages/scope-manager/tests/fixtures/export/default1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/default2.ts create mode 100644 packages/scope-manager/tests/fixtures/export/default2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/default3.ts create mode 100644 packages/scope-manager/tests/fixtures/export/default3.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/default4.ts create mode 100644 packages/scope-manager/tests/fixtures/export/default4.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/equals1.ts create mode 100644 packages/scope-manager/tests/fixtures/export/equals1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/equals2.ts create mode 100644 packages/scope-manager/tests/fixtures/export/equals2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named-dual.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named-dual.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named-source1.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named-source1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named-source2.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named-source2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named-type1.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named-type1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named1.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named2-type.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named2-type.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named2.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named3-type.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named3-type.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/named3.ts create mode 100644 packages/scope-manager/tests/fixtures/export/named3.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/export/type.ts create mode 100644 packages/scope-manager/tests/fixtures/export/type.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/params.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/params.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/params.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/params.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts create mode 100644 packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/class.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/class.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/function.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/function.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/class.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/class.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/function.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/function.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts create mode 100644 packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/implicit/implicit1.ts create mode 100644 packages/scope-manager/tests/fixtures/implicit/implicit1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/default.ts create mode 100644 packages/scope-manager/tests/fixtures/import/default.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/equals1.ts create mode 100644 packages/scope-manager/tests/fixtures/import/equals1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/equals2.ts create mode 100644 packages/scope-manager/tests/fixtures/import/equals2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/named-alias.ts create mode 100644 packages/scope-manager/tests/fixtures/import/named-alias.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/named.ts create mode 100644 packages/scope-manager/tests/fixtures/import/named.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/namespace.ts create mode 100644 packages/scope-manager/tests/fixtures/import/namespace.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/type-default.ts create mode 100644 packages/scope-manager/tests/fixtures/import/type-default.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/type-named.ts create mode 100644 packages/scope-manager/tests/fixtures/import/type-named.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/member-expression/member-expression.ts create mode 100644 packages/scope-manager/tests/fixtures/member-expression/member-expression.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-module/external-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-module/external-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-module/import.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-module/import.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-module/namespace.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-module/namespace.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-module/scope.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-module/scope.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/ts-module/self-ref.ts create mode 100644 packages/scope-manager/tests/fixtures/ts-module/self-ref.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/parameter.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts create mode 100644 packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts create mode 100644 packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-assertion/as.ts create mode 100644 packages/scope-manager/tests/fixtures/type-assertion/as.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/interface2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/mapped.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/mapped.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/tuple.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/tuple.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-query.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type-query.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type1.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type2.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type2.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type3.ts create mode 100644 packages/scope-manager/tests/fixtures/type-declaration/type3.ts.shot create mode 100644 packages/scope-manager/tests/types/reference-type.test.ts create mode 100644 packages/scope-manager/tests/types/variable-definition.test.ts create mode 100644 packages/scope-manager/tests/util/expect.ts create mode 100644 packages/scope-manager/tests/util/getSpecificNode.ts create mode 100644 packages/scope-manager/tests/util/index.ts create mode 100644 packages/scope-manager/tests/util/parse.ts create mode 100644 packages/scope-manager/tests/util/serializers/DefinitionBase.ts create mode 100644 packages/scope-manager/tests/util/serializers/Reference.ts create mode 100644 packages/scope-manager/tests/util/serializers/ScopeBase.ts create mode 100644 packages/scope-manager/tests/util/serializers/ScopeManager.ts create mode 100644 packages/scope-manager/tests/util/serializers/TSESTreeNode.ts create mode 100644 packages/scope-manager/tests/util/serializers/Variable.ts create mode 100644 packages/scope-manager/tests/util/serializers/baseSerializer.ts create mode 100644 packages/scope-manager/tests/util/serializers/index.ts create mode 100644 packages/scope-manager/tsconfig.build.json create mode 100644 packages/scope-manager/tsconfig.json diff --git a/.cspell.json b/.cspell.json index 2d939d1b4a3c..daf674b70f33 100644 --- a/.cspell.json +++ b/.cspell.json @@ -12,7 +12,8 @@ "**/*.{json,snap}", ".cspell.json", "yarn.lock", - ".github/workflows/**" + ".github/workflows/**", + ".vscode/*.json" ], "dictionaries": [ "typescript", @@ -57,6 +58,7 @@ "ESLint", "ESLint's", "espree", + "esrecurse", "estree", "IDE's", "IIFE", @@ -75,11 +77,13 @@ "Premade", "prettier's", "recurse", + "redeclared", "reimplement", "resync", "ROADMAP", "ruleset", "rulesets", + "serializers", "superset", "thenables", "transpiles", diff --git a/.eslintrc.js b/.eslintrc.js index 2c69c6ecfedf..e43526bc87f3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -55,6 +55,11 @@ module.exports = { '@typescript-eslint/prefer-nullish-coalescing': 'error', '@typescript-eslint/prefer-optional-chain': 'error', '@typescript-eslint/unbound-method': 'off', + '@typescript-eslint/prefer-as-const': 'error', + '@typescript-eslint/no-unused-vars': [ + 'warn', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], // TODO - enable these new recommended rules '@typescript-eslint/no-floating-promises': 'off', diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b60c976543f4..cfc7a1ea39e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,6 @@ on: push: branches: - master - # TODO - delete this before merging v3 into master - - v3 pull_request: branches: - '**' @@ -103,6 +101,12 @@ jobs: env: CI: true + - name: Run unit tests for scope-manager + run: yarn test + working-directory: packages/scope-manager + env: + CI: true + - name: Run unit tests for experimental-utils run: yarn test working-directory: packages/experimental-utils @@ -269,6 +273,12 @@ jobs: env: CI: true + - name: Run unit tests for scope-manager + run: yarn test + working-directory: packages/scope-manager + env: + CI: true + - name: Run unit tests for experimental-utils run: yarn test working-directory: packages/experimental-utils diff --git a/.prettierignore b/.prettierignore index 5155a78aa504..048e552b38b0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ **/tests/fixtures/**/* +!packages/scope-manager/tests/fixtures/**/* **/tests/fixture-project/**/* **/dist **/coverage diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d91eb64d0d49..3c84af70cc56 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,10 +1,11 @@ { "recommendations": [ - "esbenp.prettier-vscode", + "davidanson.vscode-markdownlint", "dbaeumer.vscode-eslint", "editorconfig.editorconfig", + "esbenp.prettier-vscode", "streetsidesoftware.code-spell-checker", - "davidanson.vscode-markdownlint" + "tlent.jest-snapshot-language-support" ], "unwantedRecommendations": ["hookyqr.beautify", "dbaeumer.jshint"] } diff --git a/.vscode/launch.json b/.vscode/launch.json index ff1507f8c3a6..5ad1e2264578 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -32,6 +32,8 @@ "${workspaceFolder}/packages/types/dist/index.js", "${workspaceFolder}/packages/visitor-keys/src/index.ts", "${workspaceFolder}/packages/visitor-keys/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", ], }, { @@ -62,6 +64,8 @@ "${workspaceFolder}/packages/types/dist/index.js", "${workspaceFolder}/packages/visitor-keys/src/index.ts", "${workspaceFolder}/packages/visitor-keys/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", ], }, { @@ -92,6 +96,8 @@ "${workspaceFolder}/packages/types/dist/index.js", "${workspaceFolder}/packages/visitor-keys/src/index.ts", "${workspaceFolder}/packages/visitor-keys/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", ], }, { @@ -122,6 +128,8 @@ "${workspaceFolder}/packages/types/dist/index.js", "${workspaceFolder}/packages/visitor-keys/src/index.ts", "${workspaceFolder}/packages/visitor-keys/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", ], }, { @@ -152,7 +160,41 @@ "${workspaceFolder}/packages/types/dist/index.js", "${workspaceFolder}/packages/visitor-keys/src/index.ts", "${workspaceFolder}/packages/visitor-keys/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", ], - } + }, + { + "type": "node", + "request": "launch", + "name": "Run currently opened scope-manager test", + "cwd": "${workspaceFolder}/packages/scope-manager/", + "program": "${workspaceFolder}/node_modules/jest/bin/jest.js", + "args": [ + "--runInBand", + "--no-cache", + "--no-coverage", + "${fileBasename}" + ], + "sourceMaps": true, + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "skipFiles": [ + "${workspaceFolder}/packages/experimental-utils/src/index.ts", + "${workspaceFolder}/packages/experimental-utils/dist/index.js", + "${workspaceFolder}/packages/experimental-utils/src/ts-estree.ts", + "${workspaceFolder}/packages/experimental-utils/dist/ts-estree.js", + "${workspaceFolder}/packages/parser/src/index.ts", + "${workspaceFolder}/packages/parser/dist/index.js", + "${workspaceFolder}/packages/typescript-estree/src/index.ts", + "${workspaceFolder}/packages/typescript-estree/dist/index.js", + "${workspaceFolder}/packages/types/src/index.ts", + "${workspaceFolder}/packages/types/dist/index.js", + "${workspaceFolder}/packages/visitor-keys/src/index.ts", + "${workspaceFolder}/packages/visitor-keys/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + "${workspaceFolder}/packages/scope-manager/dist/index.js", + ], + }, ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index dc6744448f3d..20830a2fa0b8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,4 +18,21 @@ "javascript.preferences.quoteStyle": "single", "typescript.preferences.quoteStyle": "single", "editor.defaultFormatter": "esbenp.prettier-vscode", + + // make the .shot files from jest-specific-snapshot act like normal snapshots + "files.associations": { + "*.shot": "jest-snapshot" + }, + "vsicons.associations.files": [ + { + "icon": "jest_snapshot", + "extensions": [ + ".ts.shot", + ".tsx.shot", + ".js.shot", + ".jsx.shot", + ], + "extends": "jest_snapshot" + }, + ], } diff --git a/packages/eslint-plugin-internal/jest.config.js b/packages/eslint-plugin-internal/jest.config.js index 1123e5ab8ade..cce8d6c61baf 100644 --- a/packages/eslint-plugin-internal/jest.config.js +++ b/packages/eslint-plugin-internal/jest.config.js @@ -1,5 +1,7 @@ 'use strict'; +// @ts-check +/** @type {import('@jest/types').Config.InitialOptions} */ module.exports = { globals: { 'ts-jest': { diff --git a/packages/eslint-plugin-tslint/jest.config.js b/packages/eslint-plugin-tslint/jest.config.js index 2cc2459cf655..76cf71504591 100644 --- a/packages/eslint-plugin-tslint/jest.config.js +++ b/packages/eslint-plugin-tslint/jest.config.js @@ -1,5 +1,7 @@ 'use strict'; +// @ts-check +/** @type {import('@jest/types').Config.InitialOptions} */ module.exports = { globals: { 'ts-jest': { diff --git a/packages/eslint-plugin/jest.config.js b/packages/eslint-plugin/jest.config.js index 1123e5ab8ade..cce8d6c61baf 100644 --- a/packages/eslint-plugin/jest.config.js +++ b/packages/eslint-plugin/jest.config.js @@ -1,5 +1,7 @@ 'use strict'; +// @ts-check +/** @type {import('@jest/types').Config.InitialOptions} */ module.exports = { globals: { 'ts-jest': { diff --git a/packages/experimental-utils/jest.config.js b/packages/experimental-utils/jest.config.js index 1123e5ab8ade..cce8d6c61baf 100644 --- a/packages/experimental-utils/jest.config.js +++ b/packages/experimental-utils/jest.config.js @@ -1,5 +1,7 @@ 'use strict'; +// @ts-check +/** @type {import('@jest/types').Config.InitialOptions} */ module.exports = { globals: { 'ts-jest': { diff --git a/packages/scope-manager/LICENSE b/packages/scope-manager/LICENSE new file mode 100644 index 000000000000..7e7370143b26 --- /dev/null +++ b/packages/scope-manager/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 TypeScript ESLint and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/scope-manager/README.md b/packages/scope-manager/README.md new file mode 100644 index 000000000000..2e1e2d3c93f9 --- /dev/null +++ b/packages/scope-manager/README.md @@ -0,0 +1,16 @@ +# `@typescript-eslint/scope-manager` + +TypeScript scope analyser for ESLint. +This is a fork of [`eslint-scope`](https://github.com/eslint/eslint-scope), enhanced to support TypeScript functionality. +[You can view the original licence for the code here](https://github.com/eslint/eslint-scope/blob/dbddf14d5771b21b5da704213e4508c660ca1c64/LICENSE). + +## TODO + +## References + +- https://eslint.org/docs/developer-guide/scope-manager-interface +- https://github.com/eslint/eslint-scope + +## Contributing + +[See the contributing guide here](../../CONTRIBUTING.md) diff --git a/packages/scope-manager/jest.config.js b/packages/scope-manager/jest.config.js new file mode 100644 index 000000000000..3e3bcb726edc --- /dev/null +++ b/packages/scope-manager/jest.config.js @@ -0,0 +1,24 @@ +'use strict'; + +// @ts-check +/** @type {import('@jest/types').Config.InitialOptions} */ +module.exports = { + globals: { + 'ts-jest': { + isolatedModules: true, + }, + }, + testEnvironment: 'node', + transform: { + [/^.+\.tsx?$/.source]: 'ts-jest', + }, + testRegex: [ + /.\/tests\/.+\.test\.ts$/.source, + /.\/tests\/eslint-scope\/[^/]+\.test\.ts$/.source, + ], + collectCoverage: false, + collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + coverageReporters: ['text-summary', 'lcov'], + setupFilesAfterEnv: ['./tests/util/serializers/index.ts'], +}; diff --git a/packages/scope-manager/package.json b/packages/scope-manager/package.json new file mode 100644 index 000000000000..e33bb3ddf750 --- /dev/null +++ b/packages/scope-manager/package.json @@ -0,0 +1,63 @@ +{ + "name": "@typescript-eslint/scope-manager", + "version": "3.3.0", + "description": "TypeScript scope analyser for ESLint", + "keywords": [ + "eslint", + "typescript", + "estree" + ], + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "files": [ + "dist", + "package.json", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/typescript-eslint/typescript-eslint.git", + "directory": "packages/scope-manager" + }, + "bugs": { + "url": "https://github.com/typescript-eslint/typescript-eslint/issues" + }, + "license": "MIT", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc -b tsconfig.build.json", + "postbuild": "downlevel-dts dist _ts3.4/dist", + "clean": "tsc -b tsconfig.build.json --clean", + "format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore", + "lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'", + "test": "jest --coverage", + "typecheck": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@typescript-eslint/types": "3.3.0", + "@typescript-eslint/visitor-keys": "3.3.0" + }, + "devDependencies": { + "@types/jest-specific-snapshot": "^0.5.4", + "@types/mkdirp": "^1.0.0", + "@typescript-eslint/typescript-estree": "3.3.0", + "glob": "^7.1.6", + "jest-specific-snapshot": "^3.0.0", + "make-dir": "^3.1.0", + "pretty-format": "^25.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "typesVersions": { + "<3.8": { + "*": [ + "_ts3.4/*" + ] + } + } +} diff --git a/packages/scope-manager/src/ID.ts b/packages/scope-manager/src/ID.ts new file mode 100644 index 000000000000..1595c2a137d8 --- /dev/null +++ b/packages/scope-manager/src/ID.ts @@ -0,0 +1,20 @@ +const ID_CACHE = new Map(); +let NEXT_KEY = 0; + +function createIdGenerator(): () => number { + const key = (NEXT_KEY += 1); + ID_CACHE.set(key, 0); + + return (): number => { + const current = ID_CACHE.get(key) ?? 0; + const next = current + 1; + ID_CACHE.set(key, next); + return next; + }; +} + +function resetIds(): void { + ID_CACHE.clear(); +} + +export { createIdGenerator, resetIds }; diff --git a/packages/scope-manager/src/ScopeManager.ts b/packages/scope-manager/src/ScopeManager.ts new file mode 100644 index 000000000000..0466d6b4c249 --- /dev/null +++ b/packages/scope-manager/src/ScopeManager.ts @@ -0,0 +1,247 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { assert } from './assert'; +import { + BlockScope, + CatchScope, + ClassScope, + ConditionalTypeScope, + ForScope, + FunctionExpressionNameScope, + FunctionScope, + FunctionTypeScope, + GlobalScope, + MappedTypeScope, + ModuleScope, + Scope, + SwitchScope, + TSEnumScope, + TSModuleScope, + TypeScope, + WithScope, +} from './scope'; + +import { Variable } from './Variable'; + +interface ScopeManagerOptions { + globalReturn?: boolean; + sourceType?: 'module' | 'script'; + impliedStrict?: boolean; + ecmaVersion?: number; +} + +class ScopeManager { + public currentScope: Scope | null; + public readonly declaredVariables: WeakMap; + /** + * The root scope + * @public + */ + public globalScope: GlobalScope | null; + public readonly nodeToScope: WeakMap; + readonly #options: ScopeManagerOptions; + /** + * All scopes + * @public + */ + public readonly scopes: Scope[]; + + public get variables(): Variable[] { + const variables = new Set(); + function recurse(scope: Scope): void { + scope.variables.forEach(v => variables.add(v)); + scope.childScopes.forEach(recurse); + } + this.scopes.forEach(recurse); + return Array.from(variables).sort((a, b) => a.$id - b.$id); + } + + constructor(options: ScopeManagerOptions) { + this.scopes = []; + this.globalScope = null; + this.nodeToScope = new WeakMap(); + this.currentScope = null; + this.#options = options; + this.declaredVariables = new WeakMap(); + } + + public isGlobalReturn(): boolean { + return this.#options.globalReturn === true; + } + + public isModule(): boolean { + return this.#options.sourceType === 'module'; + } + + public isStrict(): boolean { + return ( + this.#options.impliedStrict === true && + this.#options.ecmaVersion != null && + this.#options.ecmaVersion >= 5 + ); + } + + public isES6(): boolean { + return this.#options.ecmaVersion != null && this.#options.ecmaVersion >= 6; + } + + /** + * Get the variables that a given AST node defines. The gotten variables' `def[].node`/`def[].parent` property is the node. + * If the node does not define any variable, this returns an empty array. + * @param node An AST node to get their variables. + * @public + */ + public getDeclaredVariables(node: TSESTree.Node): Variable[] { + return this.declaredVariables.get(node) ?? []; + } + + /** + * Get the scope of a given AST node. The gotten scope's `block` property is the node. + * This method never returns `function-expression-name` scope. If the node does not have their scope, this returns `null`. + * + * @param node An AST node to get their scope. + * @param inner If the node has multiple scopes, this returns the outermost scope normally. + * If `inner` is `true` then this returns the innermost scope. + * @public + */ + public acquire(node: TSESTree.Node, inner = false): Scope | null { + function predicate(testScope: Scope): boolean { + if (testScope.type === 'function' && testScope.functionExpressionScope) { + return false; + } + return true; + } + + const scopes = this.nodeToScope.get(node); + + if (!scopes || scopes.length === 0) { + return null; + } + + // Heuristic selection from all scopes. + // If you would like to get all scopes, please use ScopeManager#acquireAll. + if (scopes.length === 1) { + return scopes[0]; + } + + if (inner) { + for (let i = scopes.length - 1; i >= 0; --i) { + const scope = scopes[i]; + + if (predicate(scope)) { + return scope; + } + } + } else { + for (let i = 0; i < scopes.length; ++i) { + const scope = scopes[i]; + + if (predicate(scope)) { + return scope; + } + } + } + + return null; + } + + protected nestScope(scope: Scope): Scope { + if (scope instanceof GlobalScope) { + assert(this.currentScope === null); + this.globalScope = scope; + } + this.currentScope = scope; + return scope; + } + + public nestBlockScope(node: BlockScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new BlockScope(this, this.currentScope, node)); + } + + public nestCatchScope(node: CatchScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new CatchScope(this, this.currentScope, node)); + } + + public nestClassScope(node: ClassScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new ClassScope(this, this.currentScope, node)); + } + + public nestConditionalTypeScope(node: ConditionalTypeScope['block']): Scope { + assert(this.currentScope); + return this.nestScope( + new ConditionalTypeScope(this, this.currentScope, node), + ); + } + + public nestForScope(node: ForScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new ForScope(this, this.currentScope, node)); + } + + public nestFunctionExpressionNameScope( + node: FunctionExpressionNameScope['block'], + ): Scope { + assert(this.currentScope); + return this.nestScope( + new FunctionExpressionNameScope(this, this.currentScope, node), + ); + } + + public nestFunctionScope( + node: FunctionScope['block'], + isMethodDefinition: boolean, + ): Scope { + assert(this.currentScope); + return this.nestScope( + new FunctionScope(this, this.currentScope, node, isMethodDefinition), + ); + } + + public nestFunctionTypeScope(node: FunctionTypeScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new FunctionTypeScope(this, this.currentScope, node)); + } + + public nestGlobalScope(node: GlobalScope['block']): Scope { + return this.nestScope(new GlobalScope(this, node)); + } + + public nestMappedTypeScope(node: MappedTypeScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new MappedTypeScope(this, this.currentScope, node)); + } + + public nestModuleScope(node: ModuleScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new ModuleScope(this, this.currentScope, node)); + } + + public nestSwitchScope(node: SwitchScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new SwitchScope(this, this.currentScope, node)); + } + + public nestTSEnumScope(node: TSEnumScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new TSEnumScope(this, this.currentScope, node)); + } + + public nestTSModuleScope(node: TSModuleScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new TSModuleScope(this, this.currentScope, node)); + } + + public nestTypeScope(node: TypeScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new TypeScope(this, this.currentScope, node)); + } + + public nestWithScope(node: WithScope['block']): Scope { + assert(this.currentScope); + return this.nestScope(new WithScope(this, this.currentScope, node)); + } +} + +export { ScopeManager }; diff --git a/packages/scope-manager/src/Variable.ts b/packages/scope-manager/src/Variable.ts new file mode 100644 index 000000000000..b5e06688ea51 --- /dev/null +++ b/packages/scope-manager/src/Variable.ts @@ -0,0 +1,80 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Definition } from './definition'; +import { createIdGenerator } from './ID'; +import { Reference } from './referencer/Reference'; +import { Scope } from './scope'; + +const generator = createIdGenerator(); + +/** + * A Variable represents a locally scoped identifier. These include arguments to functions. + */ +class Variable { + /** + * A unique ID for this instance - primarily used to help debugging and testing + */ + public readonly $id: number = generator(); + + /** + * The array of the definitions of this variable. + * @public + */ + public readonly defs: Definition[] = []; + /** + * True if the variable is considered used for the purposes of `no-unused-vars`, false otherwise. + * @public + */ + public eslintUsed = false; + /** + * The array of `Identifier` nodes which define this variable. + * If this variable is redeclared, this array includes two or more nodes. + * @public + */ + public readonly identifiers: TSESTree.Identifier[] = []; + /** + * The variable name, as given in the source code. + * @public + */ + public readonly name: string; + /** + * List of {@link Reference} of this variable (excluding parameter entries) in its defining scope and all nested scopes. + * For defining occurrences only see {@link Variable#defs}. + * @public + */ + public readonly references: Reference[] = []; + /** + * Reference to the enclosing Scope. + */ + public readonly scope: Scope; + + constructor(name: string, scope: Scope) { + this.name = name; + this.scope = scope; + } + + /** + * `true` if the variable is valid in a type context, false otherwise + */ + public get isTypeVariable(): boolean { + if (this.defs.length === 0) { + // we don't statically know whether this is a type or a value + return true; + } + + return this.defs.some(def => def.isTypeDefinition); + } + + /** + * `true` if the variable is valid in a value context, false otherwise + */ + public get isValueVariable(): boolean { + if (this.defs.length === 0) { + // we don't statically know whether this is a type or a value + return true; + } + + return this.defs.some(def => def.isVariableDefinition); + } +} + +export { Variable }; diff --git a/packages/scope-manager/src/analyze.ts b/packages/scope-manager/src/analyze.ts new file mode 100644 index 000000000000..20f9310b0df0 --- /dev/null +++ b/packages/scope-manager/src/analyze.ts @@ -0,0 +1,58 @@ +import { TSESTree, EcmaVersion } from '@typescript-eslint/types'; +import { visitorKeys } from '@typescript-eslint/visitor-keys'; +import { Referencer, ReferencerOptions } from './referencer'; +import { ScopeManager } from './ScopeManager'; + +interface AnalyzeOptions { + /** + * Whether the whole script is executed under node.js environment. + * When enabled, the scope manager adds a function scope immediately following the global scope. + */ + globalReturn?: boolean; + + /** + * Implied strict mode (if ecmaVersion >= 5). + */ + impliedStrict?: boolean; + + /** + * The source type of the script. + */ + sourceType?: 'script' | 'module'; + + /** + * Which ECMAScript version is considered + */ + ecmaVersion?: EcmaVersion; + + /** + * Known visitor keys. + */ + childVisitorKeys?: ReferencerOptions['childVisitorKeys']; +} + +const DEFAULT_OPTIONS: AnalyzeOptions = { + globalReturn: false, + impliedStrict: false, + sourceType: 'script', + ecmaVersion: 2018, + childVisitorKeys: visitorKeys, +}; + +/** + * Takes an AST and returns the analyzed scopes. + */ +function analyze( + tree: TSESTree.Node, + providedOptions?: AnalyzeOptions, +): ScopeManager { + const options = Object.assign({}, DEFAULT_OPTIONS, providedOptions); + const scopeManager = new ScopeManager(options); + const referencer = new Referencer(options, scopeManager); + + referencer.visit(tree); + + return scopeManager; +} + +export { analyze, AnalyzeOptions }; diff --git a/packages/scope-manager/src/assert.ts b/packages/scope-manager/src/assert.ts new file mode 100644 index 000000000000..6dc93e24b639 --- /dev/null +++ b/packages/scope-manager/src/assert.ts @@ -0,0 +1,8 @@ +// the base assert module doesn't use ts assertion syntax +function assert(value: unknown, message?: string): asserts value { + if (value == null) { + throw new Error(message); + } +} + +export { assert }; diff --git a/packages/scope-manager/src/definition/CatchClauseDefinition.ts b/packages/scope-manager/src/definition/CatchClauseDefinition.ts new file mode 100644 index 000000000000..1bfb569e044a --- /dev/null +++ b/packages/scope-manager/src/definition/CatchClauseDefinition.ts @@ -0,0 +1,19 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class CatchClauseDefinition extends DefinitionBase< + DefinitionType.CatchClause, + TSESTree.CatchClause, + null, + TSESTree.BindingName +> { + constructor(name: TSESTree.BindingName, node: CatchClauseDefinition['node']) { + super(DefinitionType.CatchClause, name, node, null); + } + + public readonly isTypeDefinition = false; + public readonly isVariableDefinition = true; +} + +export { CatchClauseDefinition }; diff --git a/packages/scope-manager/src/definition/ClassNameDefinition.ts b/packages/scope-manager/src/definition/ClassNameDefinition.ts new file mode 100644 index 000000000000..5d587b342ad0 --- /dev/null +++ b/packages/scope-manager/src/definition/ClassNameDefinition.ts @@ -0,0 +1,19 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class ClassNameDefinition extends DefinitionBase< + DefinitionType.ClassName, + TSESTree.ClassDeclaration | TSESTree.ClassExpression, + null, + TSESTree.Identifier +> { + constructor(name: TSESTree.Identifier, node: ClassNameDefinition['node']) { + super(DefinitionType.ClassName, name, node, null); + } + + public readonly isTypeDefinition = true; + public readonly isVariableDefinition = true; +} + +export { ClassNameDefinition }; diff --git a/packages/scope-manager/src/definition/Definition.ts b/packages/scope-manager/src/definition/Definition.ts new file mode 100644 index 000000000000..19814bf892d1 --- /dev/null +++ b/packages/scope-manager/src/definition/Definition.ts @@ -0,0 +1,26 @@ +import { CatchClauseDefinition } from './CatchClauseDefinition'; +import { ClassNameDefinition } from './ClassNameDefinition'; +import { FunctionNameDefinition } from './FunctionNameDefinition'; +import { ImplicitGlobalVariableDefinition } from './ImplicitGlobalVariableDefinition'; +import { ImportBindingDefinition } from './ImportBindingDefinition'; +import { ParameterDefinition } from './ParameterDefinition'; +import { TSEnumMemberDefinition } from './TSEnumMemberDefinition'; +import { TSEnumNameDefinition } from './TSEnumNameDefinition'; +import { TSModuleNameDefinition } from './TSModuleNameDefinition'; +import { TypeDefinition } from './TypeDefinition'; +import { VariableDefinition } from './VariableDefinition'; + +type Definition = + | CatchClauseDefinition + | ClassNameDefinition + | FunctionNameDefinition + | ImplicitGlobalVariableDefinition + | ImportBindingDefinition + | ParameterDefinition + | TSEnumMemberDefinition + | TSEnumNameDefinition + | TSModuleNameDefinition + | TypeDefinition + | VariableDefinition; + +export { Definition }; diff --git a/packages/scope-manager/src/definition/DefinitionBase.ts b/packages/scope-manager/src/definition/DefinitionBase.ts new file mode 100644 index 000000000000..ed25a72293d1 --- /dev/null +++ b/packages/scope-manager/src/definition/DefinitionBase.ts @@ -0,0 +1,60 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { createIdGenerator } from '../ID'; + +const generator = createIdGenerator(); + +abstract class DefinitionBase< + TType extends DefinitionType, + TNode extends TSESTree.Node, + TParent extends TSESTree.Node | null, + TName extends TSESTree.Node = TSESTree.BindingName +> { + /** + * A unique ID for this instance - primarily used to help debugging and testing + */ + public readonly $id: number = generator(); + + /** + * The type of the definition + * @public + */ + public readonly type: TType; + + /** + * The `Identifier` node of this definition + * @public + */ + public readonly name: TName; + + /** + * The enclosing node of the name. + * @public + */ + public readonly node: TNode; + + /** + * the enclosing statement node of the identifier. + * @public + */ + public readonly parent: TParent; + + constructor(type: TType, name: TName, node: TNode, parent: TParent) { + this.type = type; + this.name = name; + this.node = node; + this.parent = parent; + } + + /** + * `true` if the variable is valid in a type context, false otherwise + */ + public abstract readonly isTypeDefinition: boolean; + + /** + * `true` if the variable is valid in a value context, false otherwise + */ + public abstract readonly isVariableDefinition: boolean; +} + +export { DefinitionBase }; diff --git a/packages/scope-manager/src/definition/DefinitionType.ts b/packages/scope-manager/src/definition/DefinitionType.ts new file mode 100644 index 000000000000..7f689d45ed54 --- /dev/null +++ b/packages/scope-manager/src/definition/DefinitionType.ts @@ -0,0 +1,16 @@ +enum DefinitionType { + // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum + CatchClause = 'CatchClause', + ClassName = 'ClassName', + FunctionName = 'FunctionName', + ImplicitGlobalVariable = 'ImplicitGlobalVariable', + ImportBinding = 'ImportBinding', + Parameter = 'Parameter', + TSEnumName = 'TSEnumName', + TSEnumMember = 'TSEnumMemberName', + TSModuleName = 'TSModuleName', + Type = 'Type', + Variable = 'Variable', +} + +export { DefinitionType }; diff --git a/packages/scope-manager/src/definition/FunctionNameDefinition.ts b/packages/scope-manager/src/definition/FunctionNameDefinition.ts new file mode 100644 index 000000000000..b4cf2405552d --- /dev/null +++ b/packages/scope-manager/src/definition/FunctionNameDefinition.ts @@ -0,0 +1,22 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class FunctionNameDefinition extends DefinitionBase< + DefinitionType.FunctionName, + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression + | TSESTree.TSDeclareFunction + | TSESTree.TSEmptyBodyFunctionExpression, + null, + TSESTree.Identifier +> { + constructor(name: TSESTree.Identifier, node: FunctionNameDefinition['node']) { + super(DefinitionType.FunctionName, name, node, null); + } + + public readonly isTypeDefinition = false; + public readonly isVariableDefinition = true; +} + +export { FunctionNameDefinition }; diff --git a/packages/scope-manager/src/definition/ImplicitGlobalVariableDefinition.ts b/packages/scope-manager/src/definition/ImplicitGlobalVariableDefinition.ts new file mode 100644 index 000000000000..43012c0fce94 --- /dev/null +++ b/packages/scope-manager/src/definition/ImplicitGlobalVariableDefinition.ts @@ -0,0 +1,22 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class ImplicitGlobalVariableDefinition extends DefinitionBase< + DefinitionType.ImplicitGlobalVariable, + TSESTree.Node, + null, + TSESTree.BindingName +> { + constructor( + name: TSESTree.BindingName, + node: ImplicitGlobalVariableDefinition['node'], + ) { + super(DefinitionType.ImplicitGlobalVariable, name, node, null); + } + + public readonly isTypeDefinition = false; + public readonly isVariableDefinition = true; +} + +export { ImplicitGlobalVariableDefinition }; diff --git a/packages/scope-manager/src/definition/ImportBindingDefinition.ts b/packages/scope-manager/src/definition/ImportBindingDefinition.ts new file mode 100644 index 000000000000..e3e1d8401401 --- /dev/null +++ b/packages/scope-manager/src/definition/ImportBindingDefinition.ts @@ -0,0 +1,44 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class ImportBindingDefinition extends DefinitionBase< + DefinitionType.ImportBinding, + | TSESTree.ImportSpecifier + | TSESTree.ImportDefaultSpecifier + | TSESTree.ImportNamespaceSpecifier + | TSESTree.TSImportEqualsDeclaration, + TSESTree.ImportDeclaration | TSESTree.TSImportEqualsDeclaration, + TSESTree.Identifier +> { + constructor( + name: TSESTree.Identifier, + node: TSESTree.TSImportEqualsDeclaration, + decl: TSESTree.TSImportEqualsDeclaration, + ); + constructor( + name: TSESTree.Identifier, + node: Exclude< + ImportBindingDefinition['node'], + TSESTree.TSImportEqualsDeclaration + >, + decl: TSESTree.ImportDeclaration, + ); + constructor( + name: TSESTree.Identifier, + node: ImportBindingDefinition['node'], + decl: TSESTree.ImportDeclaration | TSESTree.TSImportEqualsDeclaration, + ) { + super(DefinitionType.ImportBinding, name, node, decl); + if ('importKind' in this.parent && this.parent.importKind === 'type') { + this.isVariableDefinition = false; + } else { + this.isVariableDefinition = true; + } + } + + public readonly isTypeDefinition = true; + public readonly isVariableDefinition: boolean; +} + +export { ImportBindingDefinition }; diff --git a/packages/scope-manager/src/definition/ParameterDefinition.ts b/packages/scope-manager/src/definition/ParameterDefinition.ts new file mode 100644 index 000000000000..b0c0ea3280dd --- /dev/null +++ b/packages/scope-manager/src/definition/ParameterDefinition.ts @@ -0,0 +1,37 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class ParameterDefinition extends DefinitionBase< + DefinitionType.Parameter, + | TSESTree.ArrowFunctionExpression + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression + | TSESTree.TSCallSignatureDeclaration + | TSESTree.TSConstructorType + | TSESTree.TSConstructSignatureDeclaration + | TSESTree.TSDeclareFunction + | TSESTree.TSEmptyBodyFunctionExpression + | TSESTree.TSFunctionType + | TSESTree.TSMethodSignature, + null, + TSESTree.BindingName +> { + /** + * Whether the parameter definition is a part of a rest parameter. + */ + public readonly rest: boolean; + constructor( + name: TSESTree.BindingName, + node: ParameterDefinition['node'], + rest: boolean, + ) { + super(DefinitionType.Parameter, name, node, null); + this.rest = rest; + } + + public readonly isTypeDefinition = false; + public readonly isVariableDefinition = true; +} + +export { ParameterDefinition }; diff --git a/packages/scope-manager/src/definition/TSEnumMemberDefinition.ts b/packages/scope-manager/src/definition/TSEnumMemberDefinition.ts new file mode 100644 index 000000000000..cff6bbaa6d1d --- /dev/null +++ b/packages/scope-manager/src/definition/TSEnumMemberDefinition.ts @@ -0,0 +1,22 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class TSEnumMemberDefinition extends DefinitionBase< + DefinitionType.TSEnumMember, + TSESTree.TSEnumMember, + null, + TSESTree.Identifier | TSESTree.StringLiteral +> { + constructor( + name: TSESTree.Identifier | TSESTree.StringLiteral, + node: TSEnumMemberDefinition['node'], + ) { + super(DefinitionType.TSEnumMember, name, node, null); + } + + public readonly isTypeDefinition = true; + public readonly isVariableDefinition = true; +} + +export { TSEnumMemberDefinition }; diff --git a/packages/scope-manager/src/definition/TSEnumNameDefinition.ts b/packages/scope-manager/src/definition/TSEnumNameDefinition.ts new file mode 100644 index 000000000000..5374a56260ab --- /dev/null +++ b/packages/scope-manager/src/definition/TSEnumNameDefinition.ts @@ -0,0 +1,19 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class TSEnumNameDefinition extends DefinitionBase< + DefinitionType.TSEnumName, + TSESTree.TSEnumDeclaration, + null, + TSESTree.Identifier +> { + constructor(name: TSESTree.Identifier, node: TSEnumNameDefinition['node']) { + super(DefinitionType.TSEnumName, name, node, null); + } + + public readonly isTypeDefinition = true; + public readonly isVariableDefinition = true; +} + +export { TSEnumNameDefinition }; diff --git a/packages/scope-manager/src/definition/TSModuleNameDefinition.ts b/packages/scope-manager/src/definition/TSModuleNameDefinition.ts new file mode 100644 index 000000000000..98f907789b73 --- /dev/null +++ b/packages/scope-manager/src/definition/TSModuleNameDefinition.ts @@ -0,0 +1,19 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class TSModuleNameDefinition extends DefinitionBase< + DefinitionType.TSModuleName, + TSESTree.TSModuleDeclaration, + null, + TSESTree.Identifier +> { + constructor(name: TSESTree.Identifier, node: TSModuleNameDefinition['node']) { + super(DefinitionType.TSModuleName, name, node, null); + } + + public readonly isTypeDefinition = true; + public readonly isVariableDefinition = true; +} + +export { TSModuleNameDefinition }; diff --git a/packages/scope-manager/src/definition/TypeDefinition.ts b/packages/scope-manager/src/definition/TypeDefinition.ts new file mode 100644 index 000000000000..ad3b43687913 --- /dev/null +++ b/packages/scope-manager/src/definition/TypeDefinition.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class TypeDefinition extends DefinitionBase< + DefinitionType.Type, + | TSESTree.TSInterfaceDeclaration + | TSESTree.TSTypeAliasDeclaration + | TSESTree.TSTypeParameter, + null, + TSESTree.Identifier +> { + constructor(name: TSESTree.Identifier, node: TypeDefinition['node']) { + super(DefinitionType.Type, name, node, null); + } + + public readonly isTypeDefinition = true; + public readonly isVariableDefinition = false; +} + +export { TypeDefinition }; diff --git a/packages/scope-manager/src/definition/VariableDefinition.ts b/packages/scope-manager/src/definition/VariableDefinition.ts new file mode 100644 index 000000000000..975c58861856 --- /dev/null +++ b/packages/scope-manager/src/definition/VariableDefinition.ts @@ -0,0 +1,23 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { DefinitionType } from './DefinitionType'; +import { DefinitionBase } from './DefinitionBase'; + +class VariableDefinition extends DefinitionBase< + DefinitionType.Variable, + TSESTree.VariableDeclarator, + TSESTree.VariableDeclaration, + TSESTree.Identifier +> { + constructor( + name: TSESTree.Identifier, + node: VariableDefinition['node'], + decl: TSESTree.VariableDeclaration, + ) { + super(DefinitionType.Variable, name, node, decl); + } + + public readonly isTypeDefinition = false; + public readonly isVariableDefinition = true; +} + +export { VariableDefinition }; diff --git a/packages/scope-manager/src/definition/index.ts b/packages/scope-manager/src/definition/index.ts new file mode 100644 index 000000000000..9bd1f0123370 --- /dev/null +++ b/packages/scope-manager/src/definition/index.ts @@ -0,0 +1,13 @@ +export * from './CatchClauseDefinition'; +export * from './ClassNameDefinition'; +export * from './Definition'; +export * from './DefinitionType'; +export * from './FunctionNameDefinition'; +export * from './ImplicitGlobalVariableDefinition'; +export * from './ImportBindingDefinition'; +export * from './ParameterDefinition'; +export * from './TSEnumMemberDefinition'; +export * from './TSEnumNameDefinition'; +export * from './TSModuleNameDefinition'; +export * from './TypeDefinition'; +export * from './VariableDefinition'; diff --git a/packages/scope-manager/src/index.ts b/packages/scope-manager/src/index.ts new file mode 100644 index 000000000000..c561eeb6617a --- /dev/null +++ b/packages/scope-manager/src/index.ts @@ -0,0 +1,12 @@ +export { analyze, AnalyzeOptions } from './analyze'; +export * from './definition'; +export { Reference } from './referencer/Reference'; +export { Visitor } from './referencer/Visitor'; +export { + PatternVisitor, + PatternVisitorCallback, + PatternVisitorOptions, +} from './referencer/PatternVisitor'; +export * from './scope'; +export { ScopeManager } from './ScopeManager'; +export { Variable } from './Variable'; diff --git a/packages/scope-manager/src/referencer/ExportVisitor.ts b/packages/scope-manager/src/referencer/ExportVisitor.ts new file mode 100644 index 000000000000..bae523ae6b21 --- /dev/null +++ b/packages/scope-manager/src/referencer/ExportVisitor.ts @@ -0,0 +1,72 @@ +import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/types'; +import { Referencer } from './Referencer'; +import { Visitor } from './Visitor'; + +type ExportNode = + | TSESTree.ExportAllDeclaration + | TSESTree.ExportDefaultDeclaration + | TSESTree.ExportNamedDeclaration; + +class ExportVisitor extends Visitor { + readonly #referencer: Referencer; + readonly #exportNode: ExportNode; + + constructor(node: ExportNode, referencer: Referencer) { + super(referencer); + this.#exportNode = node; + this.#referencer = referencer; + } + + static visit(referencer: Referencer, node: ExportNode): void { + const exportReferencer = new ExportVisitor(node, referencer); + exportReferencer.visit(node); + } + + protected Identifier(node: TSESTree.Identifier): void { + if (this.#exportNode.exportKind === 'type') { + // type exports can only reference types + this.#referencer.currentScope().referenceType(node); + } else { + this.#referencer.currentScope().referenceDualValueType(node); + } + } + + protected ExportDefaultDeclaration( + node: TSESTree.ExportDefaultDeclaration, + ): void { + if (node.declaration.type === AST_NODE_TYPES.Identifier) { + // export default A; + // this could be a type or a variable + this.visit(node.declaration); + } else { + // export const a = 1; + // export something(); + // etc + // these not included in the scope of this visitor as they are all guaranteed to be values or declare variables + } + } + + protected ExportNamedDeclaration( + node: TSESTree.ExportNamedDeclaration, + ): void { + if (node.source) { + // export ... from 'foo'; + // these are external identifiers so there shouldn't be references or defs + return; + } + + if (!node.declaration) { + // export { x }; + this.visitChildren(node); + } else { + // export const x = 1; + // this is not included in the scope of this visitor as it creates a variable + } + } + + protected ExportSpecifier(node: TSESTree.ExportSpecifier): void { + this.visit(node.local); + } +} + +export { ExportVisitor }; diff --git a/packages/scope-manager/src/referencer/ImportVisitor.ts b/packages/scope-manager/src/referencer/ImportVisitor.ts new file mode 100644 index 000000000000..19a9b1d7d5e9 --- /dev/null +++ b/packages/scope-manager/src/referencer/ImportVisitor.ts @@ -0,0 +1,59 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { ImportBindingDefinition } from '../definition'; +import { Referencer } from './Referencer'; +import { Visitor } from './Visitor'; + +class ImportVisitor extends Visitor { + readonly #declaration: TSESTree.ImportDeclaration; + readonly #referencer: Referencer; + + constructor(declaration: TSESTree.ImportDeclaration, referencer: Referencer) { + super(referencer); + this.#declaration = declaration; + this.#referencer = referencer; + } + + static visit( + referencer: Referencer, + declaration: TSESTree.ImportDeclaration, + ): void { + const importReferencer = new ImportVisitor(declaration, referencer); + importReferencer.visit(declaration); + } + + protected visitImport( + id: TSESTree.Identifier, + specifier: + | TSESTree.ImportDefaultSpecifier + | TSESTree.ImportNamespaceSpecifier + | TSESTree.ImportSpecifier, + ): void { + this.#referencer + .currentScope() + .defineIdentifier( + id, + new ImportBindingDefinition(id, specifier, this.#declaration), + ); + } + + protected ImportNamespaceSpecifier( + node: TSESTree.ImportNamespaceSpecifier, + ): void { + const local = node.local; + this.visitImport(local, node); + } + + protected ImportDefaultSpecifier( + node: TSESTree.ImportDefaultSpecifier, + ): void { + const local = node.local; + this.visitImport(local, node); + } + + protected ImportSpecifier(node: TSESTree.ImportSpecifier): void { + const local = node.local; + this.visitImport(local, node); + } +} + +export { ImportVisitor }; diff --git a/packages/scope-manager/src/referencer/PatternVisitor.ts b/packages/scope-manager/src/referencer/PatternVisitor.ts new file mode 100644 index 000000000000..eaca842cbd59 --- /dev/null +++ b/packages/scope-manager/src/referencer/PatternVisitor.ts @@ -0,0 +1,142 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { VisitorBase, VisitorOptions } from './Visitor'; + +type PatternVisitorCallback = ( + pattern: TSESTree.Identifier, + info: { + assignments: (TSESTree.AssignmentPattern | TSESTree.AssignmentExpression)[]; + rest: boolean; + topLevel: boolean; + }, +) => void; + +type PatternVisitorOptions = VisitorOptions; +class PatternVisitor extends VisitorBase { + public static isPattern( + node: TSESTree.Node, + ): node is + | TSESTree.Identifier + | TSESTree.ObjectPattern + | TSESTree.ArrayPattern + | TSESTree.SpreadElement + | TSESTree.RestElement + | TSESTree.AssignmentPattern { + const nodeType = node.type; + + return ( + nodeType === AST_NODE_TYPES.Identifier || + nodeType === AST_NODE_TYPES.ObjectPattern || + nodeType === AST_NODE_TYPES.ArrayPattern || + nodeType === AST_NODE_TYPES.SpreadElement || + nodeType === AST_NODE_TYPES.RestElement || + nodeType === AST_NODE_TYPES.AssignmentPattern + ); + } + + readonly #rootPattern: TSESTree.Node; + readonly #callback: PatternVisitorCallback; + readonly #assignments: ( + | TSESTree.AssignmentPattern + | TSESTree.AssignmentExpression + )[] = []; + public readonly rightHandNodes: TSESTree.Node[] = []; + readonly #restElements: TSESTree.RestElement[] = []; + + constructor( + options: PatternVisitorOptions, + rootPattern: TSESTree.Node, + callback: PatternVisitorCallback, + ) { + super(options); + this.#rootPattern = rootPattern; + this.#callback = callback; + } + + protected ArrayExpression(node: TSESTree.ArrayExpression): void { + node.elements.forEach(this.visit, this); + } + + protected ArrayPattern(pattern: TSESTree.ArrayPattern): void { + for (const element of pattern.elements) { + this.visit(element); + } + } + + protected AssignmentExpression(node: TSESTree.AssignmentExpression): void { + this.#assignments.push(node); + this.visit(node.left); + this.rightHandNodes.push(node.right); + this.#assignments.pop(); + } + + protected AssignmentPattern(pattern: TSESTree.AssignmentPattern): void { + this.#assignments.push(pattern); + this.visit(pattern.left); + this.rightHandNodes.push(pattern.right); + this.#assignments.pop(); + } + + protected CallExpression(node: TSESTree.CallExpression): void { + // arguments are right hand nodes. + node.arguments.forEach(a => { + this.rightHandNodes.push(a); + }); + this.visit(node.callee); + } + + protected Decorator(): void { + // don't visit any decorators when exploring a pattern + } + + protected Identifier(pattern: TSESTree.Identifier): void { + const lastRestElement = + this.#restElements[this.#restElements.length - 1] ?? null; + + this.#callback(pattern, { + topLevel: pattern === this.#rootPattern, + rest: + lastRestElement !== null && + lastRestElement !== undefined && + lastRestElement.argument === pattern, + assignments: this.#assignments, + }); + } + + protected MemberExpression(node: TSESTree.MemberExpression): void { + // Computed property's key is a right hand node. + if (node.computed) { + this.rightHandNodes.push(node.property); + } + + // the object is only read, write to its property. + this.rightHandNodes.push(node.object); + } + + protected Property(property: TSESTree.Property): void { + // Computed property's key is a right hand node. + if (property.computed) { + this.rightHandNodes.push(property.key); + } + + // If it's shorthand, its key is same as its value. + // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern). + // If it's not shorthand, the name of new variable is its value's. + this.visit(property.value); + } + + protected RestElement(pattern: TSESTree.RestElement): void { + this.#restElements.push(pattern); + this.visit(pattern.argument); + this.#restElements.pop(); + } + + protected SpreadElement(node: TSESTree.SpreadElement): void { + this.visit(node.argument); + } + + protected TSTypeAnnotation(): void { + // we don't want to visit types + } +} + +export { PatternVisitor, PatternVisitorCallback, PatternVisitorOptions }; diff --git a/packages/scope-manager/src/referencer/Reference.ts b/packages/scope-manager/src/referencer/Reference.ts new file mode 100644 index 000000000000..0e8998533db1 --- /dev/null +++ b/packages/scope-manager/src/referencer/Reference.ts @@ -0,0 +1,148 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { createIdGenerator } from '../ID'; +import { Scope } from '../scope'; +import { Variable } from '../Variable'; + +enum ReferenceFlag { + Read = 0x1, + Write = 0x2, + ReadWrite = 0x3, +} + +interface ReferenceImplicitGlobal { + node: TSESTree.Node; + pattern: TSESTree.BindingName; + ref?: Reference; +} + +const generator = createIdGenerator(); + +enum ReferenceTypeFlag { + Value = 0x1, + Type = 0x2, +} + +/** + * A Reference represents a single occurrence of an identifier in code. + */ +class Reference { + /** + * A unique ID for this instance - primarily used to help debugging and testing + */ + public readonly $id: number = generator(); + /** + * The read-write mode of the reference. + */ + readonly #flag: ReferenceFlag; + /** + * Reference to the enclosing Scope. + * @public + */ + public readonly from: Scope; + /** + * Identifier syntax node. + * @public + */ + public readonly identifier: TSESTree.Identifier; + /** + * `true` if this writing reference is a variable initializer or a default value. + * @public + */ + public readonly init?: boolean; + /** + * The {@link Variable} object that this reference refers to. If such variable was not defined, this is `null`. + * @public + */ + public resolved: Variable | null; + /** + * If reference is writeable, this is the node being written to it. + * @public + */ + public readonly writeExpr?: TSESTree.Node | null; + + public readonly maybeImplicitGlobal?: ReferenceImplicitGlobal | null; + + /** + * In some cases, a reference may be a type, value or both a type and value reference. + */ + readonly #referenceType: ReferenceTypeFlag; + + /** + * True if this reference can reference types + */ + public get isTypeReference(): boolean { + return (this.#referenceType & ReferenceTypeFlag.Type) !== 0; + } + + /** + * True if this reference can reference values + */ + public get isValueReference(): boolean { + return (this.#referenceType & ReferenceTypeFlag.Value) !== 0; + } + + constructor( + identifier: TSESTree.Identifier, + scope: Scope, + flag: ReferenceFlag, + writeExpr?: TSESTree.Node | null, + maybeImplicitGlobal?: ReferenceImplicitGlobal | null, + init?: boolean, + referenceType = ReferenceTypeFlag.Value, + ) { + this.identifier = identifier; + this.from = scope; + this.resolved = null; + this.#flag = flag; + + if (this.isWrite()) { + this.writeExpr = writeExpr; + this.init = init; + } + + this.maybeImplicitGlobal = maybeImplicitGlobal; + this.#referenceType = referenceType; + } + + /** + * Whether the reference is writeable. + * @public + */ + public isWrite(): boolean { + return !!(this.#flag & ReferenceFlag.Write); + } + + /** + * Whether the reference is readable. + * @public + */ + public isRead(): boolean { + return !!(this.#flag & ReferenceFlag.Read); + } + + /** + * Whether the reference is read-only. + * @public + */ + public isReadOnly(): boolean { + return this.#flag === ReferenceFlag.Read; + } + + /** + * Whether the reference is write-only. + * @public + */ + public isWriteOnly(): boolean { + return this.#flag === ReferenceFlag.Write; + } + + /** + * Whether the reference is read-write. + * @public + */ + public isReadWrite(): boolean { + return this.#flag === ReferenceFlag.ReadWrite; + } +} + +export { Reference, ReferenceFlag, ReferenceTypeFlag, ReferenceImplicitGlobal }; diff --git a/packages/scope-manager/src/referencer/Referencer.ts b/packages/scope-manager/src/referencer/Referencer.ts new file mode 100644 index 000000000000..89e1a9f0efb1 --- /dev/null +++ b/packages/scope-manager/src/referencer/Referencer.ts @@ -0,0 +1,745 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { ExportVisitor } from './ExportVisitor'; +import { ImportVisitor } from './ImportVisitor'; +import { PatternVisitor } from './PatternVisitor'; +import { ReferenceFlag, ReferenceImplicitGlobal } from './Reference'; +import { TypeVisitor } from './TypeVisitor'; +import { Visitor, VisitorOptions } from './Visitor'; +import { assert } from '../assert'; +import { + CatchClauseDefinition, + ClassNameDefinition, + FunctionNameDefinition, + ImportBindingDefinition, + ParameterDefinition, + TSEnumMemberDefinition, + TSEnumNameDefinition, + TSModuleNameDefinition, + VariableDefinition, +} from '../definition'; +import { Scope } from '../scope'; +import { ScopeManager } from '../ScopeManager'; + +type ReferencerOptions = VisitorOptions; +// Referencing variables and creating bindings. +class Referencer extends Visitor { + #isInnerMethodDefinition: boolean; + public readonly scopeManager: ScopeManager; + + constructor(options: ReferencerOptions, scopeManager: ScopeManager) { + super(options); + this.scopeManager = scopeManager; + this.#isInnerMethodDefinition = false; + } + + public currentScope(): Scope; + public currentScope(throwOnNull: true): Scope | null; + public currentScope(dontThrowOnNull?: true): Scope | null { + if (!dontThrowOnNull) { + assert(this.scopeManager.currentScope, 'aaa'); + } + return this.scopeManager.currentScope; + } + + public close(node: TSESTree.Node): void { + while (this.currentScope(true) && node === this.currentScope().block) { + this.scopeManager.currentScope = this.currentScope().close( + this.scopeManager, + ); + } + } + + protected pushInnerMethodDefinition( + isInnerMethodDefinition: boolean, + ): boolean { + const previous = this.#isInnerMethodDefinition; + + this.#isInnerMethodDefinition = isInnerMethodDefinition; + return previous; + } + + protected popInnerMethodDefinition( + isInnerMethodDefinition: boolean | undefined, + ): void { + this.#isInnerMethodDefinition = !!isInnerMethodDefinition; + } + + protected referencingDefaultValue( + pattern: TSESTree.Identifier, + assignments: (TSESTree.AssignmentExpression | TSESTree.AssignmentPattern)[], + maybeImplicitGlobal: ReferenceImplicitGlobal | null, + init: boolean, + ): void { + assignments.forEach(assignment => { + this.currentScope().referenceValue( + pattern, + ReferenceFlag.Write, + assignment.right, + maybeImplicitGlobal, + init, + ); + }); + } + + /////////////////// + // Visit helpers // + /////////////////// + + protected visitClass( + node: TSESTree.ClassDeclaration | TSESTree.ClassExpression, + ): void { + if (node.type === AST_NODE_TYPES.ClassDeclaration && node.id) { + this.currentScope().defineIdentifier( + node.id, + new ClassNameDefinition(node.id, node), + ); + } + + this.visit(node.superClass); + node.decorators?.forEach(d => this.visit(d)); + + this.scopeManager.nestClassScope(node); + + if (node.id) { + // define the class name again inside the new scope + // references to the class should not resolve directly to the parent class + this.currentScope().defineIdentifier( + node.id, + new ClassNameDefinition(node.id, node), + ); + } + + // visit the type param declarations + this.visitType(node.typeParameters); + // then the usages + this.visitType(node.superTypeParameters); + node.implements?.forEach(imp => this.visitType(imp)); + + this.visit(node.body); + + this.close(node); + } + + protected visitForIn( + node: TSESTree.ForInStatement | TSESTree.ForOfStatement, + ): void { + if ( + node.left.type === AST_NODE_TYPES.VariableDeclaration && + node.left.kind !== 'var' + ) { + this.scopeManager.nestForScope(node); + } + + if (node.left.type === AST_NODE_TYPES.VariableDeclaration) { + this.visit(node.left); + this.visitPattern(node.left.declarations[0].id, pattern => { + this.currentScope().referenceValue( + pattern, + ReferenceFlag.Write, + node.right, + null, + true, + ); + }); + } else { + this.visitPattern( + node.left, + (pattern, info) => { + const maybeImplicitGlobal = !this.currentScope().isStrict + ? { + pattern, + node, + } + : null; + this.referencingDefaultValue( + pattern, + info.assignments, + maybeImplicitGlobal, + false, + ); + this.currentScope().referenceValue( + pattern, + ReferenceFlag.Write, + node.right, + maybeImplicitGlobal, + false, + ); + }, + { processRightHandNodes: true }, + ); + } + this.visit(node.right); + this.visit(node.body); + + this.close(node); + } + + protected visitFunctionParameterTypeAnnotation( + node: TSESTree.Parameter, + ): void { + if ('typeAnnotation' in node) { + this.visitType(node.typeAnnotation); + } else if (node.type === AST_NODE_TYPES.AssignmentPattern) { + this.visitType(node.left.typeAnnotation); + } else if (node.type === AST_NODE_TYPES.TSParameterProperty) { + this.visitFunctionParameterTypeAnnotation(node.parameter); + } + } + protected visitFunction( + node: + | TSESTree.ArrowFunctionExpression + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression + | TSESTree.TSDeclareFunction + | TSESTree.TSEmptyBodyFunctionExpression, + ): void { + // FunctionDeclaration name is defined in upper scope + // NOTE: Not referring variableScope. It is intended. + // Since + // in ES5, FunctionDeclaration should be in FunctionBody. + // in ES6, FunctionDeclaration should be block scoped. + + if (node.type === AST_NODE_TYPES.FunctionExpression) { + if (node.id) { + // FunctionExpression with name creates its special scope; + // FunctionExpressionNameScope. + this.scopeManager.nestFunctionExpressionNameScope(node); + } + } else if (node.id) { + // id is defined in upper scope + this.currentScope().defineIdentifier( + node.id, + new FunctionNameDefinition(node.id, node), + ); + } + + // Consider this function is in the MethodDefinition. + this.scopeManager.nestFunctionScope(node, this.#isInnerMethodDefinition); + + // Process parameter declarations. + for (const param of node.params) { + this.visitPattern( + param, + (pattern, info) => { + this.currentScope().defineIdentifier( + pattern, + new ParameterDefinition(pattern, node, info.rest), + ); + + this.referencingDefaultValue(pattern, info.assignments, null, true); + }, + { processRightHandNodes: true }, + ); + this.visitFunctionParameterTypeAnnotation(param); + param.decorators?.forEach(d => this.visit(d)); + } + + this.visitType(node.returnType); + this.visitType(node.typeParameters); + + // In TypeScript there are a number of function-like constructs which have no body, + // so check it exists before traversing + if (node.body) { + // Skip BlockStatement to prevent creating BlockStatement scope. + if (node.body.type === AST_NODE_TYPES.BlockStatement) { + this.visitChildren(node.body); + } else { + this.visit(node.body); + } + } + + this.close(node); + } + + protected visitProperty( + node: + | TSESTree.ClassProperty + | TSESTree.MethodDefinition + | TSESTree.Property + | TSESTree.TSAbstractClassProperty + | TSESTree.TSAbstractMethodDefinition, + ): void { + let previous; + + if (node.computed) { + this.visit(node.key); + } + + const isMethodDefinition = node.type === AST_NODE_TYPES.MethodDefinition; + if (isMethodDefinition) { + previous = this.pushInnerMethodDefinition(true); + } + this.visit(node.value); + if (isMethodDefinition) { + this.popInnerMethodDefinition(previous); + } + + if ('decorators' in node) { + node.decorators?.forEach(d => this.visit(d)); + } + } + + protected visitType(node: TSESTree.Node | null | undefined): void { + if (!node) { + return; + } + TypeVisitor.visit(this, node); + } + + protected visitTypeAssertion( + node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion, + ): void { + this.visit(node.expression); + this.visitType(node.typeAnnotation); + } + + ///////////////////// + // Visit selectors // + ///////////////////// + + protected ArrowFunctionExpression( + node: TSESTree.ArrowFunctionExpression, + ): void { + this.visitFunction(node); + } + + protected AssignmentExpression(node: TSESTree.AssignmentExpression): void { + if (PatternVisitor.isPattern(node.left)) { + if (node.operator === '=') { + this.visitPattern( + node.left, + (pattern, info) => { + const maybeImplicitGlobal = !this.currentScope().isStrict + ? { + pattern, + node, + } + : null; + this.referencingDefaultValue( + pattern, + info.assignments, + maybeImplicitGlobal, + false, + ); + this.currentScope().referenceValue( + pattern, + ReferenceFlag.Write, + node.right, + maybeImplicitGlobal, + false, + ); + }, + { processRightHandNodes: true }, + ); + } else if (node.left.type === AST_NODE_TYPES.Identifier) { + this.currentScope().referenceValue( + node.left, + ReferenceFlag.ReadWrite, + node.right, + ); + } + } else { + this.visit(node.left); + } + this.visit(node.right); + } + + protected BlockStatement(node: TSESTree.BlockStatement): void { + if (this.scopeManager.isES6()) { + this.scopeManager.nestBlockScope(node); + } + + this.visitChildren(node); + + this.close(node); + } + + protected BreakStatement(): void { + // don't reference the break statement's label + } + + protected CallExpression( + node: TSESTree.CallExpression | TSESTree.OptionalCallExpression, + ): void { + this.visitChildren(node, ['typeParameters']); + this.visitType(node.typeParameters); + } + + protected CatchClause(node: TSESTree.CatchClause): void { + this.scopeManager.nestCatchScope(node); + + if (node.param) { + const param = node.param; + this.visitPattern( + param, + (pattern, info) => { + this.currentScope().defineIdentifier( + pattern, + new CatchClauseDefinition(param, node), + ); + this.referencingDefaultValue(pattern, info.assignments, null, true); + }, + { processRightHandNodes: true }, + ); + } + this.visit(node.body); + + this.close(node); + } + + protected ClassExpression(node: TSESTree.ClassExpression): void { + this.visitClass(node); + } + + protected ClassDeclaration(node: TSESTree.ClassDeclaration): void { + this.visitClass(node); + } + + protected ClassProperty(node: TSESTree.ClassProperty): void { + this.visitProperty(node); + this.visitType(node.typeAnnotation); + } + + protected ContinueStatement(): void { + // don't reference the continue statement's label + } + + protected ExportAllDeclaration(): void { + // this defines no local variables + } + + protected ExportDefaultDeclaration( + node: TSESTree.ExportDefaultDeclaration, + ): void { + if (node.declaration.type === AST_NODE_TYPES.Identifier) { + ExportVisitor.visit(this, node); + } else { + this.visit(node.declaration); + } + } + + protected ExportNamedDeclaration( + node: TSESTree.ExportNamedDeclaration, + ): void { + if (node.declaration) { + this.visit(node.declaration); + } else { + ExportVisitor.visit(this, node); + } + } + + protected ForInStatement(node: TSESTree.ForInStatement): void { + this.visitForIn(node); + } + + protected ForOfStatement(node: TSESTree.ForOfStatement): void { + this.visitForIn(node); + } + + protected ForStatement(node: TSESTree.ForStatement): void { + // Create ForStatement declaration. + // NOTE: In ES6, ForStatement dynamically generates per iteration environment. However, this is + // a static analyzer, we only generate one scope for ForStatement. + if ( + node.init && + node.init.type === AST_NODE_TYPES.VariableDeclaration && + node.init.kind !== 'var' + ) { + this.scopeManager.nestForScope(node); + } + + this.visitChildren(node); + + this.close(node); + } + + protected FunctionDeclaration(node: TSESTree.FunctionDeclaration): void { + this.visitFunction(node); + } + + protected FunctionExpression(node: TSESTree.FunctionExpression): void { + this.visitFunction(node); + } + + protected Identifier(node: TSESTree.Identifier): void { + this.currentScope().referenceValue(node); + this.visitType(node.typeAnnotation); + } + + protected ImportDeclaration(node: TSESTree.ImportDeclaration): void { + assert( + this.scopeManager.isES6() && this.scopeManager.isModule(), + 'ImportDeclaration should appear when the mode is ES6 and in the module context.', + ); + + ImportVisitor.visit(this, node); + } + + protected LabeledStatement(node: TSESTree.LabeledStatement): void { + this.visit(node.body); + } + + protected MemberExpression( + node: TSESTree.MemberExpression | TSESTree.OptionalMemberExpression, + ): void { + this.visit(node.object); + if (node.computed) { + this.visit(node.property); + } + } + + protected MetaProperty(): void { + // meta properties all builtin globals + } + + protected MethodDefinition(node: TSESTree.MethodDefinition): void { + this.visitProperty(node); + } + + protected OptionalCallExpression( + node: TSESTree.OptionalCallExpression, + ): void { + this.CallExpression(node); + } + + protected OptionalMemberExpression( + node: TSESTree.OptionalMemberExpression, + ): void { + this.MemberExpression(node); + } + + protected Program(node: TSESTree.Program): void { + this.scopeManager.nestGlobalScope(node); + + if (this.scopeManager.isGlobalReturn()) { + // Force strictness of GlobalScope to false when using node.js scope. + this.currentScope().isStrict = false; + this.scopeManager.nestFunctionScope(node, false); + } + + if (this.scopeManager.isES6() && this.scopeManager.isModule()) { + this.scopeManager.nestModuleScope(node); + } + + if (this.scopeManager.isStrict()) { + this.currentScope().isStrict = true; + } + + this.visitChildren(node); + this.close(node); + } + + protected Property(node: TSESTree.Property): void { + this.visitProperty(node); + } + + protected SwitchStatement(node: TSESTree.SwitchStatement): void { + this.visit(node.discriminant); + + if (this.scopeManager.isES6()) { + this.scopeManager.nestSwitchScope(node); + } + + for (const switchCase of node.cases) { + this.visit(switchCase); + } + + this.close(node); + } + + protected TSAbstractClassProperty( + node: TSESTree.TSAbstractClassProperty, + ): void { + this.visitProperty(node); + } + + protected TSAbstractMethodDefinition( + node: TSESTree.TSAbstractMethodDefinition, + ): void { + this.visitProperty(node); + } + + protected TSAsExpression(node: TSESTree.TSAsExpression): void { + this.visitTypeAssertion(node); + } + + protected TSDeclareFunction(node: TSESTree.TSDeclareFunction): void { + this.visitFunction(node); + } + + protected TSImportEqualsDeclaration( + node: TSESTree.TSImportEqualsDeclaration, + ): void { + this.currentScope().defineIdentifier( + node.id, + new ImportBindingDefinition(node.id, node, node), + ); + + if (node.moduleReference.type === AST_NODE_TYPES.TSQualifiedName) { + this.visit(node.moduleReference.left); + } else { + this.visit(node.moduleReference); + } + } + + protected TSEmptyBodyFunctionExpression( + node: TSESTree.TSEmptyBodyFunctionExpression, + ): void { + this.visitFunction(node); + } + + protected TSEnumDeclaration(node: TSESTree.TSEnumDeclaration): void { + this.currentScope().defineIdentifier( + node.id, + new TSEnumNameDefinition(node.id, node), + ); + + // enum members can be referenced within the enum body + this.scopeManager.nestTSEnumScope(node); + + // define the enum name again inside the new enum scope + // references to the enum should not resolve directly to the enum + this.currentScope().defineIdentifier( + node.id, + new TSEnumNameDefinition(node.id, node), + ); + + for (const member of node.members) { + // TS resolves literal named members to be actual names + // enum Foo { + // 'a' = 1, + // b = a, // this references the 'a' member + // } + if ( + member.id.type === AST_NODE_TYPES.Literal && + typeof member.id.value === 'string' + ) { + const name = member.id as TSESTree.StringLiteral; + this.currentScope().defineLiteralIdentifier( + name, + new TSEnumMemberDefinition(name, member), + ); + } else if ( + !member.computed && + member.id.type === AST_NODE_TYPES.Identifier + ) { + this.currentScope().defineIdentifier( + member.id, + new TSEnumMemberDefinition(member.id, member), + ); + } + + this.visit(member.initializer); + } + + this.close(node); + } + + protected TSInterfaceDeclaration( + node: TSESTree.TSInterfaceDeclaration, + ): void { + this.visitType(node); + } + + protected TSModuleDeclaration(node: TSESTree.TSModuleDeclaration): void { + if (node.id.type === AST_NODE_TYPES.Identifier) { + this.currentScope().defineIdentifier( + node.id, + new TSModuleNameDefinition(node.id, node), + ); + } + + this.scopeManager.nestTSModuleScope(node); + + if (node.id.type === AST_NODE_TYPES.Identifier) { + // define the module name again inside the new module scope + // references to the module should not resolve directly to the module + this.currentScope().defineIdentifier( + node.id, + new TSModuleNameDefinition(node.id, node), + ); + } + + this.visit(node.body); + + this.close(node); + } + + protected TSTypeAliasDeclaration( + node: TSESTree.TSTypeAliasDeclaration, + ): void { + this.visitType(node); + } + + protected TSTypeAssertion(node: TSESTree.TSTypeAssertion): void { + this.visitTypeAssertion(node); + } + + protected UpdateExpression(node: TSESTree.UpdateExpression): void { + if (PatternVisitor.isPattern(node.argument)) { + this.visitPattern(node.argument, pattern => { + this.currentScope().referenceValue( + pattern, + ReferenceFlag.ReadWrite, + null, + ); + }); + } else { + this.visitChildren(node); + } + } + + protected VariableDeclaration(node: TSESTree.VariableDeclaration): void { + const variableTargetScope = + node.kind === 'var' + ? this.currentScope().variableScope + : this.currentScope(); + + for (const decl of node.declarations) { + const init = decl.init; + + this.visitPattern( + decl.id, + (pattern, info) => { + variableTargetScope.defineIdentifier( + pattern, + new VariableDefinition(pattern, decl, node), + ); + + this.referencingDefaultValue(pattern, info.assignments, null, true); + if (init) { + this.currentScope().referenceValue( + pattern, + ReferenceFlag.Write, + init, + null, + true, + ); + } + }, + { processRightHandNodes: true }, + ); + + if (decl.init) { + this.visit(decl.init); + } + + if ('typeAnnotation' in decl.id) { + this.visitType(decl.id.typeAnnotation); + } + } + } + + protected WithStatement(node: TSESTree.WithStatement): void { + this.visit(node.object); + + // Then nest scope for WithStatement. + this.scopeManager.nestWithScope(node); + + this.visit(node.body); + + this.close(node); + } +} + +export { Referencer, ReferencerOptions }; diff --git a/packages/scope-manager/src/referencer/TypeVisitor.ts b/packages/scope-manager/src/referencer/TypeVisitor.ts new file mode 100644 index 000000000000..d4f49bb2d813 --- /dev/null +++ b/packages/scope-manager/src/referencer/TypeVisitor.ts @@ -0,0 +1,199 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { Referencer } from './Referencer'; +import { Visitor } from './Visitor'; +import { ParameterDefinition, TypeDefinition } from '../definition'; + +class TypeVisitor extends Visitor { + readonly #referencer: Referencer; + + constructor(referencer: Referencer) { + super(referencer); + this.#referencer = referencer; + } + + static visit(referencer: Referencer, node: TSESTree.Node): void { + const typeReferencer = new TypeVisitor(referencer); + typeReferencer.visit(node); + } + + /////////////////// + // Visit helpers // + /////////////////// + + protected visitFunctionType( + node: + | TSESTree.TSCallSignatureDeclaration + | TSESTree.TSConstructorType + | TSESTree.TSConstructSignatureDeclaration + | TSESTree.TSFunctionType + | TSESTree.TSMethodSignature, + ): void { + // arguments and type parameters can only be referenced from within the function + this.#referencer.scopeManager.nestFunctionTypeScope(node); + this.visit(node.typeParameters); + + for (const param of node.params) { + this.visitPattern(param, (pattern, info) => { + // a parameter name creates a value type variable which can be referenced later via typeof arg + this.#referencer + .currentScope() + .defineIdentifier( + pattern, + new ParameterDefinition(pattern, node, info.rest), + ); + this.visit(pattern.typeAnnotation); + }); + } + this.visit(node.returnType); + + this.#referencer.close(node); + } + + protected visitPropertyKey( + node: TSESTree.TSMethodSignature | TSESTree.TSPropertySignature, + ): void { + if (node.computed && node.key.type === AST_NODE_TYPES.Identifier) { + this.#referencer.currentScope().referenceValue(node.key); + } + } + + ///////////////////// + // Visit selectors // + ///////////////////// + + protected Identifier(node: TSESTree.Identifier): void { + this.#referencer.currentScope().referenceType(node); + } + + protected MemberExpression(node: TSESTree.MemberExpression): void { + this.visit(node.object); + // don't visit the property + } + + protected TSCallSignatureDeclaration( + node: TSESTree.TSCallSignatureDeclaration, + ): void { + this.visitFunctionType(node); + } + + protected TSConditionalType(node: TSESTree.TSConditionalType): void { + // conditional types can define inferred type parameters + // which are only accessible from inside the conditional parameter + this.#referencer.scopeManager.nestConditionalTypeScope(node); + + this.visitChildren(node); + + this.#referencer.close(node); + } + + protected TSConstructorType(node: TSESTree.TSConstructorType): void { + this.visitFunctionType(node); + } + + protected TSConstructSignatureDeclaration( + node: TSESTree.TSConstructSignatureDeclaration, + ): void { + this.visitFunctionType(node); + } + + protected TSFunctionType(node: TSESTree.TSFunctionType): void { + this.visitFunctionType(node); + } + + protected TSIndexSignature(node: TSESTree.TSIndexSignature): void { + for (const param of node.parameters) { + if (param.type === AST_NODE_TYPES.Identifier) { + this.visit(param.typeAnnotation); + } + } + this.visit(node.typeAnnotation); + } + + protected TSInterfaceDeclaration( + node: TSESTree.TSInterfaceDeclaration, + ): void { + this.#referencer + .currentScope() + .defineIdentifier(node.id, new TypeDefinition(node.id, node)); + + if (node.typeParameters) { + // type parameters cannot be referenced from outside their current scope + this.#referencer.scopeManager.nestTypeScope(node); + this.visit(node.typeParameters); + } + + node.extends?.forEach(this.visit, this); + node.implements?.forEach(this.visit, this); + this.visit(node.body); + + if (node.typeParameters) { + this.#referencer.close(node); + } + } + + protected TSMappedType(node: TSESTree.TSMappedType): void { + // mapped types key can only be referenced within their return value + this.#referencer.scopeManager.nestMappedTypeScope(node); + this.visitChildren(node); + this.#referencer.close(node); + } + + protected TSMethodSignature(node: TSESTree.TSMethodSignature): void { + this.visitPropertyKey(node); + this.visitFunctionType(node); + } + + protected TSPropertySignature(node: TSESTree.TSPropertySignature): void { + this.visitPropertyKey(node); + this.visit(node.typeAnnotation); + } + + protected TSQualifiedName(node: TSESTree.TSQualifiedName): void { + this.visit(node.left); + // we don't visit the right as it a name on the thing, not a name to reference + } + + protected TSTypeAliasDeclaration( + node: TSESTree.TSTypeAliasDeclaration, + ): void { + this.#referencer + .currentScope() + .defineIdentifier(node.id, new TypeDefinition(node.id, node)); + + if (node.typeParameters) { + // type parameters cannot be referenced from outside their current scope + this.#referencer.scopeManager.nestTypeScope(node); + this.visit(node.typeParameters); + } + + this.visit(node.typeAnnotation); + + if (node.typeParameters) { + this.#referencer.close(node); + } + } + + protected TSTypeParameter(node: TSESTree.TSTypeParameter): void { + this.#referencer + .currentScope() + .defineIdentifier(node.name, new TypeDefinition(node.name, node)); + + this.visit(node.constraint); + this.visit(node.default); + } + + // a type query `typeof foo` is a special case that references a _non-type_ variable, + protected TSTypeQuery(node: TSESTree.TSTypeQuery): void { + if (node.exprName.type === AST_NODE_TYPES.Identifier) { + this.#referencer.currentScope().referenceValue(node.exprName); + } else { + let expr = node.exprName.left; + while (expr.type !== AST_NODE_TYPES.Identifier) { + expr = expr.left; + } + this.#referencer.currentScope().referenceValue(expr); + } + } +} + +export { TypeVisitor }; diff --git a/packages/scope-manager/src/referencer/Visitor.ts b/packages/scope-manager/src/referencer/Visitor.ts new file mode 100644 index 000000000000..a3e1e989d519 --- /dev/null +++ b/packages/scope-manager/src/referencer/Visitor.ts @@ -0,0 +1,44 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { VisitorBase, VisitorOptions } from './VisitorBase'; +import { + PatternVisitor, + PatternVisitorCallback, + PatternVisitorOptions, +} from './PatternVisitor'; + +interface VisitPatternOptions extends PatternVisitorOptions { + processRightHandNodes?: boolean; +} +class Visitor extends VisitorBase { + readonly #options: VisitorOptions; + constructor(optionsOrVisitor: VisitorOptions | Visitor) { + super( + optionsOrVisitor instanceof Visitor + ? optionsOrVisitor.#options + : optionsOrVisitor, + ); + + this.#options = + optionsOrVisitor instanceof Visitor + ? optionsOrVisitor.#options + : optionsOrVisitor; + } + + protected visitPattern( + node: TSESTree.Node, + callback: PatternVisitorCallback, + options: VisitPatternOptions = { processRightHandNodes: false }, + ): void { + // Call the callback at left hand identifier nodes, and Collect right hand nodes. + const visitor = new PatternVisitor(this.#options, node, callback); + + visitor.visit(node); + + // Process the right hand nodes recursively. + if (options.processRightHandNodes) { + visitor.rightHandNodes.forEach(this.visit, this); + } + } +} + +export { Visitor, VisitorBase, VisitorOptions }; diff --git a/packages/scope-manager/src/referencer/VisitorBase.ts b/packages/scope-manager/src/referencer/VisitorBase.ts new file mode 100644 index 000000000000..0d37ac31e352 --- /dev/null +++ b/packages/scope-manager/src/referencer/VisitorBase.ts @@ -0,0 +1,79 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { visitorKeys, VisitorKeys } from '@typescript-eslint/visitor-keys'; + +interface VisitorOptions { + childVisitorKeys?: VisitorKeys | null; +} + +function isObject(obj: unknown): obj is Record { + return typeof obj === 'object' && obj != null; +} +function isNode(node: unknown): node is TSESTree.Node { + return isObject(node) && typeof node.type === 'string'; +} + +type NodeVisitor = { + [K in AST_NODE_TYPES]?: (node: TSESTree.Node) => void; +}; + +abstract class VisitorBase { + readonly #childVisitorKeys: VisitorKeys; + constructor(options: VisitorOptions) { + this.#childVisitorKeys = options.childVisitorKeys ?? visitorKeys; + } + + /** + * Default method for visiting children. + * @param node the node whose children should be visited + * @param exclude a list of keys to not visit + */ + visitChildren( + node: T | null | undefined, + excludeArr?: (keyof T)[], + ): void { + if (node == null || node.type == null) { + return; + } + + const exclude = new Set(excludeArr) as Set; + const children = this.#childVisitorKeys[node.type] ?? Object.keys(node); + for (const key of children) { + if (exclude.has(key)) { + continue; + } + + const child = node[key as keyof TSESTree.Node] as unknown; + if (!child) { + continue; + } + + if (Array.isArray(child)) { + for (const subChild of child) { + if (isNode(subChild)) { + this.visit(subChild); + } + } + } else if (isNode(child)) { + this.visit(child); + } + } + } + + /** + * Dispatching node. + */ + visit(node: TSESTree.Node | null | undefined): void { + if (node == null || node.type == null) { + return; + } + + const visitor = (this as NodeVisitor)[node.type]; + if (visitor) { + return visitor.call(this, node); + } + + this.visitChildren(node); + } +} + +export { VisitorBase, VisitorOptions, VisitorKeys }; diff --git a/packages/scope-manager/src/referencer/index.ts b/packages/scope-manager/src/referencer/index.ts new file mode 100644 index 000000000000..6ac29bd3e0e0 --- /dev/null +++ b/packages/scope-manager/src/referencer/index.ts @@ -0,0 +1 @@ +export { Referencer, ReferencerOptions } from './Referencer'; diff --git a/packages/scope-manager/src/scope/BlockScope.ts b/packages/scope-manager/src/scope/BlockScope.ts new file mode 100644 index 000000000000..959044282c26 --- /dev/null +++ b/packages/scope-manager/src/scope/BlockScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class BlockScope extends ScopeBase< + ScopeType.block, + TSESTree.BlockStatement, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: BlockScope['upper'], + block: BlockScope['block'], + ) { + super(scopeManager, ScopeType.block, upperScope, block, false); + } +} + +export { BlockScope }; diff --git a/packages/scope-manager/src/scope/CatchScope.ts b/packages/scope-manager/src/scope/CatchScope.ts new file mode 100644 index 000000000000..46b4005f3ac3 --- /dev/null +++ b/packages/scope-manager/src/scope/CatchScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class CatchScope extends ScopeBase< + ScopeType.catch, + TSESTree.CatchClause, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: CatchScope['upper'], + block: CatchScope['block'], + ) { + super(scopeManager, ScopeType.catch, upperScope, block, false); + } +} + +export { CatchScope }; diff --git a/packages/scope-manager/src/scope/ClassScope.ts b/packages/scope-manager/src/scope/ClassScope.ts new file mode 100644 index 000000000000..ee28a31aa08a --- /dev/null +++ b/packages/scope-manager/src/scope/ClassScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class ClassScope extends ScopeBase< + ScopeType.class, + TSESTree.ClassDeclaration | TSESTree.ClassExpression, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: ClassScope['upper'], + block: ClassScope['block'], + ) { + super(scopeManager, ScopeType.class, upperScope, block, false); + } +} + +export { ClassScope }; diff --git a/packages/scope-manager/src/scope/ConditionalTypeScope.ts b/packages/scope-manager/src/scope/ConditionalTypeScope.ts new file mode 100644 index 000000000000..c20f1217e0e4 --- /dev/null +++ b/packages/scope-manager/src/scope/ConditionalTypeScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class ConditionalTypeScope extends ScopeBase< + ScopeType.conditionalType, + TSESTree.TSConditionalType, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: ConditionalTypeScope['upper'], + block: ConditionalTypeScope['block'], + ) { + super(scopeManager, ScopeType.conditionalType, upperScope, block, false); + } +} + +export { ConditionalTypeScope }; diff --git a/packages/scope-manager/src/scope/ForScope.ts b/packages/scope-manager/src/scope/ForScope.ts new file mode 100644 index 000000000000..36703b5d197d --- /dev/null +++ b/packages/scope-manager/src/scope/ForScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class ForScope extends ScopeBase< + ScopeType.for, + TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: ForScope['upper'], + block: ForScope['block'], + ) { + super(scopeManager, ScopeType.for, upperScope, block, false); + } +} + +export { ForScope }; diff --git a/packages/scope-manager/src/scope/FunctionExpressionNameScope.ts b/packages/scope-manager/src/scope/FunctionExpressionNameScope.ts new file mode 100644 index 000000000000..a84bc4b2c8db --- /dev/null +++ b/packages/scope-manager/src/scope/FunctionExpressionNameScope.ts @@ -0,0 +1,36 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { Scope } from './Scope'; +import { FunctionNameDefinition } from '../definition'; +import { ScopeManager } from '../ScopeManager'; + +class FunctionExpressionNameScope extends ScopeBase< + ScopeType.functionExpressionName, + TSESTree.FunctionExpression, + Scope +> { + public readonly functionExpressionScope: true; + constructor( + scopeManager: ScopeManager, + upperScope: FunctionExpressionNameScope['upper'], + block: FunctionExpressionNameScope['block'], + ) { + super( + scopeManager, + ScopeType.functionExpressionName, + upperScope, + block, + false, + ); + if (block.id) { + this.defineIdentifier( + block.id, + new FunctionNameDefinition(block.id, block), + ); + } + this.functionExpressionScope = true; + } +} + +export { FunctionExpressionNameScope }; diff --git a/packages/scope-manager/src/scope/FunctionScope.ts b/packages/scope-manager/src/scope/FunctionScope.ts new file mode 100644 index 000000000000..af6f78f69074 --- /dev/null +++ b/packages/scope-manager/src/scope/FunctionScope.ts @@ -0,0 +1,65 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { Reference } from '../referencer/Reference'; +import { ScopeManager } from '../ScopeManager'; +import { Variable } from '../Variable'; + +class FunctionScope extends ScopeBase< + ScopeType.function, + | TSESTree.ArrowFunctionExpression + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression + | TSESTree.TSDeclareFunction + | TSESTree.TSEmptyBodyFunctionExpression + | TSESTree.Program, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: FunctionScope['upper'], + block: FunctionScope['block'], + isMethodDefinition: boolean, + ) { + super( + scopeManager, + ScopeType.function, + upperScope, + block, + isMethodDefinition, + ); + + // section 9.2.13, FunctionDeclarationInstantiation. + // NOTE Arrow functions never have an arguments objects. + if (this.block.type !== AST_NODE_TYPES.ArrowFunctionExpression) { + this.defineVariable('arguments', this.set, this.variables, null, null); + } + } + + // References in default parameters isn't resolved to variables which are in their function body. + // const x = 1 + // function f(a = x) { // This `x` is resolved to the `x` in the outer scope. + // const x = 2 + // console.log(a) + // } + protected isValidResolution(ref: Reference, variable: Variable): boolean { + // If `options.gloablReturn` is true, `this.block` becomes a Program node. + if (this.block.type === AST_NODE_TYPES.Program) { + return true; + } + + const bodyStart = this.block.body?.range[0] ?? -1; + + // It's invalid resolution in the following case: + return !( + ( + variable.scope === this && + ref.identifier.range[0] < bodyStart && // the reference is in the parameter part. + variable.defs.every(d => d.name.range[0] >= bodyStart) + ) // the variable is in the body. + ); + } +} + +export { FunctionScope }; diff --git a/packages/scope-manager/src/scope/FunctionTypeScope.ts b/packages/scope-manager/src/scope/FunctionTypeScope.ts new file mode 100644 index 000000000000..d459070cdf8a --- /dev/null +++ b/packages/scope-manager/src/scope/FunctionTypeScope.ts @@ -0,0 +1,25 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class FunctionTypeScope extends ScopeBase< + ScopeType.functionType, + | TSESTree.TSCallSignatureDeclaration + | TSESTree.TSConstructorType + | TSESTree.TSConstructSignatureDeclaration + | TSESTree.TSFunctionType + | TSESTree.TSMethodSignature, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: FunctionTypeScope['upper'], + block: FunctionTypeScope['block'], + ) { + super(scopeManager, ScopeType.functionType, upperScope, block, false); + } +} + +export { FunctionTypeScope }; diff --git a/packages/scope-manager/src/scope/GlobalScope.ts b/packages/scope-manager/src/scope/GlobalScope.ts new file mode 100644 index 000000000000..3d1b243340ef --- /dev/null +++ b/packages/scope-manager/src/scope/GlobalScope.ts @@ -0,0 +1,64 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { assert } from '../assert'; +import { ImplicitGlobalVariableDefinition } from '../definition/ImplicitGlobalVariableDefinition'; +import { Reference } from '../referencer/Reference'; +import { ScopeManager } from '../ScopeManager'; +import { Variable } from '../Variable'; + +class GlobalScope extends ScopeBase< + ScopeType.global, + TSESTree.Program, + /** + * The global scope has no parent. + */ + null +> { + // note this is accessed in used in the legacy eslint-scope tests, so it can't be true private + private readonly implicit: { + readonly set: Map; + readonly variables: Variable[]; + /** + * List of {@link Reference}s that are left to be resolved (i.e. which + * need to be linked to the variable they refer to). + */ + leftToBeResolved: Reference[]; + }; + + constructor(scopeManager: ScopeManager, block: GlobalScope['block']) { + super(scopeManager, ScopeType.global, null, block, false); + this.implicit = { + set: new Map(), + variables: [], + leftToBeResolved: [], + }; + } + + public close(scopeManager: ScopeManager): Scope | null { + assert(this.leftToResolve); + + for (const ref of this.leftToResolve) { + if (ref.maybeImplicitGlobal && !this.set.has(ref.identifier.name)) { + // create an implicit global variable from assignment expression + const info = ref.maybeImplicitGlobal; + const node = info.pattern; + if (node && node.type === AST_NODE_TYPES.Identifier) { + this.defineVariable( + node.name, + this.implicit.set, + this.implicit.variables, + node, + new ImplicitGlobalVariableDefinition(info.pattern, info.node), + ); + } + } + } + + this.implicit.leftToBeResolved = this.leftToResolve; + return super.close(scopeManager); + } +} + +export { GlobalScope }; diff --git a/packages/scope-manager/src/scope/MappedTypeScope.ts b/packages/scope-manager/src/scope/MappedTypeScope.ts new file mode 100644 index 000000000000..9b5c2a05d4b9 --- /dev/null +++ b/packages/scope-manager/src/scope/MappedTypeScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class MappedTypeScope extends ScopeBase< + ScopeType.mappedType, + TSESTree.TSMappedType, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: MappedTypeScope['upper'], + block: MappedTypeScope['block'], + ) { + super(scopeManager, ScopeType.mappedType, upperScope, block, false); + } +} + +export { MappedTypeScope }; diff --git a/packages/scope-manager/src/scope/ModuleScope.ts b/packages/scope-manager/src/scope/ModuleScope.ts new file mode 100644 index 000000000000..87c5ab528309 --- /dev/null +++ b/packages/scope-manager/src/scope/ModuleScope.ts @@ -0,0 +1,17 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class ModuleScope extends ScopeBase { + constructor( + scopeManager: ScopeManager, + upperScope: ModuleScope['upper'], + block: ModuleScope['block'], + ) { + super(scopeManager, ScopeType.module, upperScope, block, false); + } +} + +export { ModuleScope }; diff --git a/packages/scope-manager/src/scope/Scope.ts b/packages/scope-manager/src/scope/Scope.ts new file mode 100644 index 000000000000..7df3f941629c --- /dev/null +++ b/packages/scope-manager/src/scope/Scope.ts @@ -0,0 +1,36 @@ +import { BlockScope } from './BlockScope'; +import { CatchScope } from './CatchScope'; +import { ClassScope } from './ClassScope'; +import { ConditionalTypeScope } from './ConditionalTypeScope'; +import { ForScope } from './ForScope'; +import { FunctionExpressionNameScope } from './FunctionExpressionNameScope'; +import { FunctionScope } from './FunctionScope'; +import { FunctionTypeScope } from './FunctionTypeScope'; +import { GlobalScope } from './GlobalScope'; +import { MappedTypeScope } from './MappedTypeScope'; +import { ModuleScope } from './ModuleScope'; +import { SwitchScope } from './SwitchScope'; +import { TSEnumScope } from './TSEnumScope'; +import { TSModuleScope } from './TSModuleScope'; +import { TypeScope } from './TypeScope'; +import { WithScope } from './WithScope'; + +type Scope = + | BlockScope + | CatchScope + | ClassScope + | ConditionalTypeScope + | ForScope + | FunctionExpressionNameScope + | FunctionScope + | FunctionTypeScope + | GlobalScope + | MappedTypeScope + | ModuleScope + | SwitchScope + | TSEnumScope + | TSModuleScope + | TypeScope + | WithScope; + +export { Scope }; diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts new file mode 100644 index 000000000000..24f44d0e4a9b --- /dev/null +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -0,0 +1,495 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { FunctionScope } from './FunctionScope'; +import { GlobalScope } from './GlobalScope'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; +import { Scope } from './Scope'; +import { ModuleScope } from './ModuleScope'; +import { assert } from '../assert'; +import { Definition, DefinitionType } from '../definition'; +import { createIdGenerator } from '../ID'; +import { + Reference, + ReferenceFlag, + ReferenceImplicitGlobal, + ReferenceTypeFlag, +} from '../referencer/Reference'; +import { Variable } from '../Variable'; + +/** + * Test if scope is strict + */ +function isStrictScope( + scope: Scope, + block: TSESTree.Node, + isMethodDefinition: boolean, +): boolean { + let body: TSESTree.BlockStatement | TSESTree.Program | null | undefined; + + // When upper scope is exists and strict, inner scope is also strict. + if (scope.upper?.isStrict) { + return true; + } + + if (isMethodDefinition) { + return true; + } + + if ( + scope.type === ScopeType.class || + scope.type === ScopeType.conditionalType || + scope.type === ScopeType.functionType || + scope.type === ScopeType.mappedType || + scope.type === ScopeType.module || + scope.type === ScopeType.tsEnum || + scope.type === ScopeType.tsModule || + scope.type === ScopeType.type + ) { + return true; + } + + if (scope.type === ScopeType.block || scope.type === ScopeType.switch) { + return false; + } + + if (scope.type === ScopeType.function) { + const functionBody = block as FunctionScope['block']; + switch (functionBody.type) { + case AST_NODE_TYPES.ArrowFunctionExpression: + if (functionBody.body.type !== AST_NODE_TYPES.BlockStatement) { + return false; + } + body = functionBody.body; + break; + + case AST_NODE_TYPES.Program: + body = functionBody; + break; + + default: + body = functionBody.body; + } + + if (!body) { + return false; + } + } else if (scope.type === ScopeType.global) { + body = block as GlobalScope['block']; + } else { + return false; + } + + // Search 'use strict' directive. + for (let i = 0; i < body.body.length; ++i) { + const stmt = body.body[i]; + + if (stmt.type !== AST_NODE_TYPES.ExpressionStatement) { + break; + } + const expr = stmt.expression; + + if ( + expr.type !== AST_NODE_TYPES.Literal || + typeof expr.value !== 'string' + ) { + break; + } + if (expr.raw !== null && expr.raw !== undefined) { + if (expr.raw === '"use strict"' || expr.raw === "'use strict'") { + return true; + } + } else { + if (expr.value === 'use strict') { + return true; + } + } + } + return false; +} + +/** + * Register scope + */ +function registerScope(scopeManager: ScopeManager, scope: Scope): void { + scopeManager.scopes.push(scope); + + const scopes = scopeManager.nodeToScope.get(scope.block); + + if (scopes) { + scopes.push(scope); + } else { + scopeManager.nodeToScope.set(scope.block, [scope]); + } +} + +const generator = createIdGenerator(); + +type AnyScope = ScopeBase; +abstract class ScopeBase< + TType extends ScopeType, + TBlock extends TSESTree.Node, + TUpper extends Scope | null +> { + /** + * A unique ID for this instance - primarily used to help debugging and testing + */ + public readonly $id: number = generator(); + + /** + * The AST node which created this scope. + * @public + */ + public readonly block: TBlock; + /** + * The array of child scopes. This does not include grandchild scopes. + * @public + */ + public readonly childScopes: Scope[] = []; + /** + * A map of the variables for each node in this scope. + * This is map is a pointer to the one in the parent ScopeManager instance + */ + readonly #declaredVariables: WeakMap; + /** + * Generally, through the lexical scoping of JS you can always know which variable an identifier in the source code + * refers to. There are a few exceptions to this rule. With `global` and `with` scopes you can only decide at runtime + * which variable a reference refers to. + * All those scopes are considered "dynamic". + */ + #dynamic: boolean; + /** + * Whether this scope is created by a FunctionExpression. + * @public + */ + public readonly functionExpressionScope: boolean = false; + /** + * Whether 'use strict' is in effect in this scope. + * @public + */ + public isStrict: boolean; + /** + * List of {@link Reference}s that are left to be resolved (i.e. which + * need to be linked to the variable they refer to). + */ + protected leftToResolve: Reference[] | null = []; + /** + * Any variable {@link Reference} found in this scope. + * This includes occurrences of local variables as well as variables from parent scopes (including the global scope). + * For local variables this also includes defining occurrences (like in a 'var' statement). + * In a 'function' scope this does not include the occurrences of the formal parameter in the parameter list. + * @public + */ + public readonly references: Reference[] = []; + /** + * The map from variable names to variable objects. + * @public + */ + public readonly set = new Map(); + /** + * The {@link Reference}s that are not resolved with this scope. + * @public + */ + public readonly through: Reference[] = []; + /** + * The type of scope + * @public + */ + public readonly type: TType; + /** + * Reference to the parent {@link Scope}. + * @public + */ + public readonly upper: TUpper; + /** + * The scoped {@link Variable}s of this scope. + * In the case of a 'function' scope this includes the automatic argument `arguments` as its first element, as well + * as all further formal arguments. + * This does not include variables which are defined in child scopes. + * @public + */ + public readonly variables: Variable[] = []; + /** + * For 'global', 'function', and 'module' scopes, this is a self-reference. + * For other scope types this is the *variableScope* value of the parent scope. + * @public + */ + public readonly variableScope: GlobalScope | FunctionScope | ModuleScope; + + constructor( + scopeManager: ScopeManager, + type: TType, + upperScope: TUpper, + block: TBlock, + isMethodDefinition: boolean, + ) { + const upperScopeAsScopeBase = upperScope as Scope; + + this.type = type; + this.#dynamic = + this.type === ScopeType.global || this.type === ScopeType.with; + this.block = block; + this.variableScope = + this.type === 'global' || + this.type === 'function' || + this.type === 'module' + ? (this as AnyScope['variableScope']) + : upperScopeAsScopeBase.variableScope; + this.upper = upperScope; + + /** + * Whether 'use strict' is in effect in this scope. + * @member {boolean} Scope#isStrict + */ + this.isStrict = isStrictScope(this as Scope, block, isMethodDefinition); + + if (upperScopeAsScopeBase) { + // this is guaranteed to be correct at runtime + upperScopeAsScopeBase.childScopes.push(this as Scope); + } + + this.#declaredVariables = scopeManager.declaredVariables; + + registerScope(scopeManager, this as Scope); + } + + public shouldStaticallyClose(): boolean { + return !this.#dynamic; + } + + private shouldStaticallyCloseForGlobal( + ref: Reference, + scopeManager: ScopeManager, + ): boolean { + // On global scope, let/const/class declarations should be resolved statically. + const name = ref.identifier.name; + + const variable = this.set.get(name); + if (!variable) { + return false; + } + // variable exists on the scope + + // in module mode, we can statically resolve everything, regardless of its decl type + if (scopeManager.isModule()) { + return true; + } + + // in script mode, only certain cases should be statically resolved + // Example: + // a `var` decl is ignored by the runtime if it clashes with a global name + // this means that we should not resolve the reference to the variable + const defs = variable.defs; + return ( + defs.length > 0 && + defs.every(def => { + if ( + def.type === DefinitionType.Variable && + def.parent?.type === AST_NODE_TYPES.VariableDeclaration && + def.parent.kind === 'var' + ) { + return false; + } + return true; + }) + ); + } + + #staticCloseRef = (ref: Reference): void => { + const resolve = (): boolean => { + const name = ref.identifier.name; + const variable = this.set.get(name); + + if (!variable) { + return false; + } + + if (!this.isValidResolution(ref, variable)) { + return false; + } + + // make sure we don't match a type reference to a value variable + const isValidTypeReference = + ref.isTypeReference && variable.isTypeVariable; + const isValidValueReference = + ref.isValueReference && variable.isValueVariable; + if (!isValidTypeReference && !isValidValueReference) { + return false; + } + + variable.references.push(ref); + ref.resolved = variable; + + return true; + }; + + if (!resolve()) { + this.delegateToUpperScope(ref); + } + }; + + #dynamicCloseRef = (ref: Reference): void => { + // notify all names are through to global + let current = this as Scope | null; + + do { + current!.through.push(ref); + current = current!.upper; + } while (current); + }; + + #globalCloseRef = (ref: Reference, scopeManager: ScopeManager): void => { + // let/const/class declarations should be resolved statically. + // others should be resolved dynamically. + if (this.shouldStaticallyCloseForGlobal(ref, scopeManager)) { + this.#staticCloseRef(ref); + } else { + this.#dynamicCloseRef(ref); + } + }; + + public close(scopeManager: ScopeManager): Scope | null { + let closeRef; + + if (this.shouldStaticallyClose()) { + closeRef = this.#staticCloseRef; + } else if (this.type !== 'global') { + closeRef = this.#dynamicCloseRef; + } else { + closeRef = this.#globalCloseRef; + } + + // Try Resolving all references in this scope. + assert(this.leftToResolve); + for (let i = 0; i < this.leftToResolve.length; ++i) { + const ref = this.leftToResolve[i]; + + closeRef(ref, scopeManager); + } + this.leftToResolve = null; + + return this.upper; + } + + /** + * To override by function scopes. + * References in default parameters isn't resolved to variables which are in their function body. + */ + protected isValidResolution(_ref: Reference, _variable: Variable): boolean { + return true; + } + + protected delegateToUpperScope(ref: Reference): void { + const upper = (this.upper as Scope) as AnyScope; + if (upper?.leftToResolve) { + upper.leftToResolve.push(ref); + } + this.through.push(ref); + } + + private addDeclaredVariablesOfNode( + variable: Variable, + node: TSESTree.Node | null | undefined, + ): void { + if (node == null) { + return; + } + + let variables = this.#declaredVariables.get(node); + + if (variables == null) { + variables = []; + this.#declaredVariables.set(node, variables); + } + if (!variables.includes(variable)) { + variables.push(variable); + } + } + + protected defineVariable( + name: string, + set: Map, + variables: Variable[], + node: TSESTree.Identifier | null, + def: Definition | null, + ): void { + let variable = set.get(name); + if (!variable) { + variable = new Variable(name, this as Scope); + set.set(name, variable); + variables.push(variable); + } + + if (def) { + variable.defs.push(def); + this.addDeclaredVariablesOfNode(variable, def.node); + this.addDeclaredVariablesOfNode(variable, def.parent); + } + if (node) { + variable.identifiers.push(node); + } + } + + public defineIdentifier(node: TSESTree.Identifier, def: Definition): void { + this.defineVariable(node.name, this.set, this.variables, node, def); + } + + public defineLiteralIdentifier( + node: TSESTree.StringLiteral, + def: Definition, + ): void { + this.defineVariable(node.value, this.set, this.variables, null, def); + } + + public referenceValue( + node: TSESTree.Identifier, + assign: ReferenceFlag = ReferenceFlag.Read, + writeExpr?: TSESTree.Expression | null, + maybeImplicitGlobal?: ReferenceImplicitGlobal | null, + init = false, + ): void { + const ref = new Reference( + node, + this as Scope, + assign, + writeExpr, + maybeImplicitGlobal, + init, + ReferenceTypeFlag.Value, + ); + + this.references.push(ref); + this.leftToResolve?.push(ref); + } + + public referenceType(node: TSESTree.Identifier): void { + const ref = new Reference( + node, + this as Scope, + ReferenceFlag.Read, + null, + null, + false, + ReferenceTypeFlag.Type, + ); + + this.references.push(ref); + this.leftToResolve?.push(ref); + } + + public referenceDualValueType(node: TSESTree.Identifier): void { + const ref = new Reference( + node, + this as Scope, + ReferenceFlag.Read, + null, + null, + false, + ReferenceTypeFlag.Type | ReferenceTypeFlag.Value, + ); + + this.references.push(ref); + this.leftToResolve?.push(ref); + } +} + +export { ScopeBase }; diff --git a/packages/scope-manager/src/scope/ScopeType.ts b/packages/scope-manager/src/scope/ScopeType.ts new file mode 100644 index 000000000000..23d70fedbe80 --- /dev/null +++ b/packages/scope-manager/src/scope/ScopeType.ts @@ -0,0 +1,20 @@ +enum ScopeType { + block = 'block', + catch = 'catch', + class = 'class', + conditionalType = 'conditionalType', + for = 'for', + function = 'function', + functionExpressionName = 'function-expression-name', + functionType = 'functionType', + global = 'global', + mappedType = 'mappedType', + module = 'module', + switch = 'switch', + tsEnum = 'tsEnum', + tsModule = 'tsModule', + type = 'type', + with = 'with', +} + +export { ScopeType }; diff --git a/packages/scope-manager/src/scope/SwitchScope.ts b/packages/scope-manager/src/scope/SwitchScope.ts new file mode 100644 index 000000000000..7a684564cd4c --- /dev/null +++ b/packages/scope-manager/src/scope/SwitchScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class SwitchScope extends ScopeBase< + ScopeType.switch, + TSESTree.SwitchStatement, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: SwitchScope['upper'], + block: SwitchScope['block'], + ) { + super(scopeManager, ScopeType.switch, upperScope, block, false); + } +} + +export { SwitchScope }; diff --git a/packages/scope-manager/src/scope/TSEnumScope.ts b/packages/scope-manager/src/scope/TSEnumScope.ts new file mode 100644 index 000000000000..3962784acd21 --- /dev/null +++ b/packages/scope-manager/src/scope/TSEnumScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class TSEnumScope extends ScopeBase< + ScopeType.tsEnum, + TSESTree.TSEnumDeclaration, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: TSEnumScope['upper'], + block: TSEnumScope['block'], + ) { + super(scopeManager, ScopeType.tsEnum, upperScope, block, false); + } +} + +export { TSEnumScope }; diff --git a/packages/scope-manager/src/scope/TSModuleScope.ts b/packages/scope-manager/src/scope/TSModuleScope.ts new file mode 100644 index 000000000000..bdc7c7dc3290 --- /dev/null +++ b/packages/scope-manager/src/scope/TSModuleScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class TSModuleScope extends ScopeBase< + ScopeType.tsModule, + TSESTree.TSModuleDeclaration, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: TSModuleScope['upper'], + block: TSModuleScope['block'], + ) { + super(scopeManager, ScopeType.tsModule, upperScope, block, false); + } +} + +export { TSModuleScope }; diff --git a/packages/scope-manager/src/scope/TypeScope.ts b/packages/scope-manager/src/scope/TypeScope.ts new file mode 100644 index 000000000000..7f21a60f22bb --- /dev/null +++ b/packages/scope-manager/src/scope/TypeScope.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { ScopeManager } from '../ScopeManager'; + +class TypeScope extends ScopeBase< + ScopeType.type, + TSESTree.TSInterfaceDeclaration | TSESTree.TSTypeAliasDeclaration, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: TypeScope['upper'], + block: TypeScope['block'], + ) { + super(scopeManager, ScopeType.type, upperScope, block, false); + } +} + +export { TypeScope }; diff --git a/packages/scope-manager/src/scope/WithScope.ts b/packages/scope-manager/src/scope/WithScope.ts new file mode 100644 index 000000000000..84a3e4c76ff0 --- /dev/null +++ b/packages/scope-manager/src/scope/WithScope.ts @@ -0,0 +1,34 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { Scope } from './Scope'; +import { ScopeBase } from './ScopeBase'; +import { ScopeType } from './ScopeType'; +import { assert } from '../assert'; +import { ScopeManager } from '../ScopeManager'; + +class WithScope extends ScopeBase< + ScopeType.with, + TSESTree.WithStatement, + Scope +> { + constructor( + scopeManager: ScopeManager, + upperScope: WithScope['upper'], + block: WithScope['block'], + ) { + super(scopeManager, ScopeType.with, upperScope, block, false); + } + close(scopeManager: ScopeManager): Scope | null { + if (this.shouldStaticallyClose()) { + return super.close(scopeManager); + } + assert(this.leftToResolve); + for (let i = 0; i < this.leftToResolve.length; ++i) { + const ref = this.leftToResolve[i]; + this.delegateToUpperScope(ref); + } + this.leftToResolve = null; + return this.upper; + } +} + +export { WithScope }; diff --git a/packages/scope-manager/src/scope/index.ts b/packages/scope-manager/src/scope/index.ts new file mode 100644 index 000000000000..8e4683dbe68a --- /dev/null +++ b/packages/scope-manager/src/scope/index.ts @@ -0,0 +1,18 @@ +export * from './BlockScope'; +export * from './CatchScope'; +export * from './ClassScope'; +export * from './ConditionalTypeScope'; +export * from './ForScope'; +export * from './FunctionExpressionNameScope'; +export * from './FunctionScope'; +export * from './FunctionTypeScope'; +export * from './GlobalScope'; +export * from './MappedTypeScope'; +export * from './ModuleScope'; +export * from './Scope'; +export * from './ScopeType'; +export * from './SwitchScope'; +export * from './TSEnumScope'; +export * from './TSModuleScope'; +export * from './TypeScope'; +export * from './WithScope'; diff --git a/packages/scope-manager/tests/eslint-scope/README.md b/packages/scope-manager/tests/eslint-scope/README.md new file mode 100644 index 000000000000..1397ce3cd76a --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/README.md @@ -0,0 +1,13 @@ +# `scope-manager` `eslint-scope` Tests + +These tests are taken from the [`eslint-scope`](https://github.com/eslint/eslint-scope) package. +The intention is to help us ensure we do not regress functionality compared to the original package. + +They have been modified to: + +- be written in TypeScript +- work with jest +- work with our folder structure +- adhere to our formatting and linting style + +[The code was forked from `dbddf14d5771b21b5da704213e4508c660ca1c64`](https://github.com/eslint/eslint-scope/blob/dbddf14d5771b21b5da704213e4508c660ca1c64/tests/). diff --git a/packages/scope-manager/tests/eslint-scope/arguments.test.ts b/packages/scope-manager/tests/eslint-scope/arguments.test.ts new file mode 100644 index 000000000000..e3bbef8899f6 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/arguments.test.ts @@ -0,0 +1,29 @@ +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('arguments', () => { + it('arguments are correctly materialized', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + arguments; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].resolved).toBe(scope.variables[0]); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/catch-scope.test.ts b/packages/scope-manager/tests/eslint-scope/catch-scope.test.ts new file mode 100644 index 000000000000..bb3ad8f2b5f4 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/catch-scope.test.ts @@ -0,0 +1,48 @@ +import { + expectToBeBlockScope, + expectToBeCatchScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('catch', () => { + it('creates scope', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + try { + } catch (e) { + } + }()); + `); + + expect(scopeManager.scopes).toHaveLength(5); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[3]; + expectToBeCatchScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('e'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[4]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/child-visitor-keys.test.ts b/packages/scope-manager/tests/eslint-scope/child-visitor-keys.test.ts new file mode 100644 index 000000000000..8975dc5043d8 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/child-visitor-keys.test.ts @@ -0,0 +1,54 @@ +import { TSESTree } from '@typescript-eslint/types'; +import { parse } from '../util'; +import { analyze } from '../../src/analyze'; + +describe('childVisitorKeys option', () => { + it('should not visit to properties which are not given.', () => { + const ast = parse(` + let foo = bar; + `); + + const decl = ast.body[0] as TSESTree.VariableDeclaration; + decl.declarations[0].init = { + type: 'TestNode', + argument: decl.declarations[0].init, + } as never; + + const result = analyze(ast, { + childVisitorKeys: { + TestNode: [], + }, + }); + + expect(result.scopes).toHaveLength(1); + const globalScope = result.scopes[0]; + + // `bar` in TestNode has not been visited. + expect(globalScope.through).toHaveLength(0); + }); + + it('should visit to given properties.', () => { + const ast = parse(` + let foo = bar; + `); + + const decl = ast.body[0] as TSESTree.VariableDeclaration; + decl.declarations[0].init = { + type: 'TestNode', + argument: decl.declarations[0].init, + } as never; + + const result = analyze(ast, { + childVisitorKeys: { + TestNode: ['argument'], + }, + }); + + expect(result.scopes).toHaveLength(1); + const globalScope = result.scopes[0]; + + // `bar` in TestNode has been visited. + expect(globalScope.through).toHaveLength(1); + expect(globalScope.through[0].identifier.name).toBe('bar'); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-arrow-function-expression.test.ts b/packages/scope-manager/tests/eslint-scope/es6-arrow-function-expression.test.ts new file mode 100644 index 000000000000..3032af6726db --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-arrow-function-expression.test.ts @@ -0,0 +1,118 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 arrow function expression', () => { + it('materialize scope for arrow function expression', () => { + const { scopeManager } = parseAndAnalyze(` + var arrow = () => { + let i = 0; + var j = 20; + console.log(i); + } + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ArrowFunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(2); + + // There's no "arguments" + expect(scope.variables[0].name).toBe('i'); + expect(scope.variables[1].name).toBe('j'); + }); + + it('generate bindings for parameters', () => { + const { scopeManager } = parseAndAnalyze('var arrow = (a, b, c, d) => {}'); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ArrowFunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(4); + + // There's no "arguments" + expect(scope.variables[0].name).toBe('a'); + expect(scope.variables[1].name).toBe('b'); + expect(scope.variables[2].name).toBe('c'); + expect(scope.variables[3].name).toBe('d'); + }); + + it('inherits upper scope strictness', () => { + const { scopeManager } = parseAndAnalyze(` + "use strict"; + var arrow = () => {}; + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + + scope = scopeManager.scopes[1]; + + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ArrowFunctionExpression); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(0); + }); + + it('is strict when a strictness directive is used', () => { + const { scopeManager } = parseAndAnalyze(` + var arrow = () => { + "use strict"; + }; + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + + scope = scopeManager.scopes[1]; + + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ArrowFunctionExpression); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(0); + }); + + it('works with no body', () => { + const { scopeManager } = parseAndAnalyze('var arrow = a => a;'); + + expect(scopeManager.scopes).toHaveLength(2); + + const scope = scopeManager.scopes[1]; + + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ArrowFunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-block-scope.test.ts b/packages/scope-manager/tests/eslint-scope/es6-block-scope.test.ts new file mode 100644 index 000000000000..e2b51c0f9265 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-block-scope.test.ts @@ -0,0 +1,149 @@ +import { + expectToBeBlockScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 block scope', () => { + it('let is materialized in ES6 block scope#1', () => { + const { scopeManager } = parseAndAnalyze(` + { + let i = 20; + i; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // Program and BlockStatement scope. + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); // No variable in Program scope. + + scope = scopeManager.scopes[1]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(1); // `i` in block scope. + expect(scope.variables[0].name).toBe('i'); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[1].identifier.name).toBe('i'); + }); + + it('function delaration is materialized in ES6 block scope', () => { + const { scopeManager } = parseAndAnalyze(` + { + function test() { + } + test(); + } + `); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('test'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('test'); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + }); + + it('let is not hoistable#1', () => { + const { scopeManager } = parseAndAnalyze(` + var i = 42; (1) + { + i; // (2) ReferenceError at runtime. + let i = 20; // (2) + i; // (2) + } + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('i'); + expect(scope.references).toHaveLength(1); + + scope = scopeManager.scopes[1]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('i'); + expect(scope.references).toHaveLength(3); + expect(scope.references[0].resolved).toBe(scope.variables[0]); + expect(scope.references[1].resolved).toBe(scope.variables[0]); + expect(scope.references[2].resolved).toBe(scope.variables[0]); + }); + + it('let is not hoistable#2', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var i = 42; // (1) + i; // (1) + { + i; // (3) + { + i; // (2) + let i = 20; // (2) + i; // (2) + } + let i = 30; // (3) + i; // (3) + } + i; // (1) + }()); + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('i'); + const v1 = scope.variables[1]; + + expect(scope.references).toHaveLength(3); + expect(scope.references[0].resolved).toBe(v1); + expect(scope.references[1].resolved).toBe(v1); + expect(scope.references[2].resolved).toBe(v1); + + scope = scopeManager.scopes[2]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('i'); + const v3 = scope.variables[0]; + + expect(scope.references).toHaveLength(3); + expect(scope.references[0].resolved).toBe(v3); + expect(scope.references[1].resolved).toBe(v3); + expect(scope.references[2].resolved).toBe(v3); + + scope = scopeManager.scopes[3]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('i'); + const v2 = scope.variables[0]; + + expect(scope.references).toHaveLength(3); + expect(scope.references[0].resolved).toBe(v2); + expect(scope.references[1].resolved).toBe(v2); + expect(scope.references[2].resolved).toBe(v2); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-catch.test.ts b/packages/scope-manager/tests/eslint-scope/es6-catch.test.ts new file mode 100644 index 000000000000..906e8d8ba385 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-catch.test.ts @@ -0,0 +1,64 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeBlockScope, + expectToBeCatchScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 catch', () => { + it('takes binding pattern', () => { + const { scopeManager } = parseAndAnalyze(` + try { + } catch ({ a, b, c, d }) { + let e = 20; + a; + b; + c; + d; + } + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeBlockScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.BlockStatement); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeCatchScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.CatchClause); + expect(scope.isStrict).toBeFalsy(); + + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('a'); + expect(scope.variables[1].name).toBe('b'); + expect(scope.variables[2].name).toBe('c'); + expect(scope.variables[3].name).toBe('d'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[3]; + expectToBeBlockScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.BlockStatement); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables.map(variable => variable.name)).toEqual(['e']); + expect(scope.references.map(ref => ref.identifier.name)).toEqual([ + 'e', + 'a', + 'b', + 'c', + 'd', + ]); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-class.test.ts b/packages/scope-manager/tests/eslint-scope/es6-class.test.ts new file mode 100644 index 000000000000..1c56e4ed29ef --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-class.test.ts @@ -0,0 +1,171 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeClassScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 class', () => { + it('declaration name creates class scope', () => { + const { scopeManager } = parseAndAnalyze(` + class Derived extends Base { + constructor() { + } + } + new Derived(); + `); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('Derived'); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('Base'); + expect(scope.references[1].identifier.name).toBe('Derived'); + + scope = scopeManager.scopes[1]; + expectToBeClassScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ClassDeclaration); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('Derived'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + }); + + it('expression name creates class scope#1', () => { + const { scopeManager } = parseAndAnalyze(` + (class Derived extends Base { + constructor() { + } + }); + `); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('Base'); + + scope = scopeManager.scopes[1]; + expectToBeClassScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ClassExpression); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('Derived'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + }); + + it('expression name creates class scope#2', () => { + const { scopeManager } = parseAndAnalyze(` + (class extends Base { + constructor() { + } + }); + `); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('Base'); + + scope = scopeManager.scopes[1]; + expectToBeClassScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ClassExpression); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + }); + + it('computed property key may refer variables', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var yuyushiki = 42; + (class { + [yuyushiki]() { + } + + [yuyushiki + 40]() { + } + }); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(5); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('yuyushiki'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('yuyushiki'); + + scope = scopeManager.scopes[2]; + expectToBeClassScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.ClassExpression); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('yuyushiki'); + expect(scope.references[1].identifier.name).toBe('yuyushiki'); + }); + + it('regression #49', () => { + const { scopeManager } = parseAndAnalyze(` + class Shoe { + constructor() { + //Shoe.x = true; + } + } + let shoe = new Shoe(); + `); + + expect(scopeManager.scopes).toHaveLength(3); + + const scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('Shoe'); + expect(scope.variables[1].name).toBe('shoe'); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('shoe'); + expect(scope.references[1].identifier.name).toBe('Shoe'); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-default-parameters.test.ts b/packages/scope-manager/tests/eslint-scope/es6-default-parameters.test.ts new file mode 100644 index 000000000000..f9868a575d69 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-default-parameters.test.ts @@ -0,0 +1,338 @@ +import { parseAndAnalyze } from '../util'; + +function forEach( + obj: Record, + cb: (name: T) => void, +): void { + Object.keys(obj).forEach(name => { + cb(name as T); + }); +} + +describe('ES6 default parameters:', () => { + describe('a default parameter creates a writable reference for its initialization:', () => { + const patterns = { + FunctionDeclaration: 'function foo(a, b = 0) {}', + FunctionExpression: 'let foo = function(a, b = 0) {};', + ArrowExpression: 'let foo = (a, b = 0) => {};', + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const numVars = name === 'ArrowExpression' ? 2 : 3; + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(numVars); // [arguments?, a, b] + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('b'); + expect(reference.resolved).toBe(scope.variables[numVars - 1]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + }); + }); + + describe('a default parameter creates a readable reference for references in right:', () => { + const patterns = { + FunctionDeclaration: ` + let a; + function foo(b = a) {} + `, + FunctionExpression: ` + let a; + let foo = function(b = a) {} + `, + ArrowExpression: ` + let a; + let foo = (b = a) => {}; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const numVars = name === 'ArrowExpression' ? 1 : 2; + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(numVars); // [arguments?, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); + + describe('a default parameter creates a readable reference for references in right (for const):', () => { + const patterns = { + FunctionDeclaration: ` + const a = 0; + function foo(b = a) {} + `, + FunctionExpression: ` + const a = 0; + let foo = function(b = a) {} + `, + ArrowExpression: ` + const a = 0; + let foo = (b = a) => {}; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const numVars = name === 'ArrowExpression' ? 1 : 2; + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(numVars); // [arguments?, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); + + describe('a default parameter creates a readable reference for references in right (partial):', () => { + const patterns = { + FunctionDeclaration: ` + let a; + function foo(b = a.c) {} + `, + FunctionExpression: ` + let a; + let foo = function(b = a.c) {} + `, + ArrowExpression: ` + let a; + let foo = (b = a.c) => {}; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const numVars = name === 'ArrowExpression' ? 1 : 2; + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(numVars); // [arguments?, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); + + describe("a default parameter creates a readable reference for references in right's nested scope:", () => { + const patterns = { + FunctionDeclaration: ` + let a; + function foo(b = function() { return a; }) {} + `, + FunctionExpression: ` + let a; + let foo = function(b = function() { return a; }) {} + `, + ArrowExpression: ` + let a; + let foo = (b = function() { return a; }) => {}; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(3); // [global, foo, anonymous] + + const scope = scopeManager.scopes[2]; + + expect(scope.variables).toHaveLength(1); // [arguments] + expect(scope.references).toHaveLength(1); // [a] + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); + + describe("a default parameter creates a readable reference for references in right. It's resolved to outer scope's even if there is the variable in the function body:", () => { + const patterns = { + FunctionDeclaration: ` + let a; + function foo(b = a) { let a; } + `, + FunctionExpression: ` + let a; + let foo = function(b = a) { let a; } + `, + ArrowExpression: ` + let a; + let foo = (b = a) => { let a; }; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const numVars = name === 'ArrowExpression' ? 2 : 3; + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(numVars); // [arguments?, b, a] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); + + describe("a default parameter creates a readable reference for references in right. It's resolved to the parameter:", () => { + const patterns = { + FunctionDeclaration: ` + let a; + function foo(b = a, a) { } + `, + FunctionExpression: ` + let a; + let foo = function(b = a, a) { } + `, + ArrowExpression: ` + let a; + let foo = (b = a, a) => { }; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const numVars = name === 'ArrowExpression' ? 2 : 3; + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(numVars); // [arguments?, b, a] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe( + scope.variables[scope.variables.length - 1], + ); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); + + describe("a default parameter creates a readable reference for references in right (nested scope). It's resolved to outer scope's even if there is the variable in the function body:", () => { + const patterns = { + FunctionDeclaration: ` + let a; + function foo(b = function(){ a }) { let a; } + `, + FunctionExpression: ` + let a; + let foo = function(b = function(){ a }) { let a; } + `, + ArrowExpression: ` + let a; + let foo = (b = function(){ a }) => { let a; }; + `, + }; + + forEach(patterns, name => { + const code = patterns[name]; + + it(name, () => { + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes).toHaveLength(3); // [global, foo, anonymous function] + + const scope = scopeManager.scopes[2]; + + expect(scope.references).toHaveLength(1); // [a] + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-destructuring-assignments.test.ts b/packages/scope-manager/tests/eslint-scope/es6-destructuring-assignments.test.ts new file mode 100644 index 000000000000..53837e27cd71 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-destructuring-assignments.test.ts @@ -0,0 +1,1179 @@ +import { + expectToBeForScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeIdentifier, + expectToBeParameterDefinition, + parseAndAnalyze, +} from '../util'; + +describe('ES6 destructuring assignments', () => { + it('Pattern in var in ForInStatement', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + for (var [a, b, c] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('c'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[3]); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + }); + + it('Pattern in let in ForInStatement', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + for (let [a, b, c] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(3); // [global, function, for] + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[2]; + expectToBeForScope(scope); + expect(scope.variables).toHaveLength(3); + expect(scope.variables[0].name).toBe('a'); + expect(scope.variables[1].name).toBe('b'); + expect(scope.variables[2].name).toBe('c'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[0]); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[1]); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[2]); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + expect(scope.references[3].resolved).toBeNull(); + }); + + it('Pattern with default values in var in ForInStatement', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + for (var [a, b, c = d] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(2); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('d'); + expect(scope['implicit'].leftToBeResolved[1].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('c'); + expect(scope.references).toHaveLength(6); + expect(scope.references[0].identifier.name).toBe('c'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[0].writeExpr); + expect(scope.references[0].writeExpr.name).toBe('d'); + expect(scope.references[0].resolved).toBe(scope.variables[3]); + expect(scope.references[1].identifier.name).toBe('d'); + expect(scope.references[1].isWrite()).toBeFalsy(); + expect(scope.references[2].identifier.name).toBe('a'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[1]); + expect(scope.references[3].identifier.name).toBe('b'); + expect(scope.references[3].isWrite()).toBeTruthy(); + expect(scope.references[3].resolved).toBe(scope.variables[2]); + expect(scope.references[4].identifier.name).toBe('c'); + expect(scope.references[4].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[4].writeExpr); + expect(scope.references[4].writeExpr.name).toBe('array'); + expect(scope.references[4].resolved).toBe(scope.variables[3]); + expect(scope.references[5].identifier.name).toBe('array'); + expect(scope.references[5].isWrite()).toBeFalsy(); + }); + + it('Pattern with default values in let in ForInStatement', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + for (let [a, b, c = d] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(3); // [global, function, for] + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(2); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('d'); + expectToBeForScope(scope['implicit'].leftToBeResolved[0].from); + expect(scope['implicit'].leftToBeResolved[1].identifier.name).toBe('array'); + expectToBeForScope(scope['implicit'].leftToBeResolved[1].from); + + scope = scopeManager.scopes[2]; + expectToBeForScope(scope); + expect(scope.variables).toHaveLength(3); + expect(scope.variables[0].name).toBe('a'); + expect(scope.variables[1].name).toBe('b'); + expect(scope.variables[2].name).toBe('c'); + expect(scope.references).toHaveLength(6); + expect(scope.references[0].identifier.name).toBe('c'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[0].writeExpr); + expect(scope.references[0].writeExpr.name).toBe('d'); + expect(scope.references[0].resolved).toBe(scope.variables[2]); + expect(scope.references[1].identifier.name).toBe('d'); + expect(scope.references[1].isWrite()).toBeFalsy(); + expect(scope.references[2].identifier.name).toBe('a'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[2].writeExpr); + expect(scope.references[2].writeExpr.name).toBe('array'); + expect(scope.references[2].resolved).toBe(scope.variables[0]); + expect(scope.references[3].identifier.name).toBe('b'); + expect(scope.references[3].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[3].writeExpr); + expect(scope.references[3].writeExpr.name).toBe('array'); + expect(scope.references[3].resolved).toBe(scope.variables[1]); + expect(scope.references[4].identifier.name).toBe('c'); + expect(scope.references[4].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[4].writeExpr); + expect(scope.references[4].writeExpr.name).toBe('array'); + expect(scope.references[4].resolved).toBe(scope.variables[2]); + expect(scope.references[5].identifier.name).toBe('array'); + expect(scope.references[5].isWrite()).toBeFalsy(); + expect(scope.references[5].resolved).toBeNull(); + }); + + it('Pattern with nested default values in var in ForInStatement', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + for (var [a, [b, c = d] = e] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(3); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('d'); + expect(scope['implicit'].leftToBeResolved[1].identifier.name).toBe('e'); + expect(scope['implicit'].leftToBeResolved[2].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('c'); + expect(scope.references).toHaveLength(9); + expect(scope.references[0].identifier.name).toBe('b'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[0].writeExpr); + expect(scope.references[0].writeExpr.name).toBe('e'); + expect(scope.references[0].resolved).toBe(scope.variables[2]); + expect(scope.references[1].identifier.name).toBe('c'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[1].writeExpr); + expect(scope.references[1].writeExpr.name).toBe('e'); + expect(scope.references[1].resolved).toBe(scope.variables[3]); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[2].writeExpr); + expect(scope.references[2].writeExpr.name).toBe('d'); + expect(scope.references[2].resolved).toBe(scope.variables[3]); + expect(scope.references[3].identifier.name).toBe('d'); + expect(scope.references[3].isWrite()).toBeFalsy(); + expect(scope.references[4].identifier.name).toBe('e'); + expect(scope.references[4].isWrite()).toBeFalsy(); + expect(scope.references[5].identifier.name).toBe('a'); + expect(scope.references[5].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[5].writeExpr); + expect(scope.references[5].writeExpr.name).toBe('array'); + expect(scope.references[5].resolved).toBe(scope.variables[1]); + expect(scope.references[6].identifier.name).toBe('b'); + expect(scope.references[6].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[6].writeExpr); + expect(scope.references[6].writeExpr.name).toBe('array'); + expect(scope.references[6].resolved).toBe(scope.variables[2]); + expect(scope.references[7].identifier.name).toBe('c'); + expect(scope.references[7].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[7].writeExpr); + expect(scope.references[7].writeExpr.name).toBe('array'); + expect(scope.references[7].resolved).toBe(scope.variables[3]); + expect(scope.references[8].identifier.name).toBe('array'); + expect(scope.references[8].isWrite()).toBeFalsy(); + }); + + it('Pattern with nested default values in let in ForInStatement', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + for (let [a, [b, c = d] = e] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(3); // [global, function, for] + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(3); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('d'); + expectToBeForScope(scope['implicit'].leftToBeResolved[0].from); + expect(scope['implicit'].leftToBeResolved[1].identifier.name).toBe('e'); + expectToBeForScope(scope['implicit'].leftToBeResolved[1].from); + expect(scope['implicit'].leftToBeResolved[2].identifier.name).toBe('array'); + expectToBeForScope(scope['implicit'].leftToBeResolved[2].from); + + scope = scopeManager.scopes[2]; + expectToBeForScope(scope); + expect(scope.variables).toHaveLength(3); + expect(scope.variables[0].name).toBe('a'); + expect(scope.variables[1].name).toBe('b'); + expect(scope.variables[2].name).toBe('c'); + expect(scope.references).toHaveLength(9); + expect(scope.references[0].identifier.name).toBe('b'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[0].writeExpr); + expect(scope.references[0].writeExpr.name).toBe('e'); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('c'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[1].writeExpr); + expect(scope.references[1].writeExpr.name).toBe('e'); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[2].writeExpr); + expect(scope.references[2].writeExpr.name).toBe('d'); + expect(scope.references[2].resolved).toBe(scope.variables[2]); + expect(scope.references[3].identifier.name).toBe('d'); + expect(scope.references[3].isWrite()).toBeFalsy(); + expect(scope.references[4].identifier.name).toBe('e'); + expect(scope.references[4].isWrite()).toBeFalsy(); + expect(scope.references[5].identifier.name).toBe('a'); + expect(scope.references[5].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[5].writeExpr); + expect(scope.references[5].writeExpr.name).toBe('array'); + expect(scope.references[5].resolved).toBe(scope.variables[0]); + expect(scope.references[6].identifier.name).toBe('b'); + expect(scope.references[6].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[6].writeExpr); + expect(scope.references[6].writeExpr.name).toBe('array'); + expect(scope.references[6].resolved).toBe(scope.variables[1]); + expect(scope.references[7].identifier.name).toBe('c'); + expect(scope.references[7].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[7].writeExpr); + expect(scope.references[7].writeExpr.name).toBe('array'); + expect(scope.references[7].resolved).toBe(scope.variables[2]); + expect(scope.references[8].identifier.name).toBe('array'); + expect(scope.references[8].isWrite()).toBeFalsy(); + expect(scope.references[8].resolved).toBeNull(); + }); + + it('Pattern with default values in var in ForInStatement (separate declarations)', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var a, b, c; + for ([a, b, c = d] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(2); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('d'); + expect(scope['implicit'].leftToBeResolved[1].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('c'); + expect(scope.references).toHaveLength(6); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[2].writeExpr); + expect(scope.references[2].writeExpr.name).toBe('d'); + expect(scope.references[2].resolved).toBe(scope.variables[3]); + expect(scope.references[3].identifier.name).toBe('c'); + expect(scope.references[3].isWrite()).toBeTruthy(); + expectToBeIdentifier(scope.references[3].writeExpr); + expect(scope.references[3].writeExpr.name).toBe('array'); + expect(scope.references[3].resolved).toBe(scope.variables[3]); + expect(scope.references[4].identifier.name).toBe('d'); + expect(scope.references[4].isWrite()).toBeFalsy(); + expect(scope.references[5].identifier.name).toBe('array'); + expect(scope.references[5].isWrite()).toBeFalsy(); + }); + + it('Pattern with default values in var in ForInStatement (separate declarations and with MemberExpression)', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var obj; + for ([obj.a, obj.b, obj.c = d] in array); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(2); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('d'); + expect(scope['implicit'].leftToBeResolved[1].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('obj'); + expect(scope.references).toHaveLength(5); + expect(scope.references[0].identifier.name).toBe('obj'); // obj.a + expect(scope.references[0].isWrite()).toBeFalsy(); + expect(scope.references[0].isRead()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('obj'); // obj.b + expect(scope.references[1].isWrite()).toBeFalsy(); + expect(scope.references[1].isRead()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[1]); + expect(scope.references[2].identifier.name).toBe('obj'); // obj.c + expect(scope.references[2].isWrite()).toBeFalsy(); + expect(scope.references[2].isRead()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[1]); + expect(scope.references[3].identifier.name).toBe('d'); + expect(scope.references[3].isWrite()).toBeFalsy(); + expect(scope.references[3].isRead()).toBeTruthy(); + expect(scope.references[4].identifier.name).toBe('array'); + expect(scope.references[4].isWrite()).toBeFalsy(); + expect(scope.references[4].isRead()).toBeTruthy(); + }); + + it('ArrayPattern in var', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var [a, b, c] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('c'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[3]); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + }); + + it('SpreadElement in var', () => { + let { scopeManager } = parseAndAnalyze(` + (function () { + var [a, b, ...rest] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('rest'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + expect(scope.references[2].identifier.name).toBe('rest'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[3]); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + + ({ scopeManager } = parseAndAnalyze(` + (function () { + var [a, b, ...[c, d, ...rest]] = array; + }()); + `)); + + expect(scopeManager.scopes).toHaveLength(2); + + scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + + expect(scope.variables).toHaveLength(6); + const expectedVariableNames = ['arguments', 'a', 'b', 'c', 'd', 'rest']; + + for (let index = 0; index < expectedVariableNames.length; index++) { + expect(scope.variables[index].name).toBe(expectedVariableNames[index]); + } + + expect(scope.references).toHaveLength(6); + const expectedReferenceNames = ['a', 'b', 'c', 'd', 'rest']; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + expect(scope.references[index].isWrite()).toBeTruthy(); + } + expect(scope.references[5].identifier.name).toBe('array'); + expect(scope.references[5].isWrite()).toBeFalsy(); + }); + + it('ObjectPattern in var', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var { + shorthand, + key: value, + hello: { + world + } + } = object; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe( + 'object', + ); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('shorthand'); + expect(scope.variables[2].name).toBe('value'); + expect(scope.variables[3].name).toBe('world'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('shorthand'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('value'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + expect(scope.references[2].identifier.name).toBe('world'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[3]); + expect(scope.references[3].identifier.name).toBe('object'); + expect(scope.references[3].isWrite()).toBeFalsy(); + }); + + it('complex pattern in var', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var { + shorthand, + key: [ a, b, c, d, e ], + hello: { + world + } + } = object; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe( + 'object', + ); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(8); + const expectedVariableNames = [ + 'arguments', + 'shorthand', + 'a', + 'b', + 'c', + 'd', + 'e', + 'world', + ]; + + for (let index = 0; index < expectedVariableNames.length; index++) { + expect(scope.variables[index].name).toBe(expectedVariableNames[index]); + } + expect(scope.references).toHaveLength(8); + const expectedReferenceNames = [ + 'shorthand', + 'a', + 'b', + 'c', + 'd', + 'e', + 'world', + ]; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + expect(scope.references[index].isWrite()).toBeTruthy(); + } + expect(scope.references[7].identifier.name).toBe('object'); + expect(scope.references[7].isWrite()).toBeFalsy(); + }); + + it('ArrayPattern in AssignmentExpression', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + [a, b, c] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(4); + expect( + scope['implicit'].leftToBeResolved.map(left => left.identifier.name), + ).toEqual(['a', 'b', 'c', 'array']); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBeNull(); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBeNull(); + expect(scope.references[2].identifier.name).toBe('c'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBeNull(); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + }); + + it('ArrayPattern with MemberExpression in AssignmentExpression', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var obj; + [obj.a, obj.b, obj.c] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('obj'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('obj'); + expect(scope.references[0].isWrite()).toBeFalsy(); + expect(scope.references[0].isRead()).toBeTruthy(); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('obj'); + expect(scope.references[1].isWrite()).toBeFalsy(); + expect(scope.references[1].isRead()).toBeTruthy(); + expect(scope.references[1].resolved).toBe(scope.variables[1]); + expect(scope.references[2].identifier.name).toBe('obj'); + expect(scope.references[2].isWrite()).toBeFalsy(); + expect(scope.references[2].isRead()).toBeTruthy(); + expect(scope.references[2].resolved).toBe(scope.variables[1]); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + expect(scope.references[3].isRead()).toBeTruthy(); + }); + + it('SpreadElement in AssignmentExpression', () => { + let { scopeManager } = parseAndAnalyze(` + (function () { + [a, b, ...rest] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(4); + expect( + scope['implicit'].leftToBeResolved.map(left => left.identifier.name), + ).toEqual(['a', 'b', 'rest', 'array']); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBeNull(); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBeNull(); + expect(scope.references[2].identifier.name).toBe('rest'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBeNull(); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + + ({ scopeManager } = parseAndAnalyze(` + (function () { + [a, b, ...[c, d, ...rest]] = array; + }()); + `)); + + expect(scopeManager.scopes).toHaveLength(2); + + scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(6); + expect( + scope['implicit'].leftToBeResolved.map(left => left.identifier.name), + ).toEqual(['a', 'b', 'c', 'd', 'rest', 'array']); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + + expect(scope.references).toHaveLength(6); + const expectedReferenceNames = ['a', 'b', 'c', 'd', 'rest']; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + expect(scope.references[index].isWrite()).toBeTruthy(); + expect(scope.references[index].resolved).toBeNull(); + } + expect(scope.references[5].identifier.name).toBe('array'); + expect(scope.references[5].isWrite()).toBeFalsy(); + }); + + it('SpreadElement with MemberExpression in AssignmentExpression', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + [a, b, ...obj.rest] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(4); + expect( + scope['implicit'].leftToBeResolved.map(left => left.identifier.name), + ).toEqual(['a', 'b', 'obj', 'array']); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('a'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBeNull(); + expect(scope.references[1].identifier.name).toBe('b'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBeNull(); + expect(scope.references[2].identifier.name).toBe('obj'); + expect(scope.references[2].isWrite()).toBeFalsy(); + expect(scope.references[3].identifier.name).toBe('array'); + expect(scope.references[3].isWrite()).toBeFalsy(); + }); + + it('ObjectPattern in AssignmentExpression', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + ({ + shorthand, + key: value, + hello: { + world + } + } = object); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(4); + expect( + scope['implicit'].leftToBeResolved.map(left => left.identifier.name), + ).toEqual(['shorthand', 'value', 'world', 'object']); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('shorthand'); + expect(scope.references[0].isWrite()).toBeTruthy(); + expect(scope.references[0].resolved).toBeNull(); + expect(scope.references[1].identifier.name).toBe('value'); + expect(scope.references[1].isWrite()).toBeTruthy(); + expect(scope.references[1].resolved).toBeNull(); + expect(scope.references[2].identifier.name).toBe('world'); + expect(scope.references[2].isWrite()).toBeTruthy(); + expect(scope.references[2].resolved).toBeNull(); + expect(scope.references[3].identifier.name).toBe('object'); + expect(scope.references[3].isWrite()).toBeFalsy(); + }); + + it('complex pattern in AssignmentExpression', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + ({ + shorthand, + key: [ a, b, c, d, e ], + hello: { + world + } + } = object); + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + expect(scope['implicit'].leftToBeResolved).toHaveLength(8); + expect( + scope['implicit'].leftToBeResolved.map(left => left.identifier.name), + ).toEqual(['shorthand', 'a', 'b', 'c', 'd', 'e', 'world', 'object']); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(8); + const expectedReferenceNames = [ + 'shorthand', + 'a', + 'b', + 'c', + 'd', + 'e', + 'world', + ]; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + expect(scope.references[index].isWrite()).toBeTruthy(); + } + expect(scope.references[7].identifier.name).toBe('object'); + expect(scope.references[7].isWrite()).toBeFalsy(); + }); + + it('ArrayPattern in parameters', () => { + const { scopeManager } = parseAndAnalyze(` + (function ([a, b, c]) { + }(array)); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('array'); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('c'); + expect(scope.references).toHaveLength(0); + }); + + it('SpreadElement in parameters', () => { + const { scopeManager } = parseAndAnalyze(` + (function ([a, b, ...rest], ...rest2) { + }(array)); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('array'); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe('array'); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(5); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('a'); + expect(scope.variables[2].name).toBe('b'); + expect(scope.variables[3].name).toBe('rest'); + expectToBeParameterDefinition(scope.variables[3].defs[0]); + expect(scope.variables[3].defs[0].rest).toBeTruthy(); + expect(scope.variables[4].name).toBe('rest2'); + expectToBeParameterDefinition(scope.variables[4].defs[0]); + expect(scope.variables[4].defs[0].rest).toBeTruthy(); + expect(scope.references).toHaveLength(0); + }); + + it('ObjectPattern in parameters', () => { + const { scopeManager } = parseAndAnalyze(` + (function ({ + shorthand, + key: value, + hello: { + world + } + }) { } (object)); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('object'); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe( + 'object', + ); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(4); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('shorthand'); + expect(scope.variables[2].name).toBe('value'); + expect(scope.variables[3].name).toBe('world'); + expect(scope.references).toHaveLength(0); + }); + + it('complex pattern in parameters', () => { + const { scopeManager } = parseAndAnalyze(` + (function ({ + shorthand, + key: [ a, b, c, d, e ], + hello: { + world + } + }) { } (object)); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('object'); + expect(scope['implicit'].leftToBeResolved).toHaveLength(1); + expect(scope['implicit'].leftToBeResolved[0].identifier.name).toBe( + 'object', + ); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(8); + const expectedVariableNames = [ + 'arguments', + 'shorthand', + 'a', + 'b', + 'c', + 'd', + 'e', + 'world', + ]; + + for (let index = 0; index < expectedVariableNames.length; index++) { + expect(scope.variables[index].name).toBe(expectedVariableNames[index]); + } + expect(scope.references).toHaveLength(0); + }); + + it('default values and patterns in var', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var [a, b, c, d = 20 ] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(5); + const expectedVariableNames = ['arguments', 'a', 'b', 'c', 'd']; + + for (let index = 0; index < expectedVariableNames.length; index++) { + expect(scope.variables[index].name).toBe(expectedVariableNames[index]); + } + expect(scope.references).toHaveLength(6); + const expectedReferenceNames = [ + 'a', + 'b', + 'c', + 'd', // assign 20 + 'd', // assign array + 'array', + ]; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + } + }); + + it('default values containing references and patterns in var', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var [a, b, c, d = e ] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(5); + const expectedVariableNames = ['arguments', 'a', 'b', 'c', 'd']; + + for (let index = 0; index < expectedVariableNames.length; index++) { + expect(scope.variables[index].name).toBe(expectedVariableNames[index]); + } + expect(scope.references).toHaveLength(7); + const expectedReferenceNames = [ + 'a', // assign array + 'b', // assign array + 'c', // assign array + 'd', // assign e + 'd', // assign array + 'e', + 'array', + ]; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + } + }); + + it('nested default values containing references and patterns in var', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var [a, b, [c, d = e] = f ] = array; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(5); + const expectedVariableNames = ['arguments', 'a', 'b', 'c', 'd']; + + for (let index = 0; index < expectedVariableNames.length; index++) { + expect(scope.variables[index].name).toBe(expectedVariableNames[index]); + } + expect(scope.references).toHaveLength(10); + const expectedReferenceNames = [ + 'a', // assign array + 'b', // assign array + 'c', // assign f + 'c', // assign array + 'd', // assign f + 'd', // assign e + 'd', // assign array + 'e', + 'f', + 'array', + ]; + + for (let index = 0; index < expectedReferenceNames.length; index++) { + expect(scope.references[index].identifier.name).toBe( + expectedReferenceNames[index], + ); + } + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-export.test.ts b/packages/scope-manager/tests/eslint-scope/es6-export.test.ts new file mode 100644 index 000000000000..a172721a28f2 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-export.test.ts @@ -0,0 +1,193 @@ +import { + expectToBeFunctionNameDefinition, + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeModuleScope, + expectToBeVariableDefinition, + parseAndAnalyze, +} from '../util'; + +describe('export declaration', () => { + // http://people.mozilla.org/~jorendorff/es6-draft.html#sec-static-and-runtme-semantics-module-records + it('should create variable bindings', () => { + const { scopeManager } = parseAndAnalyze('export var v;', 'module'); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('v'); + expectToBeVariableDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + }); + + it('should create function declaration bindings', () => { + const { scopeManager } = parseAndAnalyze( + 'export default function f(){};', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('f'); + expectToBeFunctionNameDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + }); + + it('should export function expression', () => { + const { scopeManager } = parseAndAnalyze( + 'export default function(){};', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + }); + + it('should export literal', () => { + const { scopeManager } = parseAndAnalyze('export default 42;', 'module'); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + }); + + it('should refer exported references#1', () => { + const { scopeManager } = parseAndAnalyze( + 'const x = 1; export {x};', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('x'); + expect(scope.references[1].identifier.name).toBe('x'); + }); + + it('should refer exported references#2', () => { + const { scopeManager } = parseAndAnalyze( + 'const v = 1; export {v as x};', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('v'); + expect(scope.references[1].identifier.name).toBe('v'); + }); + + it('should not refer exported references from other source#1', () => { + const { scopeManager } = parseAndAnalyze( + 'export {x} from "mod";', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + }); + + it('should not refer exported references from other source#2', () => { + const { scopeManager } = parseAndAnalyze( + 'export {v as x} from "mod";', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + }); + + it('should not refer exported references from other source#3', () => { + const { scopeManager } = parseAndAnalyze('export * from "mod";', 'module'); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-import.test.ts b/packages/scope-manager/tests/eslint-scope/es6-import.test.ts new file mode 100644 index 000000000000..7edd7fd638a7 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-import.test.ts @@ -0,0 +1,134 @@ +import { parseAndAnalyze } from '../util/parse'; +import { + expectToBeGlobalScope, + expectToBeImportBindingDefinition, + expectToBeModuleScope, + expectToBeVariableDefinition, +} from '../util'; + +describe('import declaration', () => { + // http://people.mozilla.org/~jorendorff/es6-draft.html#sec-static-and-runtme-semantics-module-records + it('should import names from source', () => { + const { scopeManager } = parseAndAnalyze('import v from "mod";', 'module'); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('v'); + expectToBeImportBindingDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + }); + + it('should import namespaces', () => { + const { scopeManager } = parseAndAnalyze( + 'import * as ns from "mod";', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('ns'); + expectToBeImportBindingDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + }); + + it('should import insided names#1', () => { + const { scopeManager } = parseAndAnalyze( + 'import {x} from "mod";', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('x'); + expectToBeImportBindingDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + }); + + it('should import insided names#2', () => { + const { scopeManager } = parseAndAnalyze( + 'import {x as v} from "mod";', + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('v'); + expectToBeImportBindingDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + }); + + it('should reference imports', () => { + const imports = [ + 'import v from "mod";', + 'import { v } from "mod";', + 'import * as v from "mod";', + ]; + for (const code of imports) { + const { scopeManager } = parseAndAnalyze( + ` + ${code} + const x = v; + `, + 'module', + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(2); + const importV = scope.variables[0]; + expect(importV.name).toBe('v'); + expectToBeImportBindingDefinition(importV.defs[0]); + const variableX = scope.variables[1]; + expect(variableX.name).toBe('x'); + expectToBeVariableDefinition(variableX.defs[0]); + + expect(scope.references).toHaveLength(2); + expect(scope.references[0].resolved).toBe(variableX); + expect(scope.references[1].resolved).toBe(importV); + } + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-iteration-scope.test.ts b/packages/scope-manager/tests/eslint-scope/es6-iteration-scope.test.ts new file mode 100644 index 000000000000..4bd4a6c91797 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-iteration-scope.test.ts @@ -0,0 +1,180 @@ +import { + expectToBeBlockScope, + expectToBeForScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeVariableDefinition, + parseAndAnalyze, +} from '../util'; + +describe('ES6 iteration scope', () => { + it('let materialize iteration scope for ForInStatement#1', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + let i = 20; + for (let i in i) { + console.log(i); + } + }()); + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('i'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + + const iterScope = (scope = scopeManager.scopes[2]); + + expectToBeForScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('i'); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[0].resolved).toBe(scope.variables[0]); + expect(scope.references[1].identifier.name).toBe('i'); + expect(scope.references[1].resolved).toBe(scope.variables[0]); + + scope = scopeManager.scopes[3]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('console'); + expect(scope.references[0].resolved).toBe(null); + expect(scope.references[1].identifier.name).toBe('i'); + expect(scope.references[1].resolved).toBe(iterScope.variables[0]); + }); + + it('let materialize iteration scope for ForInStatement#2', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + let i = 20; + for (let { i, j, k } in i) { + console.log(i); + } + }()); + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('i'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + + const iterScope = (scope = scopeManager.scopes[2]); + + expectToBeForScope(scope); + expect(scope.variables).toHaveLength(3); + expect(scope.variables[0].name).toBe('i'); + expect(scope.variables[1].name).toBe('j'); + expect(scope.variables[2].name).toBe('k'); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[0].resolved).toBe(scope.variables[0]); + expect(scope.references[1].identifier.name).toBe('j'); + expect(scope.references[1].resolved).toBe(scope.variables[1]); + expect(scope.references[2].identifier.name).toBe('k'); + expect(scope.references[2].resolved).toBe(scope.variables[2]); + expect(scope.references[3].identifier.name).toBe('i'); + expect(scope.references[3].resolved).toBe(scope.variables[0]); + + scope = scopeManager.scopes[3]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('console'); + expect(scope.references[0].resolved).toBe(null); + expect(scope.references[1].identifier.name).toBe('i'); + expect(scope.references[1].resolved).toBe(iterScope.variables[0]); + }); + + it('let materialize iteration scope for ForStatement#2', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + let i = 20; + let obj = {}; + for (let { i, j, k } = obj; i < okok; ++i) { + console.log(i, j, k); + } + }()); + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + + const functionScope = (scope = scopeManager.scopes[1]); + + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(3); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('i'); + expect(scope.variables[2].name).toBe('obj'); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[0].resolved).toBe(scope.variables[1]); + expect(scope.references[1].identifier.name).toBe('obj'); + expect(scope.references[1].resolved).toBe(scope.variables[2]); + + const iterScope = (scope = scopeManager.scopes[2]); + + expectToBeForScope(scope); + expect(scope.variables).toHaveLength(3); + expect(scope.variables[0].name).toBe('i'); + expectToBeVariableDefinition(scope.variables[0].defs[0]); + expect(scope.variables[1].name).toBe('j'); + expectToBeVariableDefinition(scope.variables[1].defs[0]); + expect(scope.variables[2].name).toBe('k'); + expectToBeVariableDefinition(scope.variables[2].defs[0]); + expect(scope.references).toHaveLength(7); + expect(scope.references[0].identifier.name).toBe('i'); + expect(scope.references[0].resolved).toBe(scope.variables[0]); + expect(scope.references[1].identifier.name).toBe('j'); + expect(scope.references[1].resolved).toBe(scope.variables[1]); + expect(scope.references[2].identifier.name).toBe('k'); + expect(scope.references[2].resolved).toBe(scope.variables[2]); + expect(scope.references[3].identifier.name).toBe('obj'); + expect(scope.references[3].resolved).toBe(functionScope.variables[2]); + expect(scope.references[4].identifier.name).toBe('i'); + expect(scope.references[4].resolved).toBe(scope.variables[0]); + expect(scope.references[5].identifier.name).toBe('okok'); + expect(scope.references[5].resolved).toBeNull(); + expect(scope.references[6].identifier.name).toBe('i'); + expect(scope.references[6].resolved).toBe(scope.variables[0]); + + scope = scopeManager.scopes[3]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(4); + expect(scope.references[0].identifier.name).toBe('console'); + expect(scope.references[0].resolved).toBeNull(); + expect(scope.references[1].identifier.name).toBe('i'); + expect(scope.references[1].resolved).toBe(iterScope.variables[0]); + expect(scope.references[2].identifier.name).toBe('j'); + expect(scope.references[2].resolved).toBe(iterScope.variables[1]); + expect(scope.references[3].identifier.name).toBe('k'); + expect(scope.references[3].resolved).toBe(iterScope.variables[2]); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-new-target.test.ts b/packages/scope-manager/tests/eslint-scope/es6-new-target.test.ts new file mode 100644 index 000000000000..097eee3d98e7 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-new-target.test.ts @@ -0,0 +1,25 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { expectToBeFunctionScope, parseAndAnalyze } from '../util'; + +describe('ES6 new.target', () => { + it('should not make references of new.target', () => { + const { scopeManager } = parseAndAnalyze(` + class A { + constructor() { + new.target; + } + } + `); + + expect(scopeManager.scopes).toHaveLength(3); + + const scope = scopeManager.scopes[2]; + + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-object.test.ts b/packages/scope-manager/tests/eslint-scope/es6-object.test.ts new file mode 100644 index 000000000000..77312f7a7ccd --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-object.test.ts @@ -0,0 +1,66 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 object', () => { + it('method definition', () => { + const { scopeManager } = parseAndAnalyze(` + ({ + constructor() { + } + }) + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + }); + + it('computed property key may refer variables', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + var yuyushiki = 42; + ({ + [yuyushiki]() { + }, + + [yuyushiki + 40]() { + } + }) + }()); + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('yuyushiki'); + expect(scope.references).toHaveLength(3); + expect(scope.references[0].identifier.name).toBe('yuyushiki'); + expect(scope.references[1].identifier.name).toBe('yuyushiki'); + expect(scope.references[2].identifier.name).toBe('yuyushiki'); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-rest-args.test.ts b/packages/scope-manager/tests/eslint-scope/es6-rest-args.test.ts new file mode 100644 index 000000000000..a96f740d4e86 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-rest-args.test.ts @@ -0,0 +1,36 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeIdentifier, + expectToBeParameterDefinition, + parseAndAnalyze, +} from '../util'; + +describe('ES6 rest arguments', () => { + it('materialize rest argument in scope', () => { + const { scopeManager } = parseAndAnalyze(` + function foo(...bar) { + return bar; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('bar'); + expectToBeIdentifier(scope.variables[1].defs[0].name); + expect(scope.variables[1].defs[0].name.name).toBe('bar'); + expectToBeParameterDefinition(scope.variables[1].defs[0]); + expect(scope.variables[1].defs[0].rest).toBeTruthy(); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-super.test.ts b/packages/scope-manager/tests/eslint-scope/es6-super.test.ts new file mode 100644 index 000000000000..f0ab3383a067 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-super.test.ts @@ -0,0 +1,49 @@ +import { + expectToBeClassScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 super', () => { + it('is not handled as reference', () => { + const { scopeManager } = parseAndAnalyze(` + class Foo extends Bar { + constructor() { + super(); + } + + method() { + super.method(); + } + } + `); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('Foo'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('Bar'); + + scope = scopeManager.scopes[1]; + expectToBeClassScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('Foo'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); // super is specially handled like `this`. + + scope = scopeManager.scopes[3]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); // super is specially handled like `this`. + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-switch.test.ts b/packages/scope-manager/tests/eslint-scope/es6-switch.test.ts new file mode 100644 index 000000000000..430a17b8a790 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-switch.test.ts @@ -0,0 +1,47 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeGlobalScope, + expectToBeSwitchScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 switch', () => { + it('materialize scope', () => { + const { scopeManager } = parseAndAnalyze(` + switch (ok) { + case hello: + let i = 20; + i; + break; + + default: + let test = 30; + test; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('ok'); + + scope = scopeManager.scopes[1]; + expectToBeSwitchScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.SwitchStatement); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('i'); + expect(scope.variables[1].name).toBe('test'); + expect(scope.references).toHaveLength(5); + expect(scope.references[0].identifier.name).toBe('hello'); + expect(scope.references[1].identifier.name).toBe('i'); + expect(scope.references[2].identifier.name).toBe('i'); + expect(scope.references[3].identifier.name).toBe('test'); + expect(scope.references[4].identifier.name).toBe('test'); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/es6-template-literal.test.ts b/packages/scope-manager/tests/eslint-scope/es6-template-literal.test.ts new file mode 100644 index 000000000000..91521c39b71a --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/es6-template-literal.test.ts @@ -0,0 +1,46 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('ES6 template literal', () => { + it('refer variables', () => { + const { scopeManager } = parseAndAnalyze(` + (function () { + let i, j, k; + function testing() { } + let template = testing\`testing \${i} and \${j}\` + return template; + }()); + `); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionExpression); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(6); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('i'); + expect(scope.variables[2].name).toBe('j'); + expect(scope.variables[3].name).toBe('k'); + expect(scope.variables[4].name).toBe('testing'); + expect(scope.variables[5].name).toBe('template'); + expect(scope.references).toHaveLength(5); + expect(scope.references[0].identifier.name).toBe('template'); + expect(scope.references[1].identifier.name).toBe('testing'); + expect(scope.references[2].identifier.name).toBe('i'); + expect(scope.references[3].identifier.name).toBe('j'); + expect(scope.references[4].identifier.name).toBe('template'); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/function-expression-name.test.ts b/packages/scope-manager/tests/eslint-scope/function-expression-name.test.ts new file mode 100644 index 000000000000..b0080860710b --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/function-expression-name.test.ts @@ -0,0 +1,39 @@ +import { + expectToBeFunctionExpressionNameScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('function name', () => { + it('should create its special scope', () => { + const { scopeManager } = parseAndAnalyze(` + (function name() { + }()); + `); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + const globalScope = scope; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + // Function expression name scope + scope = scopeManager.scopes[1]; + expectToBeFunctionExpressionNameScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('name'); + expect(scope.references).toHaveLength(0); + expect(scope.upper === globalScope).toBeTruthy(); + + // Function scope + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + expect(scope.upper === scopeManager.scopes[1]).toBeTruthy(); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/get-declared-variables.test.ts b/packages/scope-manager/tests/eslint-scope/get-declared-variables.test.ts new file mode 100644 index 000000000000..7f57a4483751 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/get-declared-variables.test.ts @@ -0,0 +1,228 @@ +import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/types'; +import { simpleTraverse } from '@typescript-eslint/typescript-estree'; +import { parse } from '../util/parse'; +import { analyze } from '../../src/analyze'; + +describe('ScopeManager.prototype.getDeclaredVariables', () => { + function verify( + ast: TSESTree.Node, + type: AST_NODE_TYPES, + expectedNamesList: string[][], + ): void { + const scopeManager = analyze(ast, { + ecmaVersion: 6, + sourceType: 'module', + }); + + simpleTraverse(ast, { + [type](node) { + const expected = expectedNamesList.shift()!; + const actual = scopeManager.getDeclaredVariables(node); + + expect(actual).toHaveLength(expected.length); + if (actual.length > 0) { + const end = actual.length - 1; + + for (let i = 0; i <= end; i++) { + expect(actual[i].name).toBe(expected[i]); + } + } + }, + }); + + expect(expectedNamesList).toHaveLength(0); + } + + it('should get variables that declared on `VariableDeclaration`', () => { + const ast = parse(` + var {a, x: [b], y: {c = 0}} = foo; + let {d, x: [e], y: {f = 0}} = foo; + const {g, x: [h], y: {i = 0}} = foo, {j, k = function() { let l; }} = bar; + `); + + verify(ast, AST_NODE_TYPES.VariableDeclaration, [ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i', 'j', 'k'], + ['l'], + ]); + }); + + it('should get variables that declared on `VariableDeclaration` in for-in/of', () => { + const ast = parse(` + for (var {a, x: [b], y: {c = 0}} in foo) { + let g; + } + for (let {d, x: [e], y: {f = 0}} of foo) { + let h; + } + `); + + verify(ast, AST_NODE_TYPES.VariableDeclaration, [ + ['a', 'b', 'c'], + ['g'], + ['d', 'e', 'f'], + ['h'], + ]); + }); + + it('should get variables that declared on `VariableDeclarator`', () => { + const ast = parse(` + var {a, x: [b], y: {c = 0}} = foo; + let {d, x: [e], y: {f = 0}} = foo; + const {g, x: [h], y: {i = 0}} = foo, {j, k = function() { let l; }} = bar; + `); + + verify(ast, AST_NODE_TYPES.VariableDeclarator, [ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i'], + ['j', 'k'], + ['l'], + ]); + }); + + it('should get variables that declared on `FunctionDeclaration`', () => { + const ast = parse(` + function foo({a, x: [b], y: {c = 0}}, [d, e]) { + let z; + } + function bar({f, x: [g], y: {h = 0}}, [i, j = function(q) { let w; }]) { + let z; + } + `); + + verify(ast, AST_NODE_TYPES.FunctionDeclaration, [ + ['foo', 'a', 'b', 'c', 'd', 'e'], + ['bar', 'f', 'g', 'h', 'i', 'j'], + ]); + }); + + it('should get variables that declared on `FunctionExpression`', () => { + const ast = parse(` + (function foo({a, x: [b], y: {c = 0}}, [d, e]) { + let z; + }); + (function bar({f, x: [g], y: {h = 0}}, [i, j = function(q) { let w; }]) { + let z; + }); + `); + + verify(ast, AST_NODE_TYPES.FunctionExpression, [ + ['foo', 'a', 'b', 'c', 'd', 'e'], + ['bar', 'f', 'g', 'h', 'i', 'j'], + ['q'], + ]); + }); + + it('should get variables that declared on `ArrowFunctionExpression`', () => { + const ast = parse(` + (({a, x: [b], y: {c = 0}}, [d, e]) => { + let z; + }); + (({f, x: [g], y: {h = 0}}, [i, j]) => { + let z; + }); + `); + + verify(ast, AST_NODE_TYPES.ArrowFunctionExpression, [ + ['a', 'b', 'c', 'd', 'e'], + ['f', 'g', 'h', 'i', 'j'], + ]); + }); + + it('should get variables that declared on `ClassDeclaration`', () => { + const ast = parse(` + class A { foo(x) { let y; } } + class B { foo(x) { let y; } } + `); + + verify(ast, AST_NODE_TYPES.ClassDeclaration, [ + ['A', 'A'], // outer scope"s and inner scope"s. + ['B', 'B'], + ]); + }); + + it('should get variables that declared on `ClassExpression`', () => { + const ast = parse(` + (class A { foo(x) { let y; } }); + (class B { foo(x) { let y; } }); + `); + + verify(ast, AST_NODE_TYPES.ClassExpression, [['A'], ['B']]); + }); + + it('should get variables that declared on `CatchClause`', () => { + const ast = parse(` + try {} catch ({a, b}) { + let x; + try {} catch ({c, d}) { + let y; + } + } + `); + + verify(ast, AST_NODE_TYPES.CatchClause, [ + ['a', 'b'], + ['c', 'd'], + ]); + }); + + it('should get variables that declared on `ImportDeclaration`', () => { + const ast = parse( + ` + import "aaa"; + import * as a from "bbb"; + import b, {c, x as d} from "ccc";\ + `, + 'module', + ); + + verify(ast, AST_NODE_TYPES.ImportDeclaration, [[], ['a'], ['b', 'c', 'd']]); + }); + + it('should get variables that declared on `ImportSpecifier`', () => { + const ast = parse( + ` + import "aaa"; + import * as a from "bbb"; + import b, {c, x as d} from "ccc"; + `, + 'module', + ); + + verify(ast, AST_NODE_TYPES.ImportSpecifier, [['c'], ['d']]); + }); + + it('should get variables that declared on `ImportDefaultSpecifier`', () => { + const ast = parse( + ` + import "aaa"; + import * as a from "bbb"; + import b, {c, x as d} from "ccc"; + `, + 'module', + ); + + verify(ast, AST_NODE_TYPES.ImportDefaultSpecifier, [['b']]); + }); + + it('should get variables that declared on `ImportNamespaceSpecifier`', () => { + const ast = parse( + ` + import "aaa"; + import * as a from "bbb"; + import b, {c, x as d} from "ccc"; + `, + 'module', + ); + + verify(ast, AST_NODE_TYPES.ImportNamespaceSpecifier, [['a']]); + }); + + it("should not get duplicate even if it's declared twice", () => { + const ast = parse('var a = 0, a = 1;'); + + verify(ast, AST_NODE_TYPES.VariableDeclaration, [['a']]); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/global-increment.test.ts b/packages/scope-manager/tests/eslint-scope/global-increment.test.ts new file mode 100644 index 000000000000..4f2fd68384a4 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/global-increment.test.ts @@ -0,0 +1,15 @@ +import { expectToBeGlobalScope, parseAndAnalyze } from '../util'; + +describe('global increment', () => { + it('becomes read/write', () => { + const { scopeManager } = parseAndAnalyze('b++;'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].isReadWrite()).toBeTruthy(); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/global-return.test.ts b/packages/scope-manager/tests/eslint-scope/global-return.test.ts new file mode 100644 index 000000000000..d5e2756ffc17 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/global-return.test.ts @@ -0,0 +1,67 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeGlobalScope, + expectToBeFunctionScope, + expectToBeModuleScope, + expectToBeImportBindingDefinition, +} from '../util'; +import { parseAndAnalyze } from '../util/parse'; + +describe('gloablReturn option', () => { + it('creates a function scope following the global scope immediately', () => { + const { scopeManager } = parseAndAnalyze( + ` + "use strict"; + var hello = 20; + `, + { globalReturn: true }, + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeTruthy(); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.variables[1].name).toBe('hello'); + }); + + it('creates a function scope following the global scope immediately and creates module scope', () => { + const { scopeManager } = parseAndAnalyze("import {x as v} from 'mod';", { + sourceType: 'module', + globalReturn: true, + }); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + + scope = scopeManager.scopes[2]; + expectToBeModuleScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('v'); + expectToBeImportBindingDefinition(scope.variables[0].defs[0]); + expect(scope.references).toHaveLength(0); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/implicit-global-reference.test.ts b/packages/scope-manager/tests/eslint-scope/implicit-global-reference.test.ts new file mode 100644 index 000000000000..e4a81e017bbd --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/implicit-global-reference.test.ts @@ -0,0 +1,148 @@ +import { expectToBeGlobalScope, parseAndAnalyze } from '../util'; +import { DefinitionType } from '../../src/definition'; + +describe('implicit global reference', () => { + it('assignments global scope', () => { + const { scopeManager } = parseAndAnalyze(` + var x = 20; + x = 300; + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => + scope.variables.map(variable => variable.defs.map(def => def.type)), + ), + ).toEqual([[[DefinitionType.Variable]]]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual([]); + }); + + it('assignments global scope without definition', () => { + const { scopeManager } = parseAndAnalyze(` + x = 300; + x = 300; + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => + scope.variables.map(variable => variable.defs.map(def => def.type)), + ), + ).toEqual([[]]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual(['x']); + }); + + it('assignments global scope without definition eval', () => { + const { scopeManager } = parseAndAnalyze(` + function inner() { + eval(str); + x = 300; + } + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => + scope.variables.map(variable => variable.defs.map(def => def.type)), + ), + ).toEqual([[[DefinitionType.FunctionName]], [[]]]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual(['x']); + }); + + it('assignment leaks', () => { + const { scopeManager } = parseAndAnalyze(` + function outer() { + x = 20; + } + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => scope.variables.map(variable => variable.name)), + ).toEqual([['outer'], ['arguments']]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual(['x']); + }); + + it("assignment doesn't leak", () => { + const { scopeManager } = parseAndAnalyze(` + function outer() { + function inner() { + x = 20; + } + var x; + } + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => scope.variables.map(variable => variable.name)), + ).toEqual([['outer'], ['arguments', 'inner', 'x'], ['arguments']]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual([]); + }); + + it('for-in-statement leaks', () => { + const { scopeManager } = parseAndAnalyze(` + function outer() { + for (x in y) { } + } + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => scope.variables.map(variable => variable.name)), + ).toEqual([['outer'], ['arguments'], []]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual(['x']); + }); + + it("for-in-statement doesn't leaks", () => { + const { scopeManager } = parseAndAnalyze(` + function outer() { + function inner() { + for (x in y) { } + } + var x; + } + `); + + const scopes = scopeManager.scopes; + + expect( + scopes.map(scope => scope.variables.map(variable => variable.name)), + ).toEqual([['outer'], ['arguments', 'inner', 'x'], ['arguments'], []]); + + expectToBeGlobalScope(scopes[0]); + expect( + scopes[0]['implicit'].variables.map(variable => variable.name), + ).toEqual([]); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/implied-strict.test.ts b/packages/scope-manager/tests/eslint-scope/implied-strict.test.ts new file mode 100644 index 000000000000..645e8c83c07d --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/implied-strict.test.ts @@ -0,0 +1,124 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeModuleScope, + parseAndAnalyze, +} from '../util'; + +describe('impliedStrict option', () => { + it('ensures all user scopes are strict if ecmaVersion >= 5', () => { + const { scopeManager } = parseAndAnalyze( + ` + function foo() { + function bar() { + "use strict"; + } + } + `, + { + ecmaVersion: 5, + impliedStrict: true, + }, + ); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeTruthy(); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionDeclaration); + expect(scope.isStrict).toBeTruthy(); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionDeclaration); + expect(scope.isStrict).toBeTruthy(); + }); + + it('ensures impliedStrict option is only effective when ecmaVersion option >= 5', () => { + const { scopeManager } = parseAndAnalyze( + ` + function foo() {} + `, + { + ecmaVersion: 3, + impliedStrict: true, + }, + ); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionDeclaration); + expect(scope.isStrict).toBeFalsy(); + }); + + it('omits a nodejs global scope when ensuring all user scopes are strict', () => { + const { scopeManager } = parseAndAnalyze( + ` + function foo() {} + `, + { + ecmaVersion: 5, + globalReturn: true, + impliedStrict: true, + }, + ); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeTruthy(); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionDeclaration); + expect(scope.isStrict).toBeTruthy(); + }); + + it('omits a module global scope when ensuring all user scopes are strict', () => { + const { scopeManager } = parseAndAnalyze('function foo() {}', { + ecmaVersion: 6, + impliedStrict: true, + sourceType: 'module', + }); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + + expectToBeGlobalScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.Program); + expect(scope.isStrict).toBeFalsy(); + + scope = scopeManager.scopes[1]; + expectToBeModuleScope(scope); + expect(scope.isStrict).toBeTruthy(); + + scope = scopeManager.scopes[2]; + expectToBeFunctionScope(scope); + expect(scope.block.type).toBe(AST_NODE_TYPES.FunctionDeclaration); + expect(scope.isStrict).toBeTruthy(); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/label.test.ts b/packages/scope-manager/tests/eslint-scope/label.test.ts new file mode 100644 index 000000000000..142a8364b5e1 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/label.test.ts @@ -0,0 +1,61 @@ +import { + expectToBeBlockScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('label', () => { + it('should not create variables', () => { + const { scopeManager } = parseAndAnalyze( + 'function bar() { q: for(;;) { break q; } }', + ); + + expect(scopeManager.scopes).toHaveLength(3); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('bar'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[2]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + }); + + it('should count child node references', () => { + const { scopeManager } = parseAndAnalyze(` + var foo = 5; + + label: while (true) { + console.log(foo); + break; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('foo'); + expect(scope.through.length).toBe(3); + expect(scope.through[2].identifier.name).toBe('foo'); + expect(scope.through[2].isRead()).toBeTruthy(); + + scope = scopeManager.scopes[1]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(2); + expect(scope.references[0].identifier.name).toBe('console'); + expect(scope.references[1].identifier.name).toBe('foo'); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/references.test.ts b/packages/scope-manager/tests/eslint-scope/references.test.ts new file mode 100644 index 000000000000..cc9a4d6e8736 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/references.test.ts @@ -0,0 +1,512 @@ +import { parseAndAnalyze } from '../util'; + +describe('References:', () => { + describe('When there is a `let` declaration on global,', () => { + it('the reference on global should be resolved.', () => { + const { scopeManager } = parseAndAnalyze('let a = 0;'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[0]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('the reference in functions should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + let a = 0; + function foo() { + let b = a; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + + it('the reference in default parameters should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + let a = 0; + function foo(b = a) { + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + + describe('When there is a `const` declaration on global,', () => { + it('the reference on global should be resolved.', () => { + const { scopeManager } = parseAndAnalyze('const a = 0;'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[0]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('the reference in functions should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + const a = 0; + function foo() { + const b = a; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + + describe('When there is a `var` declaration on global,', () => { + it('the reference on global should NOT be resolved.', () => { + const { scopeManager } = parseAndAnalyze('var a = 0;'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBeNull(); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('the reference in functions should NOT be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + var a = 0; + function foo() { + var b = a; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBeNull(); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + + describe('When there is a `class` declaration on global,', () => { + it('the reference on global should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + class A {} + let b = new A(); + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, A] + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(2); // [A, b] + expect(scope.references).toHaveLength(2); // [b, A] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('A'); + expect(reference.resolved).toBe(scope.variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + + it('the reference in functions should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + class A {} + function foo() { + let b = new A(); + } + `); + + expect(scopeManager.scopes).toHaveLength(3); // [global, A, foo] + + const scope = scopeManager.scopes[2]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, A] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('A'); + expect(reference.resolved).toBe(scopeManager.scopes[0].variables[0]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + + describe('When there is a `let` declaration in functions,', () => { + it('the reference on the function should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + function foo() { + let a = 0; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(2); // [arguments, a] + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[1]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('the reference in nested functions should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + function foo() { + let a = 0; + function bar() { + let b = a; + } + } + `); + + expect(scopeManager.scopes).toHaveLength(3); // [global, foo, bar] + + const scope = scopeManager.scopes[2]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[1].variables[1]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + + describe('When there is a `var` declaration in functions,', () => { + it('the reference on the function should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + function foo() { + var a = 0; + } + `); + + expect(scopeManager.scopes).toHaveLength(2); // [global, foo] + + const scope = scopeManager.scopes[1]; + + expect(scope.variables).toHaveLength(2); // [arguments, a] + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[1]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('the reference in nested functions should be resolved.', () => { + const { scopeManager } = parseAndAnalyze(` + function foo() { + var a = 0; + function bar() { + var b = a; + } + } + `); + + expect(scopeManager.scopes).toHaveLength(3); // [global, foo, bar] + + const scope = scopeManager.scopes[2]; + + expect(scope.variables).toHaveLength(2); // [arguments, b] + expect(scope.references).toHaveLength(2); // [b, a] + + const reference = scope.references[1]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scopeManager.scopes[1].variables[1]); + expect(reference.writeExpr).toBeUndefined(); + expect(reference.isWrite()).toBeFalsy(); + expect(reference.isRead()).toBeTruthy(); + }); + }); + + describe('When there is a `let` declaration with destructuring assignment', () => { + it('"let [a] = [1];", the reference should be resolved.', () => { + const { scopeManager } = parseAndAnalyze('let [a] = [1];'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[0]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('"let {a} = {a: 1};", the reference should be resolved.', () => { + const { scopeManager } = parseAndAnalyze('let {a} = {a: 1};'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[0]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + + it('"let {a: {a}} = {a: {a: 1}};", the reference should be resolved.', () => { + const { scopeManager } = parseAndAnalyze('let {a: {a}} = {a: {a: 1}};'); + + expect(scopeManager.scopes).toHaveLength(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references).toHaveLength(1); + + const reference = scope.references[0]; + + expect(reference.from).toBe(scope); + expect(reference.identifier.name).toBe('a'); + expect(reference.resolved).toBe(scope.variables[0]); + expect(reference.writeExpr).not.toBeUndefined(); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.isRead()).toBeFalsy(); + }); + }); + + describe('Reference.init should be a boolean value of whether it is one to initialize or not.', () => { + const trueCodes = [ + 'var a = 0;', + 'let a = 0;', + 'const a = 0;', + 'var [a] = [];', + 'let [a] = [];', + 'const [a] = [];', + 'var [a = 1] = [];', + 'let [a = 1] = [];', + 'const [a = 1] = [];', + 'var {a} = {};', + 'let {a} = {};', + 'const {a} = {};', + 'var {b: a} = {};', + 'let {b: a} = {};', + 'const {b: a} = {};', + 'var {b: a = 0} = {};', + 'let {b: a = 0} = {};', + 'const {b: a = 0} = {};', + 'for (var a in []);', + 'for (let a in []);', + 'for (var [a] in []);', + 'for (let [a] in []);', + 'for (var [a = 0] in []);', + 'for (let [a = 0] in []);', + 'for (var {a} in []);', + 'for (let {a} in []);', + 'for (var {a = 0} in []);', + 'for (let {a = 0} in []);', + 'new function(a = 0) {}', + 'new function([a = 0] = []) {}', + 'new function({b: a = 0} = {}) {}', + ]; + + trueCodes.forEach(code => + it(`"${code}", all references should be true.`, () => { + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes.length).toBeGreaterThanOrEqual(1); + + const scope = scopeManager.scopes[scopeManager.scopes.length - 1]; + + expect(scope.variables.length).toBeGreaterThanOrEqual(1); + expect(scope.references.length).toBeGreaterThanOrEqual(1); + + scope.references.forEach(reference => { + expect(reference.identifier.name).toBe('a'); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.init).toBeTruthy(); + }); + }), + ); + + let falseCodes = [ + 'let a; a = 0;', + 'let a; [a] = [];', + 'let a; [a = 1] = [];', + 'let a; ({a} = {});', + 'let a; ({b: a} = {});', + 'let a; ({b: a = 0} = {});', + 'let a; for (a in []);', + 'let a; for ([a] in []);', + 'let a; for ([a = 0] in []);', + 'let a; for ({a} in []);', + 'let a; for ({a = 0} in []);', + ]; + + falseCodes.forEach(code => + it(`"${code}", all references should be false.`, () => { + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes.length).toBeGreaterThanOrEqual(1); + + const scope = scopeManager.scopes[scopeManager.scopes.length - 1]; + + expect(scope.variables).toHaveLength(1); + expect(scope.references.length).toBeGreaterThanOrEqual(1); + + scope.references.forEach(reference => { + expect(reference.identifier.name).toBe('a'); + expect(reference.isWrite()).toBeTruthy(); + expect(reference.init).toBeFalsy(); + }); + }), + ); + + falseCodes = [ + 'let a; let b = a;', + 'let a; let [b] = a;', + 'let a; let [b = a] = [];', + 'let a; for (var b in a);', + 'let a; for (var [b = a] in []);', + 'let a; for (let b in a);', + 'let a; for (let [b = a] in []);', + 'let a,b; b = a;', + 'let a,b; [b] = a;', + 'let a,b; [b = a] = [];', + 'let a,b; for (b in a);', + 'let a,b; for ([b = a] in []);', + 'let a; a.foo = 0;', + 'let a,b; b = a.foo;', + ]; + falseCodes.forEach(code => + it(`"${code}", readonly references of "a" should be undefined.`, () => { + const { scopeManager } = parseAndAnalyze(code); + + expect(scopeManager.scopes.length).toBeGreaterThanOrEqual(1); + + const scope = scopeManager.scopes[0]; + + expect(scope.variables.length).toBeGreaterThanOrEqual(1); + expect(scope.variables[0].name).toBe('a'); + + const references = scope.variables[0].references; + + expect(references.length).toBeGreaterThanOrEqual(1); + + references.forEach(reference => { + expect(reference.isRead()).toBeTruthy(); + expect(reference.init).toBeUndefined(); + }); + }), + ); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/typescript.test.ts b/packages/scope-manager/tests/eslint-scope/typescript.test.ts new file mode 100644 index 000000000000..c529ddce9624 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/typescript.test.ts @@ -0,0 +1,43 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + expectToBeFunctionScope, + expectToBeGlobalScope, + parseAndAnalyze, +} from '../util'; + +describe('typescript', () => { + describe('multiple call signatures', () => { + it('should create a function scope', () => { + const { scopeManager } = parseAndAnalyze( + ` + function foo(bar: number): number; + function foo(bar: string): string; + function foo(bar: string | number): string | number { + return bar; + } + `, + 'script', + ); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.references).toHaveLength(0); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].defs).toHaveLength(3); + + for (let i = 1; i < 4; i += 1) { + scope = scopeManager.scopes[i]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(2); + expect(scope.variables[0].name).toBe('arguments'); + if (scope.block.type === AST_NODE_TYPES.TSDeclareFunction) { + expect(scope.references).toHaveLength(0); + } else { + expect(scope.references).toHaveLength(1); + } + } + }); + }); +}); diff --git a/packages/scope-manager/tests/eslint-scope/with-scope.test.ts b/packages/scope-manager/tests/eslint-scope/with-scope.test.ts new file mode 100644 index 000000000000..7949d7734418 --- /dev/null +++ b/packages/scope-manager/tests/eslint-scope/with-scope.test.ts @@ -0,0 +1,48 @@ +import { + expectToBeBlockScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeWithScope, + parseAndAnalyze, +} from '../util'; + +describe('with', () => { + it('creates scope', () => { + const { scopeManager } = parseAndAnalyze( + ` + (function () { + with (obj) { + testing; + } + }()); + `, + 'script', + ); + + expect(scopeManager.scopes).toHaveLength(4); + + let scope = scopeManager.scopes[0]; + expectToBeGlobalScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[1]; + expectToBeFunctionScope(scope); + expect(scope.variables).toHaveLength(1); + expect(scope.variables[0].name).toBe('arguments'); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].resolved).toBeNull(); + + scope = scopeManager.scopes[2]; + expectToBeWithScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(0); + + scope = scopeManager.scopes[3]; + expectToBeBlockScope(scope); + expect(scope.variables).toHaveLength(0); + expect(scope.references).toHaveLength(1); + expect(scope.references[0].identifier.name).toBe('testing'); + expect(scope.references[0].resolved).toBeNull(); + }); +}); diff --git a/packages/scope-manager/tests/fixtures.test.ts b/packages/scope-manager/tests/fixtures.test.ts new file mode 100644 index 000000000000..784b9a56389e --- /dev/null +++ b/packages/scope-manager/tests/fixtures.test.ts @@ -0,0 +1,153 @@ +import fs from 'fs'; +import glob from 'glob'; +import makeDir from 'make-dir'; +import path from 'path'; +import { parseAndAnalyze, AnalyzeOptions } from './util'; + +// Assign a segment set to this variable to limit the test to only this segment +// This is super helpful if you need to debug why a specific fixture isn't producing the correct output +// eg. ['type-declaration', 'signatures', 'method-generic'] will only test /type-declaration/signatures/method-generic.ts +// prettier-ignore +const ONLY = [].join(path.sep); + +const FIXTURES_DIR = path.resolve(__dirname, 'fixtures'); + +const fixtures = glob + .sync(`${FIXTURES_DIR}/**/*.{js,ts,jsx,tsx}`, { + ignore: ['fixtures.test.ts'], + }) + .map(absolute => { + const relative = path.relative(FIXTURES_DIR, absolute); + const { name, dir, ext } = path.parse(relative); + const segments = dir.split(path.sep); + const snapshotPath = path.join(FIXTURES_DIR, dir); + return { + absolute, + name, + segments, + snapshotPath, + snapshotFile: path.join(snapshotPath, `${name}${ext}.shot`), + }; + }); + +const FOUR_SLASH = /^\/\/\/\/[ ]+@(\w+)[ ]*=[ ]*(.+)$/; +const QUOTED_STRING = /^["'](.+?)['"]$/; +type ALLOWED_VALUE = ['number' | 'boolean' | 'string', Set?]; +const ALLOWED_OPTIONS: Map = new Map< + keyof AnalyzeOptions, + ALLOWED_VALUE +>([ + ['ecmaVersion', ['number']], + ['globalReturn', ['boolean']], + ['impliedStrict', ['boolean']], + ['sourceType', ['string', new Set(['module', 'script'])]], +]); + +function nestDescribe( + fixture: typeof fixtures[number], + segments = fixture.segments, +): void { + if (segments.length > 0) { + describe(segments[0], () => { + nestDescribe(fixture, segments.slice(1)); + }); + } else { + const test = (): void => { + const contents = fs.readFileSync(fixture.absolute, 'utf8'); + + const lines = contents.split('\n'); + const options: Record = {}; + for (const line of lines) { + if (!line.startsWith('////')) { + continue; + } + + const match = FOUR_SLASH.exec(line); + if (!match) { + throw new Error(`Four-slash did not match expected format: ${line}`); + } + const [, key, rawValue] = match; + const type = ALLOWED_OPTIONS.get(key); + if (!type) { + throw new Error(`Unknown option ${key}`); + } + + let value: unknown = rawValue; + switch (type[0]) { + case 'string': { + const strmatch = QUOTED_STRING.exec(rawValue); + if (strmatch) { + value = strmatch[1]; + } + break; + } + + case 'number': { + const parsed = parseFloat(rawValue); + if (isNaN(parsed)) { + throw new Error( + `Expected a number for ${key}, but got ${rawValue}`, + ); + } + value = parsed; + break; + } + + case 'boolean': { + if (rawValue === 'true') { + value = true; + } else if (rawValue === 'false') { + value = false; + } else { + throw new Error( + `Expected a boolean for ${key}, but got ${rawValue}`, + ); + } + break; + } + } + + if (type[1] && !type[1].has(value)) { + throw new Error( + `Expected value for ${key} to be one of (${Array.from(type[1]).join( + ' | ', + )}), but got ${value}`, + ); + } + + if (value === 'true') { + options[key] = true; + } else if (value === 'false') { + options[key] = false; + } else { + options[key] = value; + } + } + + try { + makeDir.sync(fixture.snapshotPath); + } catch (e) { + if ('code' in e && e.code === 'EEXIST') { + // already exists - ignored + } else { + throw e; + } + } + + try { + const { scopeManager } = parseAndAnalyze(contents, options); + expect(scopeManager).toMatchSpecificSnapshot(fixture.snapshotFile); + } catch (e) { + expect(e).toMatchSpecificSnapshot(fixture.snapshotFile); + } + }; + + if ([...fixture.segments, fixture.name].join(path.sep) === ONLY) { + it.only(fixture.name, test); + } else { + it(fixture.name, test); + } + } +} + +fixtures.forEach(f => nestDescribe(f)); diff --git a/packages/scope-manager/tests/fixtures/block/inherited-scope.ts b/packages/scope-manager/tests/fixtures/block/inherited-scope.ts new file mode 100644 index 000000000000..0215e4f16442 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/block/inherited-scope.ts @@ -0,0 +1,5 @@ +const a = 1; + +{ + a; +} diff --git a/packages/scope-manager/tests/fixtures/block/inherited-scope.ts.shot b/packages/scope-manager/tests/fixtures/block/inherited-scope.ts.shot new file mode 100644 index 000000000000..c8f75265822f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/block/inherited-scope.ts.shot @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`block inherited-scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + BlockScope$2 { + block: BlockStatement$4, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map {}, + type: "block", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/block/scope.ts b/packages/scope-manager/tests/fixtures/block/scope.ts new file mode 100644 index 000000000000..a0bf546c53e5 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/block/scope.ts @@ -0,0 +1,7 @@ +{ + let i = 20; + let j = 1; + i; +} + +j; diff --git a/packages/scope-manager/tests/fixtures/block/scope.ts.shot b/packages/scope-manager/tests/fixtures/block/scope.ts.shot new file mode 100644 index 000000000000..7c445ea2c307 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/block/scope.ts.shot @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`block scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"i">, + node: VariableDeclarator$1, + }, + ], + name: "i", + references: Array [ + Reference$1 { + identifier: Identifier<"i">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$3 { + identifier: Identifier<"i">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"j">, + node: VariableDeclarator$3, + }, + ], + name: "j", + references: Array [ + Reference$2 { + identifier: Identifier<"j">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$4 { + identifier: Identifier<"j">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + BlockScope$2 { + block: BlockStatement$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "i" => Variable$1, + "j" => Variable$2, + }, + type: "block", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/call-expression/call-expression.ts b/packages/scope-manager/tests/fixtures/call-expression/call-expression.ts new file mode 100644 index 000000000000..ebfb807a1b02 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/call-expression/call-expression.ts @@ -0,0 +1,5 @@ +const foo = () => {}; +const a = 1; + +foo(a); +foo?.(a); diff --git a/packages/scope-manager/tests/fixtures/call-expression/call-expression.ts.shot b/packages/scope-manager/tests/fixtures/call-expression/call-expression.ts.shot new file mode 100644 index 000000000000..150f5513d8ab --- /dev/null +++ b/packages/scope-manager/tests/fixtures/call-expression/call-expression.ts.shot @@ -0,0 +1,107 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`call-expression call-expression 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + Reference$3 { + identifier: Identifier<"foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$5 { + identifier: Identifier<"foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"a">, + node: VariableDeclarator$3, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$4, + }, + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + Reference$6 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + ], + set: Map { + "foo" => Variable$1, + "a" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "function", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts b/packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts new file mode 100644 index 000000000000..5d613bd38585 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts @@ -0,0 +1,2 @@ +type T = 1; +foo(); diff --git a/packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts.shot b/packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts.shot new file mode 100644 index 000000000000..35154a8275db --- /dev/null +++ b/packages/scope-manager/tests/fixtures/call-expression/type-parameters1.ts.shot @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`call-expression type-parameters1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + Reference$2, + ], + set: Map { + "T" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts b/packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts new file mode 100644 index 000000000000..2bb481d63991 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts @@ -0,0 +1,2 @@ +const T = 1; +foo(); // should not resolve to value diff --git a/packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts.shot b/packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts.shot new file mode 100644 index 000000000000..b95c6b59e274 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/call-expression/type-parameters2.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`call-expression type-parameters2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"T">, + node: VariableDeclarator$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"foo">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "T" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/catch/inherited-scope.ts b/packages/scope-manager/tests/fixtures/catch/inherited-scope.ts new file mode 100644 index 000000000000..3d7202f881a1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/catch/inherited-scope.ts @@ -0,0 +1,5 @@ +const a = 1; +try { +} catch (e) { + a; +} diff --git a/packages/scope-manager/tests/fixtures/catch/inherited-scope.ts.shot b/packages/scope-manager/tests/fixtures/catch/inherited-scope.ts.shot new file mode 100644 index 000000000000..0b17168ca9e7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/catch/inherited-scope.ts.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`catch inherited-scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + CatchClauseDefinition$2 { + name: Identifier<"e">, + node: CatchClause$3, + }, + ], + name: "e", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + BlockScope$2 { + block: BlockStatement$5, + isStrict: false, + references: Array [], + set: Map {}, + type: "block", + upper: GlobalScope$1, + variables: Array [], + }, + CatchScope$3 { + block: CatchClause$3, + isStrict: false, + references: Array [], + set: Map { + "e" => Variable$2, + }, + type: "catch", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + BlockScope$4 { + block: BlockStatement$6, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map {}, + type: "block", + upper: CatchScope$3, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/catch/scope.ts b/packages/scope-manager/tests/fixtures/catch/scope.ts new file mode 100644 index 000000000000..a78dc78c8d9d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/catch/scope.ts @@ -0,0 +1,8 @@ +try { +} catch (e) { + e; + let a = 1; +} + +const unresolved = e; +const dontReference2 = a; diff --git a/packages/scope-manager/tests/fixtures/catch/scope.ts.shot b/packages/scope-manager/tests/fixtures/catch/scope.ts.shot new file mode 100644 index 000000000000..04908947c1ce --- /dev/null +++ b/packages/scope-manager/tests/fixtures/catch/scope.ts.shot @@ -0,0 +1,160 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`catch scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + CatchClauseDefinition$1 { + name: Identifier<"e">, + node: CatchClause$1, + }, + ], + name: "e", + references: Array [ + Reference$1 { + identifier: Identifier<"e">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"a">, + node: VariableDeclarator$2, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"unresolved">, + node: VariableDeclarator$4, + }, + ], + name: "unresolved", + references: Array [ + Reference$3 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"e">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"dontReference2">, + node: VariableDeclarator$5, + }, + ], + name: "dontReference2", + references: Array [ + Reference$5 { + identifier: Identifier<"dontReference2">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$3, + Reference$4 { + identifier: Identifier<"e">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + Reference$5, + Reference$6 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "unresolved" => Variable$3, + "dontReference2" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + BlockScope$2 { + block: BlockStatement$7, + isStrict: false, + references: Array [], + set: Map {}, + type: "block", + upper: GlobalScope$1, + variables: Array [], + }, + CatchScope$3 { + block: CatchClause$1, + isStrict: false, + references: Array [], + set: Map { + "e" => Variable$1, + }, + type: "catch", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + BlockScope$4 { + block: BlockStatement$8, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "a" => Variable$2, + }, + type: "block", + upper: CatchScope$3, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/abstract.ts b/packages/scope-manager/tests/fixtures/class/declaration/abstract.ts new file mode 100644 index 000000000000..ace940e1c988 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/abstract.ts @@ -0,0 +1,4 @@ +abstract class A { + abstract foo; + abstract bar(a, b); +} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/abstract.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/abstract.ts.shot new file mode 100644 index 000000000000..c49da3541307 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/abstract.ts.shot @@ -0,0 +1,108 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration abstract 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: TSEmptyBodyFunctionExpression$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"b">, + node: TSEmptyBodyFunctionExpression$2, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "A" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + FunctionScope$3 { + block: TSEmptyBodyFunctionExpression$2, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + "b" => Variable$5, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts b/packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts new file mode 100644 index 000000000000..029048eb65dd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts @@ -0,0 +1,6 @@ +const outer1 = 'a'; +const outer2 = 'b'; +class A { + [outer1] = 1; + [outer2]() {} +} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts.shot new file mode 100644 index 000000000000..4a41a73b5daf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/computed-member.ts.shot @@ -0,0 +1,144 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration computed-member 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer1">, + node: VariableDeclarator$1, + }, + ], + name: "outer1", + references: Array [ + Reference$1 { + identifier: Identifier<"outer1">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$3 { + identifier: Identifier<"outer1">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"outer2">, + node: VariableDeclarator$3, + }, + ], + name: "outer2", + references: Array [ + Reference$2 { + identifier: Identifier<"outer2">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$4, + }, + Reference$4 { + identifier: Identifier<"outer2">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"A">, + node: ClassDeclaration$5, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$4 { + name: Identifier<"A">, + node: ClassDeclaration$5, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "outer1" => Variable$1, + "outer2" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ClassScope$2 { + block: ClassDeclaration$5, + isStrict: true, + references: Array [ + Reference$3, + Reference$4, + ], + set: Map { + "A" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + FunctionScope$3 { + block: FunctionExpression$7, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts b/packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts new file mode 100644 index 000000000000..3f367dec2774 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts @@ -0,0 +1,3 @@ +class A {} +type T = string; +class B extends A {} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts.shot new file mode 100644 index 000000000000..9db0f3b3bf5a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/extends-generic.ts.shot @@ -0,0 +1,145 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration extends-generic 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$2, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + ClassNameDefinition$5 { + name: Identifier<"B">, + node: ClassDeclaration$4, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + ClassNameDefinition$6 { + name: Identifier<"B">, + node: ClassDeclaration$4, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$1, + "T" => Variable$4, + "B" => Variable$5, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + Variable$5, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + "U" => Variable$3, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ClassScope$3 { + block: ClassDeclaration$4, + isStrict: true, + references: Array [ + Reference$2, + ], + set: Map { + "B" => Variable$6, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$6, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/extends.ts b/packages/scope-manager/tests/fixtures/class/declaration/extends.ts new file mode 100644 index 000000000000..a16946fd696e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/extends.ts @@ -0,0 +1,2 @@ +class A {} +class B extends A {} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/extends.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/extends.ts.shot new file mode 100644 index 000000000000..a886cf9174c1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/extends.ts.shot @@ -0,0 +1,108 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration extends 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"B">, + node: ClassDeclaration$2, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$4 { + name: Identifier<"B">, + node: ClassDeclaration$2, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$1, + "B" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "B" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts new file mode 100644 index 000000000000..2d3b682a2fad --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts @@ -0,0 +1 @@ +class Foo extends Bar {} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts.shot new file mode 100644 index 000000000000..9a8fd8559381 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-extends.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration generic-ref-extends 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeParameter$2, + }, + ], + name: "A", + references: Array [ + Reference$2 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"Bar">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [ + Reference$2, + ], + set: Map { + "Foo" => Variable$2, + "A" => Variable$3, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts new file mode 100644 index 000000000000..3944aabaaffd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts @@ -0,0 +1 @@ +class Foo implements Bar {} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts.shot new file mode 100644 index 000000000000..c51787773057 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/generic-ref-implements.ts.shot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration generic-ref-implements 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeParameter$2, + }, + ], + name: "A", + references: Array [ + Reference$2 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [ + Reference$1 { + identifier: Identifier<"Bar">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + Reference$2, + ], + set: Map { + "Foo" => Variable$2, + "A" => Variable$3, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/generic.ts b/packages/scope-manager/tests/fixtures/class/declaration/generic.ts new file mode 100644 index 000000000000..bb133f435731 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/generic.ts @@ -0,0 +1,3 @@ +class Foo {} + +type Unresolved = A; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/generic.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/generic.ts.shot new file mode 100644 index 000000000000..9e6adbf4f184 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/generic.ts.shot @@ -0,0 +1,95 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration generic 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeParameter$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "Foo" => Variable$1, + "Unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$2, + "A" => Variable$3, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts b/packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts new file mode 100644 index 000000000000..f4e6c7cc8763 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts @@ -0,0 +1,3 @@ +interface A {} +type T = string; +class B implements A {} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts.shot new file mode 100644 index 000000000000..36b97a022f71 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/implements-generic.ts.shot @@ -0,0 +1,130 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration implements-generic 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"U">, + node: TSTypeParameter$2, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$4 { + name: Identifier<"B">, + node: ClassDeclaration$4, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + ClassNameDefinition$5 { + name: Identifier<"B">, + node: ClassDeclaration$4, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "A" => Variable$1, + "T" => Variable$3, + "B" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + Variable$4, + ], + }, + TypeScope$2 { + block: TSInterfaceDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "U" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "B" => Variable$5, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/implements.ts b/packages/scope-manager/tests/fixtures/class/declaration/implements.ts new file mode 100644 index 000000000000..8c04767cd505 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/implements.ts @@ -0,0 +1,2 @@ +interface A {} +class B implements A {} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/implements.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/implements.ts.shot new file mode 100644 index 000000000000..33d222e72fae --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/implements.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration implements 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"B">, + node: ClassDeclaration$2, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"B">, + node: ClassDeclaration$2, + }, + ], + name: "B", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "A" => Variable$1, + "B" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ClassScope$2 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "B" => Variable$3, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/method.ts b/packages/scope-manager/tests/fixtures/class/declaration/method.ts new file mode 100644 index 000000000000..fa102827d1f4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/method.ts @@ -0,0 +1,8 @@ +class A { + method(a, [b], { c }, d = 1, e = a, f) { + a; + } +} + +const unresolved1 = f; +const unresolved2 = method; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/method.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/method.ts.shot new file mode 100644 index 000000000000..5e035ce3c752 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/method.ts.shot @@ -0,0 +1,261 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration method 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionExpression$2, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"b">, + node: FunctionExpression$2, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"c">, + node: FunctionExpression$2, + }, + ], + name: "c", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"d">, + node: FunctionExpression$2, + }, + ], + name: "d", + references: Array [ + Reference$1 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"e">, + node: FunctionExpression$2, + }, + ], + name: "e", + references: Array [ + Reference$2 { + identifier: Identifier<"e">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$8, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + ParameterDefinition$8 { + name: Identifier<"f">, + node: FunctionExpression$2, + }, + ], + name: "f", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$10 { + defs: Array [ + VariableDefinition$9 { + name: Identifier<"unresolved1">, + node: VariableDeclarator$4, + }, + ], + name: "unresolved1", + references: Array [ + Reference$5 { + identifier: Identifier<"unresolved1">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$10, + writeExpr: Identifier<"f">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$11 { + defs: Array [ + VariableDefinition$10 { + name: Identifier<"unresolved2">, + node: VariableDeclarator$5, + }, + ], + name: "unresolved2", + references: Array [ + Reference$7 { + identifier: Identifier<"unresolved2">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$11, + writeExpr: Identifier<"method">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$5, + Reference$6 { + identifier: Identifier<"f">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + Reference$7, + Reference$8 { + identifier: Identifier<"method">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "A" => Variable$1, + "unresolved1" => Variable$10, + "unresolved2" => Variable$11, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$10, + Variable$11, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + FunctionScope$3 { + block: FunctionExpression$2, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + "b" => Variable$5, + "c" => Variable$6, + "d" => Variable$7, + "e" => Variable$8, + "f" => Variable$9, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + Variable$9, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/new.ts b/packages/scope-manager/tests/fixtures/class/declaration/new.ts new file mode 100644 index 000000000000..f4282faaa985 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/new.ts @@ -0,0 +1,2 @@ +class A {} +new A(); diff --git a/packages/scope-manager/tests/fixtures/class/declaration/new.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/new.ts.shot new file mode 100644 index 000000000000..49f13b7fec46 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/new.ts.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration new 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts b/packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts new file mode 100644 index 000000000000..b65d60cc5006 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts @@ -0,0 +1,16 @@ +const outer = 1; +type Outer = 1; +class A { + constructor( + private a, + private b = 1, + private c = a, + public d = outer, + public e, + readonly f: Outer, + ) { + a; + } +} + +const unresovled = e; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts.shot new file mode 100644 index 000000000000..bd145bbb2207 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/parameter-properties.ts.shot @@ -0,0 +1,294 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration parameter-properties 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer">, + node: VariableDeclarator$1, + }, + ], + name: "outer", + references: Array [ + Reference$1 { + identifier: Identifier<"outer">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$6 { + identifier: Identifier<"outer">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"Outer">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Outer", + references: Array [ + Reference$7 { + identifier: Identifier<"Outer">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"A">, + node: ClassDeclaration$4, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$4 { + name: Identifier<"A">, + node: ClassDeclaration$4, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"a">, + node: FunctionExpression$5, + }, + ], + name: "a", + references: Array [ + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + }, + Reference$8 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"b">, + node: FunctionExpression$5, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Literal$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"c">, + node: FunctionExpression$5, + }, + ], + name: "c", + references: Array [ + Reference$3 { + identifier: Identifier<"c">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$8, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + ParameterDefinition$8 { + name: Identifier<"d">, + node: FunctionExpression$5, + }, + ], + name: "d", + references: Array [ + Reference$5 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$9, + writeExpr: Identifier<"outer">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$10 { + defs: Array [ + ParameterDefinition$9 { + name: Identifier<"e">, + node: FunctionExpression$5, + }, + ], + name: "e", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$11 { + defs: Array [ + ParameterDefinition$10 { + name: Identifier<"f">, + node: FunctionExpression$5, + }, + ], + name: "f", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$12 { + defs: Array [ + VariableDefinition$11 { + name: Identifier<"unresovled">, + node: VariableDeclarator$7, + }, + ], + name: "unresovled", + references: Array [ + Reference$9 { + identifier: Identifier<"unresovled">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$12, + writeExpr: Identifier<"e">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$8, + isStrict: false, + references: Array [ + Reference$1, + Reference$9, + Reference$10 { + identifier: Identifier<"e">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "outer" => Variable$1, + "Outer" => Variable$2, + "A" => Variable$3, + "unresovled" => Variable$12, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + Variable$12, + ], + }, + ClassScope$2 { + block: ClassDeclaration$4, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + FunctionScope$3 { + block: FunctionExpression$5, + isStrict: true, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + Reference$8, + ], + set: Map { + "arguments" => Variable$5, + "a" => Variable$6, + "b" => Variable$7, + "c" => Variable$8, + "d" => Variable$9, + "e" => Variable$10, + "f" => Variable$11, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$5, + Variable$6, + Variable$7, + Variable$8, + Variable$9, + Variable$10, + Variable$11, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts b/packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts new file mode 100644 index 000000000000..824821d682e7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts @@ -0,0 +1,4 @@ +type T = 1; +class A { + prop: T; +} diff --git a/packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts.shot new file mode 100644 index 000000000000..05e304772d33 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/properties-type-annotation.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration properties-type-annotation 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"A">, + node: ClassDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ClassScope$2 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$3, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/properties.ts b/packages/scope-manager/tests/fixtures/class/declaration/properties.ts new file mode 100644 index 000000000000..c047395435ad --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/properties.ts @@ -0,0 +1,5 @@ +class A { + prop = 1; +} + +const unresolved = prop; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/properties.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/properties.ts.shot new file mode 100644 index 000000000000..5c2974fea4c4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/properties.ts.shot @@ -0,0 +1,91 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration properties 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"unresolved">, + node: VariableDeclarator$2, + }, + ], + name: "unresolved", + references: Array [ + Reference$1 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"prop">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"prop">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "A" => Variable$1, + "unresolved" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts b/packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts new file mode 100644 index 000000000000..84d674f53732 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts @@ -0,0 +1,5 @@ +class A {} + +type T1 = A; +type T2 = typeof A; +const v = A; diff --git a/packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts.shot b/packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts.shot new file mode 100644 index 000000000000..cb68e5aa2f6c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/declaration/type-reference.ts.shot @@ -0,0 +1,135 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class declaration type-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$4 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T1">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T1", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"T2">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T2", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + VariableDefinition$5 { + name: Identifier<"v">, + node: VariableDeclarator$4, + }, + ], + name: "v", + references: Array [ + Reference$3 { + identifier: Identifier<"v">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + writeExpr: Identifier<"A">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "A" => Variable$1, + "T1" => Variable$3, + "T2" => Variable$4, + "v" => Variable$5, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + Variable$4, + Variable$5, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/expression/computed-member.ts b/packages/scope-manager/tests/fixtures/class/expression/computed-member.ts new file mode 100644 index 000000000000..bba58b688ade --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/computed-member.ts @@ -0,0 +1,6 @@ +const outer1 = 'a'; +const outer2 = 'b'; +const A = class { + [outer1] = 1; + [outer2]() {} +}; diff --git a/packages/scope-manager/tests/fixtures/class/expression/computed-member.ts.shot b/packages/scope-manager/tests/fixtures/class/expression/computed-member.ts.shot new file mode 100644 index 000000000000..133275186233 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/computed-member.ts.shot @@ -0,0 +1,138 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class expression computed-member 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer1">, + node: VariableDeclarator$1, + }, + ], + name: "outer1", + references: Array [ + Reference$1 { + identifier: Identifier<"outer1">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$4 { + identifier: Identifier<"outer1">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"outer2">, + node: VariableDeclarator$3, + }, + ], + name: "outer2", + references: Array [ + Reference$2 { + identifier: Identifier<"outer2">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$4, + }, + Reference$5 { + identifier: Identifier<"outer2">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"A">, + node: VariableDeclarator$5, + }, + ], + name: "A", + references: Array [ + Reference$3 { + identifier: Identifier<"A">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: ClassExpression$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$7, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "outer1" => Variable$1, + "outer2" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ClassScope$2 { + block: ClassExpression$6, + isStrict: true, + references: Array [ + Reference$4, + Reference$5, + ], + set: Map {}, + type: "class", + upper: GlobalScope$1, + variables: Array [], + }, + FunctionScope$3 { + block: FunctionExpression$8, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$4, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/expression/extends.ts b/packages/scope-manager/tests/fixtures/class/expression/extends.ts new file mode 100644 index 000000000000..d4f414804e0a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/extends.ts @@ -0,0 +1,2 @@ +class A {} +const B = class extends A {}; diff --git a/packages/scope-manager/tests/fixtures/class/expression/extends.ts.shot b/packages/scope-manager/tests/fixtures/class/expression/extends.ts.shot new file mode 100644 index 000000000000..cefcb76aca9b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/extends.ts.shot @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class expression extends 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$2 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"A">, + node: ClassDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"B">, + node: VariableDeclarator$2, + }, + ], + name: "B", + references: Array [ + Reference$1 { + identifier: Identifier<"B">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: ClassExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "A" => Variable$1, + "B" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "A" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassExpression$3, + isStrict: true, + references: Array [], + set: Map {}, + type: "class", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/expression/method.ts b/packages/scope-manager/tests/fixtures/class/expression/method.ts new file mode 100644 index 000000000000..df973f263b76 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/method.ts @@ -0,0 +1,8 @@ +const A = class { + method(a, [b], { c }, d = 1, e = a, f) { + a; + } +}; + +const unresolved1 = f; +const unresolved2 = method; diff --git a/packages/scope-manager/tests/fixtures/class/expression/method.ts.shot b/packages/scope-manager/tests/fixtures/class/expression/method.ts.shot new file mode 100644 index 000000000000..996e9884ca26 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/method.ts.shot @@ -0,0 +1,255 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class expression method 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"A">, + node: VariableDeclarator$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ClassExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: FunctionExpression$3, + }, + ], + name: "a", + references: Array [ + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + Reference$5 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"c">, + node: FunctionExpression$3, + }, + ], + name: "c", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"d">, + node: FunctionExpression$3, + }, + ], + name: "d", + references: Array [ + Reference$2 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + writeExpr: Literal$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"e">, + node: FunctionExpression$3, + }, + ], + name: "e", + references: Array [ + Reference$3 { + identifier: Identifier<"e">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"f">, + node: FunctionExpression$3, + }, + ], + name: "f", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + VariableDefinition$8 { + name: Identifier<"unresolved1">, + node: VariableDeclarator$5, + }, + ], + name: "unresolved1", + references: Array [ + Reference$6 { + identifier: Identifier<"unresolved1">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$9, + writeExpr: Identifier<"f">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$10 { + defs: Array [ + VariableDefinition$9 { + name: Identifier<"unresolved2">, + node: VariableDeclarator$6, + }, + ], + name: "unresolved2", + references: Array [ + Reference$8 { + identifier: Identifier<"unresolved2">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$10, + writeExpr: Identifier<"method">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$7, + isStrict: false, + references: Array [ + Reference$1, + Reference$6, + Reference$7 { + identifier: Identifier<"f">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + Reference$8, + Reference$9 { + identifier: Identifier<"method">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "A" => Variable$1, + "unresolved1" => Variable$9, + "unresolved2" => Variable$10, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$9, + Variable$10, + ], + }, + ClassScope$2 { + block: ClassExpression$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "class", + upper: GlobalScope$1, + variables: Array [], + }, + FunctionScope$3 { + block: FunctionExpression$3, + isStrict: true, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + Reference$5, + ], + set: Map { + "arguments" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + "c" => Variable$5, + "d" => Variable$6, + "e" => Variable$7, + "f" => Variable$8, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/expression/new.ts b/packages/scope-manager/tests/fixtures/class/expression/new.ts new file mode 100644 index 000000000000..fffb5e1852a8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/new.ts @@ -0,0 +1,2 @@ +const A = class {}; +new A(); diff --git a/packages/scope-manager/tests/fixtures/class/expression/new.ts.shot b/packages/scope-manager/tests/fixtures/class/expression/new.ts.shot new file mode 100644 index 000000000000..0342a721cc2c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/new.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class expression new 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"A">, + node: VariableDeclarator$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ClassExpression$2, + }, + Reference$2 { + identifier: Identifier<"A">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "A" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ClassScope$2 { + block: ClassExpression$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "class", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts b/packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts new file mode 100644 index 000000000000..2c14373275ce --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts @@ -0,0 +1,16 @@ +const outer = 1; +type Outer = 1; +const A = class { + constructor( + private a, + private b = 1, + private c = a, + public d = outer, + public e, + readonly f: Outer, + ) { + a; + } +}; + +const unresovled = e; diff --git a/packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts.shot b/packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts.shot new file mode 100644 index 000000000000..2f6eb319688a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/parameter-properties.ts.shot @@ -0,0 +1,288 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class expression parameter-properties 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer">, + node: VariableDeclarator$1, + }, + ], + name: "outer", + references: Array [ + Reference$1 { + identifier: Identifier<"outer">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$7 { + identifier: Identifier<"outer">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"Outer">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Outer", + references: Array [ + Reference$8 { + identifier: Identifier<"Outer">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"A">, + node: VariableDeclarator$4, + }, + ], + name: "A", + references: Array [ + Reference$2 { + identifier: Identifier<"A">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: ClassExpression$5, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"a">, + node: FunctionExpression$6, + }, + ], + name: "a", + references: Array [ + Reference$5 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + }, + Reference$9 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"b">, + node: FunctionExpression$6, + }, + ], + name: "b", + references: Array [ + Reference$3 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + writeExpr: Literal$7, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"c">, + node: FunctionExpression$6, + }, + ], + name: "c", + references: Array [ + Reference$4 { + identifier: Identifier<"c">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"d">, + node: FunctionExpression$6, + }, + ], + name: "d", + references: Array [ + Reference$6 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$8, + writeExpr: Identifier<"outer">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + ParameterDefinition$8 { + name: Identifier<"e">, + node: FunctionExpression$6, + }, + ], + name: "e", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$10 { + defs: Array [ + ParameterDefinition$9 { + name: Identifier<"f">, + node: FunctionExpression$6, + }, + ], + name: "f", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$11 { + defs: Array [ + VariableDefinition$10 { + name: Identifier<"unresovled">, + node: VariableDeclarator$8, + }, + ], + name: "unresovled", + references: Array [ + Reference$10 { + identifier: Identifier<"unresovled">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$11, + writeExpr: Identifier<"e">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$9, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$10, + Reference$11 { + identifier: Identifier<"e">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "outer" => Variable$1, + "Outer" => Variable$2, + "A" => Variable$3, + "unresovled" => Variable$11, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + Variable$11, + ], + }, + ClassScope$2 { + block: ClassExpression$5, + isStrict: true, + references: Array [], + set: Map {}, + type: "class", + upper: GlobalScope$1, + variables: Array [], + }, + FunctionScope$3 { + block: FunctionExpression$6, + isStrict: true, + references: Array [ + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + Reference$8, + Reference$9, + ], + set: Map { + "arguments" => Variable$4, + "a" => Variable$5, + "b" => Variable$6, + "c" => Variable$7, + "d" => Variable$8, + "e" => Variable$9, + "f" => Variable$10, + }, + type: "function", + upper: ClassScope$2, + variables: Array [ + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + Variable$9, + Variable$10, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/class/expression/properties.ts b/packages/scope-manager/tests/fixtures/class/expression/properties.ts new file mode 100644 index 000000000000..49b1efe6297e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/properties.ts @@ -0,0 +1,5 @@ +const A = class { + prop = 1; +}; + +const unresolved = prop; diff --git a/packages/scope-manager/tests/fixtures/class/expression/properties.ts.shot b/packages/scope-manager/tests/fixtures/class/expression/properties.ts.shot new file mode 100644 index 000000000000..4aa6d42b2d27 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/class/expression/properties.ts.shot @@ -0,0 +1,85 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`class expression properties 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"A">, + node: VariableDeclarator$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ClassExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"unresolved">, + node: VariableDeclarator$3, + }, + ], + name: "unresolved", + references: Array [ + Reference$2 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Identifier<"prop">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3 { + identifier: Identifier<"prop">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "A" => Variable$1, + "unresolved" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ClassScope$2 { + block: ClassExpression$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "class", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/decorators/accessor.ts b/packages/scope-manager/tests/fixtures/decorators/accessor.ts new file mode 100644 index 000000000000..764ea5e33407 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/accessor.ts @@ -0,0 +1,9 @@ +function decorator() {} +class Foo { + @decorator + get foo() { + return 1; + } + @decorator + set foo() {} +} diff --git a/packages/scope-manager/tests/fixtures/decorators/accessor.ts.shot b/packages/scope-manager/tests/fixtures/decorators/accessor.ts.shot new file mode 100644 index 000000000000..542795da0546 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/accessor.ts.shot @@ -0,0 +1,150 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators accessor 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"decorator">, + node: FunctionDeclaration$1, + }, + ], + name: "decorator", + references: Array [ + Reference$1 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "decorator" => Variable$1, + "Foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "Foo" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + FunctionScope$4 { + block: FunctionExpression$4, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: ClassScope$3, + variables: Array [ + Variable$5, + ], + }, + FunctionScope$5 { + block: FunctionExpression$5, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$6, + }, + type: "function", + upper: ClassScope$3, + variables: Array [ + Variable$6, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/decorators/class-property.ts b/packages/scope-manager/tests/fixtures/decorators/class-property.ts new file mode 100644 index 000000000000..bbd51c608e5e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/class-property.ts @@ -0,0 +1,5 @@ +function decorator() {} +class Foo { + @decorator + foo; +} diff --git a/packages/scope-manager/tests/fixtures/decorators/class-property.ts.shot b/packages/scope-manager/tests/fixtures/decorators/class-property.ts.shot new file mode 100644 index 000000000000..a84bb27badd3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/class-property.ts.shot @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators class-property 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"decorator">, + node: FunctionDeclaration$1, + }, + ], + name: "decorator", + references: Array [ + Reference$1 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "decorator" => Variable$1, + "Foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/decorators/class.ts b/packages/scope-manager/tests/fixtures/decorators/class.ts new file mode 100644 index 000000000000..6ee77c778092 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/class.ts @@ -0,0 +1,3 @@ +function decorator() {} +@decorator +class Foo {} diff --git a/packages/scope-manager/tests/fixtures/decorators/class.ts.shot b/packages/scope-manager/tests/fixtures/decorators/class.ts.shot new file mode 100644 index 000000000000..d4a77260876e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/class.ts.shot @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators class 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"decorator">, + node: FunctionDeclaration$1, + }, + ], + name: "decorator", + references: Array [ + Reference$1 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "decorator" => Variable$1, + "Foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/decorators/method.ts b/packages/scope-manager/tests/fixtures/decorators/method.ts new file mode 100644 index 000000000000..1ef9323c8a4d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/method.ts @@ -0,0 +1,5 @@ +function decorator() {} +class Foo { + @decorator + foo() {} +} diff --git a/packages/scope-manager/tests/fixtures/decorators/method.ts.shot b/packages/scope-manager/tests/fixtures/decorators/method.ts.shot new file mode 100644 index 000000000000..54212a2016ea --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/method.ts.shot @@ -0,0 +1,123 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators method 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"decorator">, + node: FunctionDeclaration$1, + }, + ], + name: "decorator", + references: Array [ + Reference$1 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "decorator" => Variable$1, + "Foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + FunctionScope$4 { + block: FunctionExpression$4, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: ClassScope$3, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/decorators/parameter-property.ts b/packages/scope-manager/tests/fixtures/decorators/parameter-property.ts new file mode 100644 index 000000000000..1b2a5356f7c4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/parameter-property.ts @@ -0,0 +1,4 @@ +function decorator() {} +class Foo { + constructor(@decorator readonly a, @decorator readonly b = 1) {} +} diff --git a/packages/scope-manager/tests/fixtures/decorators/parameter-property.ts.shot b/packages/scope-manager/tests/fixtures/decorators/parameter-property.ts.shot new file mode 100644 index 000000000000..636844510a34 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/parameter-property.ts.shot @@ -0,0 +1,168 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators parameter-property 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"decorator">, + node: FunctionDeclaration$1, + }, + ], + name: "decorator", + references: Array [ + Reference$1 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$3 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ClassNameDefinition$3 { + name: Identifier<"Foo">, + node: ClassDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"a">, + node: FunctionExpression$3, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Literal$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "decorator" => Variable$1, + "Foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ClassScope$3 { + block: ClassDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + FunctionScope$4 { + block: FunctionExpression$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$5, + "a" => Variable$6, + "b" => Variable$7, + }, + type: "function", + upper: ClassScope$3, + variables: Array [ + Variable$5, + Variable$6, + Variable$7, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/decorators/parameter.ts b/packages/scope-manager/tests/fixtures/decorators/parameter.ts new file mode 100644 index 000000000000..2b9b32b2bb2f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/parameter.ts @@ -0,0 +1,7 @@ +function decorator() {} +function foo( + @decorator a, + @decorator [b], + @decorator { c }, + @decorator d = 1, +) {} diff --git a/packages/scope-manager/tests/fixtures/decorators/parameter.ts.shot b/packages/scope-manager/tests/fixtures/decorators/parameter.ts.shot new file mode 100644 index 000000000000..655435c8dcc0 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/decorators/parameter.ts.shot @@ -0,0 +1,185 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators parameter 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"decorator">, + node: FunctionDeclaration$1, + }, + ], + name: "decorator", + references: Array [ + Reference$1 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$3 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$5 { + identifier: Identifier<"decorator">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"c">, + node: FunctionDeclaration$2, + }, + ], + name: "c", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"d">, + node: FunctionDeclaration$2, + }, + ], + name: "d", + references: Array [ + Reference$4 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$8, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "decorator" => Variable$1, + "foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + FunctionScope$3 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + Reference$5, + ], + set: Map { + "arguments" => Variable$4, + "a" => Variable$5, + "b" => Variable$6, + "c" => Variable$7, + "d" => Variable$8, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts b/packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts new file mode 100644 index 000000000000..a0fb37e1edc1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts @@ -0,0 +1,3 @@ +const obj = {}; +let b, c; +[obj.a, b, [c]] = []; diff --git a/packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts.shot b/packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts.shot new file mode 100644 index 000000000000..c6176b720a14 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/array-assignment.ts.shot @@ -0,0 +1,101 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`destructuring array-assignment 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"obj">, + node: VariableDeclarator$1, + }, + ], + name: "obj", + references: Array [ + Reference$1 { + identifier: Identifier<"obj">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ObjectExpression$2, + }, + Reference$4 { + identifier: Identifier<"obj">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"b">, + node: VariableDeclarator$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: false, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrayExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"c">, + node: VariableDeclarator$5, + }, + ], + name: "c", + references: Array [ + Reference$3 { + identifier: Identifier<"c">, + init: false, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: ArrayExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "obj" => Variable$1, + "b" => Variable$2, + "c" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/destructuring/array.ts b/packages/scope-manager/tests/fixtures/destructuring/array.ts new file mode 100644 index 000000000000..86f9cf6901e3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/array.ts @@ -0,0 +1 @@ +const [a, b, c, d = 1, [e], [f] = g, ...rest] = []; diff --git a/packages/scope-manager/tests/fixtures/destructuring/array.ts.shot b/packages/scope-manager/tests/fixtures/destructuring/array.ts.shot new file mode 100644 index 000000000000..e474481643cf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/array.ts.shot @@ -0,0 +1,214 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`destructuring array 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"b">, + node: VariableDeclarator$1, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"c">, + node: VariableDeclarator$1, + }, + ], + name: "c", + references: Array [ + Reference$3 { + identifier: Identifier<"c">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"d">, + node: VariableDeclarator$1, + }, + ], + name: "d", + references: Array [ + Reference$4 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Literal$3, + }, + Reference$5 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + VariableDefinition$5 { + name: Identifier<"e">, + node: VariableDeclarator$1, + }, + ], + name: "e", + references: Array [ + Reference$6 { + identifier: Identifier<"e">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + VariableDefinition$6 { + name: Identifier<"f">, + node: VariableDeclarator$1, + }, + ], + name: "f", + references: Array [ + Reference$7 { + identifier: Identifier<"f">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + writeExpr: Identifier<"g">, + }, + Reference$8 { + identifier: Identifier<"f">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + VariableDefinition$7 { + name: Identifier<"rest">, + node: VariableDeclarator$1, + }, + ], + name: "rest", + references: Array [ + Reference$9 { + identifier: Identifier<"rest">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: ArrayExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + Reference$8, + Reference$9, + Reference$10 { + identifier: Identifier<"g">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "a" => Variable$1, + "b" => Variable$2, + "c" => Variable$3, + "d" => Variable$4, + "e" => Variable$5, + "f" => Variable$6, + "rest" => Variable$7, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts b/packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts new file mode 100644 index 000000000000..a2cc7daf8d2e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts @@ -0,0 +1,6 @@ +const obj = {}; +({ + shorthand, + key: value, + hello: { world: obj.a }, +} = object); diff --git a/packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts.shot b/packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts.shot new file mode 100644 index 000000000000..e0fefe1d2674 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/object-assignment.ts.shot @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`destructuring object-assignment 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"obj">, + node: VariableDeclarator$1, + }, + ], + name: "obj", + references: Array [ + Reference$1 { + identifier: Identifier<"obj">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ObjectExpression$2, + }, + Reference$4 { + identifier: Identifier<"obj">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"shorthand">, + init: false, + isTypeReference: false, + isValueReference: true, + resolved: null, + writeExpr: Identifier<"object">, + }, + Reference$3 { + identifier: Identifier<"value">, + init: false, + isTypeReference: false, + isValueReference: true, + resolved: null, + writeExpr: Identifier<"object">, + }, + Reference$4, + Reference$5 { + identifier: Identifier<"object">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "obj" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/destructuring/object.ts b/packages/scope-manager/tests/fixtures/destructuring/object.ts new file mode 100644 index 000000000000..1b35c309cd41 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/object.ts @@ -0,0 +1,6 @@ +const { + shorthand, + key: value, + hello: { world }, + array: [a, b, c, d], +} = object; diff --git a/packages/scope-manager/tests/fixtures/destructuring/object.ts.shot b/packages/scope-manager/tests/fixtures/destructuring/object.ts.shot new file mode 100644 index 000000000000..17617b312588 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/destructuring/object.ts.shot @@ -0,0 +1,196 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`destructuring object 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"shorthand">, + node: VariableDeclarator$1, + }, + ], + name: "shorthand", + references: Array [ + Reference$1 { + identifier: Identifier<"shorthand">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"value">, + node: VariableDeclarator$1, + }, + ], + name: "value", + references: Array [ + Reference$2 { + identifier: Identifier<"value">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"world">, + node: VariableDeclarator$1, + }, + ], + name: "world", + references: Array [ + Reference$3 { + identifier: Identifier<"world">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$4 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + VariableDefinition$5 { + name: Identifier<"b">, + node: VariableDeclarator$1, + }, + ], + name: "b", + references: Array [ + Reference$5 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + VariableDefinition$6 { + name: Identifier<"c">, + node: VariableDeclarator$1, + }, + ], + name: "c", + references: Array [ + Reference$6 { + identifier: Identifier<"c">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + VariableDefinition$7 { + name: Identifier<"d">, + node: VariableDeclarator$1, + }, + ], + name: "d", + references: Array [ + Reference$7 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Identifier<"object">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + Reference$8 { + identifier: Identifier<"object">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "shorthand" => Variable$1, + "value" => Variable$2, + "world" => Variable$3, + "a" => Variable$4, + "b" => Variable$5, + "c" => Variable$6, + "d" => Variable$7, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/all.ts b/packages/scope-manager/tests/fixtures/export/all.ts new file mode 100644 index 000000000000..05c93176fac6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/all.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +export * from 'foo'; +export * as bar from 'foo'; diff --git a/packages/scope-manager/tests/fixtures/export/all.ts.shot b/packages/scope-manager/tests/fixtures/export/all.ts.shot new file mode 100644 index 000000000000..a420ebe9cc08 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/all.ts.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export all 1`] = ` +ScopeManager { + variables: Array [], + scopes: Array [ + GlobalScope$1 { + block: Program$1, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$1, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/default-type.ts b/packages/scope-manager/tests/fixtures/export/default-type.ts new file mode 100644 index 000000000000..d62a0213891e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default-type.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +type T = 1; +export default T; diff --git a/packages/scope-manager/tests/fixtures/export/default-type.ts.shot b/packages/scope-manager/tests/fixtures/export/default-type.ts.shot new file mode 100644 index 000000000000..9c1d1fc17fd1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default-type.ts.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export default-type 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/default1.ts b/packages/scope-manager/tests/fixtures/export/default1.ts new file mode 100644 index 000000000000..b9427a508f51 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default1.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export default function f() {} diff --git a/packages/scope-manager/tests/fixtures/export/default1.ts.shot b/packages/scope-manager/tests/fixtures/export/default1.ts.shot new file mode 100644 index 000000000000..7e8fe1b48b81 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default1.ts.shot @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export default1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"f">, + node: FunctionDeclaration$1, + }, + ], + name: "f", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [], + set: Map { + "f" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$3 { + block: FunctionDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: ModuleScope$2, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/default2.ts b/packages/scope-manager/tests/fixtures/export/default2.ts new file mode 100644 index 000000000000..319a863c2456 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default2.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +const a = 1; +export default a; diff --git a/packages/scope-manager/tests/fixtures/export/default2.ts.shot b/packages/scope-manager/tests/fixtures/export/default2.ts.shot new file mode 100644 index 000000000000..99b0eb60ca57 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default2.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export default2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "a" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/default3.ts b/packages/scope-manager/tests/fixtures/export/default3.ts new file mode 100644 index 000000000000..a5d671a6b31c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default3.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export default 1; diff --git a/packages/scope-manager/tests/fixtures/export/default3.ts.shot b/packages/scope-manager/tests/fixtures/export/default3.ts.shot new file mode 100644 index 000000000000..620d33c95346 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default3.ts.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export default3 1`] = ` +ScopeManager { + variables: Array [], + scopes: Array [ + GlobalScope$1 { + block: Program$1, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$1, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/default4.ts b/packages/scope-manager/tests/fixtures/export/default4.ts new file mode 100644 index 000000000000..8a6fea86b711 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default4.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export default function () {} diff --git a/packages/scope-manager/tests/fixtures/export/default4.ts.shot b/packages/scope-manager/tests/fixtures/export/default4.ts.shot new file mode 100644 index 000000000000..c02248243ecd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/default4.ts.shot @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export default4 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$1, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$1, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + FunctionScope$3 { + block: FunctionDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$1, + }, + type: "function", + upper: ModuleScope$2, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/equals1.ts b/packages/scope-manager/tests/fixtures/export/equals1.ts new file mode 100644 index 000000000000..8bab055cb87f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/equals1.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +const x = 1; +export = x; diff --git a/packages/scope-manager/tests/fixtures/export/equals1.ts.shot b/packages/scope-manager/tests/fixtures/export/equals1.ts.shot new file mode 100644 index 000000000000..c693c5901301 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/equals1.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export equals1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "x" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/equals2.ts b/packages/scope-manager/tests/fixtures/export/equals2.ts new file mode 100644 index 000000000000..67d85f90bed8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/equals2.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export = 1; diff --git a/packages/scope-manager/tests/fixtures/export/equals2.ts.shot b/packages/scope-manager/tests/fixtures/export/equals2.ts.shot new file mode 100644 index 000000000000..3b83940b97eb --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/equals2.ts.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export equals2 1`] = ` +ScopeManager { + variables: Array [], + scopes: Array [ + GlobalScope$1 { + block: Program$1, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$1, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named-dual.ts b/packages/scope-manager/tests/fixtures/export/named-dual.ts new file mode 100644 index 000000000000..011ed067a6e2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-dual.ts @@ -0,0 +1,3 @@ +const T = 1; +type T = 1; +export { T }; diff --git a/packages/scope-manager/tests/fixtures/export/named-dual.ts.shot b/packages/scope-manager/tests/fixtures/export/named-dual.ts.shot new file mode 100644 index 000000000000..bf610032f58d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-dual.ts.shot @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named-dual 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"T">, + node: VariableDeclarator$1, + }, + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$3, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named-source1.ts b/packages/scope-manager/tests/fixtures/export/named-source1.ts new file mode 100644 index 000000000000..d7354f5d9bcf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-source1.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export { x } from 'foo'; diff --git a/packages/scope-manager/tests/fixtures/export/named-source1.ts.shot b/packages/scope-manager/tests/fixtures/export/named-source1.ts.shot new file mode 100644 index 000000000000..7598572fc78e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-source1.ts.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named-source1 1`] = ` +ScopeManager { + variables: Array [], + scopes: Array [ + GlobalScope$1 { + block: Program$1, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$1, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named-source2.ts b/packages/scope-manager/tests/fixtures/export/named-source2.ts new file mode 100644 index 000000000000..2630c6db88af --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-source2.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export { v as x } from 'foo'; diff --git a/packages/scope-manager/tests/fixtures/export/named-source2.ts.shot b/packages/scope-manager/tests/fixtures/export/named-source2.ts.shot new file mode 100644 index 000000000000..e56a8288c32a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-source2.ts.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named-source2 1`] = ` +ScopeManager { + variables: Array [], + scopes: Array [ + GlobalScope$1 { + block: Program$1, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$1, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named-type1.ts b/packages/scope-manager/tests/fixtures/export/named-type1.ts new file mode 100644 index 000000000000..7b0c1fd08785 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-type1.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export type X = 1; diff --git a/packages/scope-manager/tests/fixtures/export/named-type1.ts.shot b/packages/scope-manager/tests/fixtures/export/named-type1.ts.shot new file mode 100644 index 000000000000..f9b193e83db1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named-type1.ts.shot @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named-type1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"X">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "X", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [], + set: Map { + "X" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named1.ts b/packages/scope-manager/tests/fixtures/export/named1.ts new file mode 100644 index 000000000000..e73a99dca554 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named1.ts @@ -0,0 +1,3 @@ +//// @sourceType = module + +export const x = 1; diff --git a/packages/scope-manager/tests/fixtures/export/named1.ts.shot b/packages/scope-manager/tests/fixtures/export/named1.ts.shot new file mode 100644 index 000000000000..b10f6f58a2d7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named1.ts.shot @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "x" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named2-type.ts b/packages/scope-manager/tests/fixtures/export/named2-type.ts new file mode 100644 index 000000000000..50e977e58ba0 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named2-type.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +type A = 1; +export { A }; diff --git a/packages/scope-manager/tests/fixtures/export/named2-type.ts.shot b/packages/scope-manager/tests/fixtures/export/named2-type.ts.shot new file mode 100644 index 000000000000..6bd10e23f17d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named2-type.ts.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named2-type 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named2.ts b/packages/scope-manager/tests/fixtures/export/named2.ts new file mode 100644 index 000000000000..056e74c313b8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named2.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +const a = 1; +export { a }; diff --git a/packages/scope-manager/tests/fixtures/export/named2.ts.shot b/packages/scope-manager/tests/fixtures/export/named2.ts.shot new file mode 100644 index 000000000000..73dd13542c6d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named2.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "a" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named3-type.ts b/packages/scope-manager/tests/fixtures/export/named3-type.ts new file mode 100644 index 000000000000..543a0e996f11 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named3-type.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +type V = 1; +export { V as X }; diff --git a/packages/scope-manager/tests/fixtures/export/named3-type.ts.shot b/packages/scope-manager/tests/fixtures/export/named3-type.ts.shot new file mode 100644 index 000000000000..500935bdd76b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named3-type.ts.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named3-type 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"V">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "V", + references: Array [ + Reference$1 { + identifier: Identifier<"V">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "V" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/named3.ts b/packages/scope-manager/tests/fixtures/export/named3.ts new file mode 100644 index 000000000000..044a7dea2be4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named3.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +const v = 1; +export { v as x }; diff --git a/packages/scope-manager/tests/fixtures/export/named3.ts.shot b/packages/scope-manager/tests/fixtures/export/named3.ts.shot new file mode 100644 index 000000000000..198603fdebc1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/named3.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export named3 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"v">, + node: VariableDeclarator$1, + }, + ], + name: "v", + references: Array [ + Reference$1 { + identifier: Identifier<"v">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"v">, + isTypeReference: true, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "v" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/export/type.ts b/packages/scope-manager/tests/fixtures/export/type.ts new file mode 100644 index 000000000000..7ca93bbfefbb --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/type.ts @@ -0,0 +1,5 @@ +//// @sourceType = module + +const T = 1; // unreferenced +type T = 1; +export type { T }; diff --git a/packages/scope-manager/tests/fixtures/export/type.ts.shot b/packages/scope-manager/tests/fixtures/export/type.ts.shot new file mode 100644 index 000000000000..181f5ed6da8a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/export/type.ts.shot @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`export type 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"T">, + node: VariableDeclarator$1, + }, + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$3, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts new file mode 100644 index 000000000000..b932c662abf6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts @@ -0,0 +1,5 @@ +let a; +// the default param value is resolved to the outer scope +let foo = (b = a) => { + let a; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts.shot new file mode 100644 index 000000000000..1478c2789fca --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-body-shadow.ts.shot @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-body-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$4, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "b" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts new file mode 100644 index 000000000000..57bbb0b4cdb1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts @@ -0,0 +1,2 @@ +const a = 0; +let foo = (b = a) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts.shot new file mode 100644 index 000000000000..504bc63a07f1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-const.ts.shot @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-const 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$3, + }, + ], + name: "foo", + references: Array [ + Reference$2 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$4, + }, + ], + name: "b", + references: Array [ + Reference$3 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + Reference$4, + ], + set: Map { + "b" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts new file mode 100644 index 000000000000..4b73fa5e3a6e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts @@ -0,0 +1,2 @@ +let a; +let foo = (b = a) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts.shot new file mode 100644 index 000000000000..e9ce64886bbd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-let.ts.shot @@ -0,0 +1,104 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-let 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "b" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts new file mode 100644 index 000000000000..1413a2a15345 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts @@ -0,0 +1,8 @@ +let a; +let foo = ( + b = function () { + a; + }, +) => { + let a; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts.shot new file mode 100644 index 000000000000..0466d943655b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested-body-shadow.ts.shot @@ -0,0 +1,139 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-nested-body-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$5, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "b" => Variable$3, + "a" => Variable$5, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$5, + ], + }, + FunctionScope$3 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + ], + set: Map { + "arguments" => Variable$4, + }, + type: "function", + upper: FunctionScope$2, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts new file mode 100644 index 000000000000..1f1c08f6c83a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts @@ -0,0 +1,6 @@ +let a; +let foo = ( + b = function () { + return a; + }, +) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts.shot new file mode 100644 index 000000000000..ba9e9641cfe9 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-nested.ts.shot @@ -0,0 +1,125 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-nested 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "b" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + FunctionScope$3 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + ], + set: Map { + "arguments" => Variable$4, + }, + type: "function", + upper: FunctionScope$2, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts new file mode 100644 index 000000000000..f9a7cf72ccb3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts @@ -0,0 +1,3 @@ +let a; +// the default param value is resolved to the parameter +let foo = (b = a, a) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts.shot new file mode 100644 index 000000000000..b200c1d9d83f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-param-shadow.ts.shot @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-param-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"a">, + node: ArrowFunctionExpression$3, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "b" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts new file mode 100644 index 000000000000..6fa7d4698f54 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts @@ -0,0 +1,2 @@ +let a; +let foo = (b = a.c) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts.shot new file mode 100644 index 000000000000..8464c51df51b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/readable-ref-partial.ts.shot @@ -0,0 +1,104 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params readable-ref-partial 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrowFunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: MemberExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "b" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts new file mode 100644 index 000000000000..0bc2e3c61149 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts @@ -0,0 +1 @@ +let foo = (a, b = 0) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts.shot new file mode 100644 index 000000000000..1e52b8daf5fa --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/default-params/writable-ref.ts.shot @@ -0,0 +1,96 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow default-params writable-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: ArrowFunctionExpression$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$2, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "a" => Variable$2, + "b" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts b/packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts new file mode 100644 index 000000000000..60bbda6ce002 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts @@ -0,0 +1,5 @@ +const parentScoped = 1; + +() => { + parentScoped + 1; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts.shot new file mode 100644 index 000000000000..f1c2f84609ca --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/inherited-scope.ts.shot @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow inherited-scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"parentScoped">, + node: VariableDeclarator$1, + }, + ], + name: "parentScoped", + references: Array [ + Reference$1 { + identifier: Identifier<"parentScoped">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"parentScoped">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "parentScoped" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$4, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map {}, + type: "function", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts b/packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts new file mode 100644 index 000000000000..d24dce0d806c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts @@ -0,0 +1 @@ +a => a; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts.shot new file mode 100644 index 000000000000..a837f9931f0d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/no-body.ts.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow no-body 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ParameterDefinition$1 { + name: Identifier<"a">, + node: ArrowFunctionExpression$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$1, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/params.ts b/packages/scope-manager/tests/fixtures/functions/arrow/params.ts new file mode 100644 index 000000000000..29e5351527d2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/params.ts @@ -0,0 +1,6 @@ +const outer = 1; +(a, [b], { c }, d = 1, e = a, f = outer, g) => { + a; +}; + +const unresolved = g; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/params.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/params.ts.shot new file mode 100644 index 000000000000..fe084bc99768 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/params.ts.shot @@ -0,0 +1,238 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow params 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer">, + node: VariableDeclarator$1, + }, + ], + name: "outer", + references: Array [ + Reference$1 { + identifier: Identifier<"outer">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$6 { + identifier: Identifier<"outer">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: ArrowFunctionExpression$3, + }, + ], + name: "a", + references: Array [ + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + Reference$7 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: ArrowFunctionExpression$3, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"c">, + node: ArrowFunctionExpression$3, + }, + ], + name: "c", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"d">, + node: ArrowFunctionExpression$3, + }, + ], + name: "d", + references: Array [ + Reference$2 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + writeExpr: Literal$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"e">, + node: ArrowFunctionExpression$3, + }, + ], + name: "e", + references: Array [ + Reference$3 { + identifier: Identifier<"e">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"f">, + node: ArrowFunctionExpression$3, + }, + ], + name: "f", + references: Array [ + Reference$5 { + identifier: Identifier<"f">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Identifier<"outer">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$8 { + name: Identifier<"g">, + node: ArrowFunctionExpression$3, + }, + ], + name: "g", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + VariableDefinition$9 { + name: Identifier<"unresolved">, + node: VariableDeclarator$5, + }, + ], + name: "unresolved", + references: Array [ + Reference$8 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$9, + writeExpr: Identifier<"g">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$8, + Reference$9 { + identifier: Identifier<"g">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "outer" => Variable$1, + "unresolved" => Variable$9, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$9, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + ], + set: Map { + "a" => Variable$2, + "b" => Variable$3, + "c" => Variable$4, + "d" => Variable$5, + "e" => Variable$6, + "f" => Variable$7, + "g" => Variable$8, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/scope.ts b/packages/scope-manager/tests/fixtures/functions/arrow/scope.ts new file mode 100644 index 000000000000..6588507859cd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/scope.ts @@ -0,0 +1,8 @@ +const arrow = () => { + let i = 0; + var j = 20; + + i; +}; + +const unresolved = j; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/scope.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/scope.ts.shot new file mode 100644 index 000000000000..72ab01f0b9eb --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/scope.ts.shot @@ -0,0 +1,143 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"arrow">, + node: VariableDeclarator$1, + }, + ], + name: "arrow", + references: Array [ + Reference$1 { + identifier: Identifier<"arrow">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"i">, + node: VariableDeclarator$3, + }, + ], + name: "i", + references: Array [ + Reference$2 { + identifier: Identifier<"i">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$4, + }, + Reference$4 { + identifier: Identifier<"i">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"j">, + node: VariableDeclarator$5, + }, + ], + name: "j", + references: Array [ + Reference$3 { + identifier: Identifier<"j">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"unresolved">, + node: VariableDeclarator$7, + }, + ], + name: "unresolved", + references: Array [ + Reference$5 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"j">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$8, + isStrict: false, + references: Array [ + Reference$1, + Reference$5, + Reference$6 { + identifier: Identifier<"j">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "arrow" => Variable$1, + "unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "i" => Variable$2, + "j" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts new file mode 100644 index 000000000000..16d3f36482bd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts @@ -0,0 +1,3 @@ +const foo = () => { + let x: T; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts.shot new file mode 100644 index 000000000000..0b336fc5a85e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/body-reference.ts.shot @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow type-parameters body-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$4, + }, + ], + name: "x", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "T" => Variable$2, + "x" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts new file mode 100644 index 000000000000..eaa11b78b899 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts @@ -0,0 +1 @@ +const foo = (a: T) => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts.shot new file mode 100644 index 000000000000..b610cb39c541 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/param-reference.ts.shot @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow type-parameters param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: ArrowFunctionExpression$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "a" => Variable$2, + "T" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts new file mode 100644 index 000000000000..e18d95bc4c35 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts @@ -0,0 +1 @@ +const foo = (): T => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts.shot new file mode 100644 index 000000000000..fb8b4b88e1b3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/return-value-reference.ts.shot @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow type-parameters return-value-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "T" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts new file mode 100644 index 000000000000..6a6ca837c15d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts @@ -0,0 +1 @@ +const foo = () => {}; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts.shot new file mode 100644 index 000000000000..ce4e32ff765b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-param-reference.ts.shot @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow type-parameters type-param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$4, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "T" => Variable$2, + "U" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts new file mode 100644 index 000000000000..c863d3086fd5 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts @@ -0,0 +1,3 @@ +const foo = () => {}; + +type Unresolved = T; diff --git a/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts.shot b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts.shot new file mode 100644 index 000000000000..a83255e192de --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/arrow/type-parameters/type-parameter-declaration.ts.shot @@ -0,0 +1,91 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions arrow type-parameters type-parameter-declaration 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "foo" => Variable$1, + "Unresolved" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts new file mode 100644 index 000000000000..fbe1e8d1af6b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts @@ -0,0 +1,5 @@ +let a; +// the default param value is resolved to the outer scope +function foo(b = a) { + let a; +} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts.shot new file mode 100644 index 000000000000..bcee2db14319 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-body-shadow.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-body-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$3, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + "a" => Variable$5, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts new file mode 100644 index 000000000000..8d6ce23c6809 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts @@ -0,0 +1,2 @@ +const a = 0; +function foo(b = a) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts.shot new file mode 100644 index 000000000000..62c0cf7eafcd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-const.ts.shot @@ -0,0 +1,112 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-const 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$3, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts new file mode 100644 index 000000000000..6b82f860ad30 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts @@ -0,0 +1,2 @@ +let a; +function foo(b = a) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts.shot new file mode 100644 index 000000000000..43cb526af51b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-let.ts.shot @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-let 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts new file mode 100644 index 000000000000..39cac38f4f5b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts @@ -0,0 +1,8 @@ +let a; +function foo( + b = function () { + a; + }, +) { + let a; +} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts.shot new file mode 100644 index 000000000000..14140d27765e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested-body-shadow.ts.shot @@ -0,0 +1,137 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-nested-body-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$4, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + "a" => Variable$6, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$6, + ], + }, + FunctionScope$3 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: FunctionScope$2, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts new file mode 100644 index 000000000000..7e27579ed934 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts @@ -0,0 +1,6 @@ +let a; +function foo( + b = function () { + return a; + }, +) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts.shot new file mode 100644 index 000000000000..772c0dec0d27 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-nested.ts.shot @@ -0,0 +1,123 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-nested 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + FunctionScope$3 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: FunctionScope$2, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts new file mode 100644 index 000000000000..4a091a09d67d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts @@ -0,0 +1,3 @@ +let a; +// the default param value is resolved to the parameter +function foo(b = a, a) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts.shot new file mode 100644 index 000000000000..320f10d23612 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-param-shadow.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-param-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + "a" => Variable$5, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts new file mode 100644 index 000000000000..84945daa7407 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts @@ -0,0 +1,2 @@ +let a; +function foo(b = a.c) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts.shot new file mode 100644 index 000000000000..a4274c458a49 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/readable-ref-partial.ts.shot @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params readable-ref-partial 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: MemberExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts new file mode 100644 index 000000000000..ca81afa12686 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts @@ -0,0 +1 @@ +function foo(a, b = 0) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts.shot new file mode 100644 index 000000000000..1063bdb6d56a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/default-params/writable-ref.ts.shot @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration default-params writable-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: FunctionDeclaration$1, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionDeclaration$1, + }, + ], + name: "b", + references: Array [ + Reference$1 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Literal$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts new file mode 100644 index 000000000000..26b40f7667eb --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts @@ -0,0 +1,5 @@ +const parentScoped = 1; + +function foo() { + parentScoped + 1; +} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts.shot new file mode 100644 index 000000000000..bf664a1b49f1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/inherited-scope.ts.shot @@ -0,0 +1,88 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration inherited-scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"parentScoped">, + node: VariableDeclarator$1, + }, + ], + name: "parentScoped", + references: Array [ + Reference$1 { + identifier: Identifier<"parentScoped">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"parentScoped">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$3, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "parentScoped" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts new file mode 100644 index 000000000000..682fecea6e45 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts @@ -0,0 +1,4 @@ +function foo(a, b); +function foo(a, b) { + a; +} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts.shot new file mode 100644 index 000000000000..b6106082105f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/overload.ts.shot @@ -0,0 +1,144 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration overload 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: TSDeclareFunction$1, + }, + FunctionNameDefinition$4 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: TSDeclareFunction$1, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: TSDeclareFunction$1, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"b">, + node: FunctionDeclaration$2, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: TSDeclareFunction$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + FunctionScope$3 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$5, + "a" => Variable$6, + "b" => Variable$7, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$5, + Variable$6, + Variable$7, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts new file mode 100644 index 000000000000..202c4e4a17a3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts @@ -0,0 +1,6 @@ +const outer = 1; +function foo(a, [b], { c }, d = 1, e = a, f = outer, g) { + a; +} + +const unresolved = g; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts.shot new file mode 100644 index 000000000000..a1783e6a476f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/params.ts.shot @@ -0,0 +1,261 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration params 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer">, + node: VariableDeclarator$1, + }, + ], + name: "outer", + references: Array [ + Reference$1 { + identifier: Identifier<"outer">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$6 { + identifier: Identifier<"outer">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$3, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$3, + }, + ], + name: "a", + references: Array [ + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + Reference$7 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"b">, + node: FunctionDeclaration$3, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"c">, + node: FunctionDeclaration$3, + }, + ], + name: "c", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"d">, + node: FunctionDeclaration$3, + }, + ], + name: "d", + references: Array [ + Reference$2 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Literal$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"e">, + node: FunctionDeclaration$3, + }, + ], + name: "e", + references: Array [ + Reference$3 { + identifier: Identifier<"e">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$8, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + ParameterDefinition$8 { + name: Identifier<"f">, + node: FunctionDeclaration$3, + }, + ], + name: "f", + references: Array [ + Reference$5 { + identifier: Identifier<"f">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$9, + writeExpr: Identifier<"outer">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$10 { + defs: Array [ + ParameterDefinition$9 { + name: Identifier<"g">, + node: FunctionDeclaration$3, + }, + ], + name: "g", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$11 { + defs: Array [ + VariableDefinition$10 { + name: Identifier<"unresolved">, + node: VariableDeclarator$5, + }, + ], + name: "unresolved", + references: Array [ + Reference$8 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$11, + writeExpr: Identifier<"g">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$8, + Reference$9 { + identifier: Identifier<"g">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "outer" => Variable$1, + "foo" => Variable$2, + "unresolved" => Variable$11, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$11, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + "b" => Variable$5, + "c" => Variable$6, + "d" => Variable$7, + "e" => Variable$8, + "f" => Variable$9, + "g" => Variable$10, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + Variable$9, + Variable$10, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts new file mode 100644 index 000000000000..eba6a56b3365 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts @@ -0,0 +1,8 @@ +function foo() { + let i = 0; + var j = 20; + + i; +} + +const unresolved = j; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts.shot new file mode 100644 index 000000000000..32faa293018d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/scope.ts.shot @@ -0,0 +1,142 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"i">, + node: VariableDeclarator$2, + }, + ], + name: "i", + references: Array [ + Reference$1 { + identifier: Identifier<"i">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$3, + }, + Reference$3 { + identifier: Identifier<"i">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"j">, + node: VariableDeclarator$4, + }, + ], + name: "j", + references: Array [ + Reference$2 { + identifier: Identifier<"j">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Literal$5, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"unresolved">, + node: VariableDeclarator$6, + }, + ], + name: "unresolved", + references: Array [ + Reference$4 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + writeExpr: Identifier<"j">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$7, + isStrict: false, + references: Array [ + Reference$4, + Reference$5 { + identifier: Identifier<"j">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "foo" => Variable$1, + "unresolved" => Variable$5, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$5, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$2, + "i" => Variable$3, + "j" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts new file mode 100644 index 000000000000..109f4ac8f61f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts @@ -0,0 +1,3 @@ +function foo() { + let x: T; +} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts.shot new file mode 100644 index 000000000000..cc1205bc1b03 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/body-reference.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration type-parameters body-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$3, + }, + ], + name: "x", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + "x" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts new file mode 100644 index 000000000000..bb418f8ac3e8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts @@ -0,0 +1 @@ +function foo(a: T) {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts.shot new file mode 100644 index 000000000000..64508a4590a5 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/param-reference.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration type-parameters param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: FunctionDeclaration$1, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$2, + "a" => Variable$3, + "T" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts new file mode 100644 index 000000000000..76b3ffc19ce5 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts @@ -0,0 +1 @@ +function foo(): T {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts.shot new file mode 100644 index 000000000000..4a66bd02c614 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/return-value-reference.ts.shot @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration type-parameters return-value-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts new file mode 100644 index 000000000000..5c8d44c2e5a6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts @@ -0,0 +1 @@ +function foo() {} diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts.shot new file mode 100644 index 000000000000..4f6614cd024e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-param-reference.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration type-parameters type-param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + "U" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts new file mode 100644 index 000000000000..b72b36c61998 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts @@ -0,0 +1,3 @@ +function foo() {} + +type Unresolved = T; diff --git a/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts.shot new file mode 100644 index 000000000000..6d5a11ba0773 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-declaration/type-parameters/type-parameter-declaration.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-declaration type-parameters type-parameter-declaration 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"foo">, + node: FunctionDeclaration$1, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "foo" => Variable$1, + "Unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts new file mode 100644 index 000000000000..5c5bd89ac270 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts @@ -0,0 +1 @@ +const foo = function () {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts.shot new file mode 100644 index 000000000000..8b681e18aab3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/anonymous.ts.shot @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression anonymous 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts new file mode 100644 index 000000000000..ccaf9cd466a1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts @@ -0,0 +1,5 @@ +let a; +// the default param value is resolved to the outer scope +let foo = function (b = a) { + let a; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts.shot new file mode 100644 index 000000000000..67aa969da0af --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-body-shadow.ts.shot @@ -0,0 +1,127 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-body-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$4, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + "a" => Variable$5, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts new file mode 100644 index 000000000000..7edcf2fe655c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts @@ -0,0 +1,2 @@ +const a = 0; +let foo = function (b = a) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts.shot new file mode 100644 index 000000000000..9d7e9a8bac92 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-const.ts.shot @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-const 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$4 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$3, + }, + ], + name: "foo", + references: Array [ + Reference$2 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$4, + }, + ], + name: "b", + references: Array [ + Reference$3 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + Reference$4, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts new file mode 100644 index 000000000000..33f09d35c2ae --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts @@ -0,0 +1,2 @@ +let a; +let foo = function (b = a) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts.shot new file mode 100644 index 000000000000..5d920422c169 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-let.ts.shot @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-let 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts new file mode 100644 index 000000000000..2890469243cc --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts @@ -0,0 +1,8 @@ +let a; +let foo = function ( + b = function () { + a; + }, +) { + let a; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts.shot new file mode 100644 index 000000000000..c85e8f437109 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested-body-shadow.ts.shot @@ -0,0 +1,148 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-nested-body-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"a">, + node: VariableDeclarator$5, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + "a" => Variable$6, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$6, + ], + }, + FunctionScope$3 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + ], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: FunctionScope$2, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts new file mode 100644 index 000000000000..7f8b28bcdfcb --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts @@ -0,0 +1,6 @@ +let a; +let foo = function ( + b = function () { + return a; + }, +) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts.shot new file mode 100644 index 000000000000..c4eec31ea62d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-nested.ts.shot @@ -0,0 +1,134 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-nested 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + FunctionScope$3 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + ], + set: Map { + "arguments" => Variable$5, + }, + type: "function", + upper: FunctionScope$2, + variables: Array [ + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts new file mode 100644 index 000000000000..133703ee14d2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts @@ -0,0 +1,3 @@ +let a; +// the default param value is resolved to the parameter +let foo = function (b = a, a) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts.shot new file mode 100644 index 000000000000..e9024950a3a8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-param-shadow.ts.shot @@ -0,0 +1,127 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-param-shadow 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"a">, + node: FunctionExpression$3, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + "a" => Variable$5, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts new file mode 100644 index 000000000000..e2ee3848ae11 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts @@ -0,0 +1,2 @@ +let a; +let foo = function (b = a.c) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts.shot new file mode 100644 index 000000000000..10bf32900e63 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/readable-ref-partial.ts.shot @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params readable-ref-partial 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"a">, + node: VariableDeclarator$1, + }, + ], + name: "a", + references: Array [ + Reference$3 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$2, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$3, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: MemberExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "a" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$3, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "arguments" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts new file mode 100644 index 000000000000..02170a78993d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts @@ -0,0 +1 @@ +let foo = function (a, b = 0) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts.shot new file mode 100644 index 000000000000..d73e3baea61b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/default-params/writable-ref.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression default-params writable-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: FunctionExpression$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"b">, + node: FunctionExpression$2, + }, + ], + name: "b", + references: Array [ + Reference$2 { + identifier: Identifier<"b">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts new file mode 100644 index 000000000000..a8967da39ad2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts @@ -0,0 +1,5 @@ +const parentScoped = 1; + +const foo = function () { + parentScoped + 1; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts.shot new file mode 100644 index 000000000000..33c62baf6e2b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/inherited-scope.ts.shot @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression inherited-scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"parentScoped">, + node: VariableDeclarator$1, + }, + ], + name: "parentScoped", + references: Array [ + Reference$1 { + identifier: Identifier<"parentScoped">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$3 { + identifier: Identifier<"parentScoped">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$3, + }, + ], + name: "foo", + references: Array [ + Reference$2 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "parentScoped" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + ], + set: Map { + "arguments" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/params.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/params.ts new file mode 100644 index 000000000000..8cea8731fbf1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/params.ts @@ -0,0 +1,6 @@ +const outer = 1; +const foo = function (a, [b], { c }, d = 1, e = a, f = outer, g) { + a; +}; + +const unresolved = g; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/params.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/params.ts.shot new file mode 100644 index 000000000000..ba02af4190aa --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/params.ts.shot @@ -0,0 +1,271 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression params 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"outer">, + node: VariableDeclarator$1, + }, + ], + name: "outer", + references: Array [ + Reference$1 { + identifier: Identifier<"outer">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$7 { + identifier: Identifier<"outer">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"foo">, + node: VariableDeclarator$3, + }, + ], + name: "foo", + references: Array [ + Reference$2 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: FunctionExpression$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionExpression$4, + }, + ], + name: "a", + references: Array [ + Reference$5 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + Reference$8 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"b">, + node: FunctionExpression$4, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$5 { + name: Identifier<"c">, + node: FunctionExpression$4, + }, + ], + name: "c", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$7 { + defs: Array [ + ParameterDefinition$6 { + name: Identifier<"d">, + node: FunctionExpression$4, + }, + ], + name: "d", + references: Array [ + Reference$3 { + identifier: Identifier<"d">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$7, + writeExpr: Literal$5, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$8 { + defs: Array [ + ParameterDefinition$7 { + name: Identifier<"e">, + node: FunctionExpression$4, + }, + ], + name: "e", + references: Array [ + Reference$4 { + identifier: Identifier<"e">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$8, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$9 { + defs: Array [ + ParameterDefinition$8 { + name: Identifier<"f">, + node: FunctionExpression$4, + }, + ], + name: "f", + references: Array [ + Reference$6 { + identifier: Identifier<"f">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$9, + writeExpr: Identifier<"outer">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$10 { + defs: Array [ + ParameterDefinition$9 { + name: Identifier<"g">, + node: FunctionExpression$4, + }, + ], + name: "g", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$11 { + defs: Array [ + VariableDefinition$10 { + name: Identifier<"unresolved">, + node: VariableDeclarator$6, + }, + ], + name: "unresolved", + references: Array [ + Reference$9 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$11, + writeExpr: Identifier<"g">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$7, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$9, + Reference$10 { + identifier: Identifier<"g">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "outer" => Variable$1, + "foo" => Variable$2, + "unresolved" => Variable$11, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$11, + ], + }, + FunctionScope$2 { + block: FunctionExpression$4, + isStrict: false, + references: Array [ + Reference$3, + Reference$4, + Reference$5, + Reference$6, + Reference$7, + Reference$8, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + "b" => Variable$5, + "c" => Variable$6, + "d" => Variable$7, + "e" => Variable$8, + "f" => Variable$9, + "g" => Variable$10, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + Variable$6, + Variable$7, + Variable$8, + Variable$9, + Variable$10, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts new file mode 100644 index 000000000000..00da70da31f4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts @@ -0,0 +1,8 @@ +const foo = function () { + let i = 0; + var j = 20; + + i; +}; + +const unresolved = j; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts.shot new file mode 100644 index 000000000000..63d7cadad598 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/scope.ts.shot @@ -0,0 +1,152 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"i">, + node: VariableDeclarator$3, + }, + ], + name: "i", + references: Array [ + Reference$2 { + identifier: Identifier<"i">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$4, + }, + Reference$4 { + identifier: Identifier<"i">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"j">, + node: VariableDeclarator$5, + }, + ], + name: "j", + references: Array [ + Reference$3 { + identifier: Identifier<"j">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Literal$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"unresolved">, + node: VariableDeclarator$7, + }, + ], + name: "unresolved", + references: Array [ + Reference$5 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$5, + writeExpr: Identifier<"j">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$8, + isStrict: false, + references: Array [ + Reference$1, + Reference$5, + Reference$6 { + identifier: Identifier<"j">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "foo" => Variable$1, + "unresolved" => Variable$5, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$5, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "arguments" => Variable$2, + "i" => Variable$3, + "j" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts new file mode 100644 index 000000000000..91921492c7c3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts @@ -0,0 +1,3 @@ +const foo = function () { + let x: T; +}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts.shot new file mode 100644 index 000000000000..4c5376efab8b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/body-reference.ts.shot @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression type-parameters body-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$4, + }, + ], + name: "x", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + "x" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts new file mode 100644 index 000000000000..bc62c145195a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts @@ -0,0 +1 @@ +const foo = function (a: T) {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts.shot new file mode 100644 index 000000000000..e2e9f4b7f54b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/param-reference.ts.shot @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression type-parameters param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"a">, + node: FunctionExpression$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$2, + "a" => Variable$3, + "T" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts new file mode 100644 index 000000000000..a3182e599404 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts @@ -0,0 +1 @@ +const foo = function (): T {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts.shot new file mode 100644 index 000000000000..7cd987aebe0c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/return-value-reference.ts.shot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression type-parameters return-value-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts new file mode 100644 index 000000000000..9b759d9bf2f2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts @@ -0,0 +1 @@ +const foo = function () {}; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts.shot new file mode 100644 index 000000000000..8e67e27315d1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-param-reference.ts.shot @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression type-parameters type-param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$4, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + "U" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts new file mode 100644 index 000000000000..8554e99c45d9 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts @@ -0,0 +1,3 @@ +const foo = function () {}; + +type Unresolved = T; diff --git a/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts.shot b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts.shot new file mode 100644 index 000000000000..c664f47f132b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/functions/function-expression/type-parameters/type-parameter-declaration.ts.shot @@ -0,0 +1,100 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`functions function-expression type-parameters type-parameter-declaration 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"foo">, + node: VariableDeclarator$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: FunctionExpression$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$3, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "foo" => Variable$1, + "Unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + FunctionScope$2 { + block: FunctionExpression$2, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + "T" => Variable$3, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/class.ts b/packages/scope-manager/tests/fixtures/global-resolution/module/class.ts new file mode 100644 index 000000000000..2f3bb079ed74 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/class.ts @@ -0,0 +1,3 @@ +//// @sourceType = module +class Foo {} +new Foo(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/class.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/module/class.ts.shot new file mode 100644 index 000000000000..1af1b3c0d95b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/class.ts.shot @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution module class 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$1 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ClassScope$3 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$2, + }, + type: "class", + upper: ModuleScope$2, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/function.ts b/packages/scope-manager/tests/fixtures/global-resolution/module/function.ts new file mode 100644 index 000000000000..402d70856315 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/function.ts @@ -0,0 +1,3 @@ +//// @sourceType = module +function top() {} +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/function.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/module/function.ts.shot new file mode 100644 index 000000000000..3198fa7ec9ca --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/function.ts.shot @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution module function 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"top">, + node: FunctionDeclaration$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "top" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$3 { + block: FunctionDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: ModuleScope$2, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts new file mode 100644 index 000000000000..71a6093c3b42 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts @@ -0,0 +1,3 @@ +//// @sourceType = module +const top = () => {}; +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts.shot new file mode 100644 index 000000000000..aceb190b8e59 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-const.ts.shot @@ -0,0 +1,71 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution module variable-decl-const 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"top">, + node: VariableDeclarator$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + Reference$2 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "top" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$3 { + block: ArrowFunctionExpression$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "function", + upper: ModuleScope$2, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts new file mode 100644 index 000000000000..3be81a8d4509 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts @@ -0,0 +1,3 @@ +//// @sourceType = module +let top = () => {}; +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts.shot new file mode 100644 index 000000000000..21a7ba400356 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-let.ts.shot @@ -0,0 +1,71 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution module variable-decl-let 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"top">, + node: VariableDeclarator$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + Reference$2 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "top" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$3 { + block: ArrowFunctionExpression$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "function", + upper: ModuleScope$2, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts new file mode 100644 index 000000000000..32adea4f0a58 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts @@ -0,0 +1,3 @@ +//// @sourceType = module +var top = () => {}; +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts.shot new file mode 100644 index 000000000000..2be4f467be8b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/module/variable-decl-var.ts.shot @@ -0,0 +1,71 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution module variable-decl-var 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"top">, + node: VariableDeclarator$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + Reference$2 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "top" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$3 { + block: ArrowFunctionExpression$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "function", + upper: ModuleScope$2, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/class.ts b/packages/scope-manager/tests/fixtures/global-resolution/script/class.ts new file mode 100644 index 000000000000..e2203530d067 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/class.ts @@ -0,0 +1,3 @@ +//// @sourceType = script +class Foo {} +new Foo(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/class.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/script/class.ts.shot new file mode 100644 index 000000000000..a0a7ff849b5d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/class.ts.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution script class 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$1 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$2, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/function.ts b/packages/scope-manager/tests/fixtures/global-resolution/script/function.ts new file mode 100644 index 000000000000..08bf2eccd666 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/function.ts @@ -0,0 +1,3 @@ +//// @sourceType = script +function top() {} +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/function.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/script/function.ts.shot new file mode 100644 index 000000000000..8d155b60e74e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/function.ts.shot @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution script function 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"top">, + node: FunctionDeclaration$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "top" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [], + set: Map { + "arguments" => Variable$2, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts new file mode 100644 index 000000000000..593523f8853f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts @@ -0,0 +1,3 @@ +//// @sourceType = script +const top = () => {}; +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts.shot new file mode 100644 index 000000000000..bf2b3e24131f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-const.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution script variable-decl-const 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"top">, + node: VariableDeclarator$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + Reference$2 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "top" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "function", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts new file mode 100644 index 000000000000..41734e5e5ae2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts @@ -0,0 +1,3 @@ +//// @sourceType = script +let top = () => {}; +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts.shot new file mode 100644 index 000000000000..49d3e89ca9b4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-let.ts.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution script variable-decl-let 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"top">, + node: VariableDeclarator$1, + }, + ], + name: "top", + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ArrowFunctionExpression$2, + }, + Reference$2 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "top" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "function", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts new file mode 100644 index 000000000000..7eaa9509c71f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts @@ -0,0 +1,3 @@ +//// @sourceType = script +var top = () => {}; +top(); diff --git a/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts.shot b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts.shot new file mode 100644 index 000000000000..8d421cc889cf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/global-resolution/script/variable-decl-var.ts.shot @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global-resolution script variable-decl-var 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"top">, + node: VariableDeclarator$1, + }, + ], + name: "top", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"top">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: null, + writeExpr: ArrowFunctionExpression$3, + }, + Reference$2 { + identifier: Identifier<"top">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "top" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + FunctionScope$2 { + block: ArrowFunctionExpression$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "function", + upper: GlobalScope$1, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/implicit/implicit1.ts b/packages/scope-manager/tests/fixtures/implicit/implicit1.ts new file mode 100644 index 000000000000..89a08efd8216 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/implicit/implicit1.ts @@ -0,0 +1 @@ +const x = y; diff --git a/packages/scope-manager/tests/fixtures/implicit/implicit1.ts.shot b/packages/scope-manager/tests/fixtures/implicit/implicit1.ts.shot new file mode 100644 index 000000000000..5566bb4962d2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/implicit/implicit1.ts.shot @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`implicit implicit1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Identifier<"y">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"y">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "x" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/default.ts b/packages/scope-manager/tests/fixtures/import/default.ts new file mode 100644 index 000000000000..9f5bc0795e58 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/default.ts @@ -0,0 +1,6 @@ +//// @sourceType = module + +import v from 'foo'; + +v; +type T = v; diff --git a/packages/scope-manager/tests/fixtures/import/default.ts.shot b/packages/scope-manager/tests/fixtures/import/default.ts.shot new file mode 100644 index 000000000000..0b4010ddb559 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/default.ts.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import default 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"v">, + node: ImportDefaultSpecifier$1, + }, + ], + name: "v", + references: Array [ + Reference$1 { + identifier: Identifier<"v">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"v">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "v" => Variable$1, + "T" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/equals1.ts b/packages/scope-manager/tests/fixtures/import/equals1.ts new file mode 100644 index 000000000000..808ef4b2a26b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/equals1.ts @@ -0,0 +1,5 @@ +//// @sourceType = module + +import foo = require('a'); + +foo; diff --git a/packages/scope-manager/tests/fixtures/import/equals1.ts.shot b/packages/scope-manager/tests/fixtures/import/equals1.ts.shot new file mode 100644 index 000000000000..727353a50aa9 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/equals1.ts.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import equals1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"foo">, + node: TSImportEqualsDeclaration$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/equals2.ts b/packages/scope-manager/tests/fixtures/import/equals2.ts new file mode 100644 index 000000000000..63ac5327dc0f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/equals2.ts @@ -0,0 +1,4 @@ +//// @sourceType = module + +const x = 1; +import foo = x; diff --git a/packages/scope-manager/tests/fixtures/import/equals2.ts.shot b/packages/scope-manager/tests/fixtures/import/equals2.ts.shot new file mode 100644 index 000000000000..2c624a8b4964 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/equals2.ts.shot @@ -0,0 +1,76 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import equals2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + ImportBindingDefinition$2 { + name: Identifier<"foo">, + node: TSImportEqualsDeclaration$3, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "x" => Variable$1, + "foo" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/named-alias.ts b/packages/scope-manager/tests/fixtures/import/named-alias.ts new file mode 100644 index 000000000000..cde3625337f4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/named-alias.ts @@ -0,0 +1,6 @@ +//// @sourceType = module + +import { v as t } from 'foo'; + +t; +type T = t; diff --git a/packages/scope-manager/tests/fixtures/import/named-alias.ts.shot b/packages/scope-manager/tests/fixtures/import/named-alias.ts.shot new file mode 100644 index 000000000000..e69921218eb3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/named-alias.ts.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import named-alias 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"t">, + node: ImportSpecifier$1, + }, + ], + name: "t", + references: Array [ + Reference$1 { + identifier: Identifier<"t">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"t">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "t" => Variable$1, + "T" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/named.ts b/packages/scope-manager/tests/fixtures/import/named.ts new file mode 100644 index 000000000000..4b4b1ae7a52d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/named.ts @@ -0,0 +1,6 @@ +//// @sourceType = module + +import { v } from 'foo'; + +v; +type T = v; diff --git a/packages/scope-manager/tests/fixtures/import/named.ts.shot b/packages/scope-manager/tests/fixtures/import/named.ts.shot new file mode 100644 index 000000000000..9196f214a1f0 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/named.ts.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import named 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"v">, + node: ImportSpecifier$1, + }, + ], + name: "v", + references: Array [ + Reference$1 { + identifier: Identifier<"v">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"v">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "v" => Variable$1, + "T" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/namespace.ts b/packages/scope-manager/tests/fixtures/import/namespace.ts new file mode 100644 index 000000000000..695704b6b99f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/namespace.ts @@ -0,0 +1,6 @@ +//// @sourceType = module + +import * as v from 'foo'; + +v; +type T = v; diff --git a/packages/scope-manager/tests/fixtures/import/namespace.ts.shot b/packages/scope-manager/tests/fixtures/import/namespace.ts.shot new file mode 100644 index 000000000000..f917798fa965 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/namespace.ts.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import namespace 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"v">, + node: ImportNamespaceSpecifier$1, + }, + ], + name: "v", + references: Array [ + Reference$1 { + identifier: Identifier<"v">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"v">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "v" => Variable$1, + "T" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/type-default.ts b/packages/scope-manager/tests/fixtures/import/type-default.ts new file mode 100644 index 000000000000..1001c549f93b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-default.ts @@ -0,0 +1,6 @@ +//// @sourceType = module + +import type T from 'foo'; + +type Ref = T; +const unresolved = T; diff --git a/packages/scope-manager/tests/fixtures/import/type-default.ts.shot b/packages/scope-manager/tests/fixtures/import/type-default.ts.shot new file mode 100644 index 000000000000..c87d387f0510 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-default.ts.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import type-default 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"T">, + node: ImportDefaultSpecifier$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"Ref">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "Ref", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"unresolved">, + node: VariableDeclarator$3, + }, + ], + name: "unresolved", + references: Array [ + Reference$2 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"T">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "T" => Variable$1, + "Ref" => Variable$2, + "unresolved" => Variable$3, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/type-named.ts b/packages/scope-manager/tests/fixtures/import/type-named.ts new file mode 100644 index 000000000000..1b73102379a1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-named.ts @@ -0,0 +1,6 @@ +//// @sourceType = module + +import type { T } from 'foo'; + +type Ref = T; +const unresovled = T; diff --git a/packages/scope-manager/tests/fixtures/import/type-named.ts.shot b/packages/scope-manager/tests/fixtures/import/type-named.ts.shot new file mode 100644 index 000000000000..f9d1987b4651 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-named.ts.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import type-named 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"T">, + node: ImportSpecifier$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"Ref">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "Ref", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"unresovled">, + node: VariableDeclarator$3, + }, + ], + name: "unresovled", + references: Array [ + Reference$2 { + identifier: Identifier<"unresovled">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"T">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "T" => Variable$1, + "Ref" => Variable$2, + "unresovled" => Variable$3, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/member-expression/member-expression.ts b/packages/scope-manager/tests/fixtures/member-expression/member-expression.ts new file mode 100644 index 000000000000..fb7b5f96a874 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/member-expression/member-expression.ts @@ -0,0 +1,7 @@ +const x = {}; + +x.a; +x.a.b.c.d; +x['a']; +x?.a.b.c; +x?.['a']; diff --git a/packages/scope-manager/tests/fixtures/member-expression/member-expression.ts.shot b/packages/scope-manager/tests/fixtures/member-expression/member-expression.ts.shot new file mode 100644 index 000000000000..cd8e9f3daeec --- /dev/null +++ b/packages/scope-manager/tests/fixtures/member-expression/member-expression.ts.shot @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`member-expression member-expression 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: ObjectExpression$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$3 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$4 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$5 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + Reference$6 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + Reference$5, + Reference$6, + ], + set: Map { + "x" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts b/packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts new file mode 100644 index 000000000000..3e4a51bc1ac6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts @@ -0,0 +1,5 @@ +enum Foo { + a = 1, +} + +Foo.a; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts.shot b/packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts.shot new file mode 100644 index 000000000000..c6740c3007bc --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/external-ref.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-enum external-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSEnumNameDefinition$1 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$1 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSEnumNameDefinition$2 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSEnumMemberDefinition$3 { + name: Identifier<"a">, + node: TSEnumMember$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSEnumScope$2 { + block: TSEnumDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$2, + "a" => Variable$3, + }, + type: "tsEnum", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts b/packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts new file mode 100644 index 000000000000..4d6233bf1225 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts @@ -0,0 +1,4 @@ +enum Foo { + 'a' = 1, + b = a, +} diff --git a/packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts.shot b/packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts.shot new file mode 100644 index 000000000000..97b82b514633 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/literal-member-ref.ts.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-enum literal-member-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSEnumNameDefinition$1 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSEnumNameDefinition$2 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSEnumMemberDefinition$3 { + name: Literal$2, + node: TSEnumMember$3, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TSEnumMemberDefinition$4 { + name: Identifier<"b">, + node: TSEnumMember$4, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSEnumScope$2 { + block: TSEnumDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + }, + type: "tsEnum", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts b/packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts new file mode 100644 index 000000000000..06bc6e600aae --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts @@ -0,0 +1,3 @@ +enum Foo { + 'a' = 1, +} diff --git a/packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts.shot b/packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts.shot new file mode 100644 index 000000000000..3f4f338384ba --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/literal-member.ts.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-enum literal-member 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSEnumNameDefinition$1 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSEnumNameDefinition$2 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSEnumMemberDefinition$3 { + name: Literal$2, + node: TSEnumMember$3, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSEnumScope$2 { + block: TSEnumDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$2, + "a" => Variable$3, + }, + type: "tsEnum", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts b/packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts new file mode 100644 index 000000000000..e08824e129c1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts @@ -0,0 +1,4 @@ +enum Foo { + a = 1, + b = a, +} diff --git a/packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts.shot b/packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts.shot new file mode 100644 index 000000000000..e322d2f16d65 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/member-ref.ts.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-enum member-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSEnumNameDefinition$1 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSEnumNameDefinition$2 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSEnumMemberDefinition$3 { + name: Identifier<"a">, + node: TSEnumMember$2, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TSEnumMemberDefinition$4 { + name: Identifier<"b">, + node: TSEnumMember$3, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSEnumScope$2 { + block: TSEnumDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + }, + type: "tsEnum", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/scope.ts b/packages/scope-manager/tests/fixtures/ts-enum/scope.ts new file mode 100644 index 000000000000..da1321ea5ad2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/scope.ts @@ -0,0 +1,5 @@ +enum Foo { + a, +} + +const unresolved = a; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/scope.ts.shot b/packages/scope-manager/tests/fixtures/ts-enum/scope.ts.shot new file mode 100644 index 000000000000..c8042fc72532 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/scope.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-enum scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSEnumNameDefinition$1 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSEnumNameDefinition$2 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSEnumMemberDefinition$3 { + name: Identifier<"a">, + node: TSEnumMember$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"unresolved">, + node: VariableDeclarator$3, + }, + ], + name: "unresolved", + references: Array [ + Reference$1 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"a">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"a">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "Foo" => Variable$1, + "unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + TSEnumScope$2 { + block: TSEnumDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "Foo" => Variable$2, + "a" => Variable$3, + }, + type: "tsEnum", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts b/packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts new file mode 100644 index 000000000000..ada23ec5d814 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts @@ -0,0 +1,4 @@ +enum Foo { + a = 1, + b = Foo.a, +} diff --git a/packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts.shot b/packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts.shot new file mode 100644 index 000000000000..38321018f144 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-enum/self-ref.ts.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-enum self-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSEnumNameDefinition$1 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSEnumNameDefinition$2 { + name: Identifier<"Foo">, + node: TSEnumDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$1 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSEnumMemberDefinition$3 { + name: Identifier<"a">, + node: TSEnumMember$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TSEnumMemberDefinition$4 { + name: Identifier<"b">, + node: TSEnumMember$3, + }, + ], + name: "b", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSEnumScope$2 { + block: TSEnumDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$2, + "a" => Variable$3, + "b" => Variable$4, + }, + type: "tsEnum", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-module/external-ref.ts b/packages/scope-manager/tests/fixtures/ts-module/external-ref.ts new file mode 100644 index 000000000000..e47c0fd35d5c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/external-ref.ts @@ -0,0 +1,5 @@ +module Foo { + export const x = 1; +} + +Foo.x; diff --git a/packages/scope-manager/tests/fixtures/ts-module/external-ref.ts.shot b/packages/scope-manager/tests/fixtures/ts-module/external-ref.ts.shot new file mode 100644 index 000000000000..a9fc10d28bc1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/external-ref.ts.shot @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-module external-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSModuleNameDefinition$1 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$2 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSModuleNameDefinition$2 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$2, + ], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSModuleScope$2 { + block: TSModuleDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$2, + "x" => Variable$3, + }, + type: "tsModule", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-module/import.ts b/packages/scope-manager/tests/fixtures/ts-module/import.ts new file mode 100644 index 000000000000..62cedcc5daf9 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/import.ts @@ -0,0 +1,5 @@ +//// @sourceType = module + +declare module 'foo' { + import { bar } from 'mod'; +} diff --git a/packages/scope-manager/tests/fixtures/ts-module/import.ts.shot b/packages/scope-manager/tests/fixtures/ts-module/import.ts.shot new file mode 100644 index 000000000000..7ab8ac5e37a6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/import.ts.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-module import 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"bar">, + node: ImportSpecifier$1, + }, + ], + name: "bar", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$2, + isStrict: true, + references: Array [], + set: Map {}, + type: "module", + upper: GlobalScope$1, + variables: Array [], + }, + TSModuleScope$3 { + block: TSModuleDeclaration$3, + isStrict: true, + references: Array [], + set: Map { + "bar" => Variable$1, + }, + type: "tsModule", + upper: ModuleScope$2, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-module/namespace.ts b/packages/scope-manager/tests/fixtures/ts-module/namespace.ts new file mode 100644 index 000000000000..c84fa7350538 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/namespace.ts @@ -0,0 +1,7 @@ +namespace Foo { + export const x = 1; + Foo.x; +} + +const unresolved = x; +Foo.x; diff --git a/packages/scope-manager/tests/fixtures/ts-module/namespace.ts.shot b/packages/scope-manager/tests/fixtures/ts-module/namespace.ts.shot new file mode 100644 index 000000000000..7177a14b43c1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/namespace.ts.shot @@ -0,0 +1,132 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-module namespace 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSModuleNameDefinition$1 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$5 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSModuleNameDefinition$2 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$2 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"unresolved">, + node: VariableDeclarator$4, + }, + ], + name: "unresolved", + references: Array [ + Reference$3 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"x">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$3, + Reference$4 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + Reference$5, + ], + set: Map { + "Foo" => Variable$1, + "unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + TSModuleScope$2 { + block: TSModuleDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "Foo" => Variable$2, + "x" => Variable$3, + }, + type: "tsModule", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-module/scope.ts b/packages/scope-manager/tests/fixtures/ts-module/scope.ts new file mode 100644 index 000000000000..c1a2669446f7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/scope.ts @@ -0,0 +1,5 @@ +module Foo { + const x = 1; +} + +const unresolved = x; diff --git a/packages/scope-manager/tests/fixtures/ts-module/scope.ts.shot b/packages/scope-manager/tests/fixtures/ts-module/scope.ts.shot new file mode 100644 index 000000000000..276f424ab71d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/scope.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-module scope 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSModuleNameDefinition$1 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSModuleNameDefinition$2 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$4 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"unresolved">, + node: VariableDeclarator$4, + }, + ], + name: "unresolved", + references: Array [ + Reference$2 { + identifier: Identifier<"unresolved">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Identifier<"x">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$2, + Reference$3 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: null, + }, + ], + set: Map { + "Foo" => Variable$1, + "unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + TSModuleScope$2 { + block: TSModuleDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$2, + "x" => Variable$3, + }, + type: "tsModule", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/ts-module/self-ref.ts b/packages/scope-manager/tests/fixtures/ts-module/self-ref.ts new file mode 100644 index 000000000000..e94a766b4194 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/self-ref.ts @@ -0,0 +1,4 @@ +module Foo { + export const x = 1; + Foo.x; +} diff --git a/packages/scope-manager/tests/fixtures/ts-module/self-ref.ts.shot b/packages/scope-manager/tests/fixtures/ts-module/self-ref.ts.shot new file mode 100644 index 000000000000..16417dee9a98 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/ts-module/self-ref.ts.shot @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ts-module self-ref 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TSModuleNameDefinition$1 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSModuleNameDefinition$2 { + name: Identifier<"Foo">, + node: TSModuleDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$2 { + identifier: Identifier<"Foo">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$3 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TSModuleScope$2 { + block: TSModuleDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "Foo" => Variable$2, + "x" => Variable$3, + }, + type: "tsModule", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts b/packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts new file mode 100644 index 000000000000..ce717cd0a415 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts @@ -0,0 +1,2 @@ +type T = []; +function foo([a]: T) {} diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts.shot new file mode 100644 index 000000000000..fc38d7a41b56 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-array-destructure.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation parameter-array-destructure 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts b/packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts new file mode 100644 index 000000000000..61c1836be6ed --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts @@ -0,0 +1,2 @@ +type T = 1; +function foo(a: T = 1) {} diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts.shot new file mode 100644 index 000000000000..2fd8f742467b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-default.ts.shot @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation parameter-default 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [ + Reference$1 { + identifier: Identifier<"a">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$4, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts b/packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts new file mode 100644 index 000000000000..04824de37625 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts @@ -0,0 +1,2 @@ +type T = {}; +function foo({ a }: T) {} diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts.shot new file mode 100644 index 000000000000..9a572fd5b2ea --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-object-destructure.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation parameter-object-destructure 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts b/packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts new file mode 100644 index 000000000000..426fcd704509 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts @@ -0,0 +1,2 @@ +type T = 1; +function foo(...a: T[]) {} diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts.shot new file mode 100644 index 000000000000..d50adae94c19 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter-rest.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation parameter-rest 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter.ts b/packages/scope-manager/tests/fixtures/type-annotation/parameter.ts new file mode 100644 index 000000000000..53fd1a252db1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter.ts @@ -0,0 +1,2 @@ +type T = 1; +function foo(a: T) {} diff --git a/packages/scope-manager/tests/fixtures/type-annotation/parameter.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/parameter.ts.shot new file mode 100644 index 000000000000..a699082ede2c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/parameter.ts.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation parameter 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + FunctionNameDefinition$2 { + name: Identifier<"foo">, + node: FunctionDeclaration$2, + }, + ], + name: "foo", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"a">, + node: FunctionDeclaration$2, + }, + ], + name: "a", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$2, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arguments" => Variable$3, + "a" => Variable$4, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts b/packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts new file mode 100644 index 000000000000..d40a8608f143 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts @@ -0,0 +1,2 @@ +type T = []; +const [x]: T = []; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts.shot new file mode 100644 index 000000000000..71f9aff4ce28 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-array-destructure.ts.shot @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation variable-array-destructure 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ArrayExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$1, + "x" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts b/packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts new file mode 100644 index 000000000000..7b61add80b18 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts @@ -0,0 +1,2 @@ +type T = 1; +const x: T = 1; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts.shot new file mode 100644 index 000000000000..e16be05289dc --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-const.ts.shot @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation variable-const 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$1, + "x" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts b/packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts new file mode 100644 index 000000000000..d6b0d69dbbe6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts @@ -0,0 +1,2 @@ +type T = 1; +let x: T; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts.shot new file mode 100644 index 000000000000..6a73fc87d10a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-let.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation variable-let 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "x" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts b/packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts new file mode 100644 index 000000000000..a0a18b23ab97 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts @@ -0,0 +1,2 @@ +type T = {}; +const { x }: T = {}; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts.shot new file mode 100644 index 000000000000..3ac3f6962d95 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-object-destructure.ts.shot @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation variable-object-destructure 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: ObjectExpression$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$1, + "x" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts b/packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts new file mode 100644 index 000000000000..4423625dc4c6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts @@ -0,0 +1,2 @@ +type T = 1; +var x: T; diff --git a/packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts.shot b/packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts.shot new file mode 100644 index 000000000000..5ffad66774bf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-annotation/variable-var.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation variable-var 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"x">, + node: VariableDeclarator$2, + }, + ], + name: "x", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "x" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts b/packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts new file mode 100644 index 000000000000..c5b90146e658 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts @@ -0,0 +1,4 @@ +const x = 1; +type T = 1; + +x; diff --git a/packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts.shot b/packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts.shot new file mode 100644 index 000000000000..f385c548d893 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-assertion/angle-bracket.ts.shot @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-assertion angle-bracket 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "x" => Variable$1, + "T" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-assertion/as.ts b/packages/scope-manager/tests/fixtures/type-assertion/as.ts new file mode 100644 index 000000000000..55284491ea50 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-assertion/as.ts @@ -0,0 +1,4 @@ +const x = 1; +type T = 1; + +x as T; diff --git a/packages/scope-manager/tests/fixtures/type-assertion/as.ts.shot b/packages/scope-manager/tests/fixtures/type-assertion/as.ts.shot new file mode 100644 index 000000000000..a51c42b04add --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-assertion/as.ts.shot @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-assertion as 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "x" => Variable$1, + "T" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts b/packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts new file mode 100644 index 000000000000..c39bc79c2815 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts @@ -0,0 +1,3 @@ +type T = U extends infer V ? V : never; + +type Unresolved = V; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts.shot new file mode 100644 index 000000000000..05de4a1f9311 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/conditional1.ts.shot @@ -0,0 +1,123 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration conditional1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"U">, + node: TSTypeParameter$2, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"V">, + node: TSTypeParameter$3, + }, + ], + name: "V", + references: Array [ + Reference$2 { + identifier: Identifier<"V">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$3 { + identifier: Identifier<"V">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "T" => Variable$1, + "Unresolved" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$4, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "U" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ConditionalTypeScope$3 { + block: TSConditionalType$6, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "V" => Variable$3, + }, + type: "conditionalType", + upper: TypeScope$2, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts b/packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts new file mode 100644 index 000000000000..4fac34237bce --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts @@ -0,0 +1,3 @@ +type T = never extends infer U ? U : never; + +type Unresolved = U; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts.shot new file mode 100644 index 000000000000..dbeda86a2246 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/conditional2.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration conditional2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"U">, + node: TSTypeParameter$2, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$2 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "T" => Variable$1, + "Unresolved" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + ConditionalTypeScope$2 { + block: TSConditionalType$5, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "U" => Variable$2, + }, + type: "conditionalType", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts b/packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts new file mode 100644 index 000000000000..0dc8ae8036bc --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts @@ -0,0 +1,5 @@ +const dual = 1; +type dual = number; + +type reference1 = dual; +const reference2 = dual; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts.shot new file mode 100644 index 000000000000..8d127b17ef21 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/dual-type-value.ts.shot @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration dual-type-value 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"dual">, + node: VariableDeclarator$1, + }, + TypeDefinition$2 { + name: Identifier<"dual">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "dual", + references: Array [ + Reference$1 { + identifier: Identifier<"dual">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$3, + }, + Reference$2 { + identifier: Identifier<"dual">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$4 { + identifier: Identifier<"dual">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"reference1">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "reference1", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + VariableDefinition$4 { + name: Identifier<"reference2">, + node: VariableDeclarator$5, + }, + ], + name: "reference2", + references: Array [ + Reference$3 { + identifier: Identifier<"reference2">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + writeExpr: Identifier<"dual">, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "dual" => Variable$1, + "reference1" => Variable$2, + "reference2" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts new file mode 100644 index 000000000000..c71eeeecae9d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = new (arg: U) => T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts.shot new file mode 100644 index 000000000000..206d26b1b252 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics1.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function constructor-generics1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSConstructorType$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "U" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + FunctionTypeScope$3 { + block: TSConstructorType$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$4, + }, + type: "functionType", + upper: TypeScope$2, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts new file mode 100644 index 000000000000..2c62bffa9db0 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = new (arg: U) => T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts.shot new file mode 100644 index 000000000000..c8504114c209 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor-generics2.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function constructor-generics2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSConstructorType$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSConstructorType$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "U" => Variable$3, + "arg" => Variable$4, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts new file mode 100644 index 000000000000..9e64f174e3d1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = new (arg: T) => T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts.shot new file mode 100644 index 000000000000..5a450ec959e5 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/constructor.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function constructor 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"arg">, + node: TSConstructorType$3, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSConstructorType$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$3, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts new file mode 100644 index 000000000000..f44fdb06c8b3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = (arg: U) => T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts.shot new file mode 100644 index 000000000000..7bf926b5598b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics1.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function function-generics1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSFunctionType$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "U" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + FunctionTypeScope$3 { + block: TSFunctionType$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$4, + }, + type: "functionType", + upper: TypeScope$2, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts new file mode 100644 index 000000000000..97d8378f61f7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = (arg: U) => T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts.shot new file mode 100644 index 000000000000..9d53bfd66870 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function-generics2.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function function-generics2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSFunctionType$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSFunctionType$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "U" => Variable$3, + "arg" => Variable$4, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts new file mode 100644 index 000000000000..038fbb18159b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = (arg: T) => T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts.shot new file mode 100644 index 000000000000..e61e964d90f9 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function1.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function function1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"arg">, + node: TSFunctionType$3, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSFunctionType$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$3, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts b/packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts new file mode 100644 index 000000000000..da53e79f421b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts @@ -0,0 +1,3 @@ +const arg = 1; +// the typeof references the parameter, not the variable +type A = (arg: string) => typeof arg; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts.shot new file mode 100644 index 000000000000..4551de619d88 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/function/function2.ts.shot @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration function function2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"arg">, + node: VariableDeclarator$1, + }, + ], + name: "arg", + references: Array [ + Reference$1 { + identifier: Identifier<"arg">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"arg">, + node: TSFunctionType$4, + }, + ], + name: "arg", + references: Array [ + Reference$2 { + identifier: Identifier<"arg">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$3, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "arg" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSFunctionType$4, + isStrict: true, + references: Array [ + Reference$2, + ], + set: Map { + "arg" => Variable$3, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts b/packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts new file mode 100644 index 000000000000..544ae2158840 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts @@ -0,0 +1,2 @@ +type T = { a: string }; +type A = T['a']; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts.shot new file mode 100644 index 000000000000..11dd9cf80eed --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/index-access1.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration index-access1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts b/packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts new file mode 100644 index 000000000000..6831f20e3fbf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts @@ -0,0 +1,3 @@ +type T = { a: string }; +type K = 'a'; +type A = T[K]; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts.shot new file mode 100644 index 000000000000..7e1fbfe453bb --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/index-access2.ts.shot @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration index-access2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"K">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "K", + references: Array [ + Reference$1 { + identifier: Identifier<"K">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$1, + "K" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts b/packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts new file mode 100644 index 000000000000..76706d3507c4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts @@ -0,0 +1,3 @@ +type T = { a: string }; +const k = 'a'; +type A = T[typeof k]; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts.shot new file mode 100644 index 000000000000..1a9adea4e152 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/index-access3.ts.shot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration index-access3 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + VariableDefinition$2 { + name: Identifier<"k">, + node: VariableDeclarator$2, + }, + ], + name: "k", + references: Array [ + Reference$1 { + identifier: Identifier<"k">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + writeExpr: Literal$3, + }, + Reference$2 { + identifier: Identifier<"k">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "T" => Variable$1, + "k" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts new file mode 100644 index 000000000000..d2ce3f9de509 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts @@ -0,0 +1,2 @@ +interface Parent {} +interface Foo extends Parent {} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts.shot new file mode 100644 index 000000000000..451d7d954fb7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage1.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration interface-heritage1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Parent">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "Parent", + references: Array [ + Reference$1 { + identifier: Identifier<"Parent">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$2, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "Parent" => Variable$1, + "Foo" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts new file mode 100644 index 000000000000..72bc4fe8e8ce --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts @@ -0,0 +1,5 @@ +type unreferenced = {}; +namespace Member { + export type unreferenced = {}; +} +interface Foo extends Member.unreferenced {} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts.shot new file mode 100644 index 000000000000..c5c73045449d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface-heritage2.ts.shot @@ -0,0 +1,111 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration interface-heritage2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"unreferenced">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "unreferenced", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TSModuleNameDefinition$2 { + name: Identifier<"Member">, + node: TSModuleDeclaration$2, + }, + ], + name: "Member", + references: Array [ + Reference$1 { + identifier: Identifier<"Member">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TSModuleNameDefinition$3 { + name: Identifier<"Member">, + node: TSModuleDeclaration$2, + }, + ], + name: "Member", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"unreferenced">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "unreferenced", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + TypeDefinition$5 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$4, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "unreferenced" => Variable$1, + "Member" => Variable$2, + "Foo" => Variable$5, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$5, + ], + }, + TSModuleScope$2 { + block: TSModuleDeclaration$2, + isStrict: true, + references: Array [], + set: Map { + "Member" => Variable$3, + "unreferenced" => Variable$4, + }, + type: "tsModule", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface1.ts b/packages/scope-manager/tests/fixtures/type-declaration/interface1.ts new file mode 100644 index 000000000000..fda122177f4c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface1.ts @@ -0,0 +1,3 @@ +interface A { + a: string; +} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/interface1.ts.shot new file mode 100644 index 000000000000..d9529e5c0b93 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface1.ts.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration interface1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map { + "A" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface2.ts b/packages/scope-manager/tests/fixtures/type-declaration/interface2.ts new file mode 100644 index 000000000000..60a78f19e07f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface2.ts @@ -0,0 +1,2 @@ +interface A {} +type B = A; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/interface2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/interface2.ts.shot new file mode 100644 index 000000000000..2cc593bc60f2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/interface2.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration interface2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"B">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "B", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$1, + "B" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/mapped.ts b/packages/scope-manager/tests/fixtures/type-declaration/mapped.ts new file mode 100644 index 000000000000..a91c6ae6840f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/mapped.ts @@ -0,0 +1,2 @@ +type T = Record; +type A = { [k in string]: T[k] }; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/mapped.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/mapped.ts.shot new file mode 100644 index 000000000000..69fe517525d8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/mapped.ts.shot @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration mapped 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"k">, + node: TSTypeParameter$3, + }, + ], + name: "k", + references: Array [ + Reference$2 { + identifier: Identifier<"k">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"Record">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + MappedTypeScope$2 { + block: TSMappedType$5, + isStrict: true, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map { + "k" => Variable$3, + }, + type: "mappedType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts b/packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts new file mode 100644 index 000000000000..f0fd0249f956 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = T.B; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts.shot new file mode 100644 index 000000000000..e4424533b554 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/qualified-name.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration qualified-name 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts new file mode 100644 index 000000000000..ceeabc8cfce1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + (arg: U): T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts.shot new file mode 100644 index 000000000000..b8beef311536 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call-generics.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures call-generics 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSCallSignatureDeclaration$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSCallSignatureDeclaration$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "U" => Variable$3, + "arg" => Variable$4, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts new file mode 100644 index 000000000000..519af46a1bc5 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + (arg: T): T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts.shot new file mode 100644 index 000000000000..c04665da4ccf --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/call.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures call 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"arg">, + node: TSCallSignatureDeclaration$3, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSCallSignatureDeclaration$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$3, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts new file mode 100644 index 000000000000..0f8d05ff4629 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + new (arg: U): T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts.shot new file mode 100644 index 000000000000..04a560a8f84a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct-generics.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures construct-generics 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$1 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSConstructSignatureDeclaration$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSConstructSignatureDeclaration$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "U" => Variable$3, + "arg" => Variable$4, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts new file mode 100644 index 000000000000..f5af306ccae3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + new (arg: T): T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts.shot new file mode 100644 index 000000000000..e5b84ef904b7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/construct.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures construct 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"arg">, + node: TSConstructSignatureDeclaration$3, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSConstructSignatureDeclaration$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$3, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts new file mode 100644 index 000000000000..d3b3732aabc7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = { [k: string]: T }; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts.shot new file mode 100644 index 000000000000..a3d633bbb568 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/index-sig.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures index-sig 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts new file mode 100644 index 000000000000..386039f97f37 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts @@ -0,0 +1,5 @@ +const x = 'b'; +type T = 1; +type A = { + [x](arg: T): T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts.shot new file mode 100644 index 000000000000..9a40c25a2337 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-computed-name.ts.shot @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures method-computed-name 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + Reference$4 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSMethodSignature$5, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$6, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "x" => Variable$1, + "T" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + FunctionTypeScope$2 { + block: TSMethodSignature$5, + isStrict: true, + references: Array [ + Reference$3, + Reference$4, + ], + set: Map { + "arg" => Variable$4, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts new file mode 100644 index 000000000000..d7d80fac737a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + a(arg: T): U; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts.shot new file mode 100644 index 000000000000..2fd5d05e771a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method-generics.ts.shot @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures method-generics 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$2 { + identifier: Identifier<"U">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"arg">, + node: TSMethodSignature$4, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSMethodSignature$4, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "U" => Variable$3, + "arg" => Variable$4, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts new file mode 100644 index 000000000000..6f171c0a1809 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + a(arg: T): T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts.shot new file mode 100644 index 000000000000..ddea76762622 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/method.ts.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures method 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ParameterDefinition$3 { + name: Identifier<"arg">, + node: TSMethodSignature$3, + }, + ], + name: "arg", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + FunctionTypeScope$2 { + block: TSMethodSignature$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arg" => Variable$3, + }, + type: "functionType", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts new file mode 100644 index 000000000000..dfe5e6b0fbe3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts @@ -0,0 +1,5 @@ +const x = 'b'; +type T = 1; +type A = { + [x]: T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts.shot new file mode 100644 index 000000000000..aecf762a6e7d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property-computed-name.ts.shot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures property-computed-name 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3, + ], + set: Map { + "x" => Variable$1, + "T" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts new file mode 100644 index 000000000000..8ba711e3c2d4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts @@ -0,0 +1,4 @@ +type T = 1; +type A = { + a: T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts.shot new file mode 100644 index 000000000000..5739114d3ced --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/signatures/property.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration signatures property 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts b/packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts new file mode 100644 index 000000000000..65c675d09ad7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = [...T]; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts.shot new file mode 100644 index 000000000000..d78524f98b18 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/tuple-rest.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration tuple-rest 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/tuple.ts b/packages/scope-manager/tests/fixtures/type-declaration/tuple.ts new file mode 100644 index 000000000000..87df28769c30 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/tuple.ts @@ -0,0 +1,2 @@ +type T = 1; +type A = [T]; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/tuple.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/tuple.ts.shot new file mode 100644 index 000000000000..eb7274090b88 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/tuple.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration tuple 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts new file mode 100644 index 000000000000..9482bcd0ab5b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts @@ -0,0 +1,3 @@ +interface Foo { + prop: T; +} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts.shot new file mode 100644 index 000000000000..d4e1736e34e3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/body-reference.ts.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters interface body-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TypeScope$2 { + block: TSInterfaceDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts new file mode 100644 index 000000000000..a1f64ae23e24 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts @@ -0,0 +1,2 @@ +interface A {} +interface Foo extends A {} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts.shot new file mode 100644 index 000000000000..1eeccea3118f --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/extends-reference.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters interface extends-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$3, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"T">, + node: TSTypeParameter$4, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "A" => Variable$1, + "Foo" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + TypeScope$2 { + block: TSInterfaceDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "T" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + TypeScope$3 { + block: TSInterfaceDeclaration$3, + isStrict: true, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "T" => Variable$4, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts new file mode 100644 index 000000000000..e4e7cb258f41 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts @@ -0,0 +1 @@ +interface Foo {} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts.shot new file mode 100644 index 000000000000..569563efa38d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-param-reference.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters interface type-param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TypeScope$2 { + block: TSInterfaceDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$2, + "U" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts new file mode 100644 index 000000000000..d666577cf4ec --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts @@ -0,0 +1 @@ +interface Foo {} diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts.shot new file mode 100644 index 000000000000..4545ed7d0c5a --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration-extends.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters interface type-parameter-declaration-extends 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TypeScope$2 { + block: TSInterfaceDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$2, + "U" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts new file mode 100644 index 000000000000..169cb6c15d44 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts @@ -0,0 +1,3 @@ +interface Foo {} + +type Unresolved = T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts.shot new file mode 100644 index 000000000000..a5579bf088f1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/interface/type-parameter-declaration.ts.shot @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters interface type-parameter-declaration 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "Foo" => Variable$1, + "Unresolved" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + TypeScope$2 { + block: TSInterfaceDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "T" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts new file mode 100644 index 000000000000..2fb7debbef57 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts @@ -0,0 +1 @@ +type Foo = T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts.shot new file mode 100644 index 000000000000..1098cbfa5db8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/body-reference.ts.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters type-decl body-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts new file mode 100644 index 000000000000..b752327ba1f4 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts @@ -0,0 +1 @@ +type Foo = 1; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts.shot new file mode 100644 index 000000000000..989871fd714d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-param-reference.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters type-decl type-param-reference 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$2, + "U" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts new file mode 100644 index 000000000000..46db3056d0d2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts @@ -0,0 +1 @@ +type Foo = {}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts.shot new file mode 100644 index 000000000000..fe6857747be7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration-extends.ts.shot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters type-decl type-parameter-declaration-extends 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "Foo" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$2, + "U" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts new file mode 100644 index 000000000000..6e931a3482bd --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts @@ -0,0 +1,3 @@ +type Foo = 1; + +type Unresolved = T; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts.shot new file mode 100644 index 000000000000..22bc9f4fd222 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-parameters/type-decl/type-parameter-declaration.ts.shot @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-parameters type-decl type-parameter-declaration 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Foo">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "Foo" => Variable$1, + "Unresolved" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$3, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "T" => Variable$2, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-query.ts b/packages/scope-manager/tests/fixtures/type-declaration/type-query.ts new file mode 100644 index 000000000000..6fde05debc90 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-query.ts @@ -0,0 +1,3 @@ +const x = 1; +type T = typeof x; +type Unresolved = x; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type-query.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type-query.ts.shot new file mode 100644 index 000000000000..73af4d407eb7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type-query.ts.shot @@ -0,0 +1,87 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type-query 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + VariableDefinition$1 { + name: Identifier<"x">, + node: VariableDeclarator$1, + }, + ], + name: "x", + references: Array [ + Reference$1 { + identifier: Identifier<"x">, + init: true, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + writeExpr: Literal$2, + }, + Reference$2 { + identifier: Identifier<"x">, + isTypeReference: false, + isValueReference: true, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Unresolved">, + node: TSTypeAliasDeclaration$4, + }, + ], + name: "Unresolved", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + Reference$3 { + identifier: Identifier<"x">, + isTypeReference: true, + isValueReference: false, + resolved: null, + }, + ], + set: Map { + "x" => Variable$1, + "T" => Variable$2, + "Unresolved" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type1.ts b/packages/scope-manager/tests/fixtures/type-declaration/type1.ts new file mode 100644 index 000000000000..0d6d62642cc2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type1.ts @@ -0,0 +1 @@ +type T = 1; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type1.ts.shot new file mode 100644 index 000000000000..9328ce21e141 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type1.ts.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type1 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$2, + isStrict: false, + references: Array [], + set: Map { + "T" => Variable$1, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type2.ts b/packages/scope-manager/tests/fixtures/type-declaration/type2.ts new file mode 100644 index 000000000000..a22d5844b3a1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type2.ts @@ -0,0 +1,2 @@ +type A = 1; +type B = A; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type2.ts.shot new file mode 100644 index 000000000000..aab4fcea0297 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type2.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type2 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "A", + references: Array [ + Reference$1 { + identifier: Identifier<"A">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"B">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "B", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "A" => Variable$1, + "B" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type3.ts b/packages/scope-manager/tests/fixtures/type-declaration/type3.ts new file mode 100644 index 000000000000..1180d2a09b6e --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type3.ts @@ -0,0 +1,5 @@ +type T = 1; +type A = { + b: string; + c: T; +}; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/type3.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/type3.ts.shot new file mode 100644 index 000000000000..f37d0a68a2c2 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/type3.ts.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration type3 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$1, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [ + Reference$1, + ], + set: Map { + "T" => Variable$1, + "A" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/types/reference-type.test.ts b/packages/scope-manager/tests/types/reference-type.test.ts new file mode 100644 index 000000000000..585f29a15a53 --- /dev/null +++ b/packages/scope-manager/tests/types/reference-type.test.ts @@ -0,0 +1,196 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { getSpecificNode, parseAndAnalyze } from '../util'; + +describe('referencing a type - positive', () => { + it('records a reference when a type is referenced from a type', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type TypeDecl = string; + type OtherType = TypeDecl; + `); + const node = getSpecificNode( + ast, + AST_NODE_TYPES.TSTypeAliasDeclaration, + n => n.id.name === 'TypeDecl', + ); + const variable = scopeManager.getDeclaredVariables(node)[0]; + + expect(variable.references).toHaveLength(1); + const referencingNode = getSpecificNode( + ast, + AST_NODE_TYPES.TSTypeAliasDeclaration, + n => n.id.name === 'OtherType', + ); + expect(variable.references[0].identifier.parent?.parent).toBe( + referencingNode, + ); + }); + + it('records a reference when a dual value-type is referenced from a type', () => { + const { ast, scopeManager } = parseAndAnalyze(` + class Class {} + type Type = Class; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.ClassDeclaration); + const variable = scopeManager.getDeclaredVariables(node)[0]; + + expect(variable.references).toHaveLength(1); + const referencingNode = getSpecificNode( + ast, + AST_NODE_TYPES.TSTypeAliasDeclaration, + ); + expect(variable.references[0].identifier.parent?.parent).toBe( + referencingNode, + ); + }); + + it('records a reference when a generic type parameter is referenced from its type', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type TypeDecl = TypeParam; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeParameter); + const variable = scopeManager.getDeclaredVariables(node)[0]; + + expect(variable.references).toHaveLength(1); + const referencingNode = getSpecificNode( + ast, + AST_NODE_TYPES.TSTypeReference, + ); + expect(variable.references[0].identifier.parent).toBe(referencingNode); + }); + + it('records references when a name has both a type and a variable definition', () => { + const { ast, scopeManager } = parseAndAnalyze(` + const dual = 1; + type dual = number; + + type reference1 = dual; + const reference2 = dual; + `); + const node = getSpecificNode( + ast, + AST_NODE_TYPES.VariableDeclarator, + n => n.id.type === AST_NODE_TYPES.Identifier && n.id.name === 'dual', + ); + const variable = scopeManager.getDeclaredVariables(node)[0]; + + // it should merge the defs into a single variable + expect(variable.defs).toHaveLength(2); + + expect(variable.references).toHaveLength(3); + + // first ref is the definition of the variable + expect(variable.references[0].identifier.parent).toBe(node); + // second ref is the type reference + const referencingTypeNode = getSpecificNode( + ast, + AST_NODE_TYPES.TSTypeAliasDeclaration, + n => n.id.name === 'reference1', + ); + expect(variable.references[1].identifier.parent?.parent).toBe( + referencingTypeNode, + ); + // third ref is the variable reference + const referencingVariableNode = getSpecificNode( + ast, + AST_NODE_TYPES.VariableDeclarator, + n => + n.id.type === AST_NODE_TYPES.Identifier && n.id.name === 'reference2', + ); + expect(variable.references[2].identifier.parent).toBe( + referencingVariableNode, + ); + }); + + it('records value and type references to imported variables', () => { + const { ast, scopeManager } = parseAndAnalyze( + ` + import { foo } from 'module'; + const test = foo; + type Test = foo; + `, + 'module', + ); + const node = getSpecificNode(ast, AST_NODE_TYPES.ImportSpecifier); + const variable = scopeManager.getDeclaredVariables(node)[0]; + expect(variable.references).toHaveLength(2); + // first reference is from the variable + const variableDecl = getSpecificNode( + ast, + AST_NODE_TYPES.VariableDeclarator, + ); + expect(variable.references[0].identifier.parent).toBe(variableDecl); + // second reference is from the type + const typeRef = getSpecificNode(ast, AST_NODE_TYPES.TSTypeReference); + expect(variable.references[1].identifier.parent).toBe(typeRef); + }); + + it('records a reference when a value is referenced from a typeof predicate', () => { + const { ast, scopeManager } = parseAndAnalyze(` + const value = 1; + type Type = typeof value; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.VariableDeclarator); + const variable = scopeManager.getDeclaredVariables(node)[0]; + + expect(variable.references).toHaveLength(2); + // first ref is the definition of the variable + expect(variable.references[0].identifier.parent).toBe(node); + // second ref is the predicate reference + const referencingNode = getSpecificNode( + ast, + AST_NODE_TYPES.TSTypeAliasDeclaration, + ); + expect(variable.references[1].identifier.parent?.parent).toBe( + referencingNode, + ); + }); +}); + +describe('referencing a type - negative', () => { + it('does not record a reference when a value is referenced from a type without a typeof predicate', () => { + const { ast, scopeManager } = parseAndAnalyze(` + const value = 1; + type Type = value; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.VariableDeclarator); + const variable = scopeManager.getDeclaredVariables(node)[0]; + + // variables declare a reference to themselves if they have an initialization + // so there should be one reference from the declaration itself + expect(variable.references).toHaveLength(1); + expect(variable.references[0].identifier.parent).toBe(node); + }); + + it('does not record a reference when a type is referenced from a value', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type Type = 1; + const value = Type; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeAliasDeclaration); + const variable = scopeManager.getDeclaredVariables(node)[0]; + expect(variable.references).toHaveLength(0); + }); + + it('does not record a reference when a type is referenced from outside its declaring type', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type TypeDecl = T; + type Other = TypeParam; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeParameter); + const variable = scopeManager.getDeclaredVariables(node)[0]; + expect(variable.references).toHaveLength(0); + }); + + it('does not record a reference when a type import is referenced from a value', () => { + const { ast, scopeManager } = parseAndAnalyze( + ` + import type { foo } from 'module'; + const test = foo; + `, + 'module', + ); + const node = getSpecificNode(ast, AST_NODE_TYPES.ImportSpecifier); + const variable = scopeManager.getDeclaredVariables(node)[0]; + expect(variable.references).toHaveLength(0); + }); +}); diff --git a/packages/scope-manager/tests/types/variable-definition.test.ts b/packages/scope-manager/tests/types/variable-definition.test.ts new file mode 100644 index 000000000000..12ab0f92822a --- /dev/null +++ b/packages/scope-manager/tests/types/variable-definition.test.ts @@ -0,0 +1,109 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { getSpecificNode, parseAndAnalyze } from '../util'; + +describe('variable definition', () => { + it('defines a variable for a type declaration', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type TypeDecl = string; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeAliasDeclaration); + expect(scopeManager.getDeclaredVariables(node)).toMatchInlineSnapshot(` + Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"TypeDecl">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "TypeDecl", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ] + `); + }); + + it('defines a variable for an interface definition', () => { + const { ast, scopeManager } = parseAndAnalyze(` + interface InterfaceDecl { + prop: string; + } + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.TSInterfaceDeclaration); + expect(scopeManager.getDeclaredVariables(node)).toMatchInlineSnapshot(` + Array [ + Variable$1 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"InterfaceDecl">, + node: TSInterfaceDeclaration$1, + }, + ], + name: "InterfaceDecl", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ] + `); + }); + + it('defines a variable for a generic type', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type TypeDecl = string; + `); + const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeParameter); + expect(scopeManager.getDeclaredVariables(node)).toMatchInlineSnapshot(` + Array [ + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"TypeParam">, + node: TSTypeParameter$1, + }, + ], + name: "TypeParam", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ] + `); + }); + + it('defines a variable for an inferred generic type', () => { + const { ast, scopeManager } = parseAndAnalyze(` + type TypeDecl = TypeParam extends Foo ? Inferred : never; + `); + const node = getSpecificNode( + ast, + AST_NODE_TYPES.TSInferType, + n => n.typeParameter, + ); + expect(scopeManager.getDeclaredVariables(node)).toMatchInlineSnapshot(` + Array [ + Variable$3 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"Inferred">, + node: TSTypeParameter$1, + }, + ], + name: "Inferred", + references: Array [ + Reference$3 { + identifier: Identifier<"Inferred">, + isTypeReference: true, + isValueReference: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ] + `); + }); +}); diff --git a/packages/scope-manager/tests/util/expect.ts b/packages/scope-manager/tests/util/expect.ts new file mode 100644 index 000000000000..0057af9f85c2 --- /dev/null +++ b/packages/scope-manager/tests/util/expect.ts @@ -0,0 +1,138 @@ +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/types'; +import { + CatchClauseDefinition, + ClassNameDefinition, + Definition, + DefinitionType, + FunctionNameDefinition, + ImplicitGlobalVariableDefinition, + ImportBindingDefinition, + ParameterDefinition, + VariableDefinition, +} from '../../src/definition'; +import { + BlockScope, + CatchScope, + ClassScope, + ForScope, + FunctionExpressionNameScope, + FunctionScope, + GlobalScope, + ModuleScope, + Scope, + ScopeType, + SwitchScope, + WithScope, +} from '../../src/scope'; + +////////////////// +// EXPECT SCOPE // +////////////////// + +function expectToBeBlockScope(scope: Scope): asserts scope is BlockScope { + expect(scope.type).toBe(ScopeType.block); +} +function expectToBeCatchScope(scope: Scope): asserts scope is CatchScope { + expect(scope.type).toBe(ScopeType.catch); +} +function expectToBeClassScope(scope: Scope): asserts scope is ClassScope { + expect(scope.type).toBe(ScopeType.class); +} +function expectToBeForScope(scope: Scope): asserts scope is ForScope { + expect(scope.type).toBe(ScopeType.for); +} +function expectToBeFunctionScope(scope: Scope): asserts scope is FunctionScope { + expect(scope.type).toBe(ScopeType.function); +} +function expectToBeFunctionExpressionNameScope( + scope: Scope, +): asserts scope is FunctionExpressionNameScope { + expect(scope.type).toBe(ScopeType.functionExpressionName); +} +function expectToBeGlobalScope(scope: Scope): asserts scope is GlobalScope { + expect(scope.type).toBe(ScopeType.global); +} +function expectToBeModuleScope(scope: Scope): asserts scope is ModuleScope { + expect(scope.type).toBe(ScopeType.module); +} +function expectToBeSwitchScope(scope: Scope): asserts scope is SwitchScope { + expect(scope.type).toBe(ScopeType.switch); +} +function expectToBeWithScope(scope: Scope): asserts scope is WithScope { + expect(scope.type).toBe(ScopeType.with); +} + +export { + expectToBeBlockScope, + expectToBeCatchScope, + expectToBeClassScope, + expectToBeForScope, + expectToBeFunctionExpressionNameScope, + expectToBeFunctionScope, + expectToBeGlobalScope, + expectToBeModuleScope, + expectToBeSwitchScope, + expectToBeWithScope, +}; + +/////////////////////// +// EXPECT DEFINITION // +/////////////////////// + +function expectToBeCatchClauseDefinition( + def: Definition, +): asserts def is CatchClauseDefinition { + expect(def.type).toBe(DefinitionType.CatchClause); +} +function expectToBeClassNameDefinition( + def: Definition, +): asserts def is ClassNameDefinition { + expect(def.type).toBe(DefinitionType.ClassName); +} +function expectToBeFunctionNameDefinition( + def: Definition, +): asserts def is FunctionNameDefinition { + expect(def.type).toBe(DefinitionType.FunctionName); +} +function expectToBeImplicitGlobalVariableDefinition( + def: Definition, +): asserts def is ImplicitGlobalVariableDefinition { + expect(def.type).toBe(DefinitionType.ImplicitGlobalVariable); +} +function expectToBeImportBindingDefinition( + def: Definition, +): asserts def is ImportBindingDefinition { + expect(def.type).toBe(DefinitionType.ImportBinding); +} +function expectToBeParameterDefinition( + def: Definition, +): asserts def is ParameterDefinition { + expect(def.type).toBe(DefinitionType.Parameter); +} +function expectToBeVariableDefinition( + def: Definition, +): asserts def is VariableDefinition { + expect(def.type).toBe(DefinitionType.Variable); +} + +export { + expectToBeCatchClauseDefinition, + expectToBeClassNameDefinition, + expectToBeFunctionNameDefinition, + expectToBeImplicitGlobalVariableDefinition, + expectToBeImportBindingDefinition, + expectToBeParameterDefinition, + expectToBeVariableDefinition, +}; + +///////////////// +// EXPECT MISC // +///////////////// + +function expectToBeIdentifier( + node: TSESTree.Node | null | undefined, +): asserts node is TSESTree.Identifier { + expect(node?.type).toBe(AST_NODE_TYPES.Identifier); +} + +export { expectToBeIdentifier }; diff --git a/packages/scope-manager/tests/util/getSpecificNode.ts b/packages/scope-manager/tests/util/getSpecificNode.ts new file mode 100644 index 000000000000..d20ab14ff580 --- /dev/null +++ b/packages/scope-manager/tests/util/getSpecificNode.ts @@ -0,0 +1,52 @@ +import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/types'; +import { simpleTraverse } from '@typescript-eslint/typescript-estree'; + +function getSpecificNode< + TSelector extends AST_NODE_TYPES, + TNode extends Extract +>(ast: TSESTree.Node, selector: TSelector): TNode; +function getSpecificNode< + TSelector extends AST_NODE_TYPES, + TNode extends Extract +>( + ast: TSESTree.Node, + selector: TSelector, + cb: (node: TNode) => boolean | null | undefined, +): TNode; +function getSpecificNode< + TSelector extends AST_NODE_TYPES, + TNode extends Extract, + TReturnType extends TSESTree.Node +>( + ast: TSESTree.Node, + selector: TSelector, + cb: (node: TNode) => TReturnType | null | undefined, +): TReturnType; + +function getSpecificNode( + ast: TSESTree.Node, + selector: AST_NODE_TYPES, + cb?: (node: TSESTree.Node) => TSESTree.Node | boolean | null | undefined, +): TSESTree.Node { + let node: TSESTree.Node | null | undefined = null; + simpleTraverse( + ast, + { + [selector](n) { + const res = cb ? cb(n) : n; + if (res) { + // the callback shouldn't match multiple nodes or else tests may behave weirdly + expect(node).toBeFalsy(); + node = typeof res === 'boolean' ? n : res; + } + }, + }, + true, + ); + + // should have found at least one node + expect(node).not.toBeFalsy(); + return node!; +} + +export { getSpecificNode }; diff --git a/packages/scope-manager/tests/util/index.ts b/packages/scope-manager/tests/util/index.ts new file mode 100644 index 000000000000..295dda41ae72 --- /dev/null +++ b/packages/scope-manager/tests/util/index.ts @@ -0,0 +1,3 @@ +export * from './expect'; +export * from './getSpecificNode'; +export * from './parse'; diff --git a/packages/scope-manager/tests/util/parse.ts b/packages/scope-manager/tests/util/parse.ts new file mode 100644 index 000000000000..647396f0dcd3 --- /dev/null +++ b/packages/scope-manager/tests/util/parse.ts @@ -0,0 +1,30 @@ +import * as tseslint from '@typescript-eslint/typescript-estree'; +import { analyze, AnalyzeOptions } from '../../src/analyze'; + +type SourceType = AnalyzeOptions['sourceType']; + +function parse( + code: string, + sourceType?: SourceType, +): ReturnType { + return tseslint.parse(code, { + range: true, + sourceType, + }); +} + +function parseAndAnalyze( + code: string, + option: SourceType | AnalyzeOptions = {}, +): { + ast: ReturnType; + scopeManager: ReturnType; +} { + const sourceType = typeof option === 'string' ? option : option.sourceType; + option = typeof option === 'string' ? { sourceType } : option; + const ast = parse(code, sourceType); + const scopeManager = analyze(ast, option); + return { ast, scopeManager }; +} + +export { parse, parseAndAnalyze, AnalyzeOptions }; diff --git a/packages/scope-manager/tests/util/serializers/DefinitionBase.ts b/packages/scope-manager/tests/util/serializers/DefinitionBase.ts new file mode 100644 index 000000000000..a65781553d14 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/DefinitionBase.ts @@ -0,0 +1,20 @@ +import { createSerializer } from './baseSerializer'; +import { DefinitionBase } from '../../../src/definition/DefinitionBase'; + +// hacking around the fact that you can't use abstract classes generically +// eslint-disable-next-line @typescript-eslint/no-explicit-any +class DefinitionInstance extends DefinitionBase { + isTypeDefinition = false; + isVariableDefinition = false; +} +const serializer = createSerializer( + DefinitionBase, + [ + // + 'name', + 'node', + ], + DefinitionInstance, +); + +export { serializer }; diff --git a/packages/scope-manager/tests/util/serializers/Reference.ts b/packages/scope-manager/tests/util/serializers/Reference.ts new file mode 100644 index 000000000000..ea0838702970 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/Reference.ts @@ -0,0 +1,13 @@ +import { createSerializer } from './baseSerializer'; +import { Reference } from '../../../src/referencer/Reference'; + +const serializer = createSerializer(Reference, [ + 'identifier', + 'init', + 'isTypeReference', + 'isValueReference', + 'resolved', + 'writeExpr', +]); + +export { serializer }; diff --git a/packages/scope-manager/tests/util/serializers/ScopeBase.ts b/packages/scope-manager/tests/util/serializers/ScopeBase.ts new file mode 100644 index 000000000000..fea57627e81c --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/ScopeBase.ts @@ -0,0 +1,22 @@ +import { createSerializer } from './baseSerializer'; +import { ScopeBase } from '../../../src/scope/ScopeBase'; + +// hacking around the fact that you can't use abstract classes generically +// eslint-disable-next-line @typescript-eslint/no-explicit-any +class ScopeInstance extends ScopeBase {} +const serializer = createSerializer( + ScopeBase, + [ + // + 'block', + 'isStrict', + 'references', + 'set', + 'type', + 'upper', + 'variables', + ], + ScopeInstance, +); + +export { serializer }; diff --git a/packages/scope-manager/tests/util/serializers/ScopeManager.ts b/packages/scope-manager/tests/util/serializers/ScopeManager.ts new file mode 100644 index 000000000000..4b10150f1798 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/ScopeManager.ts @@ -0,0 +1,10 @@ +import { createSerializer } from './baseSerializer'; +import { ScopeManager } from '../../../src/ScopeManager'; + +const serializer = createSerializer(ScopeManager, [ + // purposely put variables first + 'variables', + 'scopes', +]); + +export { serializer }; diff --git a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts new file mode 100644 index 000000000000..4611ddcce736 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts @@ -0,0 +1,50 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/types'; +import { NewPlugin } from 'pretty-format'; +import { createIdGenerator } from '../../../src/ID'; + +const EXCLUDED_KEYS = new Set([ + // prevent cycles + 'parent', + // type is printed in front of the object + 'type', + // locations are just noise + 'range', + 'loc', +]); + +const generator = createIdGenerator(); +type Node = Record & { type: AST_NODE_TYPES }; +const SEEN_NODES = new Map(); + +const serializer: NewPlugin = { + test(val): boolean { + return ( + val && + typeof val === 'object' && + // make sure it's not one of the classes from the package + Object.getPrototypeOf(val) === Object.prototype && + 'type' in val && + val.type in AST_NODE_TYPES + ); + }, + serialize(node: Node): string { + if (node.type === AST_NODE_TYPES.Identifier) { + return `Identifier<"${node.name}">`; + } + + const keys = Object.keys(node).filter(k => !EXCLUDED_KEYS.has(k)); + if (keys.length === 0) { + return `${node.type}`; + } + + if (SEEN_NODES.has(node)) { + return `${node.type}$${SEEN_NODES.get(node)}`; + } + + const id = generator(); + SEEN_NODES.set(node, id); + return `${node.type}$${id}`; + }, +}; + +export { serializer }; diff --git a/packages/scope-manager/tests/util/serializers/Variable.ts b/packages/scope-manager/tests/util/serializers/Variable.ts new file mode 100644 index 000000000000..eb2638564ba1 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/Variable.ts @@ -0,0 +1,13 @@ +import { createSerializer } from './baseSerializer'; +import { Variable } from '../../../src/Variable'; + +const serializer = createSerializer(Variable, [ + // + 'defs', + 'name', + 'references', + 'isValueVariable', + 'isTypeVariable', +]); + +export { serializer }; diff --git a/packages/scope-manager/tests/util/serializers/baseSerializer.ts b/packages/scope-manager/tests/util/serializers/baseSerializer.ts new file mode 100644 index 000000000000..df8ba1fba119 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/baseSerializer.ts @@ -0,0 +1,78 @@ +import { NewPlugin } from 'pretty-format'; + +type ConstructorSignature = new (...args: never) => unknown; + +function createSerializer( + type: TConstructor, + keys: (keyof InstanceType)[], +): NewPlugin; +// A hack of signature to enable this to work with abstract classes +function createSerializer( + abstractConstructor: unknown, + keys: (keyof InstanceType)[], + instanceConstructorThatsNeverUsed: TConstructor, +): NewPlugin; + +function createSerializer( + type: TConstructor, + keys: (keyof InstanceType)[], +): NewPlugin { + const SEEN_THINGS = new Set(); + + return { + test(val): boolean { + return val instanceof type; + }, + serialize( + thing: Record & { $id?: number }, + config, + indentation, + depth, + refs, + printer, + ): string { + const id = thing.$id != null ? `$${thing.$id}` : ''; + // If `type` is a base class, we should print out the name of the subclass + const constructorName = Object.getPrototypeOf(thing).constructor.name; + + const name = `${constructorName}${id}`; + + if (thing.$id) { + if (SEEN_THINGS.has(thing)) { + return `${name}`; + } + SEEN_THINGS.add(thing); + } + + const outputLines = []; + const childIndentation = indentation + config.indent; + for (const key of keys) { + let value = thing[key as string]; + if (value === undefined) { + continue; + } + if (typeof value === 'function') { + value = value.call(thing); + } + + outputLines.push( + `${childIndentation}${key}: ${printer( + value, + config, + childIndentation, + depth, + refs, + )},`, + ); + } + + outputLines.unshift(`${name} {`); + outputLines.push(`${indentation}}`); + + const out = outputLines.join('\n'); + return out; + }, + }; +} + +export { createSerializer }; diff --git a/packages/scope-manager/tests/util/serializers/index.ts b/packages/scope-manager/tests/util/serializers/index.ts new file mode 100644 index 000000000000..d2e024d7f6c1 --- /dev/null +++ b/packages/scope-manager/tests/util/serializers/index.ts @@ -0,0 +1,28 @@ +import { addSerializer } from 'jest-specific-snapshot'; +import * as DefinitionBase from './DefinitionBase'; +import * as Reference from './Reference'; +import * as ScopeBase from './ScopeBase'; +import * as ScopeManager from './ScopeManager'; +import * as TSESTreeNode from './TSESTreeNode'; +import * as Variable from './Variable'; +import { resetIds } from '../../../src/ID'; + +const serializers = [ + DefinitionBase.serializer, + Reference.serializer, + ScopeBase.serializer, + ScopeManager.serializer, + TSESTreeNode.serializer, + Variable.serializer, +]; + +for (const serializer of serializers) { + // the jest types are wrong here + expect.addSnapshotSerializer(serializer); + addSerializer(serializer); +} + +// make sure the snapshots are isolated from one another +beforeEach(() => { + resetIds(); +}); diff --git a/packages/scope-manager/tsconfig.build.json b/packages/scope-manager/tsconfig.build.json new file mode 100644 index 000000000000..a67b4c6cfeb7 --- /dev/null +++ b/packages/scope-manager/tsconfig.build.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist", + "rootDir": "./src", + "resolveJsonModule": true + }, + "include": ["src", "typings"], + "exclude": ["tests/fixtures"], + "references": [ + { "path": "../types/tsconfig.build.json" }, + { "path": "../typescript-estree/tsconfig.build.json" }, + { "path": "../visitor-keys/tsconfig.build.json" } + ] +} diff --git a/packages/scope-manager/tsconfig.json b/packages/scope-manager/tsconfig.json new file mode 100644 index 000000000000..9cea515ba6b2 --- /dev/null +++ b/packages/scope-manager/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.build.json", + "compilerOptions": { + "composite": false, + "rootDir": "." + }, + "include": ["src", "typings", "tests", "tools"] +} diff --git a/packages/types/src/ts-estree.ts b/packages/types/src/ts-estree.ts index 9c1e14bd5b44..f268a38257bd 100644 --- a/packages/types/src/ts-estree.ts +++ b/packages/types/src/ts-estree.ts @@ -331,6 +331,13 @@ export type DeclarationStatement = | TSNamespaceExportDeclaration | TSTypeAliasDeclaration | TSEnumDeclaration; +export type DestructuringPattern = + | Identifier + | ObjectPattern + | ArrayPattern + | RestElement + | AssignmentPattern + | MemberExpression; export type EntityName = Identifier | TSQualifiedName; export type ExportDeclaration = | ClassDeclaration @@ -347,6 +354,7 @@ export type Expression = | AssignmentExpression | BinaryExpression | ConditionalExpression + | ImportExpression | JSXClosingElement | JSXClosingFragment | JSXExpressionContainer @@ -360,11 +368,7 @@ export type Expression = | SpreadElement | TSAsExpression | TSUnaryExpression - | YieldExpression - | ImportExpression; -export type ExpressionWithTypeArguments = - | TSClassImplements - | TSInterfaceHeritage; + | YieldExpression; export type ForInitialiser = Expression | VariableDeclaration; export type ImportClause = | ImportDefaultSpecifier @@ -429,19 +433,12 @@ export type OptionalMemberExpression = | OptionalMemberExpressionComputedName | OptionalMemberExpressionNonComputedName; export type Parameter = - | AssignmentPattern - | RestElement | ArrayPattern - | ObjectPattern - | Identifier - | TSParameterProperty; -export type DestructuringPattern = + | AssignmentPattern | Identifier | ObjectPattern - | ArrayPattern | RestElement - | AssignmentPattern - | MemberExpression; + | TSParameterProperty; export type PrimaryExpression = | ArrayExpression | ArrayPattern @@ -514,12 +511,10 @@ export type TypeElement = | TSMethodSignature | TSPropertySignature; export type TypeNode = - | ThisExpression | TSAnyKeyword | TSArrayType | TSBigIntKeyword | TSBooleanKeyword - | TSClassImplements | TSConditionalType | TSConstructorType | TSFunctionType @@ -575,7 +570,7 @@ interface ClassDeclarationBase extends BaseNode { id: Identifier | null; body: ClassBody; superClass: LeftHandSideExpression | null; - implements?: ExpressionWithTypeArguments[]; + implements?: TSClassImplements[]; abstract?: boolean; declare?: boolean; decorators?: Decorator[]; @@ -1422,7 +1417,7 @@ export interface TSIndexSignature extends BaseNode { export interface TSInferType extends BaseNode { type: AST_NODE_TYPES.TSInferType; - typeParameter: TSTypeParameterDeclaration; + typeParameter: TSTypeParameter; } export interface TSInterfaceDeclaration extends BaseNode { @@ -1430,8 +1425,8 @@ export interface TSInterfaceDeclaration extends BaseNode { body: TSInterfaceBody; id: Identifier; typeParameters?: TSTypeParameterDeclaration; - extends?: ExpressionWithTypeArguments[]; - implements?: ExpressionWithTypeArguments[]; + extends?: TSInterfaceHeritage[]; + implements?: TSInterfaceHeritage[]; decorators?: Decorator[]; abstract?: boolean; declare?: boolean; diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 2a6db370570b..3f53b4c8205c 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -2477,8 +2477,8 @@ export class Converter { } if (interfaceHeritageClauses.length > 0) { - const interfaceExtends: TSESTree.ExpressionWithTypeArguments[] = []; - const interfaceImplements: TSESTree.ExpressionWithTypeArguments[] = []; + const interfaceExtends: TSESTree.TSInterfaceHeritage[] = []; + const interfaceImplements: TSESTree.TSInterfaceHeritage[] = []; for (const heritageClause of interfaceHeritageClauses) { if (heritageClause.token === SyntaxKind.ExtendsKeyword) { diff --git a/packages/typescript-estree/src/index.ts b/packages/typescript-estree/src/index.ts index 88af46a20919..5151748ee996 100644 --- a/packages/typescript-estree/src/index.ts +++ b/packages/typescript-estree/src/index.ts @@ -4,7 +4,7 @@ export { parseAndGenerateServices, ParseAndGenerateServicesResult, } from './parser'; -export { ParserServices, TSESTreeOptions } from './parser-options'; +export { ParserServices, TSESTreeOptions, EcmaVersion } from './parser-options'; export { simpleTraverse } from './simple-traverse'; export * from './ts-estree'; export { clearCaches } from './create-program/createWatchProgram'; diff --git a/packages/typescript-estree/src/parser-options.ts b/packages/typescript-estree/src/parser-options.ts index 180ac418d7b2..9abdc1e10337 100644 --- a/packages/typescript-estree/src/parser-options.ts +++ b/packages/typescript-estree/src/parser-options.ts @@ -190,3 +190,20 @@ export interface ParserServices { tsNodeToESTreeNodeMap: ParserWeakMap; hasFullTypeInformation: boolean; } + +// This is defined here even though it's not used here to prevent cyclic references between packages +export type EcmaVersion = + | 3 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 2015 + | 2016 + | 2017 + | 2018 + | 2019 + | 2020; diff --git a/packages/typescript-estree/src/simple-traverse.ts b/packages/typescript-estree/src/simple-traverse.ts index 1a25187ab26e..4d4ddaa5f187 100644 --- a/packages/typescript-estree/src/simple-traverse.ts +++ b/packages/typescript-estree/src/simple-traverse.ts @@ -9,28 +9,46 @@ function isValidNode(x: any): x is TSESTree.Node { function getVisitorKeysForNode( allVisitorKeys: typeof visitorKeys, node: TSESTree.Node, -): readonly string[] { +): readonly (keyof TSESTree.Node)[] { const keys = allVisitorKeys[node.type]; - return keys ?? []; + return (keys ?? []) as never; } -interface SimpleTraverseOptions { - enter: (node: TSESTree.Node, parent: TSESTree.Node | undefined) => void; -} +type SimpleTraverseOptions = + | { + enter: (node: TSESTree.Node, parent: TSESTree.Node | undefined) => void; + } + | { + [key: string]: ( + node: TSESTree.Node, + parent: TSESTree.Node | undefined, + ) => void; + }; class SimpleTraverser { - private allVisitorKeys = visitorKeys; - private enter: SimpleTraverseOptions['enter']; + private readonly allVisitorKeys = visitorKeys; + private readonly selectors: SimpleTraverseOptions; + private readonly setParentPointers: boolean; - constructor({ enter }: SimpleTraverseOptions) { - this.enter = enter; + constructor(selectors: SimpleTraverseOptions, setParentPointers = false) { + this.selectors = selectors; + this.setParentPointers = setParentPointers; } traverse(node: unknown, parent: TSESTree.Node | undefined): void { if (!isValidNode(node)) { return; } - this.enter(node, parent); + + if (this.setParentPointers) { + node.parent = parent; + } + + if ('enter' in this.selectors) { + this.selectors.enter(node, parent); + } else if (node.type in this.selectors) { + this.selectors[node.type](node, parent); + } const keys = getVisitorKeysForNode(this.allVisitorKeys, node); if (keys.length < 1) { @@ -38,7 +56,7 @@ class SimpleTraverser { } for (const key of keys) { - const childOrChildren = node[key as keyof TSESTree.Node]; + const childOrChildren = node[key]; if (Array.isArray(childOrChildren)) { for (const child of childOrChildren) { @@ -54,6 +72,10 @@ class SimpleTraverser { export function simpleTraverse( startingNode: TSESTree.Node, options: SimpleTraverseOptions, + setParentPointers = false, ): void { - new SimpleTraverser(options).traverse(startingNode, undefined); + new SimpleTraverser(options, setParentPointers).traverse( + startingNode, + undefined, + ); } diff --git a/tests/integration/docker-compose.yml b/tests/integration/docker-compose.yml index 69f2e157f01f..abe82a67cfb6 100644 --- a/tests/integration/docker-compose.yml +++ b/tests/integration/docker-compose.yml @@ -23,6 +23,8 @@ services: - /usr/types/tests - ../../packages/visitor-keys/:/usr/visitor-keys - /usr/types/visitor-keys + - ../../packages/scope-manager/:/usr/scope-manager + - /usr/types/scope-manager # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/typescript-and-tslint-plugins-together:/usr/linked @@ -46,6 +48,8 @@ services: - /usr/types/tests - ../../packages/visitor-keys/:/usr/visitor-keys - /usr/types/visitor-keys + - ../../packages/scope-manager/:/usr/scope-manager + - /usr/types/scope-manager # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/vue-sfc:/usr/linked @@ -69,6 +73,8 @@ services: - /usr/types/tests - ../../packages/visitor-keys/:/usr/visitor-keys - /usr/types/visitor-keys + - ../../packages/scope-manager/:/usr/scope-manager + - /usr/types/scope-manager # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/vue-jsx:/usr/linked @@ -92,6 +98,8 @@ services: - /usr/types/tests - ../../packages/visitor-keys/:/usr/visitor-keys - /usr/types/visitor-keys + - ../../packages/scope-manager/:/usr/scope-manager + - /usr/types/scope-manager # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/recommended-does-not-require-program:/usr/linked @@ -115,6 +123,8 @@ services: - /usr/types/tests - ../../packages/visitor-keys/:/usr/visitor-keys - /usr/types/visitor-keys + - ../../packages/scope-manager/:/usr/scope-manager + - /usr/types/scope-manager # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/markdown:/usr/linked @@ -138,5 +148,7 @@ services: - /usr/types/tests - ../../packages/visitor-keys/:/usr/visitor-keys - /usr/types/visitor-keys + - ../../packages/scope-manager/:/usr/scope-manager + - /usr/types/scope-manager # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/eslint-v6:/usr/linked diff --git a/tests/integration/fixtures/eslint-v6/test.sh b/tests/integration/fixtures/eslint-v6/test.sh index 9f392c3687d9..ab184f9ceb15 100755 --- a/tests/integration/fixtures/eslint-v6/test.sh +++ b/tests/integration/fixtures/eslint-v6/test.sh @@ -11,6 +11,7 @@ npm install eslint@6.0.0 # Use the local volumes for our own packages npm install $(npm pack /usr/types | tail -1) npm install $(npm pack /usr/visitor-keys | tail -1) +npm install $(npm pack /usr/scope-manager | tail -1) npm install $(npm pack /usr/typescript-estree | tail -1) npm install $(npm pack /usr/parser | tail -1) npm install $(npm pack /usr/experimental-utils | tail -1) diff --git a/tests/integration/fixtures/markdown/test.sh b/tests/integration/fixtures/markdown/test.sh index 77dd83eaa214..30cd435eaac7 100755 --- a/tests/integration/fixtures/markdown/test.sh +++ b/tests/integration/fixtures/markdown/test.sh @@ -10,6 +10,7 @@ npm install # Use the local volumes for our own packages npm install $(npm pack /usr/types | tail -1) npm install $(npm pack /usr/visitor-keys | tail -1) +npm install $(npm pack /usr/scope-manager | tail -1) npm install $(npm pack /usr/typescript-estree | tail -1) npm install $(npm pack /usr/parser | tail -1) npm install $(npm pack /usr/experimental-utils | tail -1) diff --git a/tests/integration/fixtures/recommended-does-not-require-program/test.sh b/tests/integration/fixtures/recommended-does-not-require-program/test.sh index 4db9f0c4491a..cfe4d0e6d570 100755 --- a/tests/integration/fixtures/recommended-does-not-require-program/test.sh +++ b/tests/integration/fixtures/recommended-does-not-require-program/test.sh @@ -10,6 +10,7 @@ npm install # Use the local volumes for our own packages npm install $(npm pack /usr/types | tail -1) npm install $(npm pack /usr/visitor-keys | tail -1) +npm install $(npm pack /usr/scope-manager | tail -1) npm install $(npm pack /usr/typescript-estree | tail -1) npm install $(npm pack /usr/parser | tail -1) npm install $(npm pack /usr/experimental-utils | tail -1) diff --git a/tests/integration/fixtures/typescript-and-tslint-plugins-together/test.sh b/tests/integration/fixtures/typescript-and-tslint-plugins-together/test.sh index bb0389abea20..6abbeb42aa61 100755 --- a/tests/integration/fixtures/typescript-and-tslint-plugins-together/test.sh +++ b/tests/integration/fixtures/typescript-and-tslint-plugins-together/test.sh @@ -10,6 +10,7 @@ npm install # Use the local volumes for our own packages npm install $(npm pack /usr/types | tail -1) npm install $(npm pack /usr/visitor-keys | tail -1) +npm install $(npm pack /usr/scope-manager | tail -1) npm install $(npm pack /usr/typescript-estree | tail -1) npm install $(npm pack /usr/parser | tail -1) npm install $(npm pack /usr/experimental-utils | tail -1) diff --git a/tests/integration/fixtures/vue-jsx/test.sh b/tests/integration/fixtures/vue-jsx/test.sh index 71932d4e7ae1..96376fb0f83c 100755 --- a/tests/integration/fixtures/vue-jsx/test.sh +++ b/tests/integration/fixtures/vue-jsx/test.sh @@ -10,6 +10,7 @@ npm install # Use the local volumes for our own packages npm install $(npm pack /usr/types | tail -1) npm install $(npm pack /usr/visitor-keys | tail -1) +npm install $(npm pack /usr/scope-manager | tail -1) npm install $(npm pack /usr/typescript-estree | tail -1) npm install $(npm pack /usr/parser | tail -1) npm install $(npm pack /usr/experimental-utils | tail -1) diff --git a/tests/integration/fixtures/vue-sfc/test.sh b/tests/integration/fixtures/vue-sfc/test.sh index 71932d4e7ae1..96376fb0f83c 100755 --- a/tests/integration/fixtures/vue-sfc/test.sh +++ b/tests/integration/fixtures/vue-sfc/test.sh @@ -10,6 +10,7 @@ npm install # Use the local volumes for our own packages npm install $(npm pack /usr/types | tail -1) npm install $(npm pack /usr/visitor-keys | tail -1) +npm install $(npm pack /usr/scope-manager | tail -1) npm install $(npm pack /usr/typescript-estree | tail -1) npm install $(npm pack /usr/parser | tail -1) npm install $(npm pack /usr/experimental-utils | tail -1) diff --git a/yarn.lock b/yarn.lock index 337037083ad9..389888e4c810 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1590,7 +1590,14 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@^25.2.1": +"@types/jest-specific-snapshot@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@types/jest-specific-snapshot/-/jest-specific-snapshot-0.5.4.tgz#997364c39a59ddeff0ee790a19415e79dd061d1e" + integrity sha512-1qISn4fH8wkOOPFEx+uWRRjw6m/pP/It3OHLm8Ee1KQpO7Z9ZGYDtWPU5AgK05UXsNTAgOK+dPQvJKGdy9E/1g== + dependencies: + "@types/jest" "*" + +"@types/jest@*", "@types/jest@^25.2.1": version "25.2.1" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.1.tgz#9544cd438607955381c1bdbdb97767a249297db5" integrity sha512-msra1bCaAeEdkSyA0CZ6gW1ukMIvZ5YoJkdXw/qhQdsuuDlFTcEUrUw8CLCPt2rVRUfXlClVvK2gvPs9IokZaA== @@ -1623,7 +1630,19 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= -"@types/node@*", "@types/node@>= 8", "@types/node@^13.13.5": +"@types/mkdirp@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.0.tgz#16ce0eabe4a9a3afe64557ad0ee6886ec3d32927" + integrity sha512-ONFY9//bCEr3DWKON3iDv/Q8LXnhaYYaNDeFSN0AtO5o4sLf9F0pstJKKKjQhXE0kJEeHs8eR6SAsROhhc2Csw== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@>= 8": + version "12.12.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11" + integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w== + +"@types/node@^13.13.5": version "13.13.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.5.tgz#96ec3b0afafd64a4ccea9107b75bf8489f0e5765" integrity sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g== @@ -5378,7 +5397,7 @@ jest-serializer@^25.5.0: dependencies: graceful-fs "^4.2.4" -jest-snapshot@^25.5.1: +jest-snapshot@^25.1.0, jest-snapshot@^25.5.1: version "25.5.1" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.5.1.tgz#1a2a576491f9961eb8d00c2e5fd479bc28e5ff7f" integrity sha512-C02JE1TUe64p2v1auUJ2ze5vcuv32tkv9PyhEb318e8XOKF7MOyXdJ7kdjbvrp3ChPLU2usI7Rjxs97Dj5P0uQ== @@ -5399,6 +5418,13 @@ jest-snapshot@^25.5.1: pretty-format "^25.5.0" semver "^6.3.0" +jest-specific-snapshot@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/jest-specific-snapshot/-/jest-specific-snapshot-3.0.0.tgz#c203a6bccc572832aea0278feeaa3350567a306f" + integrity sha512-dMEDxj762XleVVUYnxHbRypWOxRwV3HsolUZugISyFu8jE6Xz58TkeKeXxRfT9oG6U8zxPggrH+1MSNVyLwGqg== + dependencies: + jest-snapshot "^25.1.0" + jest-util@^25.5.0: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.5.0.tgz#31c63b5d6e901274d264a4fec849230aa3fa35b0" @@ -5910,7 +5936,7 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0: +make-dir@^3.0.0, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==