Use the ESLint no-restricted-syntax rule to prevent direct usage of new Cmd()/new Name()/new Ref()

Given that all of these primitives implement caching, to avoid unnecessarily duplicating those objects *a lot* during parsing, it would thus be good to actually enforce usage of `Cmd.get()`/`Name.get()`/`Ref.get()` in the code-base.
Luckily it turns out that there's an ESLint rule, which is fairly easy to use, that can be used to disallow arbitrary JavaScript syntax.

Please find additional details about the ESLint rule at https://eslint.org/docs/rules/no-restricted-syntax
This commit is contained in:
Jonas Jenwald 2020-02-22 20:53:47 +01:00
parent 3472b671e7
commit bf09d79eea
3 changed files with 32 additions and 15 deletions

View File

@ -143,6 +143,20 @@
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 1, }],
"no-nested-ternary": "error",
"no-new-object": "error",
"no-restricted-syntax": ["error",
{
"selector": "NewExpression[callee.name='Cmd']",
"message": "Use `Cmd.get()` rather than `new Cmd()`.",
},
{
"selector": "NewExpression[callee.name='Name']",
"message": "Use `Name.get()` rather than `new Name()`.",
},
{
"selector": "NewExpression[callee.name='Ref']",
"message": "Use `Ref.get()` rather than `new Ref()`.",
},
],
"no-unneeded-ternary": "error",
"spaced-comment": ["error", "always", {
"block": {

View File

@ -29,6 +29,7 @@ var Name = (function NameClosure() {
Name.get = function Name_get(name) {
var nameValue = nameCache[name];
// eslint-disable-next-line no-restricted-syntax
return nameValue ? nameValue : (nameCache[name] = new Name(name));
};
@ -50,6 +51,7 @@ var Cmd = (function CmdClosure() {
Cmd.get = function Cmd_get(cmd) {
var cmdValue = cmdCache[cmd];
// eslint-disable-next-line no-restricted-syntax
return cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd));
};
@ -195,6 +197,7 @@ var Ref = (function RefClosure() {
Ref.get = function(num, gen) {
const key = gen === 0 ? `${num}R` : `${num}R${gen}`;
const refValue = refCache[key];
// eslint-disable-next-line no-restricted-syntax
return refValue ? refValue : (refCache[key] = new Ref(num, gen));
};

View File

@ -461,12 +461,12 @@ describe("annotation", function() {
});
it("should parse IRT and set default RT when not defined.", function(done) {
const annotationRef = new Ref(819, 0);
const annotationRef = Ref.get(819, 0);
const annotationDict = new Dict();
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Text"));
const replyRef = new Ref(820, 0);
const replyRef = Ref.get(820, 0);
const replyDict = new Dict();
replyDict.set("Type", Name.get("Annot"));
replyDict.set("Subtype", Name.get("Text"));
@ -492,7 +492,7 @@ describe("annotation", function() {
});
it("should parse IRT/RT for a group type", function(done) {
const annotationRef = new Ref(819, 0);
const annotationRef = Ref.get(819, 0);
const annotationDict = new Dict();
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Text"));
@ -502,14 +502,14 @@ describe("annotation", function() {
annotationDict.set("M", "D:20190423");
annotationDict.set("C", [0, 0, 1]);
const popupRef = new Ref(820, 0);
const popupRef = Ref.get(820, 0);
const popupDict = new Dict();
popupDict.set("Type", Name.get("Annot"));
popupDict.set("Subtype", Name.get("Popup"));
popupDict.set("Parent", annotationRef);
annotationDict.set("Popup", popupRef);
const replyRef = new Ref(821, 0);
const replyRef = Ref.get(821, 0);
const replyDict = new Dict();
replyDict.set("Type", Name.get("Annot"));
replyDict.set("Subtype", Name.get("Text"));
@ -549,7 +549,7 @@ describe("annotation", function() {
});
it("should parse IRT/RT for a reply type", function(done) {
const annotationRef = new Ref(819, 0);
const annotationRef = Ref.get(819, 0);
const annotationDict = new Dict();
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Text"));
@ -559,14 +559,14 @@ describe("annotation", function() {
annotationDict.set("M", "D:20190423");
annotationDict.set("C", [0, 0, 1]);
const popupRef = new Ref(820, 0);
const popupRef = Ref.get(820, 0);
const popupDict = new Dict();
popupDict.set("Type", Name.get("Annot"));
popupDict.set("Subtype", Name.get("Popup"));
popupDict.set("Parent", annotationRef);
annotationDict.set("Popup", popupRef);
const replyRef = new Ref(821, 0);
const replyRef = Ref.get(821, 0);
const replyDict = new Dict();
replyDict.set("Type", Name.get("Annot"));
replyDict.set("Subtype", Name.get("Text"));
@ -608,13 +608,13 @@ describe("annotation", function() {
describe("TextAnnotation", function() {
it("should not parse state model and state when not defined", function(done) {
const annotationRef = new Ref(819, 0);
const annotationRef = Ref.get(819, 0);
const annotationDict = new Dict();
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Text"));
annotationDict.set("Contents", "TestText");
const replyRef = new Ref(820, 0);
const replyRef = Ref.get(820, 0);
const replyDict = new Dict();
replyDict.set("Type", Name.get("Annot"));
replyDict.set("Subtype", Name.get("Text"));
@ -642,12 +642,12 @@ describe("annotation", function() {
});
it("should correctly parse state model and state when defined", function(done) {
const annotationRef = new Ref(819, 0);
const annotationRef = Ref.get(819, 0);
const annotationDict = new Dict();
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Text"));
const replyRef = new Ref(820, 0);
const replyRef = Ref.get(820, 0);
const replyDict = new Dict();
replyDict.set("Type", Name.get("Annot"));
replyDict.set("Subtype", Name.get("Text"));
@ -2109,7 +2109,7 @@ describe("annotation", function() {
"should correctly inherit Contents from group-master annotation " +
"if parent has ReplyType == Group",
function(done) {
const annotationRef = new Ref(819, 0);
const annotationRef = Ref.get(819, 0);
const annotationDict = new Dict();
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Text"));
@ -2118,7 +2118,7 @@ describe("annotation", function() {
annotationDict.set("M", "D:20190423");
annotationDict.set("C", [0, 0, 1]);
const replyRef = new Ref(820, 0);
const replyRef = Ref.get(820, 0);
const replyDict = new Dict();
replyDict.set("Type", Name.get("Annot"));
replyDict.set("Subtype", Name.get("Text"));
@ -2129,7 +2129,7 @@ describe("annotation", function() {
replyDict.set("M", "D:20190523");
replyDict.set("C", [0.4]);
const popupRef = new Ref(821, 0);
const popupRef = Ref.get(821, 0);
const popupDict = new Dict();
popupDict.set("Type", Name.get("Annot"));
popupDict.set("Subtype", Name.get("Popup"));