-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Improve error messages for property declarations #5559
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
Conversation
i do not think this is the right way to accomplish this change. you probably want to allow parsing @CyrusNajmabadi or @vladima can help you more here. |
I agree with @mhegazy . We know we're in parseClassElement. In that case, just pass a flag to parseClassModifiers saying that 'const should be treated as a modifier." Easy peasy. Then later during grammar checks, disallow 'const' on anything other than an enum. |
06e3cbe
to
9f393fa
Compare
It's definitely more easy peasy for you. 😄 However, I tried to move it a bit further. I don't know how to fix the fourslash test. I don't understand what |
@mhegazy Can I ask you for feedback? |
let flags = 0; | ||
let modifiers: ModifiersArray; | ||
while (true) { | ||
const modifierStart = scanner.getStartPos(); | ||
const modifierKind = token; | ||
|
||
if (!parseAnyContextualModifier()) { | ||
break; | ||
if (whitelist && whitelist.indexOf(token) >= 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.
use ts.indexOf
instead
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.
Yes, I have already found it (#5559 (comment))
@@ -1124,6 +1124,14 @@ namespace ts { | |||
return token === t && tryParse(nextTokenCanFollowModifier); | |||
} | |||
|
|||
function nextTokenIsOnSameLineAndCanFollowModifier() { |
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.
So we have nextTokenIsOnSameLineAndCanFollowModifier and nextTokenCanFollowModifier...
These are supremely easy to confuse. When would i want one, versus the other?
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.
It was nextTokenCanFollowModifierWithoutGrammarRules
before. It seemed more clear to me. Basically, I just need nextTokenCanFollowModifier
without the leading checks. I can think of several solutions here:
- Inline
nextTokenIsOnSameLineAndCanFollowModifier
toparseModifiers
(It leads to code duplication). - Rename
nextTokenIsOnSameLineAndCanFollowModifier
and use it innextTokenCanFollowModifier
as now. - Somehow pass a flag to
tryParse
. It seems like a big change becausetryParse
is a generic function that is used everywhere.
The option 2 seems reasonable overall.
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.
But why do some people needs checks, and others do not? That's the part I find confusing. How would I know from my code?
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.
Well, to be frank, I don't know why the if statements with SyntaxKind
in the following code are not a part of checker.ts
file:
function nextTokenCanFollowModifier() {
if (token === SyntaxKind.ConstKeyword) {
// 'const' is only a modifier if followed by 'enum'.
return nextToken() === SyntaxKind.EnumKeyword;
}
if (token === SyntaxKind.ExportKeyword) {
nextToken();
if (token === SyntaxKind.DefaultKeyword) {
return lookAhead(nextTokenIsClassOrFunction);
}
return token !== SyntaxKind.AsteriskToken && token !== SyntaxKind.OpenBraceToken && canFollowModifier();
}
if (token === SyntaxKind.DefaultKeyword) {
return nextTokenIsClassOrFunction();
}
if (token === SyntaxKind.StaticKeyword) {
nextToken();
return canFollowModifier();
}
nextToken();
if (scanner.hasPrecedingLineBreak()) {
return false;
}
return canFollowModifier();
}
That way, one would always have all modifiers for a property or a class (possibly something else?) and they would be checked in checker.ts
if they are correct. Then there would be no need for special handling of const
which now seems a bit like a hack. But maybe I'm missing something because I don't know have deep knowledge of the compiler.
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 think what Cyrus is sort of getting at is that more than anything else, you should be prescriptive and document why this function exists and where it should be used.
@mhegazy @DanielRosenwasser Do you have any suggestions how to make progress on this issue? |
@@ -4940,7 +4951,7 @@ namespace ts { | |||
|
|||
const fullStart = getNodePos(); | |||
const decorators = parseDecorators(); | |||
const modifiers = parseModifiers(); | |||
const modifiers = parseModifiers(true /* permitConstAsModifier */); |
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 comment will need to be moved to the front
@MartyIX is there a test with something like class C {
const
x = 10;
} |
@DanielRosenwasser I added |
Looks like there is a fourslash test failure for |
Yes, I know. I mentioned it here #5559 (comment) Some documentation for fourslash tests would be helpful. |
Oh sorry, I missed that. We provide something called "occurrences highlighting" or "highlight spans". When the caret is placed on top of certain identifiers and keywords, we'll highlight relevant matches: So with |
41ba303
to
b6871c9
Compare
@DanielRosenwasser Thanks |
@mhegazy @DanielRosenwasser Can you have a look at the code? |
@@ -1,7 +1,7 @@ | |||
/// <reference path='fourslash.ts' /> | |||
|
|||
////export const class C { | |||
//// private static c/*1*/onst foo; | |||
//// private static const f/*1*/oo; |
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 fix shouldn't be to change the marker position, it should be to ensure that the occurrence count is 0.
For some reason, we aren't observing the new error message on the following: class C {
private const foo;
constructor(const) {
}
} We report an error on the |
Have you tried debugging through it? |
I'll have a look in a few hours (as soon as I finish some other work). |
@DanielRosenwasser I added
So
https://github.com/Microsoft/TypeScript/blob/master/src/compiler/tsc.ts#L568 The conclusion is that semantic errors are not shown when parser errors occur. |
@DanielRosenwasser @mhegazy Is this behavior OK then? Or can I make the PR better? |
@@ -15324,6 +15324,11 @@ namespace ts { | |||
let flags = 0; | |||
for (const modifier of node.modifiers) { | |||
switch (modifier.kind) { | |||
case SyntaxKind.ConstKeyword: | |||
if (node.parent.kind === SyntaxKind.ClassDeclaration && node.kind !== SyntaxKind.EnumDeclaration) { |
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.
Can you switch the condition around to check for node.kind
first?
Other than the last comment I left, looks good to me! |
@DanielRosenwasser Ah, sorry. I think you have already mentioned that. I've just fixed it |
@mhegazy @DanielRosenwasser Can this be merged then? |
Sorry about that, I must have missed the alert. Can you merge from |
@DanielRosenwasser I've updated it. |
@mhegazy @DanielRosenwasser Ping :) (I'm not in a hurry to get this merged, it's just I don't want to deal with potential unnecessary conflicts.) |
Improve error messages for property declarations
Sorry about that, it's easy to miss in the flood of notifications, but thanks @MartyIX! |
Proposed fix for #4045.
I'm not entirely sure if I'm on the right track. It's more complicated than I expected.