diff --git a/src/editor/manager.test.ts b/src/editor/manager.test.ts new file mode 100644 index 0000000000..d214ba5ec6 --- /dev/null +++ b/src/editor/manager.test.ts @@ -0,0 +1,81 @@ +import { editorManager } from 'lib/singletons' +import { Diagnostic } from '@codemirror/lint' + +describe('EditorManager Class', () => { + describe('makeUniqueDiagnostics', () => { + it('should filter out duplicated diagnostics', () => { + const duplicatedDiagnostics: Diagnostic[] = [ + { + from: 2, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + { + from: 2, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + { + from: 2, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + ] + + const expected: Diagnostic[] = [ + { + from: 2, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + ] + + const actual = editorManager.makeUniqueDiagnostics(duplicatedDiagnostics) + expect(actual).toStrictEqual(expected) + }) + it('should filter out duplicated diagnostic and keep some original ones', () => { + const duplicatedDiagnostics: Diagnostic[] = [ + { + from: 0, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + { + from: 0, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + { + from: 88, + to: 99, + severity: 'hint', + message: 'my super cool message', + }, + ] + + const expected: Diagnostic[] = [ + { + from: 0, + to: 10, + severity: 'hint', + message: 'my cool message', + }, + { + from: 88, + to: 99, + severity: 'hint', + message: 'my super cool message', + }, + ] + + const actual = editorManager.makeUniqueDiagnostics(duplicatedDiagnostics) + expect(actual).toStrictEqual(expected) + }) + }) +}) diff --git a/src/editor/manager.ts b/src/editor/manager.ts index 4ed81375c8..8b2c1c9811 100644 --- a/src/editor/manager.ts +++ b/src/editor/manager.ts @@ -22,10 +22,6 @@ export const modelingMachineEvent = modelingMachineAnnotation.of(true) const setDiagnosticsAnnotation = Annotation.define() export const setDiagnosticsEvent = setDiagnosticsAnnotation.of(true) -function diagnosticIsEqual(d1: Diagnostic, d2: Diagnostic): boolean { - return d1.from === d2.from && d1.to === d2.to && d1.message === d2.message -} - export default class EditorManager { private _editorView: EditorView | null = null private _copilotEnabled: boolean = true @@ -117,20 +113,29 @@ export default class EditorManager { } } + /** + * Given an array of Diagnostics remove any duplicates by hashing a key + * in the format of from + ' ' + to + ' ' + message. + */ + makeUniqueDiagnostics(duplicatedDiagnostics: Diagnostic[]): Diagnostic[] { + const uniqueDiagnostics: Diagnostic[] = [] + const seenDiagnostic: { [key: string]: boolean } = {} + + duplicatedDiagnostics.forEach((diagnostic: Diagnostic) => { + const hash = `${diagnostic.from} ${diagnostic.to} ${diagnostic.message}` + if (!seenDiagnostic[hash]) { + uniqueDiagnostics.push(diagnostic) + seenDiagnostic[hash] = true + } + }) + + return uniqueDiagnostics + } + setDiagnostics(diagnostics: Diagnostic[]): void { if (!this._editorView) return // Clear out any existing diagnostics that are the same. - for (const diagnostic of diagnostics) { - for (const otherDiagnostic of diagnostics) { - if (diagnosticIsEqual(diagnostic, otherDiagnostic)) { - diagnostics = diagnostics.filter( - (d) => !diagnosticIsEqual(d, diagnostic) - ) - diagnostics.push(diagnostic) - break - } - } - } + diagnostics = this.makeUniqueDiagnostics(diagnostics) this._editorView.dispatch({ effects: [setDiagnosticsEffect.of(diagnostics)], diff --git a/src/lang/KclSingleton.ts b/src/lang/KclSingleton.ts index 1d55ad2537..b1b9feaae9 100644 --- a/src/lang/KclSingleton.ts +++ b/src/lang/KclSingleton.ts @@ -124,7 +124,7 @@ export class KclManager { if (this.lints.length > 0) { diagnostics = diagnostics.concat(this.lints) } - editorManager.setDiagnostics(diagnostics) + editorManager?.setDiagnostics(diagnostics) } addKclErrors(kclErrors: KCLError[]) {