diff --git a/.github/workflows/lint-sources.yml b/.github/workflows/lint-sources.yml new file mode 100644 index 0000000..4e48659 --- /dev/null +++ b/.github/workflows/lint-sources.yml @@ -0,0 +1,29 @@ +name: Lint Sources + +on: + push: + branches: + - main + tags: + - 'v*' + pull_request: + branches: + - main + +jobs: + build: + strategy: + matrix: + # node-version: ['23.x', 'latest'] + node-version: ['23.x'] + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm run lint diff --git a/client/src/test/completion.test.ts b/client/src/test/completion.test.ts deleted file mode 100644 index f355078..0000000 --- a/client/src/test/completion.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import * as vscode from 'vscode'; -import * as assert from 'assert'; -import { getDocUri, activate } from './helper'; - -suite('Should do completion', () => { - const docUri = getDocUri('completion.txt'); - - test('Completes JS/TS in txt file', async () => { - await testCompletion(docUri, new vscode.Position(0, 0), { - items: [ - { label: 'JavaScript', kind: vscode.CompletionItemKind.Text }, - { label: 'TypeScript', kind: vscode.CompletionItemKind.Text } - ] - }); - }); -}); - -async function testCompletion( - docUri: vscode.Uri, - position: vscode.Position, - expectedCompletionList: vscode.CompletionList -) { - await activate(docUri); - - // Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion - const actualCompletionList = (await vscode.commands.executeCommand( - 'vscode.executeCompletionItemProvider', - docUri, - position - )) as vscode.CompletionList; - - assert.ok(actualCompletionList.items.length >= 2); - expectedCompletionList.items.forEach((expectedItem, i) => { - const actualItem = actualCompletionList.items[i]; - assert.equal(actualItem.label, expectedItem.label); - assert.equal(actualItem.kind, expectedItem.kind); - }); -} diff --git a/client/src/test/diagnostics.test.ts b/client/src/test/diagnostics.test.ts deleted file mode 100644 index 1aa8a36..0000000 --- a/client/src/test/diagnostics.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import * as vscode from 'vscode'; -import * as assert from 'assert'; -import { getDocUri, activate } from './helper'; - -suite('Should get diagnostics', () => { - const docUri = getDocUri('diagnostics.txt'); - - test('Diagnoses uppercase texts', async () => { - await testDiagnostics(docUri, [ - { message: 'ANY is all uppercase.', range: toRange(0, 0, 0, 3), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }, - { message: 'ANY is all uppercase.', range: toRange(0, 14, 0, 17), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }, - { message: 'OS is all uppercase.', range: toRange(0, 18, 0, 20), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' } - ]); - }); -}); - -function toRange(sLine: number, sChar: number, eLine: number, eChar: number) { - const start = new vscode.Position(sLine, sChar); - const end = new vscode.Position(eLine, eChar); - return new vscode.Range(start, end); -} - -async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: vscode.Diagnostic[]) { - await activate(docUri); - - const actualDiagnostics = vscode.languages.getDiagnostics(docUri); - - assert.equal(actualDiagnostics.length, expectedDiagnostics.length); - - expectedDiagnostics.forEach((expectedDiagnostic, i) => { - const actualDiagnostic = actualDiagnostics[i]; - assert.equal(actualDiagnostic.message, expectedDiagnostic.message); - assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range); - assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity); - }); -} \ No newline at end of file diff --git a/client/src/test/helper.ts b/client/src/test/helper.ts deleted file mode 100644 index 3f0fcf5..0000000 --- a/client/src/test/helper.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import * as vscode from 'vscode'; -import * as path from 'path'; - -export let doc: vscode.TextDocument; -export let editor: vscode.TextEditor; -export let documentEol: string; -export let platformEol: string; - -/** - * Activates the vscode.lpyth extension - */ -export async function activate(docUri: vscode.Uri) { - // The extensionId is `publisher.name` from package.json - const ext = vscode.extensions.getExtension('vscode.lpyth')!; - await ext.activate(); - try { - doc = await vscode.workspace.openTextDocument(docUri); - editor = await vscode.window.showTextDocument(doc); - await sleep(2000); // Wait for server activation - } catch (e) { - console.error(e); - } -} - -async function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -export const getDocPath = (p: string) => { - return path.resolve(__dirname, '../../testFixture', p); -}; -export const getDocUri = (p: string) => { - return vscode.Uri.file(getDocPath(p)); -}; - -export async function setTestContent(content: string): Promise { - const all = new vscode.Range( - doc.positionAt(0), - doc.positionAt(doc.getText().length) - ); - return editor.edit(eb => eb.replace(all, content)); -} diff --git a/client/src/test/index.ts b/client/src/test/index.ts deleted file mode 100644 index b9de4dc..0000000 --- a/client/src/test/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -import * as path from 'path'; -import * as Mocha from 'mocha'; -import * as glob from 'glob'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd', - color: true - }); - mocha.timeout(100000); - - const testsRoot = __dirname; - - return new Promise((resolve, reject) => { - glob('**.test.js', { cwd: testsRoot }, (err, files) => { - if (err) { - return reject(err); - } - - // Add files to the test suite - files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - reject(new Error(`${failures} tests failed.`)); - } else { - resolve(); - } - }); - } catch (err) { - console.error(err); - reject(err); - } - }); - }); -} \ No newline at end of file diff --git a/client/src/test/runTest.ts b/client/src/test/runTest.ts deleted file mode 100644 index 9d8189a..0000000 --- a/client/src/test/runTest.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as path from 'path'; - -import { runTests } from '@vscode/test-electron'; - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../../'); - - // The path to test runner - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './index'); - - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -main(); diff --git a/client/testFixture/completion.txt b/client/testFixture/completion.txt deleted file mode 100644 index e69de29..0000000 diff --git a/client/testFixture/diagnostics.txt b/client/testFixture/diagnostics.txt deleted file mode 100644 index d910cfb..0000000 --- a/client/testFixture/diagnostics.txt +++ /dev/null @@ -1 +0,0 @@ -ANY browsers, ANY OS. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6addbc1..637f79c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "esbuild": "^0.24.0", "eslint": "^9.15.0", "fast-check": "^3.23.1", + "globals": "^15.12.0", "mocha": "^10.8.2", "sinon": "^19.0.2", "ts-sinon": "^2.0.2", @@ -725,6 +726,19 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3099,9 +3113,9 @@ } }, "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 1bd09f6..f0ca056 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "esbuild": "^0.24.0", "eslint": "^9.15.0", "fast-check": "^3.23.1", + "globals": "^15.12.0", "mocha": "^10.8.2", "sinon": "^19.0.2", "ts-sinon": "^2.0.2", diff --git a/scripts/e2e.sh b/scripts/e2e.sh deleted file mode 100755 index 860c62e..0000000 --- a/scripts/e2e.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -export CODE_TESTS_PATH="$(pwd)/client/out/test" -export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture" - -node "$(pwd)/client/out/test/runTest" \ No newline at end of file diff --git a/server/src/.#lfortran-accessors.ts b/server/src/.#lfortran-accessors.ts deleted file mode 120000 index d62d06b..0000000 --- a/server/src/.#lfortran-accessors.ts +++ /dev/null @@ -1 +0,0 @@ -dylon@arch-workstation.3508:1732115012 \ No newline at end of file diff --git a/server/src/lfortran-accessors.ts b/server/src/lfortran-accessors.ts index 223f2b4..1438f96 100644 --- a/server/src/lfortran-accessors.ts +++ b/server/src/lfortran-accessors.ts @@ -71,7 +71,7 @@ export class LFortranCLIAccessor implements LFortranAccessor { constructor() { // Be sure to delete the temporary file when possible. - let cleanUp = this.cleanUp.bind(this); + const cleanUp = this.cleanUp.bind(this); process.on("exit", cleanUp); process.on("SIGINT", cleanUp); process.on("uncaughtException", cleanUp); @@ -82,6 +82,7 @@ export class LFortranCLIAccessor implements LFortranAccessor { try { console.debug("Deleting temporary file: %s", this.tmpFile.name); this.tmpFile.removeCallback(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { console.error("Failed to delete temporary file: %s", this.tmpFile.name); console.error(error); @@ -122,8 +123,8 @@ export class LFortranCLIAccessor implements LFortranAccessor { } flags = flags.concat([this.tmpFile.name]); const response = spawnSync(lfortranPath, flags, { - encoding: 'utf-8', - stdio: 'pipe' + encoding: "utf-8", + stdio: "pipe" }); if (response.error) { @@ -141,6 +142,7 @@ export class LFortranCLIAccessor implements LFortranAccessor { stdout = ""; } } + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (compileError: any) { stdout = compileError.stdout; if (compileError.signal !== null) { @@ -148,16 +150,16 @@ export class LFortranCLIAccessor implements LFortranAccessor { } throw compileError; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { console.error(error); - } finally { - return stdout; } + return stdout; } async showDocumentSymbols(uri: string, - text: string, - settings: ExampleSettings): Promise { + text: string, + settings: ExampleSettings): Promise { const flags = ["--show-document-symbols"]; const stdout = await this.runCompiler(settings, flags, text); let results; @@ -171,17 +173,17 @@ export class LFortranCLIAccessor implements LFortranAccessor { if (Array.isArray(results)) { const symbols: SymbolInformation[] = results; for (let i = 0, k = symbols.length; i < k; i++) { - let symbol: SymbolInformation = symbols[i]; + const symbol: SymbolInformation = symbols[i]; - let location: Location = symbol.location; + const location: Location = symbol.location; location.uri = uri; - let range: Range = location.range; + const range: Range = location.range; - let start: Position = range.start; + const start: Position = range.start; start.character--; - let end: Position = range.end; + const end: Position = range.end; end.character--; symbol.kind = SymbolKind.Function; @@ -205,14 +207,14 @@ export class LFortranCLIAccessor implements LFortranAccessor { const stdout = await this.runCompiler(settings, flags, text); const obj = JSON.parse(stdout); for (let i = 0, k = obj.length; i < k; i++) { - let location = obj[i].location; + const location = obj[i].location; if (location) { - let range: Range = location.range; + const range: Range = location.range; - let start: Position = range.start; + const start: Position = range.start; start.character--; - let end: Position = range.end; + const end: Position = range.end; end.character--; return [{ @@ -222,6 +224,7 @@ export class LFortranCLIAccessor implements LFortranAccessor { }]; } } + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { console.error("Failed to lookup name at line=%d, column=%d", line, column); console.error(error); @@ -230,15 +233,15 @@ export class LFortranCLIAccessor implements LFortranAccessor { } async showErrors(uri: string, - text: string, - settings: ExampleSettings): Promise { + text: string, + settings: ExampleSettings): Promise { const diagnostics: Diagnostic[] = []; try { const flags = ["--show-errors"]; const stdout = await this.runCompiler(settings, flags, text); const results: ErrorDiagnostics = JSON.parse(stdout); if (results?.diagnostics) { - let k = Math.min(results.diagnostics.length, settings.maxNumberOfProblems); + const k = Math.min(results.diagnostics.length, settings.maxNumberOfProblems); for (let i = 0; i < k; i++) { const diagnostic: Diagnostic = results.diagnostics[i]; diagnostic.severity = DiagnosticSeverity.Warning; @@ -246,11 +249,11 @@ export class LFortranCLIAccessor implements LFortranAccessor { diagnostics.push(diagnostic); } } + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { console.error("Failed to show errors"); console.error(error); - } finally { - return diagnostics; } + return diagnostics; } } diff --git a/server/src/lfortran-language-server.ts b/server/src/lfortran-language-server.ts index 0dcf776..099160d 100644 --- a/server/src/lfortran-language-server.ts +++ b/server/src/lfortran-language-server.ts @@ -116,6 +116,7 @@ export class LFortranLanguageServer { return result; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars onInitialized(params: InitializedParams): void { if (this.hasConfigurationCapability) { // Register for all configuration changes. @@ -131,19 +132,19 @@ export class LFortranLanguageServer { } extractDefinition(location: Location): string | undefined { - let document = this.documents.get(location.uri); + const document = this.documents.get(location.uri); if (document !== undefined) { - let range: Range = location.range; + const range: Range = location.range; - let start: Position = range.start; - let startLine: number = start.line; - let startCol: number = start.character; + const start: Position = range.start; + const startLine: number = start.line; + const startCol: number = start.character; - let end: Position = range.end; - let endLine: number = end.line; - let endCol: number = end.character; + const end: Position = range.end; + const endLine: number = end.line; + const endCol: number = end.character; - let text = document.getText(); + const text = document.getText(); let currLine = 0; let currCol = 0; @@ -158,7 +159,7 @@ export class LFortranLanguageServer { currLine++; currCol = 0; } else if (c === '\r') { - let l = j + 1; + const l = j + 1; if ((l < k) && (text[l] === '\n')) { j = l; } @@ -168,7 +169,7 @@ export class LFortranLanguageServer { currCol++; } } - let definition: string = text.substring(i, j); + const definition: string = text.substring(i, j); return definition; } else { c = text[i]; @@ -176,7 +177,7 @@ export class LFortranLanguageServer { currLine++; currCol = 0; } else if (c === '\r') { - let j = i + 1; + const j = i + 1; if ((j < k) && (text[j] === '\n')) { i = j; } @@ -193,11 +194,11 @@ export class LFortranLanguageServer { index(uri: string, symbols: SymbolInformation[]): void { // (symbols.length == 0) => error with document, but we still need to // support auto-completion. - let terms: string[] = []; - let values: CompletionItem[] = []; + const terms: string[] = []; + const values: CompletionItem[] = []; for (let i = 0, k = symbols.length; i < k; i++) { - let symbol: SymbolInformation = symbols[i]; - let definition: string | undefined = + const symbol: SymbolInformation = symbols[i]; + const definition: string | undefined = this.extractDefinition(symbol.location); terms.push(symbol.name); values.push({ @@ -211,7 +212,7 @@ export class LFortranLanguageServer { }); } // TODO: Index temporary file by URI (maybe) - let dictionary = PrefixTrie.from(terms, values); + const dictionary = PrefixTrie.from(terms, values); this.dictionaries.set(uri, dictionary); } @@ -221,7 +222,7 @@ export class LFortranLanguageServer { const settings = await this.getDocumentSettings(uri); const text = document?.getText(); if (typeof text === "string") { - let symbols: SymbolInformation[] = + const symbols: SymbolInformation[] = await this.lfortran.showDocumentSymbols(uri, text, settings); if (symbols.length > 0) { // (symbols.length == 0) => error with document, but we still need to @@ -258,7 +259,6 @@ export class LFortranLanguageServer { this.documents.all().forEach(this.validateTextDocument); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars getDocumentSettings(resource: string): Thenable { if (!this.hasConfigurationCapability) { return Promise.resolve(this.settings); @@ -308,12 +308,12 @@ export class LFortranLanguageServer { let currCol = 0; for (let i = 0, k = text.length; i < k; i++) { - let c: string = text[i]; + const c: string = text[i]; if (c === '\n') { currLine++; currCol = 0; } else if (c === '\r') { - let j = i + 1; + const j = i + 1; if ((j < k) && (text[j] === '\n')) { i = j; } @@ -324,7 +324,7 @@ export class LFortranLanguageServer { } if ((line === currLine) && (column === currCol)) { - let re_identifiable: RegExp = RE_IDENTIFIABLE; + const re_identifiable: RegExp = RE_IDENTIFIABLE; if (re_identifiable.test(c)) { let l = i; let u = i + 1; @@ -334,7 +334,7 @@ export class LFortranLanguageServer { while ((u < k) && re_identifiable.test(text[u])) { u++; } - let query = text.substring(l, u); + const query = text.substring(l, u); return query; } } @@ -344,13 +344,13 @@ export class LFortranLanguageServer { } onCompletion(documentPosition: TextDocumentPositionParams): CompletionItem[] | CompletionList | undefined { - let uri: string = documentPosition.textDocument.uri; - let document = this.documents.get(uri); - let dictionary = this.dictionaries.get(uri); + const uri: string = documentPosition.textDocument.uri; + const document = this.documents.get(uri); + const dictionary = this.dictionaries.get(uri); if ((document !== undefined) && (dictionary !== undefined)) { - let text: string = document.getText(); - let pos: Position = documentPosition.position; - let query: string | null = this.extractQuery(text, pos.line, pos.character); + const text: string = document.getText(); + const pos: Position = documentPosition.position; + const query: string | null = this.extractQuery(text, pos.line, pos.character); if (query !== null) { return Array.from(dictionary.lookup(query)) as CompletionItem[]; } @@ -362,17 +362,17 @@ export class LFortranLanguageServer { } onHover(params: HoverParams): Hover | undefined { - let uri: string = params.textDocument.uri; - let document = this.documents.get(uri); - let dictionary = this.dictionaries.get(uri); + const uri: string = params.textDocument.uri; + const document = this.documents.get(uri); + const dictionary = this.dictionaries.get(uri); if ((document !== undefined) && (dictionary !== undefined)) { - let text: string = document.getText(); - let pos: Position = params.position; - let query: string | null = this.extractQuery(text, pos.line, pos.character); + const text: string = document.getText(); + const pos: Position = params.position; + const query: string | null = this.extractQuery(text, pos.line, pos.character); if (query !== null) { - let completion: CompletionItem | undefined = + const completion: CompletionItem | undefined = dictionary.exactLookup(query) as CompletionItem; - let definition: string | undefined = completion?.detail; + const definition: string | undefined = completion?.detail; if (definition !== undefined) { return { contents: { diff --git a/server/src/prefix-trie.ts b/server/src/prefix-trie.ts index 62721af..70570ce 100644 --- a/server/src/prefix-trie.ts +++ b/server/src/prefix-trie.ts @@ -21,14 +21,13 @@ export class PrefixNode { } transition(label: string): PrefixNode | undefined { - let child: PrefixNode | undefined = this.edges.get(label); - return child; + return this.edges.get(label); } buffer(ss: string[]): string[] { if (this.parent !== undefined) { this.parent.buffer(ss); - // @ts-ignore: next-line + // @ts-expect-error: next-line ss.push(this.label); } return ss; @@ -36,7 +35,7 @@ export class PrefixNode { collect(): object | string { if (this.value === undefined) { - let ss: string[] = []; + const ss: string[] = []; this.buffer(ss); this.value = ss.join(""); } @@ -44,7 +43,7 @@ export class PrefixNode { } toString(): string { - let ss: string[] = []; + const ss: string[] = []; ss.push("PrefixNode{isFinal="); ss.push(this.isFinal.toString()); ss.push(",edges="); @@ -55,6 +54,7 @@ export class PrefixNode { return ss.join(""); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any equalsPrefix(that: any): boolean { return (that instanceof PrefixNode) && ((this.parent === undefined) === (that.parent === undefined)) && @@ -63,17 +63,19 @@ export class PrefixNode { (this.label === that.label); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any equalsSuffix(that: any): boolean { return (that instanceof PrefixNode) && (this.isFinal === that.isFinal) && (this.label === that.label) && (this.edges.size === that.edges.size) && Array.from(this.edges).every(([label, thisChild]) => { - let thatChild = that.edges.get(label); + const thatChild = that.edges.get(label); return thisChild.equalsSuffix(thatChild); }); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any equals(that: any): boolean { return this.equalsPrefix(that) && this.equalsSuffix(that); } @@ -100,7 +102,7 @@ export class PrefixIterator { next(): IteratorValue { this.advance(); - let value = this.value; + const value = this.value; this.value = null; return { value: value, @@ -110,11 +112,11 @@ export class PrefixIterator { advance(): void { if ((this.value === null) && (this.pending.length > 0)) { - let pending: PrefixNode[] = this.pending; + const pending: PrefixNode[] = this.pending; do { - // @ts-ignore: next-line - let node: PrefixNode = pending.shift(); - for (let child of node.edges.values()) { + // @ts-expect-error: next-line + const node: PrefixNode = pending.shift(); + for (const child of node.edges.values()) { pending.push(child); } if (node.isFinal) { @@ -136,8 +138,8 @@ export class PrefixIterator { } toString(): string { - let buffer: string[] = []; - let pending: PrefixNode[] = this.pending; + const buffer: string[] = []; + const pending: PrefixNode[] = this.pending; buffer.push("PrefixIterator{value="); if (this.value !== null) { buffer.push('"'); @@ -150,7 +152,7 @@ export class PrefixIterator { buffer.push(pending.length.toString()); buffer.push(",values=["); for (let i = 0, k = pending.length; i < k; i++) { - let node: PrefixNode = pending[i]; + const node: PrefixNode = pending[i]; buffer.push('"'); buffer.push(node.toString()); buffer.push('"'); @@ -162,12 +164,13 @@ export class PrefixIterator { return buffer.join(""); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any equals(that: any): boolean { return (that instanceof PrefixIterator) && (this.value === that.value) && (this.pending.length === that.pending.length) && this.pending.every((thisNode: PrefixNode, index: number) => { - let thatNode: PrefixNode = that.pending[index]; + const thatNode: PrefixNode = that.pending[index]; return thisNode.equals(thatNode); }); } @@ -188,7 +191,7 @@ export class PrefixCursor { for (let i = 0, k = suffix.length; (i < k) && (curr !== undefined); i++) { - let label: string = suffix[i]; + const label: string = suffix[i]; prev = curr; curr = curr.transition(label); } @@ -215,11 +218,12 @@ export class PrefixCursor { } toString(): string { - let prev: string = (this.prev !== undefined) ? `"${this.prev}"` : "null"; - let curr: string = (this.curr !== undefined) ? `"${this.curr}"` : "null"; + const prev: string = (this.prev !== undefined) ? `"${this.prev}"` : "null"; + const curr: string = (this.curr !== undefined) ? `"${this.curr}"` : "null"; return `PrefixCursor{prev=${prev},curr=${curr}}`; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any equals(that: any): boolean { return (that instanceof PrefixCursor) && ((this.curr === undefined) === (that.curr === undefined)) && @@ -240,10 +244,10 @@ export class PrefixTrie { if (values === undefined) { values = terms; } - let dict = new PrefixTrie(); + const dict = new PrefixTrie(); for (let i = 0, k = terms.length; i < k; i++) { - let term: string = terms[i]; - let value: object | string = values[i]; + const term: string = terms[i]; + const value: object | string = values[i]; dict.insert(term, value); } return dict; @@ -255,10 +259,10 @@ export class PrefixTrie { } term = term.toLowerCase(); let curr: PrefixNode = this.root; - let path: PrefixNode[] = []; + const path: PrefixNode[] = []; path.push(curr); for (let i = 0, k = term.length; i < k; i++) { - let label: string = term[i]; + const label: string = term[i]; curr = curr.addEdge(label); path.push(curr); } @@ -277,7 +281,7 @@ export class PrefixTrie { for (let i = 0, k = term.length; (i < k) && (curr !== undefined); i++) { - let label: string = term[i]; + const label: string = term[i]; curr = curr.transition(label); } if ((curr === undefined) || !curr.isFinal) { @@ -286,7 +290,7 @@ export class PrefixTrie { curr.isFinal = false; curr.value = undefined; while ((curr.edges.size === 0) && !curr.isFinal) { - let label: string | undefined = curr.label; + const label: string | undefined = curr.label; curr = curr.parent; if (curr === undefined) { break; @@ -303,7 +307,7 @@ export class PrefixTrie { for (let i = 0, k = term.length; (i < k) && (curr !== undefined); i++) { - let label: string = term[i]; + const label: string = term[i]; curr = curr.transition(label); } if (curr !== undefined) { @@ -315,7 +319,7 @@ export class PrefixTrie { term = term.toLowerCase(); let curr: PrefixNode | undefined = this.root; for (let i = 0, k = term.length; i < k; i++) { - let label: string = term[i]; + const label: string = term[i]; curr = curr.transition(label); if (curr === undefined) { break; @@ -333,13 +337,13 @@ export class PrefixTrie { for (let i = 0, k = term.length; (i < k) && (curr !== undefined); i++) { - let label: string = term[i]; + const label: string = term[i]; curr = curr.transition(label); } return (curr !== undefined) && curr.isFinal; } - cursor() : PrefixCursor { + cursor(): PrefixCursor { return new PrefixCursor(this.root); } @@ -348,30 +352,33 @@ export class PrefixTrie { } toString(): string { - let buffer: string[] = []; + const buffer: string[] = []; buffer.push("PrefixTrie{size="); buffer.push(this.size.toString()) buffer.push(",terms=["); - let iter: PrefixIterator = this[Symbol.iterator](); - let { "value": term, "done": done } = iter.next(); + const iter: PrefixIterator = this[Symbol.iterator](); + const { "value": term, "done": done } = iter.next(); if (!done) { buffer.push('"'); + // @ts-expect-error: next-line buffer.push(term); buffer.push('"'); do { - let { "value": term, "done": done } = iter.next(); + const { "value": term, "done": done } = iter.next(); if (done) { break; } buffer.push(',"'); + // @ts-expect-error: next-line buffer.push(term); buffer.push('"'); - } while (true); + } while (!done); } buffer.push("]}"); return buffer.join(""); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any equals(that: any): boolean { return (that instanceof PrefixTrie) && (this.size === that.size) &&