Skip to content

Commit

Permalink
[[FIX]] latedef shouldn't warn when marking a var as exported
Browse files Browse the repository at this point in the history
Fixes #2662
  • Loading branch information
nicolo-ribaudo authored and lukeapage committed Sep 13, 2015
1 parent d0433d2 commit c630994
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 21 deletions.
53 changes: 34 additions & 19 deletions src/scope-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,6 @@ var scopeManager = function(state, predefined, exported, declared) {
}
}

function _addUsage(labelName, token) {

_setupUsages(labelName);

if (token) {
token["(function)"] = _currentFunctBody;
_current["(usages)"][labelName]["(tokens)"].push(token);
}
}

var exportedLabels = Object.keys(exported);
for (var i = 0; i < exportedLabels.length; i++) {
_addUsage(exportedLabels[i]);
}

var _getUnusedOption = function(unused_opt) {
if (unused_opt === undefined) {
unused_opt = state.option.unused;
Expand Down Expand Up @@ -572,7 +557,30 @@ var scopeManager = function(state, predefined, exported, declared) {
/**
* for the exported options, indicating a variable is used outside the file
*/
addExported: _addUsage,
addExported: function(labelName) {
var globalLabels = _scopeStack[0]["(labels)"];
if (_.has(declared, labelName)) {
// remove the declared token, so we know it is used
delete declared[labelName];
} else if (_.has(globalLabels, labelName)) {
globalLabels[labelName]["(unused)"] = false;
} else {
for (var i = 1; i < _scopeStack.length; i++) {
var scope = _scopeStack[i];
// if `scope.(type)` is not defined, it is a block scope
if (!scope["(type)"]) {
if (_.has(scope["(labels)"], labelName) &&
!scope["(labels)"][labelName]["(blockscoped)"]) {
scope["(labels)"][labelName]["(unused)"] = false;
return;
}
} else {
break;
}
}
exported[labelName] = true;
}
},

/**
* Mark an indentifier as es6 module exported
Expand All @@ -593,6 +601,8 @@ var scopeManager = function(state, predefined, exported, declared) {
var type = opts.type;
var token = opts.token;
var isblockscoped = type === "let" || type === "const" || type === "class";
var isexported = (isblockscoped ? _current : _currentFunctBody)["(type)"] === "global" &&
_.has(exported, labelName);

// outer shadow check (inner is only on non-block scoped)
_checkOuterShadow(labelName, token, type);
Expand Down Expand Up @@ -632,7 +642,7 @@ var scopeManager = function(state, predefined, exported, declared) {
}
}

scopeManagerInst.block.add(labelName, type, token, true);
scopeManagerInst.block.add(labelName, type, token, !isexported);

} else {

Expand All @@ -659,7 +669,7 @@ var scopeManager = function(state, predefined, exported, declared) {
}
}

scopeManagerInst.funct.add(labelName, type, token, true);
scopeManagerInst.funct.add(labelName, type, token, !isexported);

if (_currentFunctBody["(type)"] === "global") {
usedPredefinedAndGlobals[labelName] = marker;
Expand Down Expand Up @@ -765,7 +775,12 @@ var scopeManager = function(state, predefined, exported, declared) {
token.ignoreUndef = true;
}

_addUsage(labelName, token);
_setupUsages(labelName);

if (token) {
token["(function)"] = _currentFunctBody;
_current["(usages)"][labelName]["(tokens)"].push(token);
}
},

reassign: function(labelName, token) {
Expand Down
18 changes: 17 additions & 1 deletion tests/unit/fixtures/exported.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,20 @@ var unusedExpression = function () {};

(function () {
function cannotBeExported() {}
}());
}());

var a, b;
if (true) {
/* exported a */
}
if (true) {
for(var i = 0; i < 1; i++) {
// dont peek
}
/* exported b */
}

if (true) {
var c;
}
/* exported c */
6 changes: 6 additions & 0 deletions tests/unit/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ exports.latedef = function (test) {
.addError(48, "'ci' was used before it was defined.")
.test(esnextSrc, {esnext: true, latedef: true});

TestRun(test, "shouldn't warn when marking a var as exported")
.test("var a;", { exported: ["a"], latedef: true });

test.done();
};

Expand All @@ -272,6 +275,9 @@ exports.latedefInline = function (test) {
.addError(26, "Bad option value.")
.test(src);

TestRun(test, "shouldn't warn when marking a var as exported")
.test("/*exported a*/var a;", { latedef: true });

test.done();
};

Expand Down
27 changes: 26 additions & 1 deletion tests/unit/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1124,11 +1124,36 @@ exports.exported = function (test) {
run.test(src, {unused: true }); // es5
run.test(src, {esnext: true, unused: true });
run.test(src, {moz: true, unused: true });
run.test(src, {unused: true, latedef: true});

run = TestRun(test)
TestRun(test)
.addError(1, "'unused' is defined but never used.")
.test("var unused = 1; var used = 2;", {exported: ["used"], unused: true});

TestRun(test, "exported vars aren't used before definition")
.test("var a;", {exported:["a"], latedef: true});

var code = [
"/* exported a, b */",
"if (true) {",
" /* exported c, d */",
" let a, c, e, g;",
" const [b, d, f, h] = [];",
" /* exported e, f */",
"}",
"/* exported g, h */"
];
TestRun(test, "blockscoped variables")
.addError(4, "'a' is defined but never used.")
.addError(4, "'c' is defined but never used.")
.addError(4, "'e' is defined but never used.")
.addError(4, "'g' is defined but never used.")
.addError(5, "'b' is defined but never used.")
.addError(5, "'d' is defined but never used.")
.addError(5, "'f' is defined but never used.")
.addError(5, "'h' is defined but never used.")
.test(code, {esversion: 6, unused: true});

test.done();
};

Expand Down

1 comment on commit c630994

@gilluminate
Copy link

Choose a reason for hiding this comment

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

This change has apparently caused "nofunc" to stop working

Please sign in to comment.