diff --git a/src/mol-canvas3d/camera.ts b/src/mol-canvas3d/camera.ts index 2cd6d53480cde80288fca2c8ac53a2afd6427a8e..2b82c50df22dd208c232a961817a14dc06d11247 100644 --- a/src/mol-canvas3d/camera.ts +++ b/src/mol-canvas3d/camera.ts @@ -10,6 +10,7 @@ import { Viewport, cameraProject, cameraUnproject } from './camera/util'; import { CameraTransitionManager } from './camera/transition'; import { BehaviorSubject } from 'rxjs'; import { Scene } from '../mol-gl/scene'; +import { assertUnreachable } from '../mol-util/type-helpers'; export { ICamera, Camera }; @@ -84,7 +85,7 @@ class Camera implements ICamera { switch (this.state.mode) { case 'orthographic': updateOrtho(this); break; case 'perspective': updatePers(this); break; - default: throw new Error('unknown camera mode'); + default: assertUnreachable(this.state.mode); } const changed = !Mat4.areEqual(this.projection, this.prevProjection, EPSILON) || !Mat4.areEqual(this.view, this.prevView, EPSILON); diff --git a/src/mol-geo/geometry/text/text-builder.ts b/src/mol-geo/geometry/text/text-builder.ts index 83e0ba64792bfaaf70bff753ae20c2c70441be6a..b5d98a2ef61b384656da43492d7d205d16dc6d72 100644 --- a/src/mol-geo/geometry/text/text-builder.ts +++ b/src/mol-geo/geometry/text/text-builder.ts @@ -8,6 +8,7 @@ import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { ChunkedArray } from '../../../mol-data/util'; import { Text } from './text'; import { getFontAtlas } from './font-atlas'; +import { assertUnreachable } from '../../../mol-util/type-helpers'; const quadIndices = new Uint16Array([ 0, 1, 2, @@ -237,7 +238,7 @@ export namespace TextBuilder { yBaseCenter = yTop; break; default: - throw new Error('unsupported attachment'); + assertUnreachable(attachment); } caAdd2(mappings, xTip, yTip); // tip caAdd2(mappings, xBaseA, yBaseA); // base A diff --git a/src/mol-gl/shader-code.ts b/src/mol-gl/shader-code.ts index be5974773be01d15e33dbf8f13319e53ecae507d..1fd36f8c005446d4bf5878e85b8655ac3a1ed75a 100644 --- a/src/mol-gl/shader-code.ts +++ b/src/mol-gl/shader-code.ts @@ -202,6 +202,7 @@ export const DirectVolumeShaderCode = ShaderCode('direct-volume', directVolume_v import { image_vert } from './shader/image.vert'; import { image_frag } from './shader/image.frag'; +import { assertUnreachable } from '../mol-util/type-helpers'; export const ImageShaderCode = ShaderCode('image', image_vert, image_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit); // @@ -228,7 +229,7 @@ function getDefinesCode(defines: ShaderDefines, ignore?: IgnoreDefine) { } else if (typeof v === 'boolean') { if (v) lines.push(`#define ${name}`); } else { - throw new Error('unknown define type'); + assertUnreachable(v); } } } diff --git a/src/mol-gl/webgl/buffer.ts b/src/mol-gl/webgl/buffer.ts index eedcc63465e31cfeb3b563e0db8112409cf09919..cd579098272a4302ba1676c9d0d36214b8de5701 100644 --- a/src/mol-gl/webgl/buffer.ts +++ b/src/mol-gl/webgl/buffer.ts @@ -8,7 +8,7 @@ import { WebGLContext } from './context'; import { ValueCell } from '../../mol-util'; import { RenderableSchema } from '../renderable/schema'; import { idFactory } from '../../mol-util/id-factory'; -import { ValueOf } from '../../mol-util/type-helpers'; +import { assertUnreachable, ValueOf } from '../../mol-util/type-helpers'; import { GLRenderingContext } from './compat'; import { WebGLExtensions } from './extensions'; import { WebGLState } from './state'; @@ -66,9 +66,8 @@ function dataTypeFromArray(gl: GLRenderingContext, array: ArrayType) { return gl.INT; } else if (array instanceof Float32Array) { return gl.FLOAT; - } else { - throw new Error('Should never happen'); } + assertUnreachable(array); } export function getBufferType(gl: GLRenderingContext, bufferType: BufferType) { diff --git a/src/mol-io/common/binary-cif/classifier.ts b/src/mol-io/common/binary-cif/classifier.ts index 2c94fbc896d121c463560755c9b39b5a0cfc7887..9ad8aaaa75c7bdb5fe7ec1158ea49d3ede2e246b 100644 --- a/src/mol-io/common/binary-cif/classifier.ts +++ b/src/mol-io/common/binary-cif/classifier.ts @@ -7,6 +7,7 @@ import { ArrayEncoder, ArrayEncoding as E } from './array-encoder'; import { getArrayDigitCount } from '../../../mol-util/number'; +import { assertUnreachable } from '../../../mol-util/type-helpers'; export function classifyIntArray(xs: ArrayLike<number>) { return IntClassifier.classify(xs as number[]); @@ -62,7 +63,7 @@ namespace IntClassifier { for (let i = 0, n = data.length; i < n; i++) { incSize(info, size, data[i]); } - return { ...byteSize(size), kind: 'pack' }; + return { ...byteSize(size), kind: 'pack' as const }; } function deltaSize(data: number[], info: IntColumnInfo) { @@ -72,7 +73,7 @@ namespace IntClassifier { incSizeSigned(size, data[i] - prev); prev = data[i]; } - return { ...byteSize(size), kind: 'delta' }; + return { ...byteSize(size), kind: 'delta' as const }; } function rleSize(data: number[], info: IntColumnInfo) { @@ -90,7 +91,7 @@ namespace IntClassifier { incSize(info, size, data[data.length - 1]); incSize(info, size, run); - return { ...byteSize(size), kind: 'rle' }; + return { ...byteSize(size), kind: 'rle' as const }; } function deltaRleSize(data: number[], info: IntColumnInfo) { @@ -111,7 +112,7 @@ namespace IntClassifier { incSizeSigned(size, prevValue); incSizeSigned(size, run); - return { ...byteSize(size), kind: 'delta-rle' }; + return { ...byteSize(size), kind: 'delta-rle' as const }; } export function getSize(data: number[]) { @@ -132,9 +133,8 @@ namespace IntClassifier { case 'rle': return E.by(E.runLength).and(E.integerPacking); case 'delta': return E.by(E.delta).and(E.integerPacking); case 'delta-rle': return E.by(E.delta).and(E.runLength).and(E.integerPacking); + default: assertUnreachable(size); } - - throw new Error('should not happen :)'); } } @@ -169,9 +169,8 @@ namespace FloatClassifier { case 'rle': return fp.and(E.runLength).and(E.integerPacking); case 'delta': return fp.and(E.delta).and(E.integerPacking); case 'delta-rle': return fp.and(E.delta).and(E.runLength).and(E.integerPacking); + default: assertUnreachable(size); } - - throw new Error('should not happen :)'); } function getMultiplier(mantissaDigits: number) { diff --git a/src/mol-io/common/binary-cif/decoder.ts b/src/mol-io/common/binary-cif/decoder.ts index fe6ca9ebf8b679d1fb73becbc421774bb6a21232..10cdc28d789f7051b7ac59cf3cb3e89908c852cc 100644 --- a/src/mol-io/common/binary-cif/decoder.ts +++ b/src/mol-io/common/binary-cif/decoder.ts @@ -7,6 +7,7 @@ import { Encoding, EncodedData } from './encoding'; import { IsNativeEndianLittle, flipByteOrder } from '../binary'; +import { assertUnreachable } from '../../../mol-util/type-helpers'; /** * Fixed point, delta, RLE, integer packing adopted from https://github.com/rcsb/mmtf-javascript/ @@ -33,7 +34,7 @@ function decodeStep(data: any, encoding: Encoding): any { case Encoding.IntDataType.Uint32: return uint32(data); case Encoding.FloatDataType.Float32: return float32(data); case Encoding.FloatDataType.Float64: return float64(data); - default: throw new Error('Unsupported ByteArray type.'); + default: assertUnreachable(encoding.type); } } case 'FixedPoint': return fixedPoint(data, encoding); @@ -53,7 +54,7 @@ function getIntArray(type: Encoding.IntDataType, size: number) { case Encoding.IntDataType.Uint8: return new Uint8Array(size); case Encoding.IntDataType.Uint16: return new Uint16Array(size); case Encoding.IntDataType.Uint32: return new Uint32Array(size); - default: throw new Error('Unsupported integer data type.'); + default: assertUnreachable(type); } } @@ -61,7 +62,7 @@ function getFloatArray(type: Encoding.FloatDataType, size: number) { switch (type) { case Encoding.FloatDataType.Float32: return new Float32Array(size); case Encoding.FloatDataType.Float64: return new Float64Array(size); - default: throw new Error('Unsupported floating data type.'); + default: assertUnreachable(type); } } diff --git a/src/mol-io/writer/cif/encoder.ts b/src/mol-io/writer/cif/encoder.ts index 819ad351bcfd6ca8cdc50ad989e4d0b456de02fa..71fa7ae0eb5df7c133d48183b44508b92a9e97d9 100644 --- a/src/mol-io/writer/cif/encoder.ts +++ b/src/mol-io/writer/cif/encoder.ts @@ -11,6 +11,7 @@ import { Tensor } from '../../../mol-math/linear-algebra'; import { Encoder as EncoderBase } from '../encoder'; import { ArrayEncoder, ArrayEncoding } from '../../common/binary-cif'; import { BinaryEncodingProvider } from './encoder/binary'; +import { assertUnreachable } from '../../../mol-util/type-helpers'; // TODO: support for "coordinate fields", make "coordinate precision" a parameter of the encoder // TODO: automatically detect "precision" of floating point arrays. @@ -324,7 +325,7 @@ function cifFieldsFromTableSchema(schema: Table.Schema) { } else if (t.valueType === 'tensor') { fields.push(...getTensorDefinitions(k, t.space)); } else { - throw new Error(`Unknown valueType ${t.valueType}`); + assertUnreachable(t.valueType); } } return fields; diff --git a/src/mol-model/sequence/sequence.ts b/src/mol-model/sequence/sequence.ts index 5ac73f82f7aa50277fb548cfa76c3cfa044c16c4..e68daae6b833176faff4eaab6cd3b2679bb01c99 100644 --- a/src/mol-model/sequence/sequence.ts +++ b/src/mol-model/sequence/sequence.ts @@ -7,6 +7,7 @@ import { AminoAlphabet, NuclecicAlphabet, getProteinOneLetterCode, getRnaOneLetterCode, getDnaOneLetterCode } from './constants'; import { Column } from '../../mol-data/db'; +import { assertUnreachable } from '../../mol-util/type-helpers'; // TODO add mapping support to other sequence spaces, e.g. uniprot @@ -66,7 +67,7 @@ namespace Sequence { case Kind.DNA: code = getDnaOneLetterCode; break; case Kind.RNA: code = getRnaOneLetterCode; break; case Kind.Generic: code = () => 'X'; break; - default: throw new Error(`unknown kind '${kind}'`); + default: assertUnreachable(kind); } if (map && map.size > 0) { return (name: string) => { diff --git a/src/mol-plugin-state/actions/structure.ts b/src/mol-plugin-state/actions/structure.ts index ea267499b44f215430810999c56130f7a77c8f9c..6bdd89273e92c5346ecfaf5d8a10299285079ee4 100644 --- a/src/mol-plugin-state/actions/structure.ts +++ b/src/mol-plugin-state/actions/structure.ts @@ -155,7 +155,7 @@ const DownloadStructure = StateAction.build({ asTrajectory = !!src.params.options.asTrajectory; format = 'mol'; break; - default: throw new Error(`${(src as any).name} not supported.`); + default: assertUnreachable(src); } const representationPreset: any = params.source.params.options.representation || plugin.config.get(PluginConfig.Structure.DefaultRepresentationPreset) || PresetStructureRepresentations.auto.id; diff --git a/src/mol-plugin-state/actions/volume.ts b/src/mol-plugin-state/actions/volume.ts index f117a0a13f4ef0b8b437199a569cee9945b28605..fad2beeca7da71321ecb2c52eadb3d0e711759f8 100644 --- a/src/mol-plugin-state/actions/volume.ts +++ b/src/mol-plugin-state/actions/volume.ts @@ -15,6 +15,7 @@ import { Download } from '../transforms/data'; import { DataFormatProvider } from '../formats/provider'; import { Asset } from '../../mol-util/assets'; import { StateTransforms } from '../transforms'; +import { assertUnreachable } from '../../mol-util/type-helpers'; export type EmdbDownloadProvider = 'pdbe' | 'rcsb' @@ -109,7 +110,7 @@ const DownloadDensity = StateAction.build({ label: `RCSB PDB X-ray Density Server: ${src.params.provider.id}` }; break; - default: throw new Error(`${(src as any).name} not supported.`); + default: assertUnreachable(src); } const data = await plugin.builders.data.download(downloadParams); @@ -131,7 +132,7 @@ const DownloadDensity = StateAction.build({ entryId = src.params.provider.id; provider = plugin.dataFormats.get('dscif'); break; - default: throw new Error(`${(src as any).name} not supported.`); + default: assertUnreachable(src); } if (!provider) { diff --git a/src/mol-plugin-state/helpers/structure-component.ts b/src/mol-plugin-state/helpers/structure-component.ts index 06226bafa6f4b2352e2361fdffc1d18f7df63d18..6ddaac6b1c0c4f131985c9f23f36254ef8d4a1bb 100644 --- a/src/mol-plugin-state/helpers/structure-component.ts +++ b/src/mol-plugin-state/helpers/structure-component.ts @@ -13,6 +13,7 @@ import { PluginStateObject as SO } from '../objects'; import { StructureSelectionQueries } from './structure-selection-query'; import { StateTransformer, StateObject } from '../../mol-state'; import { Script } from '../../mol-script/script'; +import { assertUnreachable } from '../../mol-util/type-helpers'; export const StaticStructureComponentTypes = [ 'all', @@ -72,7 +73,7 @@ export function createStructureComponent(a: Structure, params: StructureComponen case 'coarse': query = StructureSelectionQueries.coarse.query; label = 'Coarse'; break; - default: throw new Error(`${params.type} is a not valid complex element.`); + default: assertUnreachable(params.type); } const result = query(new QueryContext(a)); component = Sel.unionStructure(result); diff --git a/src/mol-plugin-state/transforms/data.ts b/src/mol-plugin-state/transforms/data.ts index 4e486e22662c4a999e266c17e2219b4d7ed6eecf..0543b8f197494fe28a7c3316cade37abdaf932b8 100644 --- a/src/mol-plugin-state/transforms/data.ts +++ b/src/mol-plugin-state/transforms/data.ts @@ -20,6 +20,7 @@ import { Asset } from '../../mol-util/assets'; import { parseCube } from '../../mol-io/reader/cube/parser'; import { parseDx } from '../../mol-io/reader/dx/parser'; import { ColorNames } from '../../mol-util/color/names'; +import { assertUnreachable } from '../../mol-util/type-helpers'; export { Download }; export { DownloadBlob }; @@ -151,7 +152,7 @@ const RawData = PluginStateTransform.BuiltIn({ } else if (p.data instanceof Uint8Array) { return new SO.Data.Binary(p.data, { label: p.label ? p.label : 'Binary' }); } else { - throw new Error('Supplied binary data must be a plain array, ArrayBuffer, or Uint8Array.'); + assertUnreachable(p.data); } }); }, diff --git a/src/mol-plugin-state/transforms/model.ts b/src/mol-plugin-state/transforms/model.ts index 715201540117b88b395b7b6aebc6ec4c9cc06714..9cd34a05ba0c011493eecfab94aabac075e83eb4 100644 --- a/src/mol-plugin-state/transforms/model.ts +++ b/src/mol-plugin-state/transforms/model.ts @@ -41,6 +41,7 @@ import { parseXyz } from '../../mol-io/reader/xyz/parser'; import { trajectoryFromXyz } from '../../mol-model-formats/structure/xyz'; import { parseSdf } from '../../mol-io/reader/sdf/parser'; import { trajectoryFromSdf } from '../../mol-model-formats/structure/sdf'; +import { assertUnreachable } from '../../mol-util/type-helpers'; export { CoordinatesFromDcd }; export { CoordinatesFromXtc }; @@ -846,7 +847,7 @@ const StructureComplexElement = PluginStateTransform.BuiltIn({ case 'atomic-het': query = Queries.internal.atomicHet(); label = 'HET Groups/Ligands'; break; case 'spheres': query = Queries.internal.spheres(); label = 'Coarse Spheres'; break; - default: throw new Error(`${params.type} is a not valid complex element.`); + default: assertUnreachable(params.type); } const result = query(new QueryContext(a.data)); diff --git a/src/mol-script/language/parser.ts b/src/mol-script/language/parser.ts index 79db907d588a1a1fbd971dcfb7153b8f3575450a..c2e6b80b9d054c0abe598266777e36766b6d861d 100644 --- a/src/mol-script/language/parser.ts +++ b/src/mol-script/language/parser.ts @@ -7,6 +7,7 @@ import { MonadicParser as P } from '../../mol-util/monadic-parser'; import { Expression } from './expression'; import { MolScriptBuilder as B } from './builder'; +import { assertUnreachable } from '../../mol-util/type-helpers'; export function parseMolScript(input: string) { return Language.parse(input); @@ -17,6 +18,7 @@ namespace Language { namespace ASTNode { export type Expression = Str | Symb | List | Comment + export type ExpressionWithoutComment = Str | Symb | List export interface Str { kind: 'string', @@ -60,7 +62,7 @@ namespace Language { function getAST(input: string) { return Expressions.tryParse(input); } - function visitExpr(expr: ASTNode.Expression): Expression { + function visitExpr(expr: ASTNode.ExpressionWithoutComment): Expression { switch (expr.kind) { case 'string': return expr.value; case 'symbol': { @@ -82,15 +84,14 @@ namespace Language { case '[': return B.core.type.list(withoutComments(expr.nodes).map(visitExpr)); case '{': return B.core.type.set(withoutComments(expr.nodes).map(visitExpr)); case '(': { + if (expr.nodes[0].kind === 'comment') throw new Error('Invalid expression'); const head = visitExpr(expr.nodes[0]); return Expression.Apply(head, getArgs(expr.nodes)); } + default: assertUnreachable(expr.bracket); } - return 0 as any; - } - default: { - throw new Error('should not happen'); } + default: assertUnreachable(expr); } } @@ -116,6 +117,7 @@ namespace Language { ++i; while (i < _i && nodes[i].kind === 'comment') { i++; } if (i >= _i) throw new Error(`There must be a value foolowed a named arg ':${name}'.`); + if (nodes[i].kind === 'comment') throw new Error('Invalid expression'); args[name] = visitExpr(nodes[i]); if (isNaN(+name)) allNumeric = false; } else { @@ -158,8 +160,8 @@ namespace Language { break; } } - if (!hasComment) return nodes; - return nodes.filter(n => n.kind !== 'comment'); + if (!hasComment) return nodes as ASTNode.ExpressionWithoutComment[]; + return nodes.filter(n => n.kind !== 'comment') as ASTNode.ExpressionWithoutComment[]; } function isNumber(value: string) { diff --git a/src/mol-util/zip/deflate.ts b/src/mol-util/zip/deflate.ts index 217f929931887d8d27b3a157fd6df2e0db40cba1..71627f51b0bb630aad98df40fe00c59f70be27e4 100644 --- a/src/mol-util/zip/deflate.ts +++ b/src/mol-util/zip/deflate.ts @@ -8,7 +8,7 @@ */ import { RuntimeContext } from '../../mol-task'; -import { NumberArray } from '../type-helpers'; +import { assertUnreachable, NumberArray } from '../type-helpers'; import { _hufTree } from './huffman'; import { U, revCodes, makeCodes } from './util'; @@ -250,7 +250,7 @@ function _writeBlock(BFINAL: number, lits: Uint32Array, li: number, ebits: numbe pos = _codeTiny(lset, U.itree, out, pos); pos = _codeTiny(dset, U.itree, out, pos); } else { - throw new Error(`unknown BTYPE ${BTYPE}`); + assertUnreachable(BTYPE); } let off = o0;