Skip to content

Commit a406b35

Browse files
committed
add reference to inner variable to Definition of class
1 parent 1567e9d commit a406b35

File tree

4 files changed

+65
-15
lines changed

4 files changed

+65
-15
lines changed

src/definition.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import Variable from './variable';
2828
* @class Definition
2929
*/
3030
export default class Definition {
31-
constructor(type, name, node, parent, index, kind) {
31+
constructor(type, name, node, parent, index, kind, inner) {
3232
/**
3333
* @member {String} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...).
3434
*/
@@ -53,6 +53,10 @@ export default class Definition {
5353
* @member {String?} Definition#kind - the kind of the declaration statement.
5454
*/
5555
this.kind = kind;
56+
/**
57+
* @member {Variable} Definition#inner - the reference to the inner scope variable.
58+
*/
59+
this.inner = inner;
5660
}
5761
}
5862

src/referencer.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -233,25 +233,15 @@ export default class Referencer extends esrecurse.Visitor {
233233
}
234234

235235
visitClass(node) {
236-
if (node.type === Syntax.ClassDeclaration) {
237-
this.currentScope().__define(node.id,
238-
new Definition(
239-
Variable.ClassName,
240-
node.id,
241-
node,
242-
null,
243-
null,
244-
null
245-
));
246-
}
236+
var innerVariable;
247237

248238
// FIXME: Maybe consider TDZ.
249239
this.visit(node.superClass);
250240

251241
this.scopeManager.__nestClassScope(node);
252242

253243
if (node.id) {
254-
this.currentScope().__define(node.id,
244+
innerVariable = this.currentScope().__define(node.id,
255245
new Definition(
256246
Variable.ClassName,
257247
node.id,
@@ -261,6 +251,19 @@ export default class Referencer extends esrecurse.Visitor {
261251
this.visit(node.body);
262252

263253
this.close(node);
254+
255+
if (node.type === Syntax.ClassDeclaration) {
256+
this.currentScope().__define(node.id,
257+
new Definition(
258+
Variable.ClassName,
259+
node.id,
260+
node,
261+
null,
262+
null,
263+
null,
264+
innerVariable
265+
));
266+
}
264267
}
265268

266269
visitProperty(node) {

src/scope.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,13 @@ export default class Scope {
352352
if (node) {
353353
variable.identifiers.push(node);
354354
}
355+
356+
return variable;
355357
}
356358

357359
__define(node, def) {
358360
if (node && node.type === Syntax.Identifier) {
359-
this.__defineGeneric(
361+
return this.__defineGeneric(
360362
node.name,
361363
this.set,
362364
this.variables,
@@ -504,7 +506,7 @@ export class GlobalScope extends Scope {
504506

505507
__defineImplicit(node, def) {
506508
if (node && node.type === Syntax.Identifier) {
507-
this.__defineGeneric(
509+
return this.__defineGeneric(
508510
node.name,
509511
this.implicit.set,
510512
this.implicit.variables,

test/es6-class.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,47 @@ describe('ES6 class', function() {
191191
expect(scope.references[0].identifier.name).to.be.equal('shoe');
192192
expect(scope.references[1].identifier.name).to.be.equal('Shoe');
193193
});
194+
195+
it('reference in class', function() {
196+
const ast = parse(`
197+
class Foo {
198+
constructor() {
199+
Foo;
200+
}
201+
}
202+
`);
203+
204+
205+
const scopeManager = analyze(ast, {ecmaVersion: 6});
206+
expect(scopeManager.scopes).to.have.length(3);
207+
208+
let scope = scopeManager.scopes[0];
209+
expect(scope.type).to.be.equal('global');
210+
expect(scope.block.type).to.be.equal('Program');
211+
expect(scope.isStrict).to.be.false;
212+
expect(scope.variables).to.have.length(1);
213+
expect(scope.variables[0].name).to.be.equal('Foo');
214+
expect(scope.variables[0].defs).to.have.length(1);
215+
216+
let classDef = scope.variables[0].defs[0]
217+
218+
scope = scopeManager.scopes[1];
219+
expect(scope.type).to.be.equal('class');
220+
expect(scope.block.type).to.be.equal('ClassDeclaration');
221+
expect(scope.isStrict).to.be.true;
222+
expect(scope.variables).to.have.length(1);
223+
expect(classDef.inner).to.be.equal(scope.variables[0]);
224+
expect(scope.references).to.have.length(0);
225+
226+
scope = scopeManager.scopes[2];
227+
expect(scope.type).to.be.equal('function');
228+
expect(scope.block.type).to.be.equal('FunctionExpression');
229+
expect(scope.isStrict).to.be.true;
230+
expect(scope.variables).to.have.length(1);
231+
expect(scope.variables[0].name).to.be.equal('arguments');
232+
expect(scope.references).to.have.length(1);
233+
expect(scope.references[0].identifier.name).to.be.equal('Foo');
234+
});
194235
});
195236

196237
// vim: set sw=4 ts=4 et tw=80 :

0 commit comments

Comments
 (0)