Skip to content

feat(ast-spec): tighter types and documentation for declaration/* #9211

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

Merged
merged 8 commits into from
Jun 23, 2024

Conversation

Josh-Cena
Copy link
Member

PR Checklist

Overview

Although the types are tighter, it contains no breaking tree shape changes.

Also added a bunch of documentation.

@typescript-eslint
Copy link
Contributor

Thanks for the PR, @Josh-Cena!

typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community.

The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately.

Thanks again!


🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint.

Copy link

netlify bot commented Jun 2, 2024

Deploy Preview for typescript-eslint ready!

Name Link
🔨 Latest commit fc730f1
🔍 Latest deploy log https://app.netlify.com/sites/typescript-eslint/deploys/667820724fdaf50008c178e7
😎 Deploy Preview https://deploy-preview-9211--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 96 (🔴 down 2 from production)
Accessibility: 100 (no change from production)
Best Practices: 92 (no change from production)
SEO: 90 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

nx-cloud bot commented Jun 2, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit fc730f1. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 1 target

Sent with 💌 from NxCloud.

@Josh-Cena Josh-Cena force-pushed the ast-spec-tighten-1 branch from d02a303 to 4407bad Compare June 2, 2024 13:59
Copy link
Member Author

@Josh-Cena Josh-Cena left a comment

Choose a reason for hiding this comment

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

Some comments

*/
exported: Identifier | null;
/**
* The kind of the export.
*/
// TODO(#1852) - breaking change remove this because it is a semantic error to have it
Copy link
Member Author

Choose a reason for hiding this comment

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

TS now allows export type * from

*/
exportKind: ExportKind;
exportKind: 'value';
Copy link
Member Author

Choose a reason for hiding this comment

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

Tightened: export type default is not legal

@@ -64,9 +71,14 @@ export interface ExportNamedDeclarationWithoutSourceWithMultiple
attributes: ImportAttribute[];
declaration: null;
source: null;
specifiers: ExportSpecifier[];
Copy link
Member Author

Choose a reason for hiding this comment

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

Removals here are not breaking because these properties are already declared on the base

Comment on lines 44 to 45
// TODO: we should have a way to differentiate between these two cases
specifiers: ImportClause[];
Copy link
Member Author

Choose a reason for hiding this comment

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

For the future: specifiers should be able to be null, like how typeParameters can be both empty or null

Copy link
Member

Choose a reason for hiding this comment

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

This won't ever happen, sadly. The ESTree spec is pretty well locked in once defined and so we're stuck with the decisions of the past.

If we change something like this then we're liable to break all sorts of rules that assume it's always defined.

In general we can only ever change our AST extension shapes and the "core" AST is fixed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hhhh, I forgot this is not TS specific. Fine then.

Comment on lines 6 to 9
/**
* TS1183: An implementation cannot be declared in ambient contexts.
*/
body: undefined;
Copy link
Member Author

Choose a reason for hiding this comment

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

Tightened: I think this is safe?

Copy link
Member

Choose a reason for hiding this comment

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

This is not correct to do.
The error you cited is a semantic error, not a syntax error.
This means that TS produces an AST for the error and us we do too.

playground

Comment on lines 18 to 26
/**
* TS1040: 'async' modifier cannot be used in an ambient context.
*/
async: false;
declare: true;
/**
* TS1221: Generators are not allowed in an ambient context.
*/
generator: false;
Copy link
Member Author

Choose a reason for hiding this comment

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

Tightened

Copy link
Member

@bradzacher bradzacher Jun 2, 2024

Choose a reason for hiding this comment

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

Ditto above - the errors are semantic and TS still produces an AST - AND it includes these flags correctly.
So we can't refine these.

playgroubd

Copy link
Member Author

Choose a reason for hiding this comment

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

Aren't we supposed to throw on semantic errors? Wasn't fisker fixing some of these before?

@@ -19,7 +19,45 @@ export interface TSImportEqualsDeclaration extends BaseNode {
* import F3 = require('mod');
* ```
*/
moduleReference: EntityName | TSExternalModuleReference;
// TODO(#1852) - breaking change remove this as it is invalid
moduleReference: Identifier | TSQualifiedName | TSExternalModuleReference;
Copy link
Member Author

Choose a reason for hiding this comment

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

Slight tightening: EntityName is a moving target and doesn't really make sense here. I will continue to fix uses of it. It broke when ThisExpression became a valid EntityName.

Comment on lines +61 to +63
export type TSImportEqualsDeclaration =
| TSImportEqualsNamespaceDeclaration
| TSImportEqualsRequireDeclaration;
Copy link
Member Author

Choose a reason for hiding this comment

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

Changed to union

Comment on lines +114 to +116
// TODO: we emit the wrong AST for `module A.B {}`
// https://github.com/typescript-eslint/typescript-eslint/pull/6272 only fixed namespaces
// Maybe not worth fixing since it's legacy
Copy link
Member Author

Choose a reason for hiding this comment

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

Worth pointing out

Comment on lines 94 to 98
export type LetOrConstOrVarDeclaration =
| LetOrVarDeclaredDeclaration
| LetOrVarNonDeclaredDeclaration
| ConstDeclaredDeclaration
| ConstNonDeclaredDeclaration;
Copy link
Member Author

Choose a reason for hiding this comment

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

The biggest change: made LetOrConstOrVarDeclaration much stricter.

Copy link
Member

@bradzacher bradzacher Jun 2, 2024

Choose a reason for hiding this comment

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

The thing that needs to be checked with these changes is like const x; - do we have a syntax error or do we produce an AST.

If it's the latter then we can't refine the types as the types have to reflect the AST we output.

For the specific example of const x: - we produce an AST so the types must allow the case of const with an init: null. playground

or eg const x! = 1; - we produce an AST so the tyoes nust allow the case. playground

Copy link
Member

@bradzacher bradzacher left a comment

Choose a reason for hiding this comment

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

A lot of this is great!
But there's a chunk that I think causes drift between the types and the ASTs we produce.

The important distinction when looking at TS errors is "does TS crash, or does it produce an AST"? In most cases it's the latter.
TS's parser is very forgiving and most errors are semantic errors, not syntactic errors - meaning it produces an AST even if the code has errors.

If TS produces an AST then in most cases we do too. So we need to ensure that the types respect that.

We can always add hard errors to our AST translation step to enforce invariants so that we can change the types! But doing so will be a breaking change for the v8 branch.

Please also add tests for any cases / permutations that you think are missing. More AST snapshots is always good!

@Josh-Cena
Copy link
Member Author

We can always add hard errors to our AST translation step to enforce invariants so that we can change the types! But doing so will be a breaking change for the v8 branch.

Really, even when the AST is nonsense and no program is not going to work? For example #7202 was not breaking

@bradzacher
Copy link
Member

bradzacher commented Jun 3, 2024

It generally would require a quick chat with the prettier folk. We want to make sure that we're not breaking their experience by throwing on parsable code. If they're okay then we can land it non-breaking.

In the past a lot of the invariants we've encoded were just the invariants that prettier itself encoded (allowing them to delete the checks and make assumptions).

I'm all for a stricter AST transform - just don't want to kill downstream usecases with it.

@Josh-Cena
Copy link
Member Author

#9219, #9220, #9221

@Josh-Cena Josh-Cena marked this pull request as draft June 3, 2024 05:06
@Josh-Cena Josh-Cena marked this pull request as ready for review June 3, 2024 11:53
@Josh-Cena
Copy link
Member Author

@bradzacher I am splitting normative changes out into separate PRs

@Josh-Cena Josh-Cena requested a review from bradzacher June 4, 2024 06:52
@Josh-Cena Josh-Cena changed the title feat(ast-spec): tighter types for declaration/* feat(ast-spec): tighter types and documentation for declaration/* Jun 4, 2024
bradzacher
bradzacher previously approved these changes Jun 23, 2024
Copy link
Member

@bradzacher bradzacher left a comment

Choose a reason for hiding this comment

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

@bradzacher bradzacher added the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Jun 23, 2024
@bradzacher
Copy link
Member

a few lint errors @Josh-Cena otherwise ready to ship

@bradzacher bradzacher added the awaiting response Issues waiting for a reply from the OP or another party label Jun 23, 2024
@bradzacher bradzacher merged commit 5c4a5de into typescript-eslint:main Jun 23, 2024
61 checks passed
@Josh-Cena Josh-Cena deleted the ast-spec-tighten-1 branch June 23, 2024 13:58
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge awaiting response Issues waiting for a reply from the OP or another party
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants