Skip to content

Implement SE-0039 (Modernizing Playground Literals) #2215

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 14 commits into from
Apr 25, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Parse old object literals names using new syntax and provide FixIt.
For example, parse "#Image(imageLiteral:...)" and provide a FixIt to
change it to "#imageLiteral(resourceName:...)".  Now we see something like:

test.swift:4:9: error: '#Image' has been renamed to '#imageLiteral
var y = #Image(imageLiteral: "image.jpg")
        ^~~~~~ ~~~~~~~~~~~~
        #imageLiteral resourceName

Handling the old syntax, and providing a FixIt for that, will be handled in a separate
commit.

Needs tests.  Will be provided in later commit once full parsing support is done.
  • Loading branch information
tkremenek committed Apr 19, 2016
commit 1156672863b906447810d3a547271d245d9072ac
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,8 @@ ERROR(expected_rsquare_array_expr,PointsToFirstBadToken,
// Object literal expressions
ERROR(expected_arg_list_in_object_literal,none,
"expected argument list in object literal", ())
ERROR(object_literal_legacy_name,none,
"'%0' has been renamed to '%1", (StringRef, StringRef))

// If expressions
ERROR(expected_expr_after_if_question,none,
Expand Down
8 changes: 7 additions & 1 deletion include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,13 @@ class Parser {

Expr *parseExprAnonClosureArg();
ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok);
ParserResult<Expr> parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LK);

/// Parse an object literal.
///
/// \param LK The literal kind as determined by the first token.
/// \param NewName New name for a legacy literal.
ParserResult<Expr> parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LK,
StringRef NewName = StringRef());
ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn,
Identifier firstSelectorPiece
= Identifier(),
Expand Down
18 changes: 14 additions & 4 deletions include/swift/Parse/Tokens.def
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
#define POUND_OBJECT_LITERAL(kw, desc, proto) POUND_KEYWORD(kw)
#endif

/// POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)
/// Every keyword in the #foo namespace representing an object literal.
#ifndef POUND_OLD_OBJECT_LITERAL
#define POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg) POUND_KEYWORD(kw)
#endif

/// POUND_CONFIG(kw)
/// Every keyword in the #foo namespace representing a configuration.
#ifndef POUND_CONFIG
Expand Down Expand Up @@ -192,14 +198,17 @@ POUND_KEYWORD(selector)
// Keywords in the # namespace that are build configurations.
POUND_CONFIG(available)

// FIXME: It feels like a layering violation to mention the protocol
// kind and description here, but essentially there is a single
// delcarative way to specify the shape of object literals, their
// descriptive text, and their protocols.

// Declaratively define object literals, including their
// corresponding protocols.
POUND_OBJECT_LITERAL(fileLiteral, "file reference", FileReferenceLiteralConvertible)
POUND_OBJECT_LITERAL(imageLiteral, "image", ImageLiteralConvertible)
POUND_OBJECT_LITERAL(colorLiteral, "color", ColorLiteralConvertible)

POUND_OLD_OBJECT_LITERAL(FileReference, fileLiteral, fileReferenceLiteral, resourceName)
POUND_OLD_OBJECT_LITERAL(Image, imageLiteral, imageLiteral, resourceName)
POUND_OLD_OBJECT_LITERAL(Color, colorLiteral, colorLiteralRed, red)

POUND_KEYWORD(file)
POUND_KEYWORD(column)
POUND_KEYWORD(function)
Expand All @@ -214,4 +223,5 @@ POUND_KEYWORD(dsohandle)
#undef POUND_KEYWORD
#undef POUND_NORMAL_KEYWORD
#undef POUND_OBJECT_LITERAL
#undef POUND_OLD_OBJECT_LITERAL
#undef POUND_CONFIG
1 change: 1 addition & 0 deletions lib/IDE/SyntaxModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ SyntaxModelContext::SyntaxModelContext(SourceFile &SrcFile)

#define POUND_NORMAL_KEYWORD(Name) case tok::pound_##Name:
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) case tok::pound_##Name:
#define POUND_OLD_OBJECT_LITERAL(Name, NewName, OldArg, NewArg) case tok::pound_##Name:
#include "swift/Parse/Tokens.def"
Kind = SyntaxNodeKind::Keyword;
break;
Expand Down
47 changes: 46 additions & 1 deletion lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,12 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
break;
#include "swift/Parse/Tokens.def"

#define POUND_OLD_OBJECT_LITERAL(Name, NewName, NewArg, OldArg)\
case tok::pound_##Name:\
Result = parseExprObjectLiteral(ObjectLiteralExpr::NewName, "#" #NewName);\
break;
#include "swift/Parse/Tokens.def"

case tok::code_complete:
Result = makeParserResult(new (Context) CodeCompletionExpr(Tok.getRange()));
Result.setHasCodeCompletion();
Expand Down Expand Up @@ -2322,7 +2328,9 @@ ParserResult<Expr> Parser::parseExprList(tok LeftTok, tok RightTok) {
/// expr-literal:
/// '#' identifier expr-paren
ParserResult<Expr>
Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind) {
Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,
StringRef NewName) {
auto PoundTok = Tok;
SourceLoc PoundLoc = consumeToken();
// Parse a tuple of args
if (!Tok.is(tok::l_paren)) {
Expand All @@ -2337,6 +2345,43 @@ Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind) {
if (Arg.isParseError()) {
return makeParserError();
}
// If the legacy name was used (e.g., #Image instead of #imageLiteral)
// prompt an error and a fixit.
if (!NewName.empty()) {
auto diag =
diagnose(PoundTok, diag::object_literal_legacy_name,
PoundTok.getText(), NewName);
auto Range = PoundTok.getRange();

// Create a FixIt for the keyword.
diag.fixItReplaceChars(Range.getStart(), Range.getEnd(), NewName);

// Try and construct a FixIt for the argument label.
if (TupleExpr *TE = dyn_cast_or_null<TupleExpr>(Arg.get())) {
auto ArgLoc = TE->getElementNameLoc(0);
auto FirstElementName = TE->getElementName(0);

if (ArgLoc.isValid() && !FirstElementName.empty()) {
auto OldArg = FirstElementName.str();
auto NewArg =
llvm::StringSwitch<StringRef>(OldArg)
#define POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)\
.Case(#old_arg, #new_arg)
#include "swift/Parse/Tokens.def"
.Default("");

if (!NewArg.empty()) {
auto Loc = TE->getElementNameLoc(0);
diag.fixItReplaceChars(Loc,
Loc.getAdvancedLocOrInvalid(OldArg.size()),
NewArg);
}
}
}

return makeParserError();
}

return makeParserResult(
new (Context) ObjectLiteralExpr(PoundLoc, LitKind, Arg.get(),
/*implicit=*/false));
Expand Down