From 8b6ec68a9d1b79d2434b80effa739bc03a7d3dc3 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 5 Jun 2017 20:25:12 +0200 Subject: [PATCH] handle references to class from inner scope correctly Create only a single variable to ClassDeclarations instead of two for inner and outer scope. --- src/referencer.js | 2 +- test/es6-class.js | 42 ++++++++++++++++++++++++++++++++-- test/es6-super.js | 3 +-- test/get-declared-variables.js | 4 ++-- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/referencer.js b/src/referencer.js index bd81080..1900b6e 100644 --- a/src/referencer.js +++ b/src/referencer.js @@ -250,7 +250,7 @@ export default class Referencer extends esrecurse.Visitor { this.scopeManager.__nestClassScope(node); - if (node.id) { + if (node.id && node.type !== Syntax.ClassDeclaration) { this.currentScope().__define(node.id, new Definition( Variable.ClassName, diff --git a/test/es6-class.js b/test/es6-class.js index 8c6ffac..84a4637 100644 --- a/test/es6-class.js +++ b/test/es6-class.js @@ -52,8 +52,7 @@ describe('ES6 class', function() { expect(scope.type).to.be.equal('class'); expect(scope.block.type).to.be.equal('ClassDeclaration'); expect(scope.isStrict).to.be.true; - expect(scope.variables).to.have.length(1); - expect(scope.variables[0].name).to.be.equal('Derived'); + expect(scope.variables).to.have.length(0); expect(scope.references).to.have.length(0); scope = scopeManager.scopes[2]; @@ -191,6 +190,45 @@ describe('ES6 class', function() { expect(scope.references[0].identifier.name).to.be.equal('shoe'); expect(scope.references[1].identifier.name).to.be.equal('Shoe'); }); + + it('reference in class', function() { + const ast = parse(` + class Foo { + constructor() { + Foo; + } + } + `); + + + const scopeManager = analyze(ast, {ecmaVersion: 6}); + expect(scopeManager.scopes).to.have.length(3); + + let scope = scopeManager.scopes[0]; + expect(scope.type).to.be.equal('global'); + expect(scope.block.type).to.be.equal('Program'); + expect(scope.isStrict).to.be.false; + expect(scope.variables).to.have.length(1); + expect(scope.variables[0].name).to.be.equal('Foo'); + expect(scope.variables[0].references).to.have.length(1); + expect(scope.variables[0].references[0].identifier.name).to.be.equal('Foo'); + + scope = scopeManager.scopes[1]; + expect(scope.type).to.be.equal('class'); + expect(scope.block.type).to.be.equal('ClassDeclaration'); + expect(scope.isStrict).to.be.true; + expect(scope.variables).to.have.length(0); + expect(scope.references).to.have.length(0); + + scope = scopeManager.scopes[2]; + expect(scope.type).to.be.equal('function'); + expect(scope.block.type).to.be.equal('FunctionExpression'); + expect(scope.isStrict).to.be.true; + expect(scope.variables).to.have.length(1); + expect(scope.variables[0].name).to.be.equal('arguments'); + expect(scope.references).to.have.length(1); + expect(scope.references[0].identifier.name).to.be.equal('Foo'); + }); }); // vim: set sw=4 ts=4 et tw=80 : diff --git a/test/es6-super.js b/test/es6-super.js index 4da988d..ae6bcaf 100644 --- a/test/es6-super.js +++ b/test/es6-super.js @@ -50,8 +50,7 @@ describe('ES6 super', function() { scope = scopeManager.scopes[1]; expect(scope.type).to.be.equal('class'); - expect(scope.variables).to.have.length(1); - expect(scope.variables[0].name).to.be.equal('Hello'); + expect(scope.variables).to.have.length(0); expect(scope.references).to.have.length(0); scope = scopeManager.scopes[2]; diff --git a/test/get-declared-variables.js b/test/get-declared-variables.js index ef0e227..1f2eb28 100644 --- a/test/get-declared-variables.js +++ b/test/get-declared-variables.js @@ -165,8 +165,8 @@ describe('ScopeManager.prototype.getDeclaredVariables', function() { `); verify(ast, 'ClassDeclaration', [ - ['A', 'A'], // outer scope's and inner scope's. - ['B', 'B'] + ['A'], + ['B'] ]); });