From b2c0477f0255f685e9dc961a52a400fdbba5b1fe Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 00:19:48 -0600 Subject: [PATCH 01/57] A cursor's RangeAndText type can be undefined --- src/util/cursor-get-text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/cursor-get-text.ts b/src/util/cursor-get-text.ts index fcb70f67b..ce46a7e69 100644 --- a/src/util/cursor-get-text.ts +++ b/src/util/cursor-get-text.ts @@ -4,7 +4,7 @@ import { EditableDocument } from '../cursor-doc/model'; -export type RangeAndText = [[number, number], string]; +export type RangeAndText = [[number, number], string] | [undefined, '']; export function currentTopLevelFunction( doc: EditableDocument, From 0e8cdd17d87f27ef305d35980b9337e34a07443e Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 00:22:37 -0600 Subject: [PATCH 02/57] Account for SelectionAndText possibly being undefined --- src/util/get-text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/get-text.ts b/src/util/get-text.ts index 0f60520f2..258677902 100644 --- a/src/util/get-text.ts +++ b/src/util/get-text.ts @@ -5,7 +5,7 @@ import * as docMirror from '../doc-mirror/index'; import * as cursorTextGetter from './cursor-get-text'; import { EditableDocument } from '../cursor-doc/model'; -export type SelectionAndText = [vscode.Selection, string]; +export type SelectionAndText = [vscode.Selection, string] | [undefined, '']; function _currentFormText( doc: vscode.TextDocument, From fca5cee9363e91517a0b4c0057c4fbcfff13f68e Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 01:16:24 -0600 Subject: [PATCH 03/57] Fix types for getTokenCursor for Editable(Document|Model) --- src/cursor-doc/model.ts | 13 ++++++++++++- src/cursor-doc/paredit.ts | 4 ++-- src/doc-mirror/index.ts | 10 ++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/cursor-doc/model.ts b/src/cursor-doc/model.ts index 83ac5f3a8..d4d9da1d1 100644 --- a/src/cursor-doc/model.ts +++ b/src/cursor-doc/model.ts @@ -1,6 +1,7 @@ import { Scanner, Token, ScannerState } from './clojure-lexer'; import { LispTokenCursor } from './token-cursor'; import { deepEqual as equal } from '../util/object'; +import { isUndefined } from 'lodash'; let scanner: Scanner; @@ -581,6 +582,8 @@ export class LineInputModel implements EditableModel { lastIndex = i; } return new LispTokenCursor(this, row, line.tokens.length - 1); + } else { + throw new Error('Unable to get token cursor for LineInputModel!'); } } } @@ -609,7 +612,15 @@ export class StringDocument implements EditableDocument { selectionStack: ModelEditSelection[] = []; getTokenCursor(offset?: number, previous?: boolean): LispTokenCursor { - return this.model.getTokenCursor(offset); + const cursor = isUndefined(offset) + ? undefined + : this.model.getTokenCursor(offset); + + if (isUndefined(cursor)) { + throw new Error('Expected a cursor for StringDocument!'); + } + + return cursor; } insertString(text: string) { diff --git a/src/cursor-doc/paredit.ts b/src/cursor-doc/paredit.ts index ef6e97f14..f0eab5387 100644 --- a/src/cursor-doc/paredit.ts +++ b/src/cursor-doc/paredit.ts @@ -817,10 +817,10 @@ export function backspace( start: number = doc.selection.anchor, end: number = doc.selection.active ): Thenable { - const cursor = doc.getTokenCursor(start); if (start != end) { return doc.backspace(); } else { + const cursor = doc.getTokenCursor(start); const nextToken = cursor.getToken(); const p = start; const prevToken = @@ -867,10 +867,10 @@ export function deleteForward( start: number = doc.selectionLeft, end: number = doc.selectionRight ) { - const cursor = doc.getTokenCursor(start); if (start != end) { void doc.delete(); } else { + const cursor = doc.getTokenCursor(start); const prevToken = cursor.getPrevToken(); const nextToken = cursor.getToken(); const p = start; diff --git a/src/doc-mirror/index.ts b/src/doc-mirror/index.ts index ffe3bc0a9..69baf9b64 100644 --- a/src/doc-mirror/index.ts +++ b/src/doc-mirror/index.ts @@ -135,7 +135,7 @@ export class DocumentModel implements EditableModel { return this.lineInputModel.getOffsetForLine(line); } - public getTokenCursor(offset: number, previous: boolean = false) { + public getTokenCursor(offset: number, previous?: boolean) { return this.lineInputModel.getTokenCursor(offset, previous); } } @@ -162,7 +162,13 @@ export class MirroredDocument implements EditableDocument { offset: number = this.selectionRight, previous: boolean = false ): LispTokenCursor { - return this.model.getTokenCursor(offset, previous); + const cursor = this.model.getTokenCursor(offset, previous); + + if (isUndefined(cursor)) { + throw new Error('Expected a cursor for MirrorDocument!'); + } + + return cursor; } public insertString(text: string) { From 6a22a6a087dfdee6c53713757ee36bb000f6731d Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 02:05:39 -0600 Subject: [PATCH 04/57] Fix null checks for util.getDocument --- src/clojuredocs.ts | 4 +-- src/doc-mirror/index.ts | 2 +- src/evaluate.ts | 2 +- src/namespace.ts | 2 +- src/nrepl/repl-session.ts | 5 ++-- src/project-root.ts | 2 +- src/results-output/results-doc.ts | 4 +-- src/select.ts | 2 +- src/utilities.ts | 50 +++++++++++++++++-------------- 9 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 69a19aa05..64a37b781 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -62,7 +62,7 @@ export function printTextToRichCommentCommand(args: { [x: string]: string }) { } function printTextToRichComment(text: string, position?: number) { - const doc = util.getDocument({}); + const doc = util.mustGetDocument({}); const mirrorDoc = docMirror.mustGetDocument(doc); paredit.addRichComment( mirrorDoc, @@ -182,7 +182,7 @@ async function clojureDocsLookup( d?: vscode.TextDocument, p?: vscode.Position ): Promise { - const doc = d ? d : util.getDocument({}); + const doc = d ? d : util.mustGetDocument({}); const position = p ? p : util.mustGetActiveTextEditor().selection.active; const symbol = util.getWordAtPosition(doc, position); const ns = namespace.getNamespace(doc); diff --git a/src/doc-mirror/index.ts b/src/doc-mirror/index.ts index 69baf9b64..4a6c7f457 100644 --- a/src/doc-mirror/index.ts +++ b/src/doc-mirror/index.ts @@ -266,7 +266,7 @@ export function getDocumentOffset( return model.getOffsetForLine(position.line) + position.character; } -function addDocument(doc: vscode.TextDocument): boolean { +function addDocument(doc?: vscode.TextDocument): boolean { if (doc && doc.languageId == 'clojure') { if (!documents.has(doc)) { const document = new MirroredDocument(doc); diff --git a/src/evaluate.ts b/src/evaluate.ts index 605262974..94fd6893c 100644 --- a/src/evaluate.ts +++ b/src/evaluate.ts @@ -253,7 +253,6 @@ async function evaluateCode( } async function evaluateSelection(document = {}, options) { - const doc = util.getDocument(document); const selectionFn: ( editor: vscode.TextEditor ) => [vscode.Selection, string] = options.selectionFn; @@ -266,6 +265,7 @@ async function evaluateSelection(document = {}, options) { let code = selection[1]; [codeSelection, code]; + const doc = util.mustGetDocument(document); const ns = namespace.getNamespace(doc); const line = codeSelection.start.line; const column = codeSelection.start.character; diff --git a/src/namespace.ts b/src/namespace.ts index 121c53a4d..33e926e50 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -8,7 +8,7 @@ import * as utilities from './utilities'; import * as replSession from './nrepl/repl-session'; import { NReplSession } from './nrepl'; -export function getNamespace(doc: vscode.TextDocument) { +export function getNamespace(doc?: vscode.TextDocument) { if (outputWindow.isResultsDoc(doc)) { return outputWindow.getNs(); } diff --git a/src/nrepl/repl-session.ts b/src/nrepl/repl-session.ts index 1bfe04f84..35eb59b44 100644 --- a/src/nrepl/repl-session.ts +++ b/src/nrepl/repl-session.ts @@ -1,11 +1,12 @@ import { NReplSession } from '.'; import { cljsLib, getDocument, getFileType } from '../utilities'; import * as outputWindow from '../results-output/results-doc'; +import { isUndefined } from 'lodash'; -function getSession(fileType = undefined): NReplSession { +function getSession(fileType?: string): NReplSession { const doc = getDocument({}); - if (fileType === undefined) { + if (isUndefined(fileType)) { fileType = getFileType(doc); } if (fileType.match(/^clj[sc]?/)) { diff --git a/src/project-root.ts b/src/project-root.ts index 517951515..8955feda7 100644 --- a/src/project-root.ts +++ b/src/project-root.ts @@ -22,7 +22,7 @@ export function getProjectWsFolder(): vscode.WorkspaceFolder { export async function findProjectRootUri( projectFileNames: string[], - doc: vscode.TextDocument, + doc: vscode.TextDocument | undefined, workspaceFolder: vscode.WorkspaceFolder ): Promise { let searchUri = doc?.uri || workspaceFolder?.uri; diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 18e850b3c..7a3a41da6 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -102,8 +102,8 @@ export function setSession(session: NReplSession, newNs: string): void { } } -export function isResultsDoc(doc: vscode.TextDocument): boolean { - return doc && path.basename(doc.fileName) === RESULTS_DOC_NAME; +export function isResultsDoc(doc?: vscode.TextDocument): boolean { + return !!doc && path.basename(doc.fileName) === RESULTS_DOC_NAME; } function getViewColumn(): vscode.ViewColumn { diff --git a/src/select.ts b/src/select.ts index 82f456358..cb182b4fd 100644 --- a/src/select.ts +++ b/src/select.ts @@ -53,7 +53,7 @@ function selectForm( toplevel: boolean ) { const editor = util.mustGetActiveTextEditor(), - doc = util.getDocument(document), + doc = util.mustGetDocument(document), selection = editor.selection; if (selection.isEmpty) { diff --git a/src/utilities.ts b/src/utilities.ts index 49f0dec0f..8251e9042 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -32,18 +32,15 @@ export function isNonEmptyString(value: any): boolean { async function quickPickSingle(opts: { values: string[]; - saveAs?: string; + saveAs: string; placeHolder: string; autoSelect?: boolean; }) { if (opts.values.length == 0) { return; } - let selected: string; - const saveAs: string = opts.saveAs ? `qps-${opts.saveAs}` : null; - if (saveAs) { - selected = state.extensionContext.workspaceState.get(saveAs); - } + const saveAs = `qps-${opts.saveAs}`; + const selected = state.extensionContext.workspaceState.get(saveAs); let result; if (opts.autoSelect && opts.values.length == 1) { @@ -60,14 +57,12 @@ async function quickPickSingle(opts: { async function quickPickMulti(opts: { values: string[]; - saveAs?: string; + saveAs: string; placeHolder: string; }) { - let selected: string[]; - const saveAs: string = opts.saveAs ? `qps-${opts.saveAs}` : null; - if (saveAs) { - selected = state.extensionContext.workspaceState.get(saveAs) || []; - } + const saveAs = `qps-${opts.saveAs}`; + const selected = + state.extensionContext.workspaceState.get(saveAs) || []; const result = await quickPick(opts.values, [], selected, { placeHolder: opts.placeHolder, canPickMany: true, @@ -95,19 +90,19 @@ async function quickPick( active: string[], selected: string[], options: vscode.QuickPickOptions -): Promise { +): Promise { const items = itemsToPick.map((x) => ({ label: x })); const qp = vscode.window.createQuickPick(); - qp.canSelectMany = options.canPickMany; + qp.canSelectMany = !!options.canPickMany; qp.placeholder = options.placeHolder; - qp.ignoreFocusOut = options.ignoreFocusOut; - qp.matchOnDescription = options.matchOnDescription; - qp.matchOnDetail = options.matchOnDetail; + qp.ignoreFocusOut = !!options.ignoreFocusOut; + qp.matchOnDescription = !!options.matchOnDescription; + qp.matchOnDetail = !!options.matchOnDetail; qp.items = items; qp.activeItems = items.filter((x) => active.indexOf(x.label) != -1); qp.selectedItems = items.filter((x) => selected.indexOf(x.label) != -1); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { qp.show(); qp.onDidAccept(() => { if (qp.canSelectMany) { @@ -174,7 +169,7 @@ function getWordAtPosition(document, position) { function getDocument( document: vscode.TextDocument | Record -): vscode.TextDocument { +): vscode.TextDocument | undefined { const activeTextEditor = getActiveTextEditor(); if ( document && @@ -190,10 +185,20 @@ function getDocument( const editor = vscode.window.visibleTextEditors.find( (editor) => editor.document && editor.document.languageId !== 'Log' ); - return editor ? editor.document : null; - } else { - return null; + return editor?.document; + } +} + +function mustGetDocument( + document: vscode.TextDocument | Record +): vscode.TextDocument { + const doc = getDocument(document); + + if (isUndefined(doc)) { + throw new Error('Expected an activeTextEditor with a document!'); } + + return doc; } function getFileType(document) { @@ -575,6 +580,7 @@ export { distinct, getWordAtPosition, getDocument, + mustGetDocument, getFileType, getLaunchingState, setLaunchingState, From a08278aaef21d96ebcd0fe564c1a447245607d1a Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 15:47:53 -0600 Subject: [PATCH 05/57] Rename document fetching functions as per @PEZ's request --- src/calva-fmt/src/format.ts | 8 ++++---- src/calva-fmt/src/providers/ontype_formatter.ts | 3 +-- src/clojuredocs.ts | 6 +++--- src/debugger/calva-debug.ts | 2 +- src/doc-mirror/index.ts | 10 +++++----- src/edit.ts | 4 ++-- src/evaluate.ts | 14 +++++++------- .../integration/suite/extension-test.ts | 4 ++-- src/highlight/src/extension.ts | 4 ++-- src/lsp/main.ts | 2 +- src/namespace.ts | 6 +++--- src/nrepl/repl-session.ts | 6 +++--- src/paredit/extension.ts | 2 +- src/project-root.ts | 4 ++-- src/providers/completion.ts | 2 +- src/providers/signature.ts | 6 +++--- src/refresh.ts | 4 ++-- src/results-output/results-doc.ts | 6 +++--- src/select.ts | 6 +++--- src/state.ts | 4 ++-- src/statusbar.ts | 2 +- src/testRunner.ts | 4 ++-- src/util/get-text.ts | 6 +++--- src/utilities.ts | 10 +++++----- src/when-contexts.ts | 2 +- 25 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/calva-fmt/src/format.ts b/src/calva-fmt/src/format.ts index 346e519a8..e45e050d2 100644 --- a/src/calva-fmt/src/format.ts +++ b/src/calva-fmt/src/format.ts @@ -5,7 +5,7 @@ import { getIndent, getDocumentOffset, MirroredDocument, - mustGetDocument, + getDocument, } from '../../doc-mirror/index'; import { formatTextAtRange, @@ -24,7 +24,7 @@ export async function indentPosition( const editor = util.mustGetActiveTextEditor(); const pos = new vscode.Position(position.line, 0); const indent = getIndent( - mustGetDocument(document).model.lineInputModel, + getDocument(document).model.lineInputModel, getDocumentOffset(document, position), await config.getConfig() ); @@ -56,7 +56,7 @@ export async function formatRangeEdits( range: vscode.Range ): Promise { const text: string = document.getText(range); - const mirroredDoc: MirroredDocument = mustGetDocument(document); + const mirroredDoc: MirroredDocument = getDocument(document); const startIndex = document.offsetAt(range.start); const endIndex = document.offsetAt(range.end); const cursor = mirroredDoc.getTokenCursor(startIndex); @@ -91,7 +91,7 @@ export async function formatPositionInfo( const doc: vscode.TextDocument = editor.document; const pos: vscode.Position = editor.selection.active; const index = doc.offsetAt(pos); - const mirroredDoc: MirroredDocument = mustGetDocument(doc); + const mirroredDoc: MirroredDocument = getDocument(doc); const cursor = mirroredDoc.getTokenCursor(index); const formatDepth = extraConfig['format-depth'] ? extraConfig['format-depth'] diff --git a/src/calva-fmt/src/providers/ontype_formatter.ts b/src/calva-fmt/src/providers/ontype_formatter.ts index ba22fc94f..271e29372 100644 --- a/src/calva-fmt/src/providers/ontype_formatter.ts +++ b/src/calva-fmt/src/providers/ontype_formatter.ts @@ -24,8 +24,7 @@ export class FormatOnTypeEditProvider keyMap === 'strict' && getConfig().strictPreventUnmatchedClosingBracket ) { - const mDoc: EditableDocument = - docMirror.mustGetDocument(document); + const mDoc: EditableDocument = docMirror.getDocument(document); const tokenCursor = mDoc.getTokenCursor(); if (tokenCursor.withinComment()) { return null; diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 64a37b781..668098674 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -62,8 +62,8 @@ export function printTextToRichCommentCommand(args: { [x: string]: string }) { } function printTextToRichComment(text: string, position?: number) { - const doc = util.mustGetDocument({}); - const mirrorDoc = docMirror.mustGetDocument(doc); + const doc = util.getDocument({}); + const mirrorDoc = docMirror.getDocument(doc); paredit.addRichComment( mirrorDoc, position ? position : mirrorDoc.selection.active, @@ -182,7 +182,7 @@ async function clojureDocsLookup( d?: vscode.TextDocument, p?: vscode.Position ): Promise { - const doc = d ? d : util.mustGetDocument({}); + const doc = d ? d : util.getDocument({}); const position = p ? p : util.mustGetActiveTextEditor().selection.active; const symbol = util.getWordAtPosition(doc, position); const ns = namespace.getNamespace(doc); diff --git a/src/debugger/calva-debug.ts b/src/debugger/calva-debug.ts index c7beced36..d74a6680b 100644 --- a/src/debugger/calva-debug.ts +++ b/src/debugger/calva-debug.ts @@ -287,7 +287,7 @@ class CalvaDebugSession extends LoggingDebugSession { new Position(positionLine, positionColumn) ); const tokenCursor = docMirror - .mustGetDocument(document) + .getDocument(document) .getTokenCursor(offset); try { diff --git a/src/doc-mirror/index.ts b/src/doc-mirror/index.ts index 4a6c7f457..2d7753c0b 100644 --- a/src/doc-mirror/index.ts +++ b/src/doc-mirror/index.ts @@ -244,12 +244,12 @@ function processChanges(event: vscode.TextDocumentChangeEvent) { model.lineInputModel.deletedLines.clear(); } -export function getDocument(doc: vscode.TextDocument) { +export function tryToGetDocument(doc: vscode.TextDocument) { return documents.get(doc); } -export function mustGetDocument(doc: vscode.TextDocument) { - const mirrorDoc = documents.get(doc); +export function getDocument(doc: vscode.TextDocument) { + const mirrorDoc = tryToGetDocument(doc); if (isUndefined(mirrorDoc)) { throw new Error('Missing mirror document!'); @@ -262,7 +262,7 @@ export function getDocumentOffset( doc: vscode.TextDocument, position: vscode.Position ) { - const model = mustGetDocument(doc).model; + const model = getDocument(doc).model; return model.getOffsetForLine(position.line) + position.character; } @@ -287,7 +287,7 @@ export function activate() { } registered = true; - addDocument(utilities.getDocument({})); + addDocument(utilities.tryToGetDocument({})); vscode.workspace.onDidCloseTextDocument((e) => { if (e.languageId == 'clojure') { diff --git a/src/edit.ts b/src/edit.ts index 0599a71b1..4a13d2aff 100644 --- a/src/edit.ts +++ b/src/edit.ts @@ -5,11 +5,11 @@ import * as docMirror from './doc-mirror/index'; // Relies on that `when` claus guards this from being called // when the cursor is before the comment marker export function continueCommentCommand() { - const document = util.getDocument({}); + const document = util.tryToGetDocument({}); if (document && document.languageId === 'clojure') { const editor = util.mustGetActiveTextEditor(); const position = editor.selection.active; - const cursor = docMirror.mustGetDocument(document).getTokenCursor(); + const cursor = docMirror.getDocument(document).getTokenCursor(); if (cursor.getToken().type !== 'comment') { if (cursor.getPrevToken().type === 'comment') { cursor.previous(); diff --git a/src/evaluate.ts b/src/evaluate.ts index 94fd6893c..0528ff4b0 100644 --- a/src/evaluate.ts +++ b/src/evaluate.ts @@ -265,7 +265,7 @@ async function evaluateSelection(document = {}, options) { let code = selection[1]; [codeSelection, code]; - const doc = util.mustGetDocument(document); + const doc = util.getDocument(document); const ns = namespace.getNamespace(doc); const line = codeSelection.start.line; const column = codeSelection.start.character; @@ -472,7 +472,7 @@ function evaluateStartOfFileToCursor(document = {}, options = {}) { } async function loadFile(document, pprintOptions: PrettyPrintingOptions) { - const doc = util.getDocument(document); + const doc = util.tryToGetDocument(document); const fileType = util.getFileType(doc); const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); @@ -524,7 +524,7 @@ async function loadFile(document, pprintOptions: PrettyPrintingOptions) { } async function evaluateUser(code: string) { - const fileType = util.getFileType(util.getDocument({})), + const fileType = util.getFileType(util.tryToGetDocument({})), session = replSession.getSession(fileType); if (session) { try { @@ -543,20 +543,20 @@ async function evaluateUser(code: string) { async function requireREPLUtilitiesCommand() { if (util.getConnectedState()) { const chan = state.outputChannel(), - ns = namespace.getDocumentNamespace(util.getDocument({})), + ns = namespace.getDocumentNamespace(util.tryToGetDocument({})), CLJS_FORM = "(use '[cljs.repl :only [apropos dir doc find-doc print-doc pst source]])", CLJ_FORM = '(clojure.core/apply clojure.core/require clojure.main/repl-requires)', sessionType = replSession.getReplSessionTypeFromState(), form = sessionType == 'cljs' ? CLJS_FORM : CLJ_FORM, - fileType = util.getFileType(util.getDocument({})), + fileType = util.getFileType(util.tryToGetDocument({})), session = replSession.getSession(fileType); if (session) { try { await namespace.createNamespaceFromDocumentIfNotExists( - util.getDocument({}) + util.tryToGetDocument({}) ); await session.eval("(in-ns '" + ns + ')', session.client.ns) .value; @@ -580,7 +580,7 @@ async function requireREPLUtilitiesCommand() { async function copyLastResultCommand() { const chan = state.outputChannel(); const session = replSession.getSession( - util.getFileType(util.getDocument({})) + util.getFileType(util.tryToGetDocument({})) ); const value = await session.eval('*1', session.client.ns).value; diff --git a/src/extension-test/integration/suite/extension-test.ts b/src/extension-test/integration/suite/extension-test.ts index dd7fb84ff..c52fe1a0b 100644 --- a/src/extension-test/integration/suite/extension-test.ts +++ b/src/extension-test/integration/suite/extension-test.ts @@ -12,7 +12,7 @@ import * as vscode from 'vscode'; // import * as myExtension from '../extension'; import * as outputWindow from '../../../results-output/results-doc'; import { commands } from 'vscode'; -import { mustGetDocument } from '../../../doc-mirror'; +import { getDocument } from '../../../doc-mirror'; void vscode.window.showInformationMessage('Tests running. Yay!'); @@ -85,7 +85,7 @@ suite('Extension Test Suite', () => { await sleep(500); // wait a little longer for repl output to be done console.log('connected to repl'); - const resultsDoc = mustGetDocument(await outputWindow.openResultsDoc()); + const resultsDoc = getDocument(await outputWindow.openResultsDoc()); // focus the clojure file await vscode.workspace.openTextDocument(testUri).then((doc) => diff --git a/src/highlight/src/extension.ts b/src/highlight/src/extension.ts index ffe5ad24c..6a9b684f3 100755 --- a/src/highlight/src/extension.ts +++ b/src/highlight/src/extension.ts @@ -265,7 +265,7 @@ function updateRainbowBrackets() { } const doc = activeEditor.document, - mirrorDoc = docMirror.mustGetDocument(doc), + mirrorDoc = docMirror.getDocument(doc), rainbow = rainbowTypes.map(() => []), rainbowGuides = rainbowTypes.map(() => []), misplaced = [], @@ -549,7 +549,7 @@ function decorateActiveGuides() { } activeEditor.selections.forEach((selection) => { const doc = activeEditor.document; - const mirrorDoc = docMirror.mustGetDocument(doc); + const mirrorDoc = docMirror.getDocument(doc); const cursor = mirrorDoc.getTokenCursor(doc.offsetAt(selection.start)); const visitedEndPositions = [selection.start]; findActiveGuide: while (cursor.forwardList() && cursor.upList()) { diff --git a/src/lsp/main.ts b/src/lsp/main.ts index 09ba061f5..74b20dee0 100644 --- a/src/lsp/main.ts +++ b/src/lsp/main.ts @@ -300,7 +300,7 @@ function registerLspCommand( )}`; return vscode.commands.registerCommand(vscodeCommand, async () => { const editor = util.mustGetActiveTextEditor(); - const document = util.getDocument(editor.document); + const document = util.tryToGetDocument(editor.document); if (document && document.languageId === 'clojure') { const line = editor.selection.start.line; const column = editor.selection.start.character; diff --git a/src/namespace.ts b/src/namespace.ts index 33e926e50..adec7e909 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -16,7 +16,7 @@ export function getNamespace(doc?: vscode.TextDocument) { if (doc && doc.languageId == 'clojure') { try { const cursor: LispTokenCursor = docMirror - .mustGetDocument(doc) + .getDocument(doc) .getTokenCursor(0); cursor.forwardWhitespace(true); let token: Token = null, @@ -72,7 +72,7 @@ export function getNamespace(doc?: vscode.TextDocument) { export async function createNamespaceFromDocumentIfNotExists(doc) { if (utilities.getConnectedState()) { - const document = utilities.getDocument(doc); + const document = utilities.tryToGetDocument(doc); if (document) { const ns = getNamespace(document); const client = replSession.getSession( @@ -90,7 +90,7 @@ export async function createNamespaceFromDocumentIfNotExists(doc) { } export function getDocumentNamespace(document = {}) { - const doc = utilities.getDocument(document); + const doc = utilities.tryToGetDocument(document); return getNamespace(doc); } diff --git a/src/nrepl/repl-session.ts b/src/nrepl/repl-session.ts index 35eb59b44..6cd54537e 100644 --- a/src/nrepl/repl-session.ts +++ b/src/nrepl/repl-session.ts @@ -1,10 +1,10 @@ import { NReplSession } from '.'; -import { cljsLib, getDocument, getFileType } from '../utilities'; +import { cljsLib, tryToGetDocument, getFileType } from '../utilities'; import * as outputWindow from '../results-output/results-doc'; import { isUndefined } from 'lodash'; function getSession(fileType?: string): NReplSession { - const doc = getDocument({}); + const doc = tryToGetDocument({}); if (isUndefined(fileType)) { fileType = getFileType(doc); @@ -21,7 +21,7 @@ function getSession(fileType?: string): NReplSession { } function getReplSessionType(connected: boolean): string { - const doc = getDocument({}); + const doc = tryToGetDocument({}); const fileType = getFileType(doc); let sessionType: string = null; diff --git a/src/paredit/extension.ts b/src/paredit/extension.ts index 2c7ec9def..a037d994b 100644 --- a/src/paredit/extension.ts +++ b/src/paredit/extension.ts @@ -365,7 +365,7 @@ function wrapPareditCommand(command: PareditCommand) { return () => { try { const textEditor = window.activeTextEditor, - mDoc: EditableDocument = docMirror.mustGetDocument( + mDoc: EditableDocument = docMirror.getDocument( textEditor.document ); if (!enabled || !languages.has(textEditor.document.languageId)) { diff --git a/src/project-root.ts b/src/project-root.ts index 8955feda7..e9e5f8acb 100644 --- a/src/project-root.ts +++ b/src/project-root.ts @@ -4,7 +4,7 @@ import * as util from './utilities'; // TODO - this module has some code common with `state`. We can refactor `state` to use this functions. export function getProjectWsFolder(): vscode.WorkspaceFolder { - const doc = util.getDocument({}); + const doc = util.tryToGetDocument({}); if (doc) { const folder = vscode.workspace.getWorkspaceFolder(doc.uri); if (folder) { @@ -57,7 +57,7 @@ export async function getProjectRootUri(): Promise { 'shadow-cljs.edn', 'deps.edn', ]; - const doc = util.getDocument({}); + const doc = util.tryToGetDocument({}); const workspaceFolder = getProjectWsFolder(); return findProjectRootUri(projectFileNames, doc, workspaceFolder); } diff --git a/src/providers/completion.ts b/src/providers/completion.ts index 896d3c584..4296f151b 100644 --- a/src/providers/completion.ts +++ b/src/providers/completion.ts @@ -49,7 +49,7 @@ export async function provideCompletionItems( toplevel = document.getText(toplevelSelection), toplevelStartOffset = document.offsetAt(toplevelSelection.start), toplevelStartCursor = docMirror - .mustGetDocument(document) + .getDocument(document) .getTokenCursor(toplevelStartOffset + 1), wordRange = document.getWordRangeAtPosition(position), wordStartLocalOffset = diff --git a/src/providers/signature.ts b/src/providers/signature.ts index 22ee10ffc..b868a36fd 100644 --- a/src/providers/signature.ts +++ b/src/providers/signature.ts @@ -75,7 +75,7 @@ export async function provideSignatureHelp( function getCurrentArgsRanges(document: TextDocument, idx: number): Range[] { const cursor: LispTokenCursor = docMirror - .mustGetDocument(document) + .getDocument(document) .getTokenCursor(idx), allRanges = cursor.rowColRangesForSexpsInList('('); @@ -112,7 +112,7 @@ function getActiveSignatureIdx( function getSymbol(document: TextDocument, idx: number): string { const cursor: LispTokenCursor = docMirror - .mustGetDocument(document) + .getDocument(document) .getTokenCursor(idx); return cursor.getFunctionName(); } @@ -123,7 +123,7 @@ function coordsToRange(coords: [[number, number], [number, number]]): Range { function getPreviousRangeIndexAndFunction(document: TextDocument, idx: number) { const peekBehindCursor: LispTokenCursor = docMirror - .mustGetDocument(document) + .getDocument(document) .getTokenCursor(idx); peekBehindCursor.backwardFunction(1); const previousFunction = peekBehindCursor.getFunctionName(0), diff --git a/src/refresh.ts b/src/refresh.ts index 02677c210..dc2853828 100644 --- a/src/refresh.ts +++ b/src/refresh.ts @@ -21,7 +21,7 @@ function report(res, chan: vscode.OutputChannel) { } function refresh(document = {}) { - const doc = util.getDocument(document), + const doc = util.tryToGetDocument(document), client: NReplSession = replSession.getSession(util.getFileType(doc)), chan: vscode.OutputChannel = state.outputChannel(); @@ -36,7 +36,7 @@ function refresh(document = {}) { } function refreshAll(document = {}) { - const doc = util.getDocument(document), + const doc = util.tryToGetDocument(document), client: NReplSession = replSession.getSession(util.getFileType(doc)), chan: vscode.OutputChannel = state.outputChannel(); diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 7a3a41da6..258500058 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -186,7 +186,7 @@ export async function initResultsDoc(): Promise { const document = event.textEditor.document; if (isResultsDoc(document)) { const idx = document.offsetAt(event.selections[0].active); - const mirrorDoc = docMirror.mustGetDocument(document); + const mirrorDoc = docMirror.getDocument(document); const selectionCursor = mirrorDoc.getTokenCursor(idx); selectionCursor.forwardWhitespace(); if (selectionCursor.atEnd()) { @@ -255,7 +255,7 @@ export async function revealDocForCurrentNS(preserveFocus: boolean = true) { export async function setNamespaceFromCurrentFile() { const session = replSession.getSession(); - const ns = namespace.getNamespace(util.getDocument({})); + const ns = namespace.getNamespace(util.tryToGetDocument({})); if (getNs() !== ns) { await session.eval("(in-ns '" + ns + ')', session.client.ns).value; } @@ -265,7 +265,7 @@ export async function setNamespaceFromCurrentFile() { async function appendFormGrabbingSessionAndNS(topLevel: boolean) { const session = replSession.getSession(); - const ns = namespace.getNamespace(util.getDocument({})); + const ns = namespace.getNamespace(util.tryToGetDocument({})); const editor = util.mustGetActiveTextEditor(); const doc = editor.document; const selection = editor.selection; diff --git a/src/select.ts b/src/select.ts index cb182b4fd..ac3cd4abd 100644 --- a/src/select.ts +++ b/src/select.ts @@ -18,7 +18,7 @@ function getFormSelection( topLevel: boolean ): vscode.Selection { const idx = doc.offsetAt(pos); - const cursor = docMirror.mustGetDocument(doc).getTokenCursor(idx); + const cursor = docMirror.getDocument(doc).getTokenCursor(idx); const range = topLevel ? cursor.rangeForDefun(idx) : cursor.rangeForCurrentForm(idx); @@ -32,7 +32,7 @@ function getEnclosingFormSelection( pos: vscode.Position ): vscode.Selection { const idx = doc.offsetAt(pos); - const cursor = docMirror.mustGetDocument(doc).getTokenCursor(idx); + const cursor = docMirror.getDocument(doc).getTokenCursor(idx); if (cursor.backwardList()) { cursor.backwardUpList(); const start = cursor.offsetStart; @@ -53,7 +53,7 @@ function selectForm( toplevel: boolean ) { const editor = util.mustGetActiveTextEditor(), - doc = util.mustGetDocument(document), + doc = util.getDocument(document), selection = editor.selection; if (selection.isEmpty) { diff --git a/src/state.ts b/src/state.ts index 024541d6b..166fca217 100644 --- a/src/state.ts +++ b/src/state.ts @@ -131,7 +131,7 @@ export async function getOrCreateNonProjectRoot( } function getProjectWsFolder(): vscode.WorkspaceFolder { - const doc = util.getDocument({}); + const doc = util.tryToGetDocument({}); if (doc) { const folder = vscode.workspace.getWorkspaceFolder(doc.uri); if (folder) { @@ -169,7 +169,7 @@ export async function initProjectDir(uri?: vscode.Uri): Promise { 'shadow-cljs.edn', 'deps.edn', ]; - const doc = util.getDocument({}); + const doc = util.tryToGetDocument({}); const workspaceFolder = getProjectWsFolder(); await findLocalProjectRoot(projectFileNames, doc, workspaceFolder); await findProjectRootUri(projectFileNames, doc, workspaceFolder); diff --git a/src/statusbar.ts b/src/statusbar.ts index 36072f226..ba331c2e0 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -54,7 +54,7 @@ function update(context = state.extensionContext) { }` ); - const doc = util.getDocument({}), + const doc = util.tryToGetDocument({}), fileType = util.getFileType(doc), cljsBuild = getStateValue('cljsBuild'); diff --git a/src/testRunner.ts b/src/testRunner.ts index 1d772bfc5..49ad061df 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -348,7 +348,7 @@ async function runNamespaceTests( controller: vscode.TestController, document: vscode.TextDocument ) { - const doc = util.getDocument(document); + const doc = util.tryToGetDocument(document); if (outputWindow.isResultsDoc(doc)) { return; } @@ -369,7 +369,7 @@ function getTestUnderCursor() { } async function runTestUnderCursor(controller: vscode.TestController) { - const doc = util.getDocument({}); + const doc = util.tryToGetDocument({}); const session = getSession(util.getFileType(doc)); const ns = namespace.getNamespace(doc); const test = getTestUnderCursor(); diff --git a/src/util/get-text.ts b/src/util/get-text.ts index 258677902..22e3d0b82 100644 --- a/src/util/get-text.ts +++ b/src/util/get-text.ts @@ -46,7 +46,7 @@ export function currentEnclosingFormText( export function currentFunction(doc: vscode.TextDocument): SelectionAndText { if (doc) { - const tokenCursor = docMirror.mustGetDocument(doc).getTokenCursor(); + const tokenCursor = docMirror.getDocument(doc).getTokenCursor(); const [start, end] = tokenCursor.getFunctionSexpRange(); if (start && end) { const startPos = doc.positionAt(start); @@ -67,7 +67,7 @@ function selectionAndText( pos: vscode.Position ): SelectionAndText { if (doc) { - const mirrorDoc = docMirror.mustGetDocument(doc); + const mirrorDoc = docMirror.getDocument(doc); const [range, text] = textGetter(mirrorDoc, doc.offsetAt(pos)); if (range) { return [select.selectionFromOffsetRange(doc, range), text]; @@ -117,7 +117,7 @@ function fromFn( cursorDocFn: (doc: EditableDocument, offset?: number) => [number, number] ): SelectionAndText { if (doc) { - const cursorDoc = docMirror.mustGetDocument(doc); + const cursorDoc = docMirror.getDocument(doc); const range = cursorDocFn(cursorDoc); const selection = select.selectionFromOffsetRange(doc, range); const text = doc.getText(selection); diff --git a/src/utilities.ts b/src/utilities.ts index 8251e9042..e37e5f88b 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -167,7 +167,7 @@ function getWordAtPosition(document, position) { return text; } -function getDocument( +function tryToGetDocument( document: vscode.TextDocument | Record ): vscode.TextDocument | undefined { const activeTextEditor = getActiveTextEditor(); @@ -189,10 +189,10 @@ function getDocument( } } -function mustGetDocument( +function getDocument( document: vscode.TextDocument | Record ): vscode.TextDocument { - const doc = getDocument(document); + const doc = tryToGetDocument(document); if (isUndefined(doc)) { throw new Error('Expected an activeTextEditor with a document!'); @@ -202,7 +202,7 @@ function mustGetDocument( } function getFileType(document) { - const doc = getDocument(document); + const doc = tryToGetDocument(document); if (doc) { return path.extname(doc.fileName).replace(/^\./, ''); @@ -579,8 +579,8 @@ function mustGetActiveTextEditor(): vscode.TextEditor { export { distinct, getWordAtPosition, + tryToGetDocument, getDocument, - mustGetDocument, getFileType, getLaunchingState, setLaunchingState, diff --git a/src/when-contexts.ts b/src/when-contexts.ts index dc41941fc..6652fdf75 100644 --- a/src/when-contexts.ts +++ b/src/when-contexts.ts @@ -28,7 +28,7 @@ function determineCursorContexts( document: vscode.TextDocument, position: vscode.Position ): context.CursorContext[] { - const mirrorDoc = docMirror.mustGetDocument(document); + const mirrorDoc = docMirror.getDocument(document); return context.determineContexts(mirrorDoc, document.offsetAt(position)); } From 28b9b4c91d19965c97a7fddeb69bfa8257b2222c Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 15:50:05 -0600 Subject: [PATCH 06/57] Rename active text editor fetch functions as per @PEZ's request --- src/calva-fmt/src/format.ts | 2 +- .../src/providers/ontype_formatter.ts | 2 +- src/clojuredocs.ts | 2 +- src/connector.ts | 4 +--- src/custom-snippets.ts | 2 +- src/debugger/decorations.ts | 4 ++-- src/doc-mirror/index.ts | 18 +++++++++--------- src/edit.ts | 2 +- src/evaluate.ts | 4 ++-- src/file-switcher/file-switcher.ts | 4 ++-- src/highlight/src/extension.ts | 8 ++++---- src/lsp/main.ts | 6 +++--- src/providers/annotations.ts | 5 +++-- src/providers/hover.ts | 2 +- src/results-output/repl-history.ts | 4 ++-- src/results-output/results-doc.ts | 4 ++-- src/select.ts | 2 +- src/testRunner.ts | 15 +++++++-------- src/utilities.ts | 14 +++++++------- src/when-contexts.ts | 2 +- 20 files changed, 52 insertions(+), 54 deletions(-) diff --git a/src/calva-fmt/src/format.ts b/src/calva-fmt/src/format.ts index e45e050d2..bad7f4c3f 100644 --- a/src/calva-fmt/src/format.ts +++ b/src/calva-fmt/src/format.ts @@ -21,7 +21,7 @@ export async function indentPosition( position: vscode.Position, document: vscode.TextDocument ) { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const pos = new vscode.Position(position.line, 0); const indent = getIndent( getDocument(document).model.lineInputModel, diff --git a/src/calva-fmt/src/providers/ontype_formatter.ts b/src/calva-fmt/src/providers/ontype_formatter.ts index 271e29372..c9e65d214 100644 --- a/src/calva-fmt/src/providers/ontype_formatter.ts +++ b/src/calva-fmt/src/providers/ontype_formatter.ts @@ -37,7 +37,7 @@ export class FormatOnTypeEditProvider return null; } } - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const pos = editor.selection.active; if ( diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 668098674..cd397fb02 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -183,7 +183,7 @@ async function clojureDocsLookup( p?: vscode.Position ): Promise { const doc = d ? d : util.getDocument({}); - const position = p ? p : util.mustGetActiveTextEditor().selection.active; + const position = p ? p : util.getActiveTextEditor().selection.active; const symbol = util.getWordAtPosition(doc, position); const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); diff --git a/src/connector.ts b/src/connector.ts index ff8fd40e8..83ec36c2e 100644 --- a/src/connector.ts +++ b/src/connector.ts @@ -836,9 +836,7 @@ export default { } setStateValue('cljc', newSession); if ( - outputWindow.isResultsDoc( - util.mustGetActiveTextEditor().document - ) + outputWindow.isResultsDoc(util.getActiveTextEditor().document) ) { outputWindow.setSession(newSession, undefined); replSession.updateReplSessionType(); diff --git a/src/custom-snippets.ts b/src/custom-snippets.ts index 62fc47469..7af83d708 100644 --- a/src/custom-snippets.ts +++ b/src/custom-snippets.ts @@ -15,7 +15,7 @@ async function evaluateCustomCodeSnippetCommand(codeOrKey?: string) { } async function evaluateCodeOrKey(codeOrKey?: string) { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const currentLine = editor.selection.active.line; const currentColumn = editor.selection.active.character; const currentFilename = editor.document.fileName; diff --git a/src/debugger/decorations.ts b/src/debugger/decorations.ts index e1cc7f057..7f6fee061 100644 --- a/src/debugger/decorations.ts +++ b/src/debugger/decorations.ts @@ -144,7 +144,7 @@ function triggerUpdateAndRenderDecorations() { timeout = undefined; } if (enabled) { - const editor = util.getActiveTextEditor(); + const editor = util.tryToGetActiveTextEditor(); if (editor) { timeout = setTimeout(() => { const cljSession = replSession.getSession('clj'); @@ -166,7 +166,7 @@ function activate() { }); vscode.workspace.onDidChangeTextDocument((event) => { - const activeEditor = util.getActiveTextEditor(); + const activeEditor = util.tryToGetActiveTextEditor(); if ( activeEditor && event.document === activeEditor.document && diff --git a/src/doc-mirror/index.ts b/src/doc-mirror/index.ts index 2d7753c0b..e75877b2e 100644 --- a/src/doc-mirror/index.ts +++ b/src/doc-mirror/index.ts @@ -29,7 +29,7 @@ export class DocumentModel implements EditableModel { modelEdits: ModelEdit[], options: ModelEditOptions ): Thenable { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), undoStopBefore = !!options.undoStopBefore; return editor .edit( @@ -85,7 +85,7 @@ export class DocumentModel implements EditableModel { oldSelection?: [number, number], newSelection?: [number, number] ) { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), document = editor.document; builder.insert(document.positionAt(offset), text); } @@ -98,7 +98,7 @@ export class DocumentModel implements EditableModel { oldSelection?: [number, number], newSelection?: [number, number] ) { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), document = editor.document, range = new vscode.Range( document.positionAt(start), @@ -114,7 +114,7 @@ export class DocumentModel implements EditableModel { oldSelection?: [number, number], newSelection?: [number, number] ) { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), document = editor.document, range = new vscode.Range( document.positionAt(offset), @@ -144,13 +144,13 @@ export class MirroredDocument implements EditableDocument { get selectionLeft(): number { return this.document.offsetAt( - utilities.mustGetActiveTextEditor().selection.anchor + utilities.getActiveTextEditor().selection.anchor ); } get selectionRight(): number { return this.document.offsetAt( - utilities.mustGetActiveTextEditor().selection.active + utilities.getActiveTextEditor().selection.active ); } @@ -172,7 +172,7 @@ export class MirroredDocument implements EditableDocument { } public insertString(text: string) { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), selection = editor.selection, wsEdit = new vscode.WorkspaceEdit(), edit = vscode.TextEdit.insert( @@ -186,7 +186,7 @@ export class MirroredDocument implements EditableDocument { } set selection(selection: ModelEditSelection) { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), document = editor.document, anchor = document.positionAt(selection.anchor), active = document.positionAt(selection.active); @@ -199,7 +199,7 @@ export class MirroredDocument implements EditableDocument { } public getSelectionText() { - const editor = utilities.mustGetActiveTextEditor(), + const editor = utilities.getActiveTextEditor(), selection = editor.selection; return this.document.getText(selection); } diff --git a/src/edit.ts b/src/edit.ts index 4a13d2aff..27ce93b42 100644 --- a/src/edit.ts +++ b/src/edit.ts @@ -7,7 +7,7 @@ import * as docMirror from './doc-mirror/index'; export function continueCommentCommand() { const document = util.tryToGetDocument({}); if (document && document.languageId === 'clojure') { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const position = editor.selection.active; const cursor = docMirror.getDocument(document).getTokenCursor(); if (cursor.getToken().type !== 'comment') { diff --git a/src/evaluate.ts b/src/evaluate.ts index 0528ff4b0..bc2ea0b15 100644 --- a/src/evaluate.ts +++ b/src/evaluate.ts @@ -91,7 +91,7 @@ async function evaluateCode( const filePath = options.filePath; const session: NReplSession = options.session; const ns = options.ns; - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); let result = null; if (code.length > 0) { @@ -258,7 +258,7 @@ async function evaluateSelection(document = {}, options) { ) => [vscode.Selection, string] = options.selectionFn; if (getStateValue('connected')) { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); state.analytics().logEvent('Evaluation', 'selectionFn').send(); const selection = selectionFn(editor); const codeSelection: vscode.Selection = selection[0]; diff --git a/src/file-switcher/file-switcher.ts b/src/file-switcher/file-switcher.ts index 8aa32dbf4..4d3b450b8 100644 --- a/src/file-switcher/file-switcher.ts +++ b/src/file-switcher/file-switcher.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as util from './util'; import * as projectRoot from '../project-root'; -import { mustGetActiveTextEditor } from '../utilities'; +import { getActiveTextEditor } from '../utilities'; function openFile(file) { return vscode.workspace @@ -40,7 +40,7 @@ function askToCreateANewFile(dir, file) { } export async function toggleBetweenImplAndTest() { - const activeFile = mustGetActiveTextEditor(); + const activeFile = getActiveTextEditor(); const openedFilename = activeFile.document.fileName; const projectRootUri = await projectRoot.getProjectRootUri(); diff --git a/src/highlight/src/extension.ts b/src/highlight/src/extension.ts index 6a9b684f3..9d52c2f06 100755 --- a/src/highlight/src/extension.ts +++ b/src/highlight/src/extension.ts @@ -5,7 +5,7 @@ import { isArray } from 'util'; import * as docMirror from '../../doc-mirror/index'; import { Token, validPair } from '../../cursor-doc/clojure-lexer'; import { LispTokenCursor } from '../../cursor-doc/token-cursor'; -import { getActiveTextEditor, mustGetActiveTextEditor } from '../../utilities'; +import { tryToGetActiveTextEditor, getActiveTextEditor } from '../../utilities'; type StackItem = { char: string; @@ -541,7 +541,7 @@ function decorateGuide( function decorateActiveGuides() { const activeGuides = []; - activeEditor = mustGetActiveTextEditor(); + activeEditor = getActiveTextEditor(); if (activeGuidesTypes) { activeGuidesTypes.forEach((type) => activeEditor.setDecorations(type, []) @@ -586,7 +586,7 @@ function decorateActiveGuides() { } export function activate(context: vscode.ExtensionContext) { - activeEditor = mustGetActiveTextEditor(); + activeEditor = getActiveTextEditor(); vscode.window.onDidChangeActiveTextEditor( (editor) => { @@ -602,7 +602,7 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.onDidChangeTextEditorSelection( (event) => { if ( - event.textEditor === getActiveTextEditor() && + event.textEditor === tryToGetActiveTextEditor() && is_clojure(event.textEditor) ) { if (lastHighlightedEditor !== event.textEditor) { diff --git a/src/lsp/main.ts b/src/lsp/main.ts index 74b20dee0..3918a13c7 100644 --- a/src/lsp/main.ts +++ b/src/lsp/main.ts @@ -299,7 +299,7 @@ function registerLspCommand( (m) => m.substring(1).toUpperCase() )}`; return vscode.commands.registerCommand(vscodeCommand, async () => { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const document = util.tryToGetDocument(editor.document); if (document && document.languageId === 'clojure') { const line = editor.selection.start.line; @@ -320,7 +320,7 @@ function registerLspCommand( } async function codeLensReferencesHandler(_, line, character): Promise { - util.mustGetActiveTextEditor().selection = new vscode.Selection( + util.getActiveTextEditor().selection = new vscode.Selection( line - 1, character - 1, line - 1, @@ -332,7 +332,7 @@ async function codeLensReferencesHandler(_, line, character): Promise { } function resolveMacroAsCommandHandler(): void { - const activeTextEditor = util.getActiveTextEditor(); + const activeTextEditor = util.tryToGetActiveTextEditor(); if (activeTextEditor?.document?.languageId === 'clojure') { const documentUri = decodeURIComponent( activeTextEditor.document.uri.toString() diff --git a/src/providers/annotations.ts b/src/providers/annotations.ts index 7b6eda148..40ea0ba25 100644 --- a/src/providers/annotations.ts +++ b/src/providers/annotations.ts @@ -95,7 +95,7 @@ function setSelectionDecorations(editor, ranges, status) { } function clearEvaluationDecorations(editor?: vscode.TextEditor) { - editor = editor || util.getActiveTextEditor(); + editor = editor || util.tryToGetActiveTextEditor(); if (editor) { util.cljsLib.removeStateValue( editor.document.uri + ':resultDecorationRanges' @@ -204,7 +204,8 @@ function decorateSelection( function onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { if (event.contentChanges.length) { - const activeTextEditor: vscode.TextEditor = util.getActiveTextEditor(); + const activeTextEditor: vscode.TextEditor = + util.tryToGetActiveTextEditor(); if (activeTextEditor) { const activeDocument = activeTextEditor.document, changeDocument = event.document; diff --git a/src/providers/hover.ts b/src/providers/hover.ts index 99e8059c3..3de4b41af 100644 --- a/src/providers/hover.ts +++ b/src/providers/hover.ts @@ -34,7 +34,7 @@ export async function provideHover( hovers.push(docsMd, clojureDocsMd); } - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const context = { ns, diff --git a/src/results-output/repl-history.ts b/src/results-output/repl-history.ts index c91962ca5..e4d072d07 100644 --- a/src/results-output/repl-history.ts +++ b/src/results-output/repl-history.ts @@ -117,7 +117,7 @@ function prependNewline(text: string) { } function showPreviousReplHistoryEntry(): void { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const doc = editor.document; const replSessionType = getSessionType(); const history = getHistory(replSessionType); @@ -139,7 +139,7 @@ function showPreviousReplHistoryEntry(): void { } function showNextReplHistoryEntry(): void { - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const doc = editor.document; const replSessionType = getSessionType(); const history = getHistory(replSessionType); diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 258500058..ac65f1d8c 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -219,7 +219,7 @@ export async function initResultsDoc(): Promise { // If the output window is active when initResultsDoc is run, these contexts won't be set properly without the below // until the next time it's focused - const activeTextEditor = util.getActiveTextEditor(); + const activeTextEditor = util.tryToGetActiveTextEditor(); if (activeTextEditor && isResultsDoc(activeTextEditor.document)) { setContextForOutputWindowActive(true); replHistory.setReplHistoryCommandsActiveContext(activeTextEditor); @@ -266,7 +266,7 @@ export async function setNamespaceFromCurrentFile() { async function appendFormGrabbingSessionAndNS(topLevel: boolean) { const session = replSession.getSession(); const ns = namespace.getNamespace(util.tryToGetDocument({})); - const editor = util.mustGetActiveTextEditor(); + const editor = util.getActiveTextEditor(); const doc = editor.document; const selection = editor.selection; let code = ''; diff --git a/src/select.ts b/src/select.ts index ac3cd4abd..9f28f7255 100644 --- a/src/select.ts +++ b/src/select.ts @@ -52,7 +52,7 @@ function selectForm( ) => vscode.Selection, toplevel: boolean ) { - const editor = util.mustGetActiveTextEditor(), + const editor = util.getActiveTextEditor(), doc = util.getDocument(document), selection = editor.selection; diff --git a/src/testRunner.ts b/src/testRunner.ts index 49ad061df..4d6b3e91a 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -359,7 +359,7 @@ async function runNamespaceTests( } function getTestUnderCursor() { - const editor = util.getActiveTextEditor(); + const editor = util.tryToGetActiveTextEditor(); if (editor) { return getText.currentTopLevelFunction( editor?.document, @@ -407,12 +407,11 @@ function runNamespaceTestsCommand(controller: vscode.TestController) { ); return; } - runNamespaceTests( - controller, - util.mustGetActiveTextEditor().document - ).catch((msg) => { - void vscode.window.showWarningMessage(msg); - }); + runNamespaceTests(controller, util.getActiveTextEditor().document).catch( + (msg) => { + void vscode.window.showWarningMessage(msg); + } + ); } async function rerunTests(controller: vscode.TestController, document = {}) { @@ -477,7 +476,7 @@ function initialize(controller: vscode.TestController): void { // The next steps here would be to turn request.exclude and requst.include // into a Cider var-query that can be passed to test-var query directly. const namespaces = util.distinct(runItems.map((ri) => ri[0])); - const doc = util.mustGetActiveTextEditor().document; + const doc = util.getActiveTextEditor().document; runNamespaceTestsImpl(controller, doc, namespaces).catch((msg) => { void vscode.window.showWarningMessage(msg); }); diff --git a/src/utilities.ts b/src/utilities.ts index e37e5f88b..31bb58e73 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -170,7 +170,7 @@ function getWordAtPosition(document, position) { function tryToGetDocument( document: vscode.TextDocument | Record ): vscode.TextDocument | undefined { - const activeTextEditor = getActiveTextEditor(); + const activeTextEditor = tryToGetActiveTextEditor(); if ( document && Object.prototype.hasOwnProperty.call(document, 'fileName') @@ -303,7 +303,7 @@ function markError(error) { } const diagnostic = cljsLib.getStateValue('diagnosticCollection'), - editor = mustGetActiveTextEditor(); + editor = getActiveTextEditor(); //editor.selection = new vscode.Selection(position, position); const line = error.line - 1, @@ -352,7 +352,7 @@ function markWarning(warning) { } const diagnostic = cljsLib.getStateValue('diagnosticCollection'), - editor = mustGetActiveTextEditor(); + editor = getActiveTextEditor(); //editor.selection = new vscode.Selection(position, position); const line = Math.max(0, warning.line - 1), @@ -562,12 +562,12 @@ function distinct(coll: T[]): T[] { return [...new Set(coll)]; } -function getActiveTextEditor(): vscode.TextEditor | undefined { +function tryToGetActiveTextEditor(): vscode.TextEditor | undefined { return vscode.window.activeTextEditor; } -function mustGetActiveTextEditor(): vscode.TextEditor { - const editor = getActiveTextEditor(); +function getActiveTextEditor(): vscode.TextEditor { + const editor = tryToGetActiveTextEditor(); if (isUndefined(editor)) { throw new Error('Expected active text editor!'); @@ -613,6 +613,6 @@ export { cljsLib, randomSlug, isWindows, + tryToGetActiveTextEditor, getActiveTextEditor, - mustGetActiveTextEditor, }; diff --git a/src/when-contexts.ts b/src/when-contexts.ts index 6652fdf75..9f1a6f484 100644 --- a/src/when-contexts.ts +++ b/src/when-contexts.ts @@ -11,7 +11,7 @@ export function setCursorContextIfChanged(editor: vscode.TextEditor) { !editor || !editor.document || editor.document.languageId !== 'clojure' || - editor !== util.getActiveTextEditor() + editor !== util.tryToGetActiveTextEditor() ) { return; } From fb8c92f92735c971c4373165bf2e1a0ae8183a5d Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 15:54:35 -0600 Subject: [PATCH 07/57] Return undefined instead of null for provideOnTypeFormattingEdits --- src/calva-fmt/src/providers/ontype_formatter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/calva-fmt/src/providers/ontype_formatter.ts b/src/calva-fmt/src/providers/ontype_formatter.ts index c9e65d214..52f2924ee 100644 --- a/src/calva-fmt/src/providers/ontype_formatter.ts +++ b/src/calva-fmt/src/providers/ontype_formatter.ts @@ -14,7 +14,7 @@ export class FormatOnTypeEditProvider _position: vscode.Position, ch: string, _options - ): Promise { + ): Promise { let keyMap = vscode.workspace .getConfiguration() .get('calva.paredit.defaultKeyMap'); @@ -27,14 +27,14 @@ export class FormatOnTypeEditProvider const mDoc: EditableDocument = docMirror.getDocument(document); const tokenCursor = mDoc.getTokenCursor(); if (tokenCursor.withinComment()) { - return null; + return undefined; } return paredit.backspace(mDoc).then((fulfilled) => { paredit.close(mDoc, ch); - return null; + return undefined; }); } else { - return null; + return undefined; } } const editor = util.getActiveTextEditor(); From 695222166ba032ac66973d596706c4d2f3ceb543 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 16:13:06 -0600 Subject: [PATCH 08/57] Fix some return types that can return undefined --- src/analytics.ts | 2 +- src/calva-fmt/src/format.ts | 4 ++-- src/calva-fmt/src/providers/ontype_formatter.ts | 2 +- src/clojuredocs.ts | 8 ++++---- src/connector.ts | 10 ++++++---- src/testRunner.ts | 2 +- src/util/string.ts | 4 ++-- src/utilities.ts | 4 +++- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/analytics.ts b/src/analytics.ts index 5ca7b9996..cb29d2ab0 100644 --- a/src/analytics.ts +++ b/src/analytics.ts @@ -45,7 +45,7 @@ export default class Analytics { ); } - private userID(): string { + private userID(): string | undefined { const KEY = 'userLogID'; if (this.store.get(KEY) == undefined) { const newID = uuid.uuid(); diff --git a/src/calva-fmt/src/format.ts b/src/calva-fmt/src/format.ts index bad7f4c3f..b42b69380 100644 --- a/src/calva-fmt/src/format.ts +++ b/src/calva-fmt/src/format.ts @@ -54,7 +54,7 @@ export async function indentPosition( export async function formatRangeEdits( document: vscode.TextDocument, range: vscode.Range -): Promise { +): Promise { const text: string = document.getText(range); const mirroredDoc: MirroredDocument = getDocument(document); const startIndex = document.offsetAt(range.start); @@ -240,7 +240,7 @@ async function _formatRange( allText: string, range: number[], eol: string -): Promise { +): Promise { const d = { 'range-text': rangeText, 'all-text': allText, diff --git a/src/calva-fmt/src/providers/ontype_formatter.ts b/src/calva-fmt/src/providers/ontype_formatter.ts index 52f2924ee..d1e074234 100644 --- a/src/calva-fmt/src/providers/ontype_formatter.ts +++ b/src/calva-fmt/src/providers/ontype_formatter.ts @@ -60,6 +60,6 @@ export class FormatOnTypeEditProvider } } - return null; + return undefined; } } diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index cd397fb02..333a7812a 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -74,10 +74,10 @@ function printTextToRichComment(text: string, position?: number) { export async function getExamplesHover( document: vscode.TextDocument, position: vscode.Position -): Promise { +): Promise { const docs = await clojureDocsLookup(document, position); if (!docs) { - return null; + return undefined; } return getHoverForDocs( docs, @@ -237,7 +237,7 @@ function rawDocs2DocsEntry( docsResult: any, symbol: string, ns: string -): DocsEntry { +): DocsEntry | undefined { const docs = docsResult.clojuredocs; if (docs) { return { @@ -262,6 +262,6 @@ function rawDocs2DocsEntry( }; } else { // console.log(`No results for ${ns}/${symbol} from ${docsResult.fromServer}`); - return null; + return undefined; } } diff --git a/src/connector.ts b/src/connector.ts index 83ec36c2e..5d2d37a4d 100644 --- a/src/connector.ts +++ b/src/connector.ts @@ -238,7 +238,7 @@ type connectFn = ( session: NReplSession, name: string, checkSuccess: checkConnectedFn -) => Promise; +) => Promise; async function evalConnectCode( newCljsSession: NReplSession, @@ -290,7 +290,9 @@ export interface ReplType { let translatedReplType: ReplType; -async function figwheelOrShadowBuilds(cljsTypeName: string): Promise { +async function figwheelOrShadowBuilds( + cljsTypeName: string +): Promise { if (cljsTypeName.includes('Figwheel Main')) { return await getFigwheelMainBuilds(); } else if (cljsTypeName.includes('shadow-cljs')) { @@ -298,7 +300,7 @@ async function figwheelOrShadowBuilds(cljsTypeName: string): Promise { } } -function updateInitCode(build: string, initCode): string { +function updateInitCode(build: string, initCode): string | undefined { if (build && typeof initCode === 'object') { if (['node-repl', 'browser-repl'].includes(build)) { return initCode.repl.replace('%REPL%', build); @@ -308,7 +310,7 @@ function updateInitCode(build: string, initCode): string { } else if (build && typeof initCode === 'string') { return initCode.replace('%BUILD%', `"${build}"`); } - return null; + return undefined; } function createCLJSReplType( diff --git a/src/testRunner.ts b/src/testRunner.ts index 4d6b3e91a..d1cc4acb9 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -200,7 +200,7 @@ async function onTestResults( run.end(); } -function useTestExplorer(): boolean { +function useTestExplorer(): boolean | undefined { return vscode.workspace.getConfiguration('calva').get('useTestExplorer'); } diff --git a/src/util/string.ts b/src/util/string.ts index 2a8ff9bea..c6fbcf2cb 100644 --- a/src/util/string.ts +++ b/src/util/string.ts @@ -27,10 +27,10 @@ function getIndexAfterLastNonWhitespace(text: string): number { function getTextAfterLastOccurrenceOfSubstring( text: string, substring: string -): string { +): string | undefined { const indexOfLastPrompt = text.lastIndexOf(substring); if (indexOfLastPrompt === -1) { - return null; + return undefined; } const indexOfEndOfPrompt = indexOfLastPrompt + substring.length; return text.substring(indexOfEndOfPrompt); diff --git a/src/utilities.ts b/src/utilities.ts index 31bb58e73..cf567c082 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -372,7 +372,9 @@ function markWarning(warning) { diagnostic.set(editor.document.uri, warnings); } -async function promptForUserInputString(prompt: string): Promise { +async function promptForUserInputString( + prompt: string +): Promise { return vscode.window.showInputBox({ prompt: prompt, ignoreFocusOut: true, From eb3d2645b99ce927a28cabf1164aba9c8fd33036 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 16:25:43 -0600 Subject: [PATCH 09/57] Fix the types of various arrays With strict nulls on these arrays mostly become never[] and so we must explicitly set their type. --- src/connector.ts | 4 ++-- src/cursor-doc/model.ts | 2 +- src/highlight/src/extension.ts | 2 +- src/nrepl/cider.ts | 6 +++--- src/nrepl/project-types.ts | 2 +- src/providers/hover.ts | 8 ++++++-- src/results-output/results-doc.ts | 2 +- src/utilities.ts | 5 ++--- 8 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/connector.ts b/src/connector.ts index 5d2d37a4d..2626b1ce2 100644 --- a/src/connector.ts +++ b/src/connector.ts @@ -249,8 +249,8 @@ async function evalConnectCode( errorProcessors: processOutputFn[] = [] ): Promise { const chan = state.connectionLogChannel(); - const err = [], - out = [], + const err: string[] = [], + out: string[] = [], result = newCljsSession.eval(code, 'user', { stdout: (x) => { out.push(util.stripAnsi(x)); diff --git a/src/cursor-doc/model.ts b/src/cursor-doc/model.ts index d4d9da1d1..d5b4b95da 100644 --- a/src/cursor-doc/model.ts +++ b/src/cursor-doc/model.ts @@ -292,7 +292,7 @@ export class LineInputModel implements EditableModel { const st = this.getRowCol(Math.min(start, end)); const en = this.getRowCol(Math.max(start, end)); - const lines = []; + const lines: string[] = []; if (st[0] == en[0]) { lines[0] = this.lines[st[0]].text.substring(st[1], en[1]); } else { diff --git a/src/highlight/src/extension.ts b/src/highlight/src/extension.ts index 9d52c2f06..0171bf6a8 100755 --- a/src/highlight/src/extension.ts +++ b/src/highlight/src/extension.ts @@ -498,7 +498,7 @@ function matchPairs() { return; } - const matches = []; + const matches: { range: vscode.Range }[] = []; activeEditor.selections.forEach((selection) => { const match_before = matchBefore(selection), match_after = matchAfter(selection); diff --git a/src/nrepl/cider.ts b/src/nrepl/cider.ts index dfa0d0dc2..aed44c6c4 100644 --- a/src/nrepl/cider.ts +++ b/src/nrepl/cider.ts @@ -64,7 +64,7 @@ function stripTrailingNewlines(s: string): string { } function resultMessage(resultItem: Readonly): string { - const msg = []; + const msg: string[] = []; if (resultItem.context && resultItem.context !== 'false') { msg.push(resultItem.context); } @@ -89,7 +89,7 @@ export function cleanUpWhiteSpace(result: TestResult) { // ; 6 tests finished, all passing 👍, ns: 1, vars: 2 // ; 6 tests finished, problems found. 😭 errors: 0, failures: 1, ns: 1, vars: 2 export function summaryMessage(summary: Readonly): string { - const msg = []; + const msg: string[] = []; if (summary.test > 0) { msg.push(summary.test + ' tests finished'); @@ -156,7 +156,7 @@ export function lineInformation(result: TestResult): string { // The message contains "comment" lines that are prepended with ; // and "data" lines that should be printed verbatim into the REPL. export function detailedMessage(result: TestResult): string { - const messages = []; + const messages: string[] = []; const message = resultMessage(result); const location = lineInformation(result); diff --git a/src/nrepl/project-types.ts b/src/nrepl/project-types.ts index 61509182b..bd9f37623 100644 --- a/src/nrepl/project-types.ts +++ b/src/nrepl/project-types.ts @@ -542,7 +542,7 @@ async function cljCommandLine( ? menuSelections.cljAliases : undefined; let aliases: string[] = []; - const aliasesWithMain = []; + const aliasesWithMain: string[] = []; if (launchAliases) { aliases = launchAliases.map(keywordize); } else { diff --git a/src/providers/hover.ts b/src/providers/hover.ts index 3de4b41af..7d3ad38f1 100644 --- a/src/providers/hover.ts +++ b/src/providers/hover.ts @@ -21,7 +21,7 @@ export async function provideHover( await namespace.createNamespaceFromDocumentIfNotExists(document); const res = await client.info(ns, text); const customREPLHoverSnippets = getConfig().customREPLHoverSnippets; - const hovers = []; + const hovers: vscode.MarkdownString[] = []; if ( !res.status.includes('error') && !res.status.includes('no-info') @@ -32,7 +32,11 @@ export async function provideHover( position ); - hovers.push(docsMd, clojureDocsMd); + hovers.push(docsMd); + + if (clojureDocsMd) { + hovers.push(clojureDocsMd); + } } const editor = util.getActiveTextEditor(); diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index ac65f1d8c..4ff0d739f 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -301,7 +301,7 @@ let scrollToBottomSub: vscode.Disposable; export interface OnAppendedCallback { (insertLocation: vscode.Location, newPosition?: vscode.Location): any; } -let editQueue: [string, OnAppendedCallback][] = []; +let editQueue: [string, OnAppendedCallback | undefined][] = []; let applyingEdit = false; /* Because this function can be called several times asynchronously by the handling of incoming nrepl messages, we should never await it, because that await could possibly not return until way later, after edits that came in from elsewhere diff --git a/src/utilities.ts b/src/utilities.ts index cf567c082..5a0225d5a 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -395,8 +395,7 @@ function filterVisibleRanges( r.contains(visibleRange) ); }); - filtered = [].concat( - filtered, + filtered = filtered.concat( combine ? [ new vscode.Range( @@ -466,7 +465,7 @@ async function getJarContents(uri: vscode.Uri | string) { } function sortByPresetOrder(arr: any[], presetOrder: any[]) { - const result = []; + const result: any[] = []; presetOrder.forEach((preset) => { if (arr.indexOf(preset) != -1) { result.push(preset); From 4ff30c66461500d057f21e54b309665fda135ba4 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 6 Mar 2022 16:27:15 -0600 Subject: [PATCH 10/57] Update a return type in cider --- src/nrepl/cider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nrepl/cider.ts b/src/nrepl/cider.ts index aed44c6c4..86df59f62 100644 --- a/src/nrepl/cider.ts +++ b/src/nrepl/cider.ts @@ -155,7 +155,7 @@ export function lineInformation(result: TestResult): string { // If the test passed, return the empty string. // The message contains "comment" lines that are prepended with ; // and "data" lines that should be printed verbatim into the REPL. -export function detailedMessage(result: TestResult): string { +export function detailedMessage(result: TestResult): string | undefined { const messages: string[] = []; const message = resultMessage(result); const location = lineInformation(result); @@ -183,7 +183,7 @@ export function detailedMessage(result: TestResult): string { messages.push(`; actual:\n${result.actual}`); } } - return messages.length > 0 ? messages.join('\n') : null; + return messages.length > 0 ? messages.join('\n') : undefined; } // Return a short message that can be shown to user as a Diagnostic. From 49f760a77d098ea60d2dcd9448a7ac09b40b099e Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Mon, 7 Mar 2022 13:19:43 -0600 Subject: [PATCH 11/57] Fix some return types and the variables they are assigned to --- src/nrepl/repl-session.ts | 4 ++-- src/nrepl/repl-start.ts | 2 +- src/printer.ts | 2 +- src/project-root.ts | 6 +++--- src/providers/annotations.ts | 8 +++++--- src/providers/completion.ts | 2 +- src/providers/infoparser.ts | 24 ++++++++++++++---------- src/providers/signature.ts | 8 ++++---- src/results-output/results-doc.ts | 7 +++---- src/select.ts | 4 ++-- src/state.ts | 18 +++++++++--------- src/statusbar.ts | 2 +- src/testRunner.ts | 2 +- 13 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/nrepl/repl-session.ts b/src/nrepl/repl-session.ts index 6cd54537e..2deccddc3 100644 --- a/src/nrepl/repl-session.ts +++ b/src/nrepl/repl-session.ts @@ -20,10 +20,10 @@ function getSession(fileType?: string): NReplSession { } } -function getReplSessionType(connected: boolean): string { +function getReplSessionType(connected: boolean): string | undefined { const doc = tryToGetDocument({}); const fileType = getFileType(doc); - let sessionType: string = null; + let sessionType: string | undefined = undefined; if (connected) { if (outputWindow.isResultsDoc(doc)) { diff --git a/src/nrepl/repl-start.ts b/src/nrepl/repl-start.ts index 9efffacc9..812960010 100644 --- a/src/nrepl/repl-start.ts +++ b/src/nrepl/repl-start.ts @@ -107,7 +107,7 @@ async function openStoredDoc( storageUri: vscode.Uri, tempDirUri: vscode.Uri, dramFile: DramFile -): Promise<[vscode.TextDocument, vscode.TextEditor]> { +): Promise<[vscode.TextDocument, vscode.TextEditor] | undefined> { const sourceUri = vscode.Uri.file( path.join(storageUri.fsPath, dramFile.path) ); diff --git a/src/printer.ts b/src/printer.ts index e75ef4c47..a36789066 100644 --- a/src/printer.ts +++ b/src/printer.ts @@ -107,7 +107,7 @@ export function getServerSidePrinter(pprintOptions: PrettyPrintingOptions) { } } -export function prettyPrintingOptions(): PrettyPrintingOptions { +export function prettyPrintingOptions(): PrettyPrintingOptions | undefined { return getConfig().prettyPrintingOptions; } diff --git a/src/project-root.ts b/src/project-root.ts index e9e5f8acb..ccd19e8a4 100644 --- a/src/project-root.ts +++ b/src/project-root.ts @@ -3,7 +3,7 @@ import * as util from './utilities'; // TODO - this module has some code common with `state`. We can refactor `state` to use this functions. -export function getProjectWsFolder(): vscode.WorkspaceFolder { +export function getProjectWsFolder(): vscode.WorkspaceFolder | undefined { const doc = util.tryToGetDocument({}); if (doc) { const folder = vscode.workspace.getWorkspaceFolder(doc.uri); @@ -24,10 +24,10 @@ export async function findProjectRootUri( projectFileNames: string[], doc: vscode.TextDocument | undefined, workspaceFolder: vscode.WorkspaceFolder -): Promise { +): Promise { let searchUri = doc?.uri || workspaceFolder?.uri; if (searchUri && !(searchUri.scheme === 'untitled')) { - let prev: vscode.Uri; + let prev: vscode.Uri | undefined = undefined; while (searchUri != prev) { try { for (const projectFile of projectFileNames) { diff --git a/src/providers/annotations.ts b/src/providers/annotations.ts index 40ea0ba25..b0db35a48 100644 --- a/src/providers/annotations.ts +++ b/src/providers/annotations.ts @@ -29,7 +29,7 @@ const evalResultsDecorationType = vscode.window.createTextEditorDecorationType({ let resultsLocations: [vscode.Range, vscode.Position, vscode.Location][] = []; -function getResultsLocation(pos: vscode.Position): vscode.Location { +function getResultsLocation(pos: vscode.Position): vscode.Location | undefined { for (const [range, _evaluatePosition, location] of resultsLocations) { if (range.contains(pos)) { return location; @@ -37,7 +37,9 @@ function getResultsLocation(pos: vscode.Position): vscode.Location { } } -function getEvaluationPosition(pos: vscode.Position): vscode.Position { +function getEvaluationPosition( + pos: vscode.Position +): vscode.Position | undefined { for (const [range, evaluatePosition, _location] of resultsLocations) { if (range.contains(pos)) { return evaluatePosition; @@ -204,7 +206,7 @@ function decorateSelection( function onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { if (event.contentChanges.length) { - const activeTextEditor: vscode.TextEditor = + const activeTextEditor: vscode.TextEditor | undefined = util.tryToGetActiveTextEditor(); if (activeTextEditor) { const activeDocument = activeTextEditor.document, diff --git a/src/providers/completion.ts b/src/providers/completion.ts index 4296f151b..7ace28887 100644 --- a/src/providers/completion.ts +++ b/src/providers/completion.ts @@ -67,7 +67,7 @@ export async function provideCompletionItems( res = await client.complete( ns, text, - toplevelIsValidForm ? context : null + toplevelIsValidForm ? context : undefined ), results = res.completions || []; diff --git a/src/providers/infoparser.ts b/src/providers/infoparser.ts index cbe4d49d5..7caabf247 100644 --- a/src/providers/infoparser.ts +++ b/src/providers/infoparser.ts @@ -7,13 +7,13 @@ import * as tokenCursor from '../cursor-doc/token-cursor'; import { getConfig } from '../config'; export class REPLInfoParser { - private _name: string = undefined; + private _name: string | undefined = undefined; - private _arglist: string = undefined; + private _arglist: string | undefined = undefined; - private _formsString: string = undefined; + private _formsString: string | undefined = undefined; - private _docString: string = undefined; + private _docString: string | undefined = undefined; private _specialForm: boolean = false; @@ -55,7 +55,7 @@ export class REPLInfoParser { private getParameters( symbol: string, argList: string - ): ParameterInformation[] { + ): ParameterInformation[] | undefined { const offsets = this.getParameterOffsets(symbol, argList); if (offsets !== undefined) { return offsets.map((o) => { @@ -67,7 +67,7 @@ export class REPLInfoParser { private getParameterOffsets( symbol: string, argList: string - ): [number, number][] { + ): [number, number][] | undefined { const cursor: tokenCursor.LispTokenCursor = tokenCursor.createStringCursor(argList); if (cursor.downList()) { @@ -144,7 +144,9 @@ export class REPLInfoParser { return result; } - getCompletion(): [string | MarkdownString, string] { + getCompletion(): + | [string | MarkdownString, string] + | [undefined, undefined] { const name = new MarkdownString(this._docString); if (this._name !== '') { if (this._specialForm) { @@ -156,7 +158,7 @@ export class REPLInfoParser { return [undefined, undefined]; } - getSignatures(symbol: string): SignatureInformation[] { + getSignatures(symbol: string): SignatureInformation[] | undefined { if (this._name !== '') { const argLists = this._arglist ? this._arglist : this._formsString; if (argLists) { @@ -202,13 +204,15 @@ export function getHoverNotAvailable(text: string): string { return new REPLInfoParser({ name: text }).getHoverNotAvailable(); } -export function getCompletion(msg: any): [string | MarkdownString, string] { +export function getCompletion( + msg: any +): [string | MarkdownString, string] | [undefined, undefined] { return new REPLInfoParser(msg).getCompletion(); } export function getSignatures( msg: any, symbol: string -): SignatureInformation[] { +): SignatureInformation[] | undefined { return new REPLInfoParser(msg).getSignatures(symbol); } diff --git a/src/providers/signature.ts b/src/providers/signature.ts index b868a36fd..0ef95ecb7 100644 --- a/src/providers/signature.ts +++ b/src/providers/signature.ts @@ -19,7 +19,7 @@ export class CalvaSignatureHelpProvider implements SignatureHelpProvider { document: TextDocument, position: Position, token: CancellationToken - ): Promise { + ): Promise { return provideSignatureHelp(document, position, token); } } @@ -28,7 +28,7 @@ export async function provideSignatureHelp( document: TextDocument, position: Position, _token: CancellationToken -): Promise { +): Promise { if (util.getConnectedState()) { const ns = namespace.getNamespace(document), idx = document.offsetAt(position), @@ -70,7 +70,7 @@ export async function provideSignatureHelp( } } } - return null; + return undefined; } function getCurrentArgsRanges(document: TextDocument, idx: number): Range[] { @@ -86,7 +86,7 @@ function getCurrentArgsRanges(document: TextDocument, idx: number): Range[] { (previousRangeIndex > 1 && ['->', 'some->'].includes(previousFunction)) || (previousRangeIndex > 1 && - previousRangeIndex % 2 && + previousRangeIndex % 2 !== 0 && previousFunction === 'cond->'); if (allRanges !== undefined) { diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 4ff0d739f..ef57d0292 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -107,9 +107,8 @@ export function isResultsDoc(doc?: vscode.TextDocument): boolean { } function getViewColumn(): vscode.ViewColumn { - const column: vscode.ViewColumn = state.extensionContext.workspaceState.get( - `outputWindowViewColumn` - ); + const column: vscode.ViewColumn | undefined = + state.extensionContext.workspaceState.get(`outputWindowViewColumn`); return column ? column : vscode.ViewColumn.Two; } @@ -339,7 +338,7 @@ export function append(text: string, onAppended?: OnAppendedCallback): void { if (visibleResultsEditors.length == 0) { scrollToBottomSub = vscode.window.onDidChangeActiveTextEditor((editor) => { - if (isResultsDoc(editor.document)) { + if (editor && isResultsDoc(editor.document)) { util.scrollToBottom(editor); scrollToBottomSub.dispose(); } diff --git a/src/select.ts b/src/select.ts index 9f28f7255..0fe9333f9 100644 --- a/src/select.ts +++ b/src/select.ts @@ -16,7 +16,7 @@ function getFormSelection( doc: vscode.TextDocument, pos: vscode.Position, topLevel: boolean -): vscode.Selection { +): vscode.Selection | undefined { const idx = doc.offsetAt(pos); const cursor = docMirror.getDocument(doc).getTokenCursor(idx); const range = topLevel @@ -30,7 +30,7 @@ function getFormSelection( function getEnclosingFormSelection( doc: vscode.TextDocument, pos: vscode.Position -): vscode.Selection { +): vscode.Selection | undefined { const idx = doc.offsetAt(pos); const cursor = docMirror.getDocument(doc).getTokenCursor(idx); if (cursor.backwardList()) { diff --git a/src/state.ts b/src/state.ts index 166fca217..3fa7da6c7 100644 --- a/src/state.ts +++ b/src/state.ts @@ -46,7 +46,7 @@ const PROJECT_DIR_KEY = 'connect.projectDir'; const PROJECT_DIR_URI_KEY = 'connect.projectDirNew'; const PROJECT_CONFIG_MAP = 'config'; -export function getProjectRootLocal(useCache = true): string { +export function getProjectRootLocal(useCache = true): string | undefined { if (useCache) { return getStateValue(PROJECT_DIR_KEY); } @@ -62,7 +62,7 @@ export function setProjectConfig(config) { return setStateValue(PROJECT_CONFIG_MAP, config); } -export function getProjectRootUri(useCache = true): vscode.Uri { +export function getProjectRootUri(useCache = true): vscode.Uri | undefined { if (useCache) { return getStateValue(PROJECT_DIR_URI_KEY); } @@ -72,8 +72,8 @@ const NON_PROJECT_DIR_KEY = 'calva.connect.nonProjectDir'; export async function getNonProjectRootDir( context: vscode.ExtensionContext -): Promise { - let root: vscode.Uri; +): Promise { + let root: vscode.Uri | undefined = undefined; if (!process.env['NEW_DRAMS']) { root = await context.globalState.get>( NON_PROJECT_DIR_KEY @@ -108,7 +108,7 @@ export async function getOrCreateNonProjectRoot( context: vscode.ExtensionContext, preferProjectDir = false ): Promise { - let root: vscode.Uri; + let root: vscode.Uri | undefined = undefined; if (preferProjectDir) { root = getProjectRootUri(); } @@ -130,7 +130,7 @@ export async function getOrCreateNonProjectRoot( return root; } -function getProjectWsFolder(): vscode.WorkspaceFolder { +function getProjectWsFolder(): vscode.WorkspaceFolder | undefined { const doc = util.tryToGetDocument({}); if (doc) { const folder = vscode.workspace.getWorkspaceFolder(doc.uri); @@ -180,14 +180,14 @@ function findLocalProjectRoot( projectFileNames, doc, workspaceFolder -): Promise { +): undefined { if (workspaceFolder) { let rootPath: string = path.resolve(workspaceFolder.uri.fsPath); setStateValue(PROJECT_DIR_KEY, rootPath); setStateValue(PROJECT_DIR_URI_KEY, workspaceFolder.uri); - let d = null; - let prev = null; + let d: any; + let prev: any; if (doc && path.dirname(doc.uri.fsPath) !== '.') { d = path.dirname(doc.uri.fsPath); } else { diff --git a/src/statusbar.ts b/src/statusbar.ts index ba331c2e0..2cb1f8533 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -81,7 +81,7 @@ function update(context = state.extensionContext) { cljsBuildStatus.text = null; cljsBuildStatus.command = 'calva.switchCljsBuild'; - cljsBuildStatus.tooltip = null; + cljsBuildStatus.tooltip = undefined; if (getStateValue('connected')) { connectionStatus.text = 'REPL $(zap)'; diff --git a/src/testRunner.ts b/src/testRunner.ts index d1cc4acb9..b73445bbe 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -78,7 +78,7 @@ export function assertionName(result: cider.TestResult): string { function existingUriForNameSpace( controller: vscode.TestController, nsName: string -): vscode.Uri | null { +): vscode.Uri | undefined { return controller.items.get(nsName)?.uri; } From ab0ca8770d9a7ec210be658d59cf5376c1a2596f Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Mon, 7 Mar 2022 13:20:35 -0600 Subject: [PATCH 12/57] Make certain arguments optional that are actually so --- src/printer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/printer.ts b/src/printer.ts index a36789066..96792d981 100644 --- a/src/printer.ts +++ b/src/printer.ts @@ -11,7 +11,7 @@ export type PrettyPrintingOptions = { enabled: boolean; printFn?: PrintFnOptions; printEngine?: 'calva' | 'pprint' | 'fipp' | 'puget' | 'zprint' | 'custom'; - width: number; + width?: number; maxLength?: number; maxDepth?: number; }; @@ -27,9 +27,9 @@ export const disabledPrettyPrinter: PrettyPrintingOptions = { function getPrinter( pprintOptions: PrettyPrintingOptions, printerFn: string, - widthSlug: string, - lengthSlug: string, - depthsSlug: string, + widthSlug?: string, + lengthSlug?: string, + depthsSlug?: string, moreOptions = {} ) { const PRINTER_FN = 'nrepl.middleware.print/print', From ba04613ca0c794002f2b5c16607d583c46d7ff88 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Mon, 7 Mar 2022 13:22:14 -0600 Subject: [PATCH 13/57] Fix unit tests for new return values --- src/extension-test/unit/test-runner-test.ts | 2 +- src/extension-test/unit/util/string-test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extension-test/unit/test-runner-test.ts b/src/extension-test/unit/test-runner-test.ts index 76059af0f..3454ff176 100644 --- a/src/extension-test/unit/test-runner-test.ts +++ b/src/extension-test/unit/test-runner-test.ts @@ -123,7 +123,7 @@ describe('test result processing', () => { var: 'test', message: '', }) - ).toBe(null); + ).toBeUndefined(); expect( cider.detailedMessage({ diff --git a/src/extension-test/unit/util/string-test.ts b/src/extension-test/unit/util/string-test.ts index 7e4008345..70f4ef7c4 100644 --- a/src/extension-test/unit/util/string-test.ts +++ b/src/extension-test/unit/util/string-test.ts @@ -41,8 +41,8 @@ describe('string', () => { }); describe('getTextAfterLastOccurrenceOfSubstring', () => { - it('returns null if substring does not exist', () => { - expect(null).toBe( + it('returns undefined if substring does not exist', () => { + expect(undefined).toBe( getTextAfterLastOccurrenceOfSubstring('hello world', '123') ); }); From e60870c038b415186f8edf33a40e7b254268c4bc Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Mon, 7 Mar 2022 13:25:57 -0600 Subject: [PATCH 14/57] Fix linter error --- src/state.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state.ts b/src/state.ts index 3fa7da6c7..9a9e06014 100644 --- a/src/state.ts +++ b/src/state.ts @@ -171,7 +171,7 @@ export async function initProjectDir(uri?: vscode.Uri): Promise { ]; const doc = util.tryToGetDocument({}); const workspaceFolder = getProjectWsFolder(); - await findLocalProjectRoot(projectFileNames, doc, workspaceFolder); + findLocalProjectRoot(projectFileNames, doc, workspaceFolder); await findProjectRootUri(projectFileNames, doc, workspaceFolder); } } From 87bc6b117697f543297850faec5cbe585f9ef79a Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Mon, 7 Mar 2022 13:28:07 -0600 Subject: [PATCH 15/57] Add an entry in the CHANGELOG for PR #1581 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c1f7de00..f7af355dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Changes to Calva. - Fix: [Structural editing hangs in specific cases of unbalanced forms](https://github.com/BetterThanTomorrow/calva/pull/1585) - Fix: [Hover snippet markdown and adds example](https://github.com/BetterThanTomorrow/calva/pull/1582) - Maintenance: [Begin work on enabling strictNullChecks in the TypeScript config.](https://github.com/BetterThanTomorrow/calva/pull/1568) +- Maintenance: [Update more TypeScript code to be compatible with strictNullChecks.](https://github.com/BetterThanTomorrow/calva/pull/1581) ## [2.0.252] - 2022-03-05 - Fix: [Tab doesn't work in snippet mode](https://github.com/BetterThanTomorrow/calva/pull/1580) From e462a623427bc06088acc8208b6e73485bda91b3 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 16:29:09 -0600 Subject: [PATCH 16/57] Apparently this confuses older typescript versions? --- src/util/get-text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/get-text.ts b/src/util/get-text.ts index 22e3d0b82..9205aba49 100644 --- a/src/util/get-text.ts +++ b/src/util/get-text.ts @@ -5,7 +5,7 @@ import * as docMirror from '../doc-mirror/index'; import * as cursorTextGetter from './cursor-get-text'; import { EditableDocument } from '../cursor-doc/model'; -export type SelectionAndText = [vscode.Selection, string] | [undefined, '']; +export type SelectionAndText = [vscode.Selection | undefined, string]; function _currentFormText( doc: vscode.TextDocument, From f44a2e5ff440d09e5d44e719eb1963a127551922 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 16:29:42 -0600 Subject: [PATCH 17/57] Add an assertIsDefined function --- src/utilities.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/utilities.ts b/src/utilities.ts index 5a0225d5a..625b4b85c 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -10,6 +10,7 @@ import * as outputWindow from './results-output/results-doc'; import * as cljsLib from '../out/cljs-lib/cljs-lib'; import * as url from 'url'; import { isUndefined } from 'lodash'; +import { isNullOrUndefined } from 'util'; const specialWords = ['-', '+', '/', '*']; //TODO: Add more here const syntaxQuoteSymbol = '`'; @@ -22,6 +23,17 @@ export function stripAnsi(str: string) { ); } +// This needs to be a function and not an arrow function +// because assertion types are special. +export function assertIsDefined( + value: T | undefined | null, + message: string | (() => string) +): asserts value is T { + if (isNullOrUndefined(value)) { + throw new Error(typeof message === 'string' ? message : message()); + } +} + export function escapeStringRegexp(s: string): string { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } From db3d72c1279f5bce04d6d466b844cbc20cad9cc8 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 16:29:59 -0600 Subject: [PATCH 18/57] Use assertions in the calling code for test runner results --- src/testRunner.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/testRunner.ts b/src/testRunner.ts index b73445bbe..9deff6199 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -215,7 +215,20 @@ function reportTests( diagnosticCollection.clear(); const recordDiagnostic = (result: cider.TestResult) => { + const { line, file } = result; + + util.assertIsDefined( + result.line, + 'Expected cider test result to have a line!' + ); + + util.assertIsDefined( + result.file, + 'Expected cider test result to have a file!' + ); + const msg = cider.diagnosticMessage(result); + const err = new vscode.Diagnostic( new vscode.Range(result.line - 1, 0, result.line - 1, 1000), msg, From 0aef19eb484d2131f6e973fd4fb3b5cc7d6e99c9 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 16:51:48 -0600 Subject: [PATCH 19/57] Add/improve cider test result assertions. --- src/nrepl/cider.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/nrepl/cider.ts b/src/nrepl/cider.ts index 86df59f62..baeb2fb26 100644 --- a/src/nrepl/cider.ts +++ b/src/nrepl/cider.ts @@ -214,6 +214,33 @@ export function shortMessage(result: TestResult): string { } } -export function hasLineNumber(result: TestResult): boolean { +type TestResultWithLineNumber = Omit & { + line: NonNullable; +}; + +type TestResultWithFile = Omit & { + file: NonNullable; +}; + +type TestResultWithLineNumberAndFile = Omit & { + line: TestResultWithLineNumber['line']; + file: TestResultWithFile['file']; +}; + +export const hasLineNumber = ( + result: TestResult | TestResultWithLineNumber +): result is TestResultWithLineNumber => { return typeof result.line === 'number'; +}; + +export function hasFile( + result: TestResult | TestResultWithFile +): result is TestResultWithFile { + return typeof result.file === 'string'; } + +export const hasLineNumberAndFile = ( + result: TestResult | TestResultWithLineNumberAndFile +): result is TestResultWithLineNumberAndFile => { + return hasLineNumber(result) && hasFile(result); +}; From e3a312f4d382a207753b20c876769dbd0c335cb0 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 16:55:21 -0600 Subject: [PATCH 20/57] Fix a couple of undefined checks in testRunner --- src/testRunner.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/testRunner.ts b/src/testRunner.ts index 9deff6199..d228c46b9 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -9,6 +9,7 @@ import * as lsp from './lsp/types'; import * as namespace from './namespace'; import { getSession, updateReplSessionType } from './nrepl/repl-session'; import * as getText from './util/get-text'; +import { isUndefined } from 'lodash'; const diagnosticCollection = vscode.languages.createDiagnosticCollection('calva'); @@ -114,13 +115,12 @@ async function onTestResult( .filter(cider.hasLineNumber) .map((a) => a.line) .sort(); - if (lines.length > 0) { - test.range = new vscode.Range( - lines[0] - 1, - 0, - lines[lines.length - 1], - 1000 - ); + + const startOfRange = lines[0]; + const endOfRange = lines[lines.length - 1]; + + if (!isUndefined(startOfRange) && !isUndefined(endOfRange)) { + test.range = new vscode.Range(startOfRange, 0, endOfRange, 1000); } } @@ -215,8 +215,6 @@ function reportTests( diagnosticCollection.clear(); const recordDiagnostic = (result: cider.TestResult) => { - const { line, file } = result; - util.assertIsDefined( result.line, 'Expected cider test result to have a line!' From 8c3cd75fdd5412db1b61d12bf4631decfde0cc68 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 16:55:48 -0600 Subject: [PATCH 21/57] Add an isDefined function, so we don't have to do !isUndefinedOrNull --- src/utilities.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utilities.ts b/src/utilities.ts index 625b4b85c..51739c8f8 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -23,6 +23,10 @@ export function stripAnsi(str: string) { ); } +export const isDefined = (value: T | undefined | null): value is T => { + return !isNullOrUndefined(value); +}; + // This needs to be a function and not an arrow function // because assertion types are special. export function assertIsDefined( From 1f998eb4def4a2e02568b04d9a42c61aeb1d7c09 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:12:15 -0600 Subject: [PATCH 22/57] Fix an undefined when checking if a file is writable --- src/utilities.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/utilities.ts b/src/utilities.ts index 51739c8f8..79709e2ed 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -565,12 +565,18 @@ const isWindows = process.platform === 'win32'; export async function isDocumentWritable( document: vscode.TextDocument -): Promise { +): Promise { if (!vscode.workspace.fs.isWritableFileSystem(document.uri.scheme)) { return false; } const fileStat = await vscode.workspace.fs.stat(document.uri); - return (fileStat.permissions & vscode.FilePermission.Readonly) !== 1; + + return ( + // Try treating it as writable when we can't get the permissions, + // let it error later when we go to use the file. + isUndefined(fileStat.permissions) || + (fileStat.permissions & vscode.FilePermission.Readonly) !== 1 + ); } // Returns the elements of coll with duplicates removed From 6bed3370b57df237f42e0f7f42555e1adefc29b4 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:13:52 -0600 Subject: [PATCH 23/57] Set the defaults to an empty string or undefined as null is incorrect --- src/statusbar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/statusbar.ts b/src/statusbar.ts index 2cb1f8533..131c78c10 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -71,15 +71,15 @@ function update(context = state.extensionContext) { prettyPrintToggle.tooltip = `Turn pretty printing ${pprint ? 'off' : 'on'}`; prettyPrintToggle.command = 'calva.togglePrettyPrint'; - typeStatus.command = null; + typeStatus.command = undefined; typeStatus.text = 'Disconnected'; typeStatus.tooltip = 'No active REPL session'; typeStatus.color = colorValue('disconnectedColor', currentConf); - connectionStatus.command = null; + connectionStatus.command = undefined; connectionStatus.tooltip = 'REPL connection status'; - cljsBuildStatus.text = null; + cljsBuildStatus.text = ''; cljsBuildStatus.command = 'calva.switchCljsBuild'; cljsBuildStatus.tooltip = undefined; From 6f947f228e6fc9461491a05bfca0ba30703b7ad2 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:15:39 -0600 Subject: [PATCH 24/57] When there are no pretty printing options, treat it as disabled --- src/statusbar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/statusbar.ts b/src/statusbar.ts index 131c78c10..a8c4ddde7 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -65,7 +65,7 @@ function update(context = state.extensionContext) { //let disconnectedColor = "rgb(192,192,192)"; - const pprint = config.getConfig().prettyPrintingOptions.enabled; + const pprint = config.getConfig().prettyPrintingOptions?.enabled; prettyPrintToggle.text = 'pprint'; prettyPrintToggle.color = pprint ? undefined : color.inactive; prettyPrintToggle.tooltip = `Turn pretty printing ${pprint ? 'off' : 'on'}`; From ebf598be5d7e5e981e7c55c7c5bead948f1bb654 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:22:14 -0600 Subject: [PATCH 25/57] Make fetching color value more safe --- src/statusbar.ts | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/statusbar.ts b/src/statusbar.ts index a8c4ddde7..4e2df3e20 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -37,12 +37,28 @@ function colorValue( section: string, currentConf: vscode.WorkspaceConfiguration ): string { + const configSection = currentConf.inspect(section); + + util.assertIsDefined( + configSection, + () => `Expected config section "${section}" to be defined!` + ); + const { defaultValue, globalValue, workspaceFolderValue, workspaceValue } = - currentConf.inspect(section); - return (workspaceFolderValue || - workspaceValue || - globalValue || - defaultValue) as string; + configSection; + + const value = + workspaceFolderValue || workspaceValue || globalValue || defaultValue; + + if (typeof value !== 'string') { + throw new Error( + `Expected color value to be a string! We got ${JSON.stringify( + value + )}` + ); + } + + return value; } function update(context = state.extensionContext) { From ce80e01dfb00627cebd7e5668d30a0a00dc7e891 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:23:58 -0600 Subject: [PATCH 26/57] Fixing more return types --- src/select.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/select.ts b/src/select.ts index 0fe9333f9..425039f22 100644 --- a/src/select.ts +++ b/src/select.ts @@ -49,7 +49,7 @@ function selectForm( doc: vscode.TextDocument, pos: vscode.Position, topLevel: boolean - ) => vscode.Selection, + ) => vscode.Selection | undefined, toplevel: boolean ) { const editor = util.getActiveTextEditor(), From 69326a49c3c2e4e47ca0d4e8974401747199402d Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:29:34 -0600 Subject: [PATCH 27/57] We expect and require there to be a project root --- src/results-output/results-doc.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index ef57d0292..33e56184d 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -42,6 +42,7 @@ export const CLJS_CONNECT_GREETINGS = function outputFileDir() { const projectRoot = state.getProjectRootUri(); + util.assertIsDefined(projectRoot, 'Expected there to be a project root!'); try { return vscode.Uri.joinPath(projectRoot, '.calva', 'output-window'); } catch { From b668df2126d32758df0283081c2bd99d3871ac83 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:29:49 -0600 Subject: [PATCH 28/57] Fix return types of these functions --- src/results-output/results-doc.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 33e56184d..9c6b84270 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -79,7 +79,7 @@ export function getPrompt(): string { return prompt; } -export function getNs(): string { +export function getNs(): string | undefined { return _sessionInfo[_sessionType].ns; } @@ -87,7 +87,7 @@ export function getSessionType(): ReplSessionType { return _sessionType; } -export function getSession(): NReplSession { +export function getSession(): NReplSession | undefined { return _sessionInfo[_sessionType].session; } @@ -113,7 +113,7 @@ function getViewColumn(): vscode.ViewColumn { return column ? column : vscode.ViewColumn.Two; } -function setViewColumn(column: vscode.ViewColumn) { +function setViewColumn(column: vscode.ViewColumn | undefined) { return state.extensionContext.workspaceState.update( `outputWindowViewColumn`, column @@ -394,7 +394,7 @@ export function discardPendingPrints(): void { export type OutputStacktraceEntry = { uri: vscode.Uri; line: number }; let _lastStacktrace: any[] = []; -let _lastStackTraceRange: vscode.Range; +let _lastStackTraceRange: vscode.Range | undefined; const _stacktraceEntries = {} as OutputStacktraceEntry; export function getStacktraceEntryForKey(key: string): OutputStacktraceEntry { @@ -435,7 +435,7 @@ export function markLastStacktraceRange(location: vscode.Location): void { _lastStackTraceRange = location.range; //new vscode.Range(newPosition, newPosition); } -export function getLastStackTraceRange(): vscode.Range { +export function getLastStackTraceRange(): vscode.Range | undefined { return _lastStackTraceRange; } From bf9745fd524b3691081c8fe5e23cdd0360f2188b Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:40:27 -0600 Subject: [PATCH 29/57] Fix cases for which ns can be missing --- src/results-output/results-doc.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 9c6b84270..aa9b7931c 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -91,7 +91,7 @@ export function getSession(): NReplSession | undefined { return _sessionInfo[_sessionType].session; } -export function setSession(session: NReplSession, newNs: string): void { +export function setSession(session: NReplSession, newNs?: string): void { if (session) { if (session.replType) { _sessionType = session.replType; @@ -256,7 +256,7 @@ export async function revealDocForCurrentNS(preserveFocus: boolean = true) { export async function setNamespaceFromCurrentFile() { const session = replSession.getSession(); const ns = namespace.getNamespace(util.tryToGetDocument({})); - if (getNs() !== ns) { + if (getNs() !== ns && util.isDefined(ns)) { await session.eval("(in-ns '" + ns + ')', session.client.ns).value; } setSession(session, ns); @@ -452,5 +452,10 @@ export function appendPrompt(onAppended?: OnAppendedCallback) { } function getUriForCurrentNamespace(): Promise { - return namespace.getUriForNamespace(getSession(), getNs()); + const session = getSession(); + const ns = getNs(); + + util.assertIsDefined(session, 'Expected a session to be defined!'); + util.assertIsDefined(ns, 'Expected an ns to be defined!'); + return namespace.getUriForNamespace(session, ns); } From da288fec9927bcf3c1034017c123b2a413bd06bc Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:40:50 -0600 Subject: [PATCH 30/57] Fix types for editQueue --- src/results-output/results-doc.ts | 5 ++++- src/results-output/util.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index aa9b7931c..2e42b87a1 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -377,7 +377,10 @@ export function append(text: string, onAppended?: OnAppendedCallback): void { editQueue = remainingEditQueue; return append(textBatch.join('\n')); } else { - return append(...editQueue.shift()); + // we're sure there's a value in the queue at this point + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const [text, onAppended] = editQueue.shift()!; + return append(text, onAppended); } } }); diff --git a/src/results-output/util.ts b/src/results-output/util.ts index 69b6e63b5..8a0d965db 100644 --- a/src/results-output/util.ts +++ b/src/results-output/util.ts @@ -18,9 +18,9 @@ function formatAsLineComments(error: string): string { } function splitEditQueueForTextBatching( - editQueue: [string, OnAppendedCallback][], + editQueue: [string, OnAppendedCallback | undefined][], maxBatchSize: number = 1000 -): [string[], [string, OnAppendedCallback][]] { +): [string[], [string, OnAppendedCallback | undefined][]] { const textBatch = takeWhile(editQueue, (value, index) => { return index < maxBatchSize && !value[1]; }).map((value) => value[0]); From 1baaed1781f660b10c8243f47bd7054afa3f805a Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:47:55 -0600 Subject: [PATCH 31/57] Assert that output window has a namespace, since it should have one --- src/namespace.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/namespace.ts b/src/namespace.ts index adec7e909..d5ac6eff9 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -10,7 +10,12 @@ import { NReplSession } from './nrepl'; export function getNamespace(doc?: vscode.TextDocument) { if (outputWindow.isResultsDoc(doc)) { - return outputWindow.getNs(); + const outputWindowNs = outputWindow.getNs(); + utilities.assertIsDefined( + outputWindowNs, + 'Expected output window to have a namespace!' + ); + return outputWindowNs; } let ns = 'user'; if (doc && doc.languageId == 'clojure') { From 72c33985d1d7bb1b616e98ce261d7161532cead3 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:48:22 -0600 Subject: [PATCH 32/57] Set token to undefined instead of null --- src/namespace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/namespace.ts b/src/namespace.ts index d5ac6eff9..c813d3b69 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -24,7 +24,7 @@ export function getNamespace(doc?: vscode.TextDocument) { .getDocument(doc) .getTokenCursor(0); cursor.forwardWhitespace(true); - let token: Token = null, + let token: Token | undefined = undefined, foundNsToken: boolean = false, foundNsId: boolean = false; do { From 2ddf9de4b3607f86d54a887636e7949b24604fb8 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Tue, 8 Mar 2022 17:55:10 -0600 Subject: [PATCH 33/57] Handle undefined checks in repl-history --- src/results-output/repl-history.ts | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/results-output/repl-history.ts b/src/results-output/repl-history.ts index e4d072d07..2d7a4db28 100644 --- a/src/results-output/repl-history.ts +++ b/src/results-output/repl-history.ts @@ -8,10 +8,11 @@ import { import type { ReplSessionType } from '../config'; import { isResultsDoc, getSessionType, getPrompt, append } from './results-doc'; import { addToHistory } from './util'; +import { isUndefined } from 'lodash'; const replHistoryCommandsActiveContext = 'calva:replHistoryCommandsActive'; -let historyIndex = null; -let lastTextAtPrompt = null; +let historyIndex: number | undefined = undefined; +let lastTextAtPrompt: string | undefined = undefined; function setReplHistoryCommandsActiveContext(editor: vscode.TextEditor): void { if (editor && util.getConnectedState() && isResultsDoc(editor.document)) { @@ -37,8 +38,8 @@ function setReplHistoryCommandsActiveContext(editor: vscode.TextEditor): void { } function resetState(): void { - historyIndex = null; - lastTextAtPrompt = null; + historyIndex = undefined; + lastTextAtPrompt = undefined; } function getHistoryKey(replSessionType: ReplSessionType): string { @@ -83,7 +84,7 @@ function clearHistory() { } function showReplHistoryEntry( - historyEntry: string, + historyEntry: string | undefined, resultsEditor: vscode.TextEditor ): void { const prompt = getPrompt(); @@ -128,10 +129,14 @@ function showPreviousReplHistoryEntry(): void { doc.getText(), getPrompt() ); - if (historyIndex === null) { + if (isUndefined(historyIndex)) { historyIndex = history.length; lastTextAtPrompt = textAtPrompt; } else { + util.assertIsDefined( + textAtPrompt, + 'Expected to find text at the prompt!' + ); updateReplHistory(replSessionType, history, textAtPrompt, historyIndex); } historyIndex--; @@ -147,13 +152,21 @@ function showNextReplHistoryEntry(): void { return; } if (historyIndex === history.length - 1) { - historyIndex = null; + historyIndex = undefined; showReplHistoryEntry(lastTextAtPrompt, editor); } else { const textAtPrompt = getTextAfterLastOccurrenceOfSubstring( doc.getText(), getPrompt() ); + util.assertIsDefined( + textAtPrompt, + 'Expected to find text at the prompt!' + ); + util.assertIsDefined( + historyIndex, + 'Expected a value for historyIndex!' + ); updateReplHistory(replSessionType, history, textAtPrompt, historyIndex); historyIndex++; const nextHistoryEntry = history[historyIndex]; From 70c441be2e6053015cd17428280dac97c56bb340 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 13:44:19 -0500 Subject: [PATCH 34/57] model.getTokenCursor already throws an error so simplify this fn --- src/cursor-doc/model.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/cursor-doc/model.ts b/src/cursor-doc/model.ts index d5b4b95da..71127f5d5 100644 --- a/src/cursor-doc/model.ts +++ b/src/cursor-doc/model.ts @@ -612,15 +612,11 @@ export class StringDocument implements EditableDocument { selectionStack: ModelEditSelection[] = []; getTokenCursor(offset?: number, previous?: boolean): LispTokenCursor { - const cursor = isUndefined(offset) - ? undefined - : this.model.getTokenCursor(offset); - - if (isUndefined(cursor)) { + if (isUndefined(offset)) { throw new Error('Expected a cursor for StringDocument!'); } - return cursor; + return this.model.getTokenCursor(offset); } insertString(text: string) { From 8ca6e29799b47ed9f7d7419f88bd5517946c8147 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 13:49:27 -0500 Subject: [PATCH 35/57] Simplify now that this does not return undefined --- src/doc-mirror/index.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/doc-mirror/index.ts b/src/doc-mirror/index.ts index e75877b2e..4d4f7774e 100644 --- a/src/doc-mirror/index.ts +++ b/src/doc-mirror/index.ts @@ -162,13 +162,7 @@ export class MirroredDocument implements EditableDocument { offset: number = this.selectionRight, previous: boolean = false ): LispTokenCursor { - const cursor = this.model.getTokenCursor(offset, previous); - - if (isUndefined(cursor)) { - throw new Error('Expected a cursor for MirrorDocument!'); - } - - return cursor; + return this.model.getTokenCursor(offset, previous); } public insertString(text: string) { From 208e7eb525f9ecdfe8bb9a7578794d389c72e5d0 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 13:51:19 -0500 Subject: [PATCH 36/57] Use the built-in function for checking undefined --- src/extension-test/unit/util/string-test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extension-test/unit/util/string-test.ts b/src/extension-test/unit/util/string-test.ts index 70f4ef7c4..231c50899 100644 --- a/src/extension-test/unit/util/string-test.ts +++ b/src/extension-test/unit/util/string-test.ts @@ -42,9 +42,9 @@ describe('string', () => { describe('getTextAfterLastOccurrenceOfSubstring', () => { it('returns undefined if substring does not exist', () => { - expect(undefined).toBe( + expect( getTextAfterLastOccurrenceOfSubstring('hello world', '123') - ); + ).toBeUndefined(); }); it('returns text after last occurrence of substring', () => { expect('foo').toBe( From 98da60ff054e402d4b09989662af4390a2a0721f Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 13:56:25 -0500 Subject: [PATCH 37/57] Let's not muddy this with unused functions --- src/nrepl/cider.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/nrepl/cider.ts b/src/nrepl/cider.ts index baeb2fb26..9f2e80d74 100644 --- a/src/nrepl/cider.ts +++ b/src/nrepl/cider.ts @@ -218,29 +218,8 @@ type TestResultWithLineNumber = Omit & { line: NonNullable; }; -type TestResultWithFile = Omit & { - file: NonNullable; -}; - -type TestResultWithLineNumberAndFile = Omit & { - line: TestResultWithLineNumber['line']; - file: TestResultWithFile['file']; -}; - export const hasLineNumber = ( result: TestResult | TestResultWithLineNumber ): result is TestResultWithLineNumber => { return typeof result.line === 'number'; }; - -export function hasFile( - result: TestResult | TestResultWithFile -): result is TestResultWithFile { - return typeof result.file === 'string'; -} - -export const hasLineNumberAndFile = ( - result: TestResult | TestResultWithLineNumberAndFile -): result is TestResultWithLineNumberAndFile => { - return hasLineNumber(result) && hasFile(result); -}; From 586c4f439dca155fcf1f3f4b3472db1439ab2b90 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 14:04:13 -0500 Subject: [PATCH 38/57] Allow undefined for documents --- src/utilities.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utilities.ts b/src/utilities.ts index 79709e2ed..bffcd124e 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -184,7 +184,7 @@ function getWordAtPosition(document, position) { } function tryToGetDocument( - document: vscode.TextDocument | Record + document: vscode.TextDocument | Record | undefined ): vscode.TextDocument | undefined { const activeTextEditor = tryToGetActiveTextEditor(); if ( @@ -217,7 +217,9 @@ function getDocument( return doc; } -function getFileType(document) { +function getFileType( + document: vscode.TextDocument | Record | undefined +) { const doc = tryToGetDocument(document); if (doc) { From 76f03948228010ca0873bfe05588631f62d3c3ae Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 14:49:02 -0500 Subject: [PATCH 39/57] Restore old behavior because what to do here is not clear --- src/results-output/results-doc.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 2e42b87a1..77250b36d 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -455,10 +455,5 @@ export function appendPrompt(onAppended?: OnAppendedCallback) { } function getUriForCurrentNamespace(): Promise { - const session = getSession(); - const ns = getNs(); - - util.assertIsDefined(session, 'Expected a session to be defined!'); - util.assertIsDefined(ns, 'Expected an ns to be defined!'); - return namespace.getUriForNamespace(session, ns); + return namespace.getUriForNamespace(getSession(), getNs()); } From 90648ad9c9e2c0fa86ce6e66c40cfecd7887facd Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:02:01 -0500 Subject: [PATCH 40/57] Refactor findLocalProjectRoot to have types --- src/state.ts | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/state.ts b/src/state.ts index 9a9e06014..9d388b615 100644 --- a/src/state.ts +++ b/src/state.ts @@ -177,42 +177,43 @@ export async function initProjectDir(uri?: vscode.Uri): Promise { } function findLocalProjectRoot( - projectFileNames, - doc, - workspaceFolder + projectFileNames: string[], + doc: vscode.TextDocument | undefined, + workspaceFolder: vscode.WorkspaceFolder | undefined ): undefined { if (workspaceFolder) { let rootPath: string = path.resolve(workspaceFolder.uri.fsPath); setStateValue(PROJECT_DIR_KEY, rootPath); setStateValue(PROJECT_DIR_URI_KEY, workspaceFolder.uri); + const docPath = doc && path.dirname(doc.uri.fsPath); - let d: any; - let prev: any; - if (doc && path.dirname(doc.uri.fsPath) !== '.') { - d = path.dirname(doc.uri.fsPath); - } else { - d = workspaceFolder.uri.fsPath; - } - while (d !== prev) { - for (const projectFile in projectFileNames) { - const p = path.resolve(d, projectFileNames[projectFile]); - if (fs.existsSync(p)) { - rootPath = d; + let currentPath = + util.isDefined(docPath) && docPath !== '.' + ? docPath + : workspaceFolder.uri.fsPath; + + let previousPath = ''; + + do { + for (const projectFile of projectFileNames) { + const fullPath = path.resolve(currentPath, projectFile); + if (fs.existsSync(fullPath)) { + rootPath = currentPath; break; } } - if (d === rootPath) { + if (currentPath === rootPath) { break; } - prev = d; - d = path.resolve(d, '..'); - } + previousPath = currentPath; + currentPath = path.resolve(currentPath, '..'); + } while (currentPath !== previousPath); // at least be sure the the root folder contains a // supported project. - for (const projectFile in projectFileNames) { - const p = path.resolve(rootPath, projectFileNames[projectFile]); - if (fs.existsSync(p)) { + for (const projectFile of projectFileNames) { + const fullPath = path.resolve(rootPath, projectFile); + if (fs.existsSync(fullPath)) { setStateValue(PROJECT_DIR_KEY, rootPath); setStateValue(PROJECT_DIR_URI_KEY, vscode.Uri.file(rootPath)); return; From fbec889a138374d406371b23da5da23b4a8d7406 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:14:18 -0500 Subject: [PATCH 41/57] Improve getting the color value to be better for types --- src/statusbar.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/statusbar.ts b/src/statusbar.ts index 4e2df3e20..a087d35f1 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -37,7 +37,7 @@ function colorValue( section: string, currentConf: vscode.WorkspaceConfiguration ): string { - const configSection = currentConf.inspect(section); + const configSection = currentConf.inspect(section); util.assertIsDefined( configSection, @@ -50,13 +50,13 @@ function colorValue( const value = workspaceFolderValue || workspaceValue || globalValue || defaultValue; - if (typeof value !== 'string') { - throw new Error( + util.assertIsString( + value, + () => `Expected color value to be a string! We got ${JSON.stringify( value )}` - ); - } + ); return value; } From a0e494ce001a2e67f67e2c6fa06bb77f8d80336b Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:16:50 -0500 Subject: [PATCH 42/57] Restore old behavior --- src/statusbar.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/statusbar.ts b/src/statusbar.ts index a087d35f1..57b967dd6 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -50,15 +50,12 @@ function colorValue( const value = workspaceFolderValue || workspaceValue || globalValue || defaultValue; - util.assertIsString( - value, - () => - `Expected color value to be a string! We got ${JSON.stringify( - value - )}` - ); - - return value; + // Current behavior is to assert that this is a string even though it may + // not be. Maintaining current behavior for the moment but we should + // eventually do an assertion here or allow the function to return + // undefined. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return value!; } function update(context = state.extensionContext) { From 6a28b9a154613168c1d410e9485e1403ba66f7d6 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:17:16 -0500 Subject: [PATCH 43/57] Restore old behavior since we're just satisfying the compiler --- src/testRunner.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/testRunner.ts b/src/testRunner.ts index d228c46b9..feba12d59 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -9,7 +9,6 @@ import * as lsp from './lsp/types'; import * as namespace from './namespace'; import { getSession, updateReplSessionType } from './nrepl/repl-session'; import * as getText from './util/get-text'; -import { isUndefined } from 'lodash'; const diagnosticCollection = vscode.languages.createDiagnosticCollection('calva'); @@ -116,11 +115,13 @@ async function onTestResult( .map((a) => a.line) .sort(); - const startOfRange = lines[0]; - const endOfRange = lines[lines.length - 1]; - - if (!isUndefined(startOfRange) && !isUndefined(endOfRange)) { - test.range = new vscode.Range(startOfRange, 0, endOfRange, 1000); + if (lines.length > 0) { + test.range = new vscode.Range( + lines[0] - 1, + 0, + lines[lines.length - 1], + 1000 + ); } } From a470f350f31cfc6add11c1f3495029ca9f3eb861 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:22:58 -0500 Subject: [PATCH 44/57] Restore original behavior --- src/utilities.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/utilities.ts b/src/utilities.ts index bffcd124e..ffa386762 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -573,12 +573,11 @@ export async function isDocumentWritable( } const fileStat = await vscode.workspace.fs.stat(document.uri); - return ( - // Try treating it as writable when we can't get the permissions, - // let it error later when we go to use the file. - isUndefined(fileStat.permissions) || - (fileStat.permissions & vscode.FilePermission.Readonly) !== 1 - ); + // I'm not sure in which cases fileStat permissions can be missing + // and so it's not clear what to do if it is. For the moment we can + // ignore this to maintain current behavior. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return (fileStat.permissions! & vscode.FilePermission.Readonly) !== 1; } // Returns the elements of coll with duplicates removed From 2172d8b1d65dbf39474305623bbdd03c6fe4ea87 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:27:39 -0500 Subject: [PATCH 45/57] Fix types to match reality --- src/providers/infoparser.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/providers/infoparser.ts b/src/providers/infoparser.ts index 7caabf247..5c3409fb7 100644 --- a/src/providers/infoparser.ts +++ b/src/providers/infoparser.ts @@ -158,7 +158,9 @@ export class REPLInfoParser { return [undefined, undefined]; } - getSignatures(symbol: string): SignatureInformation[] | undefined { + getSignatures( + symbol: string + ): (SignatureInformation | undefined)[] | undefined { if (this._name !== '') { const argLists = this._arglist ? this._arglist : this._formsString; if (argLists) { From deae3537055f37063a97cb70b2247830fbc14bfe Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:30:40 -0500 Subject: [PATCH 46/57] Restore old types as vscode requires these --- src/providers/infoparser.ts | 4 +--- src/providers/signature.ts | 9 ++++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/providers/infoparser.ts b/src/providers/infoparser.ts index 5c3409fb7..7caabf247 100644 --- a/src/providers/infoparser.ts +++ b/src/providers/infoparser.ts @@ -158,9 +158,7 @@ export class REPLInfoParser { return [undefined, undefined]; } - getSignatures( - symbol: string - ): (SignatureInformation | undefined)[] | undefined { + getSignatures(symbol: string): SignatureInformation[] | undefined { if (this._name !== '') { const argLists = this._arglist ? this._arglist : this._formsString; if (argLists) { diff --git a/src/providers/signature.ts b/src/providers/signature.ts index 0ef95ecb7..c73f7a3a5 100644 --- a/src/providers/signature.ts +++ b/src/providers/signature.ts @@ -57,6 +57,10 @@ export async function provideSignatureHelp( (range) => range.contains(position) ), activeSignature = signatures[help.activeSignature]; + util.assertIsDefined( + activeSignature, + 'Expected activeSignature to be defined!' + ); help.activeParameter = activeSignature.label.match(/&/) !== null ? Math.min( @@ -73,7 +77,10 @@ export async function provideSignatureHelp( return undefined; } -function getCurrentArgsRanges(document: TextDocument, idx: number): Range[] { +function getCurrentArgsRanges( + document: TextDocument, + idx: number +): Range[] | undefined { const cursor: LispTokenCursor = docMirror .getDocument(document) .getTokenCursor(idx), From 03dad0a50791f9c2ebefed52ff65fc9c04fa20c4 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:34:34 -0500 Subject: [PATCH 47/57] Formalize the type for Completions --- src/providers/infoparser.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/providers/infoparser.ts b/src/providers/infoparser.ts index 7caabf247..e81716288 100644 --- a/src/providers/infoparser.ts +++ b/src/providers/infoparser.ts @@ -6,6 +6,11 @@ import { import * as tokenCursor from '../cursor-doc/token-cursor'; import { getConfig } from '../config'; +export type Completion = + | [string, string] + | [MarkdownString, string | undefined] + | [undefined, undefined]; + export class REPLInfoParser { private _name: string | undefined = undefined; @@ -144,9 +149,7 @@ export class REPLInfoParser { return result; } - getCompletion(): - | [string | MarkdownString, string] - | [undefined, undefined] { + getCompletion(): Completion { const name = new MarkdownString(this._docString); if (this._name !== '') { if (this._specialForm) { @@ -204,9 +207,7 @@ export function getHoverNotAvailable(text: string): string { return new REPLInfoParser({ name: text }).getHoverNotAvailable(); } -export function getCompletion( - msg: any -): [string | MarkdownString, string] | [undefined, undefined] { +export function getCompletion(msg: any): Completion { return new REPLInfoParser(msg).getCompletion(); } From 114724e811eb87727aed9fdd9eb8d68cf978b9eb Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:38:40 -0500 Subject: [PATCH 48/57] Assert window has an active text editor --- src/providers/completion.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/providers/completion.ts b/src/providers/completion.ts index 7ace28887..dffe8ea52 100644 --- a/src/providers/completion.ts +++ b/src/providers/completion.ts @@ -109,12 +109,17 @@ export default class CalvaCompletionItemProvider token: CancellationToken ) { if (util.getConnectedState()) { + const activeTextEditor = window.activeTextEditor; + util.assertIsDefined( + activeTextEditor, + 'Expected window to have activeTextEditor defined!' + ); const client = replSession.getSession( - util.getFileType(window.activeTextEditor.document) + util.getFileType(activeTextEditor.document) ); if (client) { await namespace.createNamespaceFromDocumentIfNotExists( - window.activeTextEditor.document + activeTextEditor.document ); const ns = namespace.getDocumentNamespace(); const result = await client.info( From 24692578b0210f6883e5a48ab6426b3a540b7dcc Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:49:07 -0500 Subject: [PATCH 49/57] Allow another undefined argument --- src/project-root.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project-root.ts b/src/project-root.ts index ccd19e8a4..02801647e 100644 --- a/src/project-root.ts +++ b/src/project-root.ts @@ -23,7 +23,7 @@ export function getProjectWsFolder(): vscode.WorkspaceFolder | undefined { export async function findProjectRootUri( projectFileNames: string[], doc: vscode.TextDocument | undefined, - workspaceFolder: vscode.WorkspaceFolder + workspaceFolder: vscode.WorkspaceFolder | undefined ): Promise { let searchUri = doc?.uri || workspaceFolder?.uri; if (searchUri && !(searchUri.scheme === 'untitled')) { From 9a84049617517a066946fe9a35e7c65b94b04045 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:49:21 -0500 Subject: [PATCH 50/57] Add type assertions within a very long const --- src/providers/completion.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/providers/completion.ts b/src/providers/completion.ts index dffe8ea52..5ed895e78 100644 --- a/src/providers/completion.ts +++ b/src/providers/completion.ts @@ -42,17 +42,26 @@ export async function provideCompletionItems( if (util.getConnectedState()) { const toplevelSelection = select.getFormSelection( - document, - position, - true - ), - toplevel = document.getText(toplevelSelection), + document, + position, + true + ); + + util.assertIsDefined( + toplevelSelection, + 'Expected a topLevelSelection!' + ); + + const toplevel = document.getText(toplevelSelection), toplevelStartOffset = document.offsetAt(toplevelSelection.start), toplevelStartCursor = docMirror .getDocument(document) .getTokenCursor(toplevelStartOffset + 1), - wordRange = document.getWordRangeAtPosition(position), - wordStartLocalOffset = + wordRange = document.getWordRangeAtPosition(position); + + util.assertIsDefined(wordRange, 'Expected a wordRange!'); + + const wordStartLocalOffset = document.offsetAt(wordRange.start) - toplevelStartOffset, wordEndLocalOffset = document.offsetAt(wordRange.end) - toplevelStartOffset, From 38ec4f395d71108e1f0e52a0be336d6a7cc63b3c Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:53:42 -0500 Subject: [PATCH 51/57] Handle when some values are undefined --- src/paredit/extension.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/paredit/extension.ts b/src/paredit/extension.ts index a037d994b..90723947d 100644 --- a/src/paredit/extension.ts +++ b/src/paredit/extension.ts @@ -13,6 +13,7 @@ import { import * as paredit from '../cursor-doc/paredit'; import * as docMirror from '../doc-mirror/index'; import { EditableDocument } from '../cursor-doc/model'; +import { assertIsDefined } from '../utilities'; const onPareditKeyMapChangedEmitter = new EventEmitter(); @@ -364,10 +365,16 @@ const pareditCommands: PareditCommand[] = [ function wrapPareditCommand(command: PareditCommand) { return () => { try { - const textEditor = window.activeTextEditor, - mDoc: EditableDocument = docMirror.getDocument( - textEditor.document - ); + const textEditor = window.activeTextEditor; + + assertIsDefined( + textEditor, + 'Expected window to have an activeTextEditor!' + ); + + const mDoc: EditableDocument = docMirror.getDocument( + textEditor.document + ); if (!enabled || !languages.has(textEditor.document.languageId)) { return; } From 01eeb88991aa10140f9005391caaddc992286f28 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:53:57 -0500 Subject: [PATCH 52/57] Handle when pretty printing options are undefined --- src/printer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/printer.ts b/src/printer.ts index 96792d981..f792c49dc 100644 --- a/src/printer.ts +++ b/src/printer.ts @@ -1,4 +1,5 @@ import { getConfig } from './config'; +import { assertIsDefined } from './utilities'; export type PrintFnOptions = { name: string; @@ -116,7 +117,10 @@ export const zprintDependencies = { }; export function getServerSidePrinterDependencies() { - if (prettyPrintingOptions().printEngine === 'zprint') { + const options = prettyPrintingOptions(); + assertIsDefined(options, 'Expected prettyPrintingOptions to be defined!'); + + if (options.printEngine === 'zprint') { return zprintDependencies; } else { return {}; From f1ff9dbedd0cd89f25f97676bc34abca19ba5f12 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 15:57:01 -0500 Subject: [PATCH 53/57] Add type for document to make it easier to type check --- src/evaluate.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/evaluate.ts b/src/evaluate.ts index bc2ea0b15..5e84b12c7 100644 --- a/src/evaluate.ts +++ b/src/evaluate.ts @@ -471,7 +471,10 @@ function evaluateStartOfFileToCursor(document = {}, options = {}) { ); } -async function loadFile(document, pprintOptions: PrettyPrintingOptions) { +async function loadFile( + document: vscode.TextDocument | Record | undefined, + pprintOptions: PrettyPrintingOptions +) { const doc = util.tryToGetDocument(document); const fileType = util.getFileType(doc); const ns = namespace.getNamespace(doc); From 4c0227887d11c28761823c7fcb4a90948092ebe5 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 16:05:51 -0500 Subject: [PATCH 54/57] disable additional eslint rule for these type assertions These type assertions are for when we have strictNullChecks enabled but eslint sees them an not needed when we have it disabled. In order for it to work both ways, enabled and disabled, we need to also disable this additional eslint rule for this line. --- src/statusbar.ts | 2 +- src/utilities.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/statusbar.ts b/src/statusbar.ts index 57b967dd6..3c74359f8 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -54,7 +54,7 @@ function colorValue( // not be. Maintaining current behavior for the moment but we should // eventually do an assertion here or allow the function to return // undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion return value!; } diff --git a/src/utilities.ts b/src/utilities.ts index ffa386762..c5ab90ca4 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -576,7 +576,7 @@ export async function isDocumentWritable( // I'm not sure in which cases fileStat permissions can be missing // and so it's not clear what to do if it is. For the moment we can // ignore this to maintain current behavior. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion return (fileStat.permissions! & vscode.FilePermission.Readonly) !== 1; } From 0168a98346cf731208b1429bd4841e54ea9311c8 Mon Sep 17 00:00:00 2001 From: Cora Sutton Date: Sun, 13 Mar 2022 16:09:25 -0500 Subject: [PATCH 55/57] Update the changelog to reflect changes --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7af355dc..98d3edef9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,12 @@ Changes to Calva. ## [Unreleased] +- Maintenance: [Update more TypeScript code to be compatible with strictNullChecks.](https://github.com/BetterThanTomorrow/calva/pull/1581) ## [2.0.253] - 2022-03-09 - Fix: [Structural editing hangs in specific cases of unbalanced forms](https://github.com/BetterThanTomorrow/calva/pull/1585) - Fix: [Hover snippet markdown and adds example](https://github.com/BetterThanTomorrow/calva/pull/1582) - Maintenance: [Begin work on enabling strictNullChecks in the TypeScript config.](https://github.com/BetterThanTomorrow/calva/pull/1568) -- Maintenance: [Update more TypeScript code to be compatible with strictNullChecks.](https://github.com/BetterThanTomorrow/calva/pull/1581) ## [2.0.252] - 2022-03-05 - Fix: [Tab doesn't work in snippet mode](https://github.com/BetterThanTomorrow/calva/pull/1580) From cf95171ee844043cff5f20ad39a29f683a068a50 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 16 Mar 2022 12:13:38 +0000 Subject: [PATCH 56/57] Bring on version 2.0.255! --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0000ecd3..a0a7bb3e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "calva", - "version": "2.0.254", + "version": "2.0.255", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "calva", - "version": "2.0.254", + "version": "2.0.255", "license": "MIT", "dependencies": { "@types/escape-html": "0.0.20", diff --git a/package.json b/package.json index 00f3f8750..db44d655c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Calva: Clojure & ClojureScript Interactive Programming", "description": "Integrated REPL, formatter, Paredit, and more. Powered by cider-nrepl and clojure-lsp.", "icon": "assets/calva.png", - "version": "2.0.254", + "version": "2.0.255", "publisher": "betterthantomorrow", "author": { "name": "Better Than Tomorrow", From b9ea42afb3931270d138028ec9604a2bfb3ac444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Fri, 18 Mar 2022 08:16:01 +0100 Subject: [PATCH 57/57] Add changelog section for v2.0.255 [skip ci] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3409687d..d48d60832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Changes to Calva. ## [Unreleased] + +## [2.0.255] - 2022-03-18 - Maintenance: [Update more TypeScript code to be compatible with strictNullChecks.](https://github.com/BetterThanTomorrow/calva/pull/1581) ## [2.0.254] - 2022-03-16