-
Notifications
You must be signed in to change notification settings - Fork 13
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
chore: accurate null checks #132
base: master
Are you sure you want to change the base?
Conversation
lib/adapters/apply-edit-adapter.ts
Outdated
@@ -90,7 +90,7 @@ export default class ApplyEditAdapter { | |||
const startRow = edit.oldRange.start.row | |||
const startCol = edit.oldRange.start.column | |||
const lineLength = buffer.lineLengthForRow(startRow) | |||
if (lineLength == null || startCol > lineLength) { | |||
if (startCol > lineLength) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should fix the original types then. Writing code based on the wrong types or docs is not a good idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. My point is, we really should verify we don't accidentally break stuff by these linter-driven changes. Regrettably, TS isn't Haskell, so it can lie about types, especially when definitions are written by fallible humans.
@@ -53,6 +53,7 @@ export default class DatatipAdapter { | |||
} | |||
|
|||
private static isEmptyHover(hover: Hover): boolean { | |||
// TODO hover.contents is never null! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types can lie. Especially Microsoft's types. You sure it's never null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And are we sure something won't change to make it be null in the future? I think we should keep these checks unless we have tests so future dependency updates won't break something these checks would catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather disable an eslint rule than remove these checks and waste time figuring out where a null bug is coming from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And are we sure something won't change to make it be null in the future?
Ideally, that should be caught by types on dependency update. But as I said, types can lie. The "proper" thing to do is to fix type definitions, and not pepper the code base with redundant checks. Regrettably, fixing type definitions is not always straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "proper" thing to do is to fix type definitions, and not pepper the code base with redundant checks.
Yes Ideally this would be caught by typescript. Unfortunately we don't live in an ideal world and I would estimate that at any given time about 50% of the types in DefinitelyTyped are wrong because the dependency updated and no one bothered to update the types.
If we were only dealing with strictly typescript packages (where they have some process to catch when types are wrong) that would be one thing, but we are not. Which is why these checks are here.
Essentially, types do not catch runtime errors, but these checks do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types can lie. Especially Microsoft's types. You sure it's never null?
Research is needed. One of us (MS vs Atom) is wrong. No matter who is right, it will result in a better code/interface.
waste time figuring out where a null bug is coming from.
This is not wasting time. If there is a null bug, we should either commit to it by updating the original types or remove the excess check.
-
If the issue is that an undocumented null/undefined is being returned from the types coming from
@atom/types
orlsp
types, then the original types should be updated, and then we update our interfaces to take that into account. TypeScript will do a new analysis based on the available information. This is not the same as throwing some random null checks here and there in the dark. -
If the interface is correct, then we are doing an extra null-check for no reason. By removing it we simplify the code.
And are we sure something won't change to make it be null in the future?
Keeping the implementation loose, encourages using the interfaces loosely, which means people send null
, and based on their tests it works although it wasn't documented. So, this is their mistake and not us. By tightening the interface and implementation, we prevent others from making mistakes.
Essentially, types do not catch runtime errors, but these checks do.
Random runtime checks have no value and encourage more errors. If you intend to keep the interface loose, then we should commit to it. We need to update the interface, so TypeScript analyzes the new interface, and we correctly handle it instead of randomly checking things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random runtime checks have no value and encourage more errors.
I totally agree. I think the best thing to do when given the wrong data is throw an error. Unfortunately the way it is currently written is very loose which means us changing this could very easily break someone else's code that used to pass. I'm not advocating that we keep the checks, I'm advocating that if we are going to change our api like this (even if it is wrong) we need to bump the major version to let people know the api changed, or we need to keep the checks so the api doesn't change.
This is not wasting time. If there is a null bug, we should either commit to it by updating the original types or remove the excess check.
Where is your commitment to the null bugs in minimap. Your solution was to remove parts of the code that were correct instead of finding the actual bug. I agree, in an ideal world, unfortunately we don't live in an ideal world and sometimes (probably most times) it is good enough to write checks instead of doing it correctly. </rant>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typescript handles most compile time errors but do not catch run time errors. If we wanted to actually do it correctly we would keep these check and throw appropriate errors so the code is not so loose and bugs are easier to fix.
return null | ||
} | ||
|
||
let queryRange | ||
if (serverCapabilities.documentHighlightProvider) { | ||
const highlights = await connection.documentHighlight(documentPositionParams) | ||
if (highlights != null && highlights.length > 0) { | ||
if (highlights.length > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, are we sure connection always returns something? I know with tsserver that is not the case, the official types lie a lot about null
.
af5804e
to
5aef4a6
Compare
No description provided.