Permalink
Browse files

Merge branch 'es5-duplicate-accessors' of https://github.com/Wolfgang…

…Kluge/jshint into WolfgangKluge-es5-duplicate-accessors
  • Loading branch information...
2 parents 5b5470a + fd1fa16 commit 0ab2389fd4ae1e522679552b0e695da2d8ded3b9 @valueof valueof committed Dec 31, 2011
Showing with 112 additions and 24 deletions.
  1. +37 −24 jshint.js
  2. +35 −0 tests/envs.js
  3. +40 −0 tests/fixtures/es5.js
View
@@ -195,7 +195,7 @@
VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator,
XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a,
addEventListener, address, alert, apply, applicationCache, arguments, arity,
- asi, b, bitwise, block, blur, boolOptions, boss, browser, c, call, callee,
+ asi, b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, c, call, callee,
caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,
close, closed, closure, comment, condition, confirm, console, constructor,
content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,
@@ -204,7 +204,7 @@
entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,
ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,
forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,
- g, gc, getComputedStyle, getRow, getter, GLOBAL, global, globals, globalstrict,
+ g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,
hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,
indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,
isDigit, isFinite, isNaN, iterator, java, join, jshint,
@@ -3215,22 +3215,41 @@ loop: for (;;) {
(function (x) {
x.nud = function () {
- var b, f, i, j, p, seen = {}, t;
- var prop, acc = {}; // Accessor methods
+ var b, f, i, j, p, t;
+ var props = {}; // All properties, including accessors
+
+ function saveProperty(name, token) {
+ if (props[name] && is_own(props, name))
+ warning("Duplicate member '{a}'.", nexttoken, i);
+ else
+ props[name] = {};
+
+ props[name].basic = true;
+ props[name].basicToken = token;
+ }
function saveSetter(name, token) {
- if (!acc[name]) {
- acc[name] = {};
+ if (props[name] && is_own(props, name)) {
+ if (props[name].basic || props[name].setter)
+ warning("Duplicate member '{a}'.", nexttoken, i);
+ } else {
+ props[name] = {};
}
- acc[name].setter = true;
- acc[name].setterToken = token;
+
+ props[name].setter = true;
+ props[name].setterToken = token;
}
function saveGetter(name) {
- if (!acc[name]) {
- acc[name] = {};
+ if (props[name] && is_own(props, name)) {
+ if (props[name].basic || props[name].getter)
+ warning("Duplicate member '{a}'.", nexttoken, i);
+ } else {
+ props[name] = {};
}
- acc[name].getter = true;
+
+ props[name].getter = true;
+ props[name].getterToken = token;
}
b = token.line !== nexttoken.line;
@@ -3260,9 +3279,6 @@ loop: for (;;) {
t = nexttoken;
adjacent(token, nexttoken);
f = doFunction();
- if (!option.loopfunc && funct['(loopage)']) {
- warning("Don't make functions within a loop.", t);
- }
p = f['(params)'];
if (p) {
warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
@@ -3278,27 +3294,24 @@ loop: for (;;) {
error("Missing property name.");
}
saveSetter(i, nexttoken);
- seen[i] = false;
t = nexttoken;
adjacent(token, nexttoken);
f = doFunction();
p = f['(params)'];
- if (!p || p.length !== 1 || p[0] !== 'value') {
- warning("Expected (value) in set {a} function.", t, i);
+ if (!p || p.length !== 1) {
+ warning("Expected a single parameter in set {a} function.", t, i);
}
} else {
i = property_name();
+ saveProperty(i, nexttoken);
if (typeof i !== 'string') {
break;
}
advance(':');
nonadjacent(token, nexttoken);
expression(10);
}
- if (seen[i] === true) {
- warning("Duplicate member '{a}'.", nexttoken, i);
- }
- seen[i] = true;
+
countMember(i);
if (nexttoken.id === ',') {
comma();
@@ -3319,9 +3332,9 @@ loop: for (;;) {
// Check for lonely setters if in the ES5 mode.
if (option.es5) {
- for (prop in acc) {
- if (acc.hasOwnProperty(prop) && acc[prop].setter && !acc[prop].getter) {
- warning("Setter is defined without getter.", acc[prop].setterToken);
+ for (var name in props) {
+ if (is_own(props, name) && props[name].setter && !props[name].getter) {
+ warning("Setter is defined without getter.", props[name].setterToken);
}
}
}
View
@@ -387,10 +387,45 @@ exports.es5 = function () {
.addError(30, "get/set are ES5 features.")
.addError(31, "get/set are ES5 features.")
.addError(36, "get/set are ES5 features.")
+ .addError(41, "get/set are ES5 features.")
+ .addError(42, "get/set are ES5 features.")
+ .addError(43, "Duplicate member 'x'.")
+ .addError(47, "get/set are ES5 features.")
+ .addError(48, "get/set are ES5 features.")
+ .addError(48, "Duplicate member 'x'.")
+ .addError(52, "get/set are ES5 features.")
+ .addError(53, "get/set are ES5 features.")
+ .addError(54, "get/set are ES5 features.")
+ .addError(54, "Duplicate member 'x'.")
+ .addError(58, "get/set are ES5 features.")
+ .addError(58, "Unexpected parameter 'a' in get x function.")
+ .addError(59, "get/set are ES5 features.")
+ .addError(59, "Unexpected parameter 'a' in get y function.")
+ .addError(60, "get/set are ES5 features.")
+ .addError(62, "get/set are ES5 features.")
+ .addError(62, "Expected a single parameter in set x function.")
+ .addError(63, "get/set are ES5 features.")
+ .addError(64, "get/set are ES5 features.")
+ .addError(64, "Expected a single parameter in set z function.")
+ .addError(68, "get/set are ES5 features.")
+ .addError(69, "get/set are ES5 features.")
+ .addError(68, "Missing property name.")
+ .addError(69, "Missing property name.")
+ .addError(75, "get/set are ES5 features.")
+ .addError(76, "get/set are ES5 features.")
.test(src);
TestRun()
.addError(36, "Setter is defined without getter.")
+ .addError(43, "Duplicate member 'x'.")
+ .addError(48, "Duplicate member 'x'.")
+ .addError(54, "Duplicate member 'x'.")
+ .addError(58, "Unexpected parameter 'a' in get x function.")
+ .addError(59, "Unexpected parameter 'a' in get y function.")
+ .addError(62, "Expected a single parameter in set x function.")
+ .addError(64, "Expected a single parameter in set z function.")
+ .addError(68, "Missing property name.")
+ .addError(69, "Missing property name.")
.test(src, { es5: true });
// Make sure that JSHint parses getters/setters as function expressions
View
@@ -35,4 +35,44 @@ var b = {
var onlySetter = {
set x(value) { _x = value; }
};
+
+ // Check for duplicate members
+ var dup = {
+ get x() { return _x; },
+ set x(value) { _x = value; },
+ x: 'sup?'
+ };
+
+ var dup2 = {
+ get x() { return _x; },
+ get x() { return _x + 1; }
+ };
+
+ var dup3 = {
+ get x() { return _x; },
+ set x(value) { _x = value; },
+ set x(value) { _x = value - 1; }
+ };
+
+ var parameters = {
+ get x(a) { return _x; },
+ get y(a, b) { return _x; },
+ get z() { return _x; },
+
+ set x() { _x = 1; },
+ set y(a) { _x = a; },
+ set z(a, b) { _x = a; }
+ };
+
+ var nameless = {
+ get () { return _x; },
+ set (value) { _x = value; }
+ };
+
+ // Regression test for a bug when a getter followed a setter produced a faulty
+ // Duplicate Member warning.
+ var setThenGet = {
+ set x(value) { _x = value; },
+ get x() { return _x; }
+ };
}());

0 comments on commit 0ab2389

Please sign in to comment.