Skip to content

[Parse] Improve diagnostic and add fixit to correct '#else if' to '#elseif' #25008

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 1 commit into from
May 24, 2019

Conversation

owenv
Copy link
Contributor

@owenv owenv commented May 23, 2019

Resolves SR-10581

diagnose(Tok.getLoc(),
diag::unexpected_if_following_else_compilation_directive)
.fixItReplace(
SourceRange(ClauseLoc, Tok.getLoc().getAdvancedLoc(1)),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe you can extract this into a separate line otherwise it makes the indentation looks a bit weird IMO.

auto diag = diag::unexpected_if_following_else_compilation_directive;
auto rangeToReplace = SourceRange(ClauseLoc, Tok.getLoc().getAdvancedLoc(1));
diagnose(Tok.getLoc(), diag).fixItReplace(rangeToReplace, "#elseif");

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out this was a little more complicated then it needed to be, it reads much better now that I've simplified it a bit


#if FOO
#else if BAR
// expected-error@-1 {{unexpected 'if' keyword following '#else' conditional compilation directive; did you mean '#elseif?'}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is supposed to be just expected-error. Also, you can also check whether the fix-it is correctly applied by using this syntax:

{{column_start-column_end=<text>}}

so for example:

// expected-error {{unexpected 'if' keyword following '#else' conditional compilation directive; did you mean '#elseif?'}}{{0-9=#elseif}}

(wrote this without running, so you might have to tweak the range).

Copy link
Contributor

@beccadax beccadax May 23, 2019

Choose a reason for hiding this comment

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

expected-error@-1 is correct; it says the error should appear on the line before the comment.

You're correct that this needs to test the fix-it, though. Columns are 1-based (this confuses me all the time), so I think the range is 1-9.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry, I meant we could use expected-error and put it on the same line as #else if BAR? I suppose it's fine otherwise because the line would become even longer 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, thanks!

@theblixguy
Copy link
Collaborator

cc @rintaro @brentdax (who filed this bug)

@beccadax beccadax requested review from beccadax and rintaro May 23, 2019 20:29
Copy link
Contributor

@beccadax beccadax left a comment

Choose a reason for hiding this comment

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

Thank you for fixing this! I make this mistake all the time; it'll be nice to have the compiler point me to the right code. My suggestions are pretty minor—you've done a good job here.

diagnose(Tok.getLoc(),
diag::unexpected_if_following_else_compilation_directive)
.fixItReplace(
SourceRange(ClauseLoc, Tok.getLoc().getAdvancedLoc(1)),
Copy link
Member

Choose a reason for hiding this comment

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

.getAdvancedLoc(1) shouldn't be needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@@ -623,8 +623,18 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
foundActive |= isActive;

if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
diagnose(Tok.getLoc(),
diag::extra_tokens_conditional_compilation_directive);
if (isElse && Tok.is(tok::kw_if)) {
Copy link
Member

@rintaro rintaro May 23, 2019

Choose a reason for hiding this comment

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

To maximize the recovery, I think you should do this before line 599. Like:

     bool isElse = Tok.is(tok::pound_else);
     SourceLoc ClauseLoc = consumeToken();
+    if (isElse && Tok.is(tok::kw_if) && !Tok.isAtStartOfLine()) {
+      .. Emit error and fix-it ..
+      consumeToken(tok::kw_if);
+      isElse = false;
+    }
+
     Expr *Condition = nullptr;
     bool isActive = false;

     // Parse the condition.  Evaluate it to determine the active
     // clause unless we're doing a parse-only pass.
     if (isElse) {

This way, the parser automatically parse and possibly diagnose the condition after #else if.

For example, given

#else if SOME == THING

In this case, we want to diagnose both:

  • #else if for fix-it #elseif
  • == for error: expected '&&' or '||' expression

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, recovering here seems to work well and catch parse errors in the condition. Thanks!

@@ -623,8 +623,18 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
foundActive |= isActive;

if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
diagnose(Tok.getLoc(),
Copy link
Member

Choose a reason for hiding this comment

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

Small tips: Parser has diagnose(Token Tok, Diagnostic Diag) function. You don't need .getLoc() here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@owenv owenv force-pushed the improved_#else_if_diagnostic branch from 326271d to 901d947 Compare May 24, 2019 02:35
@owenv
Copy link
Contributor Author

owenv commented May 24, 2019

Thanks for the feedback @theblixguy @rintaro @brentdax . I think I've addressed all the issues raised

@beccadax
Copy link
Contributor

@swift-ci please smoke test

Copy link
Member

@rintaro rintaro left a comment

Choose a reason for hiding this comment

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

Thank you!

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.

4 participants