mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[libSyntax] Model parameter modifiers as a ModifierList
This fixes a libSyntax misparse where the first parameter name was parsed as the `isolated` token.
This commit is contained in:
@@ -254,70 +254,75 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
|
||||
status.setHasCodeCompletionAndIsError();
|
||||
}
|
||||
}
|
||||
|
||||
// ('inout' | '__shared' | '__owned' | isolated)?
|
||||
bool hasSpecifier = false;
|
||||
while (Tok.is(tok::kw_inout) ||
|
||||
Tok.isContextualKeyword("__shared") ||
|
||||
Tok.isContextualKeyword("__owned") ||
|
||||
Tok.isContextualKeyword("isolated") ||
|
||||
Tok.isContextualKeyword("_const")) {
|
||||
|
||||
if (Tok.isContextualKeyword("isolated")) {
|
||||
// did we already find an 'isolated' type modifier?
|
||||
if (param.IsolatedLoc.isValid()) {
|
||||
diagnose(Tok, diag::parameter_specifier_repeated)
|
||||
{
|
||||
SyntaxParsingContext ModifiersContext(SyntaxContext, SyntaxKind::ModifierList);
|
||||
|
||||
// ('inout' | '__shared' | '__owned' | isolated)?
|
||||
bool hasSpecifier = false;
|
||||
while (Tok.is(tok::kw_inout) ||
|
||||
Tok.isContextualKeyword("__shared") ||
|
||||
Tok.isContextualKeyword("__owned") ||
|
||||
Tok.isContextualKeyword("isolated") ||
|
||||
Tok.isContextualKeyword("_const")) {
|
||||
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
|
||||
|
||||
if (Tok.isContextualKeyword("isolated")) {
|
||||
// did we already find an 'isolated' type modifier?
|
||||
if (param.IsolatedLoc.isValid()) {
|
||||
diagnose(Tok, diag::parameter_specifier_repeated)
|
||||
.fixItRemove(Tok.getLoc());
|
||||
consumeToken();
|
||||
consumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
// is this 'isolated' token the identifier of an argument label?
|
||||
bool partOfArgumentLabel = lookahead<bool>(1, [&](CancellableBacktrackingScope &) {
|
||||
if (Tok.is(tok::colon))
|
||||
return true; // isolated :
|
||||
|
||||
// isolated x :
|
||||
return Tok.canBeArgumentLabel() && peekToken().is(tok::colon);
|
||||
});
|
||||
|
||||
if (partOfArgumentLabel)
|
||||
break;
|
||||
|
||||
// consume 'isolated' as type modifier
|
||||
param.IsolatedLoc = consumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
// is this 'isolated' token the identifier of an argument label?
|
||||
bool partOfArgumentLabel = lookahead<bool>(1, [&](CancellableBacktrackingScope &) {
|
||||
if (Tok.is(tok::colon))
|
||||
return true; // isolated :
|
||||
|
||||
// isolated x :
|
||||
return Tok.canBeArgumentLabel() && peekToken().is(tok::colon);
|
||||
});
|
||||
|
||||
if (partOfArgumentLabel)
|
||||
break;
|
||||
|
||||
// consume 'isolated' as type modifier
|
||||
param.IsolatedLoc = consumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Tok.isContextualKeyword("_const")) {
|
||||
param.CompileConstLoc = consumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hasSpecifier) {
|
||||
if (Tok.is(tok::kw_inout)) {
|
||||
// This case is handled later when mapping to ParamDecls for
|
||||
// better fixits.
|
||||
param.SpecifierKind = ParamDecl::Specifier::InOut;
|
||||
param.SpecifierLoc = consumeToken();
|
||||
} else if (Tok.isContextualKeyword("__shared")) {
|
||||
// This case is handled later when mapping to ParamDecls for
|
||||
// better fixits.
|
||||
param.SpecifierKind = ParamDecl::Specifier::Shared;
|
||||
param.SpecifierLoc = consumeToken();
|
||||
} else if (Tok.isContextualKeyword("__owned")) {
|
||||
// This case is handled later when mapping to ParamDecls for
|
||||
// better fixits.
|
||||
param.SpecifierKind = ParamDecl::Specifier::Owned;
|
||||
param.SpecifierLoc = consumeToken();
|
||||
if (Tok.isContextualKeyword("_const")) {
|
||||
param.CompileConstLoc = consumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hasSpecifier) {
|
||||
if (Tok.is(tok::kw_inout)) {
|
||||
// This case is handled later when mapping to ParamDecls for
|
||||
// better fixits.
|
||||
param.SpecifierKind = ParamDecl::Specifier::InOut;
|
||||
param.SpecifierLoc = consumeToken();
|
||||
} else if (Tok.isContextualKeyword("__shared")) {
|
||||
// This case is handled later when mapping to ParamDecls for
|
||||
// better fixits.
|
||||
param.SpecifierKind = ParamDecl::Specifier::Shared;
|
||||
param.SpecifierLoc = consumeToken();
|
||||
} else if (Tok.isContextualKeyword("__owned")) {
|
||||
// This case is handled later when mapping to ParamDecls for
|
||||
// better fixits.
|
||||
param.SpecifierKind = ParamDecl::Specifier::Owned;
|
||||
param.SpecifierLoc = consumeToken();
|
||||
}
|
||||
hasSpecifier = true;
|
||||
} else {
|
||||
// Redundant specifiers are fairly common, recognize, reject, and
|
||||
// recover from this gracefully.
|
||||
diagnose(Tok, diag::parameter_specifier_repeated)
|
||||
.fixItRemove(Tok.getLoc());
|
||||
consumeToken();
|
||||
}
|
||||
hasSpecifier = true;
|
||||
} else {
|
||||
// Redundant specifiers are fairly common, recognize, reject, and
|
||||
// recover from this gracefully.
|
||||
diagnose(Tok, diag::parameter_specifier_repeated)
|
||||
.fixItRemove(Tok.getLoc());
|
||||
consumeToken();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user