From cc68f8311da79d498b659601b32612396c7b88d0 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alexander.rose@weirdbyte.de>
Date: Sun, 12 Sep 2021 16:22:43 -0700
Subject: [PATCH] lint: add no-throw-literal rule

---
 .eslintrc.json                                  | 3 ++-
 src/cli/cifschema/index.ts                      | 2 +-
 src/extensions/anvil/algorithm.ts               | 2 +-
 src/mol-gl/_spec/gl.shim.ts                     | 4 ++--
 src/mol-math/linear-algebra/matrix/evd.ts       | 2 +-
 src/mol-model/structure/export/mmcif.ts         | 2 +-
 src/mol-model/structure/structure/properties.ts | 6 +++---
 src/mol-util/zip/bin.ts                         | 4 ++--
 src/mol-util/zip/zip.ts                         | 2 +-
 src/servers/model/server/api.ts                 | 4 ++--
 src/servers/volume/server/query/execute.ts      | 4 ++--
 11 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index df6b9f8a7..82b9a5e71 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -38,7 +38,8 @@
                 "selector": "ExportDefaultDeclaration",
                 "message": "Default exports are not allowed"
             }
-        ]
+        ],
+        "no-throw-literal": "error"
     },
     "overrides": [
         {
diff --git a/src/cli/cifschema/index.ts b/src/cli/cifschema/index.ts
index bfcdf04f7..8845afe9c 100644
--- a/src/cli/cifschema/index.ts
+++ b/src/cli/cifschema/index.ts
@@ -124,7 +124,7 @@ async function getFieldNamesFilter(fieldNamesPath: string): Promise<Filter> {
     const csvFile = parsed.result;
 
     const fieldNamesCol = csvFile.table.getColumn('0');
-    if (!fieldNamesCol) throw 'error getting fields columns';
+    if (!fieldNamesCol) throw new Error('error getting fields columns');
     const fieldNames = fieldNamesCol.toStringArray();
 
     const filter: Filter = {};
diff --git a/src/extensions/anvil/algorithm.ts b/src/extensions/anvil/algorithm.ts
index 8c960bffc..6ce492717 100644
--- a/src/extensions/anvil/algorithm.ts
+++ b/src/extensions/anvil/algorithm.ts
@@ -446,7 +446,7 @@ function membraneSegments(ctx: ANVILContext, membrane: MembraneCandidate): Array
 }
 
 function notAtomic(): never {
-    throw 'Property only available for atomic models.';
+    throw new Error('Property only available for atomic models.');
 }
 
 /** Filter for membrane residues and calculate the final extent of the membrane layer */
diff --git a/src/mol-gl/_spec/gl.shim.ts b/src/mol-gl/_spec/gl.shim.ts
index f0304b670..99c5a3404 100644
--- a/src/mol-gl/_spec/gl.shim.ts
+++ b/src/mol-gl/_spec/gl.shim.ts
@@ -601,7 +601,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL
             switch (pname) {
                 case gl.SHADER_TYPE: return items[shader as number].type;
                 case gl.COMPILE_STATUS: return true;
-                default: throw `getShaderParameter ${pname}`;
+                default: throw new Error(`getShaderParameter ${pname}`);
             }
         },
         shaderSource: function () { },
@@ -628,7 +628,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL
                 case gl.DELETE_STATUS: return false;
                 case gl.VALIDATE_STATUS: return true;
                 case gl.ATTACHED_SHADERS: return 2;
-                default: throw `getProgramParameter ${pname}`;
+                default: throw new Error(`getProgramParameter ${pname}`);
             }
         },
         deleteShader: function () { },
diff --git a/src/mol-math/linear-algebra/matrix/evd.ts b/src/mol-math/linear-algebra/matrix/evd.ts
index 06e81db62..eae45e574 100644
--- a/src/mol-math/linear-algebra/matrix/evd.ts
+++ b/src/mol-math/linear-algebra/matrix/evd.ts
@@ -263,7 +263,7 @@ function symmetricDiagonalize(a: number[], d: number[], e: number[], order: numb
                 // Check for convergence. If too many iterations have been performed,
                 // throw exception that Convergence Failed
                 if (iter >= maxiter) {
-                    throw 'SVD: Not converging.';
+                    throw new Error('SVD: Not converging.');
                 }
             } while (Math.abs(e[l]) > eps * tst1);
         }
diff --git a/src/mol-model/structure/export/mmcif.ts b/src/mol-model/structure/export/mmcif.ts
index eed0dd230..6615a4f87 100644
--- a/src/mol-model/structure/export/mmcif.ts
+++ b/src/mol-model/structure/export/mmcif.ts
@@ -140,7 +140,7 @@ type encode_mmCIF_categories_Params = {
 export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structures: Structure | Structure[], params?: encode_mmCIF_categories_Params) {
     const first = Array.isArray(structures) ? structures[0] : (structures as Structure);
     const models = first.models;
-    if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.';
+    if (models.length !== 1) throw new Error('Can\'t export stucture composed from multiple models.');
 
     const ctx: CifExportContext = params?.exportCtx || CifExportContext.create(structures);
 
diff --git a/src/mol-model/structure/structure/properties.ts b/src/mol-model/structure/structure/properties.ts
index 1157777ce..f526e642f 100644
--- a/src/mol-model/structure/structure/properties.ts
+++ b/src/mol-model/structure/structure/properties.ts
@@ -21,12 +21,12 @@ const constant = {
 };
 
 function notAtomic(): never {
-    throw 'Property only available for atomic models.';
+    throw new Error('Property only available for atomic models.');
 }
 
 function notCoarse(kind?: string): never {
-    if (!!kind) throw `Property only available for coarse models (${kind}).`;
-    throw `Property only available for coarse models.`;
+    if (!!kind) throw new Error(`Property only available for coarse models (${kind}).`);
+    throw new Error('Property only available for coarse models.');
 }
 
 // TODO: remove the type checks?
diff --git a/src/mol-util/zip/bin.ts b/src/mol-util/zip/bin.ts
index ed36a8fe4..9d2192f6a 100644
--- a/src/mol-util/zip/bin.ts
+++ b/src/mol-util/zip/bin.ts
@@ -81,7 +81,7 @@ export function writeUTF8(buff: Uint8Array, p: number, str: string) {
             buff[p + i + 2] = (128 | ((code >> 6) & 63));
             buff[p + i + 3] = (128 | ((code >> 0) & 63));
             i += 4;
-        } else throw 'e';
+        } else throw new Error('e');
     }
     return i;
 }
@@ -100,7 +100,7 @@ export function sizeUTF8(str: string) {
         } else if((code & (0xffffffff - (1 << 21) + 1)) === 0) {
             i += 4;
         } else {
-            throw 'e';
+            throw new Error('e');
         }
     }
     return i;
diff --git a/src/mol-util/zip/zip.ts b/src/mol-util/zip/zip.ts
index b38898adc..8086d307c 100644
--- a/src/mol-util/zip/zip.ts
+++ b/src/mol-util/zip/zip.ts
@@ -106,7 +106,7 @@ async function _readLocal(runtime: RuntimeContext, data: Uint8Array, o: number,
         await inflateRaw(runtime, file, buf);
         out[name] = buf;
     } else {
-        throw `unknown compression method: ${cmpr}`;
+        throw new Error(`unknown compression method: ${cmpr}`);
     }
 }
 
diff --git a/src/servers/model/server/api.ts b/src/servers/model/server/api.ts
index 76edf445d..159ef411b 100644
--- a/src/servers/model/server/api.ts
+++ b/src/servers/model/server/api.ts
@@ -125,7 +125,7 @@ const RadiusParam: QueryParamInfo = {
     description: 'Value in Angstroms.',
     validation(v: any) {
         if (v < 1 || v > 10) {
-            throw `Invalid radius for residue interaction query (must be a value between 1 and 10).`;
+            throw new Error('Invalid radius for residue interaction query (must be a value between 1 and 10).');
         }
     }
 };
@@ -286,7 +286,7 @@ function _normalizeQueryParams(params: { [p: string]: string }, paramList: Query
         let el: any;
         if (typeof value === 'undefined' || (typeof value !== 'undefined' && value !== null && value['length'] === 0)) {
             if (p.required) {
-                throw `The parameter '${key}' is required.`;
+                throw new Error(`The parameter '${key}' is required.`);
             }
             if (typeof p.defaultValue !== 'undefined') el = p.defaultValue;
         } else {
diff --git a/src/servers/volume/server/query/execute.ts b/src/servers/volume/server/query/execute.ts
index 6975279a0..de874adeb 100644
--- a/src/servers/volume/server/query/execute.ts
+++ b/src/servers/volume/server/query/execute.ts
@@ -166,11 +166,11 @@ function createQueryContext(data: Data.DataContext, params: Data.QueryParams, gu
 
     const dimensions = Box.dimensions(queryBox);
     if (dimensions.some(d => isNaN(d))) {
-        throw `The query box is not defined.`;
+        throw new Error('The query box is not defined.');
     }
 
     if (dimensions[0] * dimensions[1] * dimensions[2] > LimitsConfig.maxFractionalBoxVolume) {
-        throw `The query box volume is too big.`;
+        throw new Error('The query box volume is too big.');
     }
 
     const samplingInfo = pickSampling(data, queryBox, params.forcedSamplingLevel !== void 0 ? params.forcedSamplingLevel : 0, params.detail);
-- 
GitLab