Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: YASNCB (Yet Another Strict Null Checks Branch) #1703

Draft
wants to merge 73 commits into
base: dev
Choose a base branch
from

Conversation

corasaurus-hex
Copy link
Contributor

What has Changed?

This turns on strictNullChecks in TypeScript and fixes all the remaining issues in the codebase that were preventing us from turning this setting on.

My Calva PR Checklist

I have:

  • Read How to Contribute.
  • Directed this pull request at the dev branch. (Or have specific reasons to target some other branch.)
  • Made sure I have changed the PR base branch, so that it is not published. (Sorry for the nagging.)
  • Updated the [Unreleased] entry in CHANGELOG.md, linking the issue(s) that the PR is addressing.
  • Figured if anything about the fix warrants tests on Mac/Linux/Windows/Remote/Whatever, and either tested it there if so, or mentioned it in the PR.
  • Added to or updated docs in this branch, if appropriate
  • Tests
    • Tested the particular change
    • Figured if the change might have some side effects and tested those as well.
    • Smoke tested the extension as such.
    • Tested the VSIX built from the PR (so, after you've submitted the PR). You'll find the artifacts by clicking Show all checks in the CI section of the PR page, and then Details on the ci/circleci: build test.
  • [~] Referenced the issue I am fixing/addressing in a commit message for the pull request.
    • [~] If I am fixing the issue, I have used GitHub's fixes/closes syntax
    • [~] If I am fixing just part of the issue, I have just referenced it w/o any of the "fixes” keywords.
  • [~] Created the issue I am fixing/addressing, if it was not present.
  • [~] Formatted all JavaScript and TypeScript code that was changed. (use the prettier extension or run npm run prettier-format)
  • [~] Confirmed that there are no linter warnings or errors (use the eslint extension, run npm run eslint before creating your PR, or run npm run eslint-watch to eslint as you go).

Ping @PEZ, @bpringe, @corasaurus-hex, @Cyrik

This is an odd one. The types were very different for useRowCol = true
and useRowCol = false and so I needed to use generics to clean it up.
@@ -185,7 +185,7 @@ export class LineInputModel implements EditableModel {
}
return [a, b];
})
.filter((x) => x !== null)
.filter((x) => x !== null) as [number, number][]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same same.

@@ -224,7 +224,7 @@ export class LineInputModel implements EditableModel {
const seen = new Set<number>();
this.dirtyLines.sort();
while (this.dirtyLines.length) {
let nextIdx = this.dirtyLines.shift();
let nextIdx = this.dirtyLines.shift() as number;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, TypeScript isn't smart enough to figure out that the length check on the previous line means this will never be undefined and will always be a number.

cursorStartField: StartFieldKey,
cursorEndField: EndFieldKey
): [LispTokenCursor[StartFieldKey], LispTokenCursor[EndFieldKey]][] => {
const ranges: [LispTokenCursor[StartFieldKey], LispTokenCursor[EndFieldKey]][] = [];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explanation for this function is that we needed a generic version of _rangesForSexpsInList that didn't need really long types and weird type contortions in order to use it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably an improvement. But with my limited command over the typing system, right now this turned from ”this is messy” to ”I don't understand what I'm reading at all”. Not sure what to do about that...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might also be that I am having a hard time trying to puzzle together the code in my head from the diffs.

if (step) {
step.undo(c);
this.redos.push(step);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More TypeScript silliness. The length check means pop will always work but TypeScript can't figure that out.


const options = {};

if (pick !== undefined) {
options['evaluationSendCodeToOutputWindow'] =
snippetsDict[pick].evaluationSendCodeToOutputWindow;
options['evaluationSendCodeToOutputWindow'] = replSnippet?.evaluationSendCodeToOutputWindow;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strange note: evaluationSendCodeToOutputWindow was missing from customREPLCommandSnippet and I had to add it.

@@ -271,6 +271,7 @@ class CalvaDebugSession extends LoggingDebugSession {
// Pass scheme in path argument to Source contructor so that if it's a jar file it's handled correctly
const source = new Source(basename(debugResponse.file), debugResponse.file);
const name = tokenCursor.getFunctionName();
util.assertIsDefined(name, 'Expected to find a function name!');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StackFrame doesn't allow for an undefined name.

@@ -169,18 +169,21 @@ export class MirroredDocument implements EditableDocument {
}

public delete(): Thenable<boolean> {
return vscode.commands.executeCommand('deleteRight');
return vscode.commands.executeCommand('deleteRight').then((v) => !!v);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual return type here was Thenable<true | undefined> and so this fixes the type so it's Thenable<boolean> again.

@@ -381,6 +382,7 @@ export class NReplSession {
if (evaluation.onMessage(msg, pprintOptions)) {
return true;
}
return false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure of this behavior but we must return a boolean from this function and it clearly shouldn't return true.

}
}

export { isNonEmptyString, isNullOrUndefined, isDefined, assertIsDefined };
Copy link
Contributor Author

@corasaurus-hex corasaurus-hex May 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We needed to split this out into its own file so it could be imported in files where vscode isn't available. Importing utilities was breaking unit tests because of this.

@PEZ
Copy link
Collaborator

PEZ commented May 2, 2022

I found this in the noise where the integration test broke:

UNRESPONSIVE extension host: 'betterthantomorrow.calva' took 100% of 5100.624ms, saved PROFILE here: 'file:///tmp/exthost-19cc55.cpuprofile' [ { id: 'betterthantomorrow.calva', total: 5100381, percentage: 100 } ]

https://app.circleci.com/pipelines/github/BetterThanTomorrow/calva/5020/workflows/5edc3168-da3a-4cf8-ab29-02c887c079c0/jobs/21872?invite=true#step-104-114

Before that I also find:

[137:0501/213503.162639:ERROR:bus.cc(397)] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")

Which I am not sure if we usually see or not, but if not maybe it could be the cause of the timeout.

Anyway, those UNRESPONSIVE extension host: 'betterthantomorrow.calva' took 100% of 5100.624ms messages I sometimes see in the dev console when I have introduced some change causing Calva to go into a spin while activating.

I would see if I could run these tests locally. If you haven't before, it's surprisingly easy:

  1. Quit VS Code Insiders if you have it running
  2. In an integrated terminal of regular VS Code: npm run integration-test

@corasaurus-hex
Copy link
Contributor Author

I ran it locally and profiled the code to find where it's stuck. I just need to figure out why it's stuck. I have the last known working commit sha for integration tests but it's not clear why it's broken by the following commit

@PEZ
Copy link
Collaborator

PEZ commented May 3, 2022

Which commits does the bisect give you? Maybe we can see what could be the cause with more eyes on it.

@PEZ
Copy link
Collaborator

PEZ commented May 3, 2022

Is it here?

fcf14e0

If so, that is still a bit opaque to me. 😄 I don't know what the implications are for enabling strict null checks.

if (menuSelections && menuSelections.cljsDefaultBuild && useDefaultBuild) {
build = menuSelections.cljsDefaultBuild;
useDefaultBuild = false;
} else {
if (typeof initCode === 'object' || initCode.includes('%BUILD%')) {
const buildsForSelection = startedBuilds
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stopped and wondered if we somehow consider the current selection here. Maybe name it builds? Or buildCandidates?.

Comment on lines +675 to +677
const previous = cursor.clone().previous();
assertIsDefined(previous, 'Expected a token to be before the cursor!');
const offset = previous.offsetStart;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I am reading this correctly. But generally in Paredit and token cursor code we need to gracefully handle when the structure does not match some expectation. We most often leave things unchanged in those cases. Does this change mean that we croak? I realize that that would be happening before the change as well, I'm more wondering about what we should be doing here...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants