Add fixit for '-> throws' to 'throws ->' (#3335)

This commit is contained in:
Harlan
2016-07-05 11:29:55 -07:00
committed by GitHub
parent 32c55956de
commit 162648d219
4 changed files with 49 additions and 24 deletions

View File

@@ -648,6 +648,26 @@ Parser::parseFunctionSignature(Identifier SimpleName,
}
SourceLoc arrowLoc;
auto diagnoseInvalidThrows = [&]() -> Optional<InFlightDiagnostic> {
if (throwsLoc.isValid())
return None;
if (Tok.is(tok::kw_throws)) {
throwsLoc = consumeToken();
} else if (Tok.is(tok::kw_rethrows)) {
throwsLoc = consumeToken();
rethrows = true;
}
if (!throwsLoc.isValid())
return None;
auto diag = rethrows ? diag::rethrows_in_wrong_position
: diag::throws_in_wrong_position;
return diagnose(Tok, diag);
};
// If there's a trailing arrow, parse the rest as the result type.
if (Tok.isAny(tok::arrow, tok::colon)) {
if (!consumeIf(tok::arrow, arrowLoc)) {
@@ -657,6 +677,15 @@ Parser::parseFunctionSignature(Identifier SimpleName,
arrowLoc = consumeToken(tok::colon);
}
// Check for 'throws' and 'rethrows' after the arrow, but
// before the type, and correct it.
if (auto diagOpt = diagnoseInvalidThrows()) {
assert(arrowLoc.isValid());
assert(throwsLoc.isValid());
(*diagOpt).fixItExchange(SourceRange(arrowLoc),
SourceRange(throwsLoc));
}
ParserResult<TypeRepr> ResultType =
parseType(diag::expected_type_function_result);
if (ResultType.hasCodeCompletion())
@@ -672,26 +701,14 @@ Parser::parseFunctionSignature(Identifier SimpleName,
}
// Check for 'throws' and 'rethrows' after the type and correct it.
if (!throwsLoc.isValid()) {
if (Tok.is(tok::kw_throws)) {
throwsLoc = consumeToken();
} else if (Tok.is(tok::kw_rethrows)) {
throwsLoc = consumeToken();
rethrows = true;
}
if (throwsLoc.isValid()) {
assert(arrowLoc.isValid());
assert(retType);
auto diag = rethrows ? diag::rethrows_after_function_result
: diag::throws_after_function_result;
SourceLoc typeEndLoc = Lexer::getLocForEndOfToken(SourceMgr,
retType->getEndLoc());
SourceLoc throwsEndLoc = Lexer::getLocForEndOfToken(SourceMgr, throwsLoc);
diagnose(Tok, diag)
.fixItInsert(arrowLoc, rethrows ? "rethrows " : "throws ")
.fixItRemoveChars(typeEndLoc, throwsEndLoc);
}
if (auto diagOpt = diagnoseInvalidThrows()) {
assert(arrowLoc.isValid());
assert(retType);
SourceLoc typeEndLoc = Lexer::getLocForEndOfToken(SourceMgr,
retType->getEndLoc());
SourceLoc throwsEndLoc = Lexer::getLocForEndOfToken(SourceMgr, throwsLoc);
(*diagOpt).fixItInsert(arrowLoc, rethrows ? "rethrows " : "throws ")
.fixItRemoveChars(typeEndLoc, throwsEndLoc);
}
return Status;