eslint-plugin-botland
Advanced tools
Comparing version 2.0.1 to 2.1.0
54
api.json
@@ -148,4 +148,4 @@ { | ||
"entrypoints": [ | ||
"update", | ||
"init" | ||
"init", | ||
"update" | ||
], | ||
@@ -445,3 +445,53 @@ "requiredEntry": [ | ||
] | ||
}, | ||
"returns": { | ||
"getX": "x", | ||
"getY": "y", | ||
"canMove": "boolean", | ||
"canMoveTo": "boolean", | ||
"canCloak": "boolean", | ||
"canZap": "boolean", | ||
"canEMP": "boolean", | ||
"canReflect": "boolean", | ||
"canLayMine": "boolean", | ||
"isCloaked": "boolean", | ||
"isZapping": "boolean", | ||
"isReflecting": "boolean", | ||
"getDistanceTo": "number", | ||
"getEntityAt": "entity", | ||
"isEnemyMineAt": "boolean", | ||
"willMissilesHit": "boolean", | ||
"willLasersHit": "boolean", | ||
"findClosestEnemyBot": "entity", | ||
"canSenseEntity": "boolean", | ||
"exists": "boolean", | ||
"reduceEntities": "entity[]", | ||
"getLife": "number", | ||
"findEntity": "entity", | ||
"findEntities": "entity[]", | ||
"findEntitiesInRange": "entity[]", | ||
"filterEntities": "entity[]", | ||
"percentChance": "boolean", | ||
"randInt": "number", | ||
"clampNumber": "number", | ||
"size": "number", | ||
"abs": "number", | ||
"floor": "number", | ||
"ceil": "number", | ||
"round": "number", | ||
"min": "number", | ||
"max": "number", | ||
"canTeleport": "boolean", | ||
"areSensorsActivated": "boolean", | ||
"canActivateSensors": "boolean", | ||
"willRepair": "boolean", | ||
"findMyCpu": "entity", | ||
"isAdjacent": "boolean", | ||
"willArtilleryHit": "boolean", | ||
"willMeleeHit": "boolean", | ||
"canCharge": "boolean", | ||
"isOnFire": "boolean", | ||
"isShielded": "boolean", | ||
"canShield": "boolean" | ||
} | ||
} |
@@ -87,2 +87,3 @@ "use strict"; | ||
"botland/no-unreachable-code": "error", | ||
"botland/no-args-in-entry-point": "error", | ||
"botland/no-terminator-in-init": "warn", | ||
@@ -89,0 +90,0 @@ "botland/prefer-function": "warn", |
@@ -8,2 +8,3 @@ "use strict"; | ||
//"use-guarded-terminator": require("./rules/use-guarded-terminator"), terminators must have an if around them | ||
"no-args-in-entry-point": require("./rules/no-args-in-entry-point"), | ||
"no-unreachable-code": require("./rules/no-unreachable-code"), | ||
@@ -10,0 +11,0 @@ "no-unset": require("./rules/no-unset"), |
{ | ||
"name": "eslint-plugin-botland", | ||
"version": "2.0.1", | ||
"version": "2.1.0", | ||
"description": "Lint your botland JS scripts", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -12,2 +12,4 @@ # eslint-plugin-botland | ||
Check that the script has the required `update` function. Marks all entry points as used. | ||
- `no-args-in-entry-point` | ||
Entry points get passed no arguments. | ||
- `no-big-array` | ||
@@ -37,2 +39,3 @@ Items on arrays can only be assigned to indexes between 0 and 99. | ||
- `no-nan-in-init` warns about `getX`/`getY` resp. `entity.x`/`entity.y` being `NaN` inside the `init` code path. | ||
- `no-reassign-loopvar-in-call` warns about loop variables being reset in a function called within the loop. | ||
@@ -39,0 +42,0 @@ ## Configs |
@@ -33,5 +33,5 @@ "use strict"; | ||
}, | ||
"Program > ExpressionStatement > AssignmentExpression[operator=\"=\"][right.type=\"Identifier\"][left.type=\"FunctionExpression\"]"(node) { | ||
if(api.entrypoints.includes(node.left.name)) { | ||
context.markVariableAsUsed(node.left.name); | ||
"Program > ExpressionStatement > AssignmentExpression[operator=\"=\"][right.type=\"FunctionExpression\"] > Identifier.left"(node) { | ||
if(api.entrypoints.includes(node.name)) { | ||
context.markVariableAsUsed(node.name); | ||
} | ||
@@ -38,0 +38,0 @@ } |
"use strict"; | ||
const api = require("../api.json"), | ||
const api = require("../api.json"); | ||
walkBodies = (node, cbk) => { | ||
if(node.type === "FunctionExpression" || node.type === "WhileStatement") { | ||
if(node.test) { | ||
walkBodies(node.test, cbk); | ||
} | ||
walkBodies(node.body, cbk); | ||
} | ||
else if(node.type === "FunctionBody" || node.type === "BlockStatement") { | ||
for(const n of node.body) { | ||
walkBodies(n, cbk); | ||
} | ||
} | ||
else if(node.type === "ExpressionStatement") { | ||
return walkBodies(node.expression, cbk); | ||
} | ||
else if(node.type === "SwitchStatement") { | ||
walkBodies(node.discriminant, cbk); | ||
for(const n of node.cases) { | ||
walkBodies(n, cbk); | ||
} | ||
} | ||
else if(node.type === "SwitchCase") { | ||
walkBodies(node.test, cbk); | ||
for(const n of node.consequent) { | ||
walkBodies(n, cbk); | ||
} | ||
} | ||
else if(node.type === "IfStatement") { | ||
walkBodies(node.test, cbk); | ||
walkBodies(node.consequent, cbk); | ||
if(node.alternate) { | ||
walkBodies(node.alternate, cbk); | ||
} | ||
} | ||
else if(node.type === "CallExpression") { | ||
cbk(node); | ||
} | ||
}; | ||
module.exports = { | ||
create(context) { | ||
const calledFuncs = new Set(), | ||
calledTerminators = {}; | ||
let currentFunc; | ||
return { | ||
'Program ExpressionStatement > AssignmentExpression[operator="="][left.type="Identifier"][left.name="init"][right.type="FunctionExpression"]'(node) { | ||
walkBodies(node.right, (hit) => { | ||
if(hit.callee.type === "Identifier" && | ||
api.terminators.includes(hit.callee.name)) { | ||
context.report({ | ||
node: hit, | ||
message: "Terminators in the init entry point have no effect" | ||
}); | ||
'Program ExpressionStatement > AssignmentExpression[operator="="][left.type="Identifier"][left.name="init"][right.type="FunctionExpression"] CallExpression'(node) { | ||
if(node.callee.type === "Identifier" && | ||
api.terminators.includes(node.callee.name)) { | ||
context.report({ | ||
node, | ||
message: "Terminators in the init entry point have no effect" | ||
}); | ||
} | ||
else if(!api.functions.includes(node.callee.name)) { | ||
calledFuncs.add(node.callee.name); | ||
} | ||
}, | ||
'FunctionExpression[parent.left.name!="init"]'(node) { | ||
currentFunc = node.parent.left.name; | ||
}, | ||
'FunctionExpression:exit'() { | ||
currentFunc = undefined; | ||
}, | ||
'CallExpression'(node) { | ||
if(currentFunc && api.terminators.includes(node.callee.name)) { | ||
if(!calledTerminators.hasOwnProperty(currentFunc)) { | ||
calledTerminators[currentFunc] = []; | ||
} | ||
}); | ||
calledTerminators[currentFunc].push(node); | ||
} | ||
}, | ||
'Program:exit'() { | ||
for(const func of calledFuncs) { | ||
if(calledTerminators.hasOwnProperty(func)) { | ||
for(const node of calledTerminators[func]) { | ||
context.report({ | ||
node, | ||
message: "Terminators within the init entry point code path have no effect" | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
@@ -58,0 +49,0 @@ }; |
@@ -8,3 +8,3 @@ "use strict"; | ||
for(const command of functions[name].commands) { | ||
if(functions.hasOwnProperty(command.name)) { | ||
if(functions.hasOwnProperty(command.name) && !calledFunctions.has(command.name)) { | ||
walkFunction(command.name, functions, calledFunctions); | ||
@@ -11,0 +11,0 @@ } |
"use strict"; | ||
const scopeHasVariable = (scope, varname) => scope.set.has(varname) || (scope.upper && scopeHasVariable(scope.upper, varname)), | ||
walkFunction = (name, functions, setVars, ctx) => { | ||
const api = require("../api.json"), | ||
scopeHasVariable = (scope, varname) => scope.set.has(varname) || (scope.upper && scopeHasVariable(scope.upper, varname)), | ||
walkFunction = (name, functions, setVars, ctx, called) => { | ||
const args = new Set(); | ||
called.add(name); | ||
for(const command of functions[name].commands) { | ||
switch(command.type) { | ||
case "call": | ||
if(functions.hasOwnProperty(command.name)) { | ||
walkFunction(command.name, functions, setVars, ctx); | ||
if(functions.hasOwnProperty(command.name) && !called.has(command.name)) { | ||
walkFunction(command.name, functions, setVars, ctx, called); | ||
} | ||
else if(!scopeHasVariable(command.scope, command.name)) { | ||
else if(!scopeHasVariable(command.scope, command.name) && !called.has(command.name)) { | ||
ctx.report({ | ||
@@ -97,9 +98,9 @@ node: command.node, | ||
'Program:exit'() { | ||
const setVars = new Set(); | ||
if(functions.hasOwnProperty("init")) { | ||
walkFunction("init", functions, setVars, context); | ||
const setVars = new Set(), | ||
calledFuncs = new Set(); | ||
for(const entryPoint of api.entrypoints) { | ||
if(functions.hasOwnProperty(entryPoint)) { | ||
walkFunction(entryPoint, functions, setVars, context, calledFuncs); | ||
} | ||
} | ||
if(functions.hasOwnProperty("update")) { | ||
walkFunction("update", functions, setVars, context); | ||
} | ||
} | ||
@@ -106,0 +107,0 @@ }; |
@@ -30,3 +30,2 @@ "use strict"; | ||
"CallExpression"(node) { | ||
//TODO honor prefer mappings | ||
if(aliases.includes(node.callee.name)) { | ||
@@ -33,0 +32,0 @@ context.report({ |
"use strict"; | ||
const api = require("../api.json"); | ||
const api = require("../api.json"), | ||
getValue = require("../get-value"), | ||
DEFAULT_INDEX = 0; | ||
@@ -25,6 +27,3 @@ module.exports = { | ||
} | ||
else if((node.property.type !== "Literal" || | ||
typeof node.property.value !== "number") && | ||
node.property.type !== "Identifier") { | ||
//TODO try to get type of identifier | ||
else if(typeof getValue(node.property, context.getScope(), DEFAULT_INDEX) !== "number") { | ||
context.report({ | ||
@@ -31,0 +30,0 @@ node: node.property, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42352
18
1248
58