@@ -244,6 +244,10 @@ Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) {
244
244
result = generate (*specializeExpr, Loc);
245
245
else if (auto editorPlaceHolderExpr = E.getAs <EditorPlaceholderExprSyntax>())
246
246
result = generate (*editorPlaceHolderExpr, Loc);
247
+ else if (auto arrayExpr = E.getAs <ArrayExprSyntax>())
248
+ result = generate (*arrayExpr, Loc);
249
+ else if (auto dictionaryExpr = E.getAs <DictionaryExprSyntax>())
250
+ result = generate (*dictionaryExpr, Loc);
247
251
else if (auto integerLiteralExpr = E.getAs <IntegerLiteralExprSyntax>())
248
252
result = generate (*integerLiteralExpr, Loc);
249
253
else if (auto floatLiteralExpr = E.getAs <FloatLiteralExprSyntax>())
@@ -434,6 +438,94 @@ Expr *ASTGen::generate(const SpecializeExprSyntax &E, const SourceLoc Loc) {
434
438
rAngleLoc);
435
439
}
436
440
441
+ // / validateCollectionElement - Check if a given collection element is valid.
442
+ // /
443
+ // / At the moment, this checks whether a given collection element is a subscript
444
+ // / expression and whether we're subscripting into an array. If we are, then it
445
+ // / we emit a diagnostic in case it was not something that the user was
446
+ // / expecting.
447
+ // /
448
+ // / For example: `let array [ [0, 1] [42] ]`
449
+ void ASTGen::validateCollectionElement (Expr *elementExpr) {
450
+ if (!elementExpr)
451
+ return ;
452
+
453
+ if (!isa<SubscriptExpr>(elementExpr))
454
+ return ;
455
+
456
+ auto subscriptExpr = cast<SubscriptExpr>(elementExpr);
457
+ if (!isa<ArrayExpr>(subscriptExpr->getBase ()))
458
+ return ;
459
+
460
+ auto arrayExpr = cast<ArrayExpr>(subscriptExpr->getBase ());
461
+
462
+ auto startLocOfSubscript = subscriptExpr->getIndex ()->getStartLoc ();
463
+ auto endLocOfArray = arrayExpr->getEndLoc ();
464
+
465
+ auto locForEndOfTokenArray =
466
+ Lexer::getLocForEndOfToken (Context.SourceMgr , endLocOfArray);
467
+
468
+ if (locForEndOfTokenArray != startLocOfSubscript) {
469
+ auto subscriptLoc = subscriptExpr->getLoc ();
470
+ P.diagnose (subscriptLoc, diag::subscript_array_element)
471
+ .highlight (subscriptExpr->getSourceRange ());
472
+ P.diagnose (subscriptLoc, diag::subscript_array_element_fix_it_add_comma)
473
+ .fixItInsertAfter (endLocOfArray, " ," );
474
+ P.diagnose (subscriptLoc, diag::subscript_array_element_fix_it_remove_space)
475
+ .fixItRemoveChars (locForEndOfTokenArray, startLocOfSubscript);
476
+ }
477
+ }
478
+
479
+ Expr *ASTGen::generate (const ArrayExprSyntax &E, const SourceLoc Loc) {
480
+ SmallVector<Expr *, 8 > elements;
481
+ SmallVector<SourceLoc, 8 > commaLocs;
482
+ elements.reserve (E.getElements ().size ());
483
+ for (auto elemSyntax : E.getElements ()) {
484
+ if (auto elemAST = generate (elemSyntax.getExpression (), Loc)) {
485
+ validateCollectionElement (elemAST);
486
+ elements.push_back (elemAST);
487
+ }
488
+ if (auto comma = elemSyntax.getTrailingComma ())
489
+ commaLocs.push_back (advanceLocBegin (Loc, *comma));
490
+ }
491
+
492
+ // Don't bother to create expression if any expressions aren't parsed.
493
+ if (elements.empty () && !E.getElements ().empty ())
494
+ return nullptr ;
495
+
496
+ auto LSquareLoc = advanceLocBegin (Loc, E);
497
+ auto RSquareLoc = advanceLocEnd (Loc, E);
498
+ return ArrayExpr::create (Context, LSquareLoc, elements, commaLocs,
499
+ RSquareLoc);
500
+ }
501
+
502
+ Expr *ASTGen::generate (const DictionaryExprSyntax &E, const SourceLoc Loc) {
503
+ SmallVector<Expr *, 8 > elements;
504
+ SmallVector<SourceLoc, 8 > commaLocs;
505
+ if (auto contents = E.getContent ().getAs <DictionaryElementListSyntax>()) {
506
+ elements.reserve (contents->size ());
507
+ for (auto elemSyntax : *contents) {
508
+ if (auto key = generate (elemSyntax.getKeyExpression (), Loc)) {
509
+ auto val = generate (elemSyntax.getValueExpression (), Loc);
510
+ if (!val)
511
+ val = new (Context) ErrorExpr (advanceLocEnd (Loc, elemSyntax));
512
+ auto elemAST = TupleExpr::createImplicit (Context, {key, val}, {});
513
+ elements.push_back (elemAST);
514
+ }
515
+ if (auto comma = elemSyntax.getTrailingComma ())
516
+ commaLocs.push_back (advanceLocBegin (Loc, *comma));
517
+ }
518
+ // Don't bother to create expression if any expressions aren't parsed.
519
+ if (elements.empty () && !contents->empty ())
520
+ return nullptr ;
521
+ }
522
+
523
+ auto LSquareLoc = advanceLocBegin (Loc, E);
524
+ auto RSquareLoc = advanceLocEnd (Loc, E);
525
+ return DictionaryExpr::create (Context, LSquareLoc, elements, commaLocs,
526
+ RSquareLoc);
527
+ }
528
+
437
529
Expr *ASTGen::generate (const IntegerLiteralExprSyntax &Expr,
438
530
const SourceLoc Loc) {
439
531
auto Digits = Expr.getDigits ();
0 commit comments