diff --git a/include/swift/Parse/ASTGen.h b/include/swift/Parse/ASTGen.h index 06896bf6bc664..7cec25cbea816 100644 --- a/include/swift/Parse/ASTGen.h +++ b/include/swift/Parse/ASTGen.h @@ -16,7 +16,6 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" #include "swift/AST/Expr.h" -#include "swift/AST/TypeRepr.h" #include "swift/Parse/PersistentParserState.h" #include "swift/Syntax/SyntaxNodes.h" #include "llvm/ADT/DenseMap.h" @@ -44,30 +43,6 @@ class ASTGen { SourceLoc generate(const syntax::TokenSyntax &Tok, const SourceLoc Loc); - SourceLoc generateIdentifierDeclName(const syntax::TokenSyntax &Tok, - const SourceLoc, Identifier &Identifier); - -public: - //===--------------------------------------------------------------------===// - // Decls. - - Decl *generate(const syntax::DeclSyntax &Decl, const SourceLoc Loc); - TypeDecl *generate(const syntax::AssociatedtypeDeclSyntax &Decl, - const SourceLoc Loc); - - TrailingWhereClause *generate(const syntax::GenericWhereClauseSyntax &syntax, - const SourceLoc Loc); - MutableArrayRef - generate(const syntax::TypeInheritanceClauseSyntax &syntax, - const SourceLoc Loc, bool allowClassRequirement); - -private: - DeclAttributes - generateDeclAttributes(const syntax::DeclSyntax &D, - const Optional &attrs, - const Optional &modifiers, - SourceLoc Loc, bool includeComments); - public: //===--------------------------------------------------------------------===// // Expressions. @@ -122,8 +97,6 @@ class ASTGen { const SourceLoc Loc); TypeRepr *generate(const syntax::ImplicitlyUnwrappedOptionalTypeSyntax &Type, const SourceLoc Loc); - TypeRepr *generate(const syntax::ClassRestrictionTypeSyntax &Type, - const SourceLoc Loc); TypeRepr *generate(const syntax::CodeCompletionTypeSyntax &Type, const SourceLoc Loc); TypeRepr *generate(const syntax::UnknownTypeSyntax &Type, diff --git a/include/swift/Parse/LibSyntaxGenerator.h b/include/swift/Parse/LibSyntaxGenerator.h index 4f725904f2753..1333ed74af219 100644 --- a/include/swift/Parse/LibSyntaxGenerator.h +++ b/include/swift/Parse/LibSyntaxGenerator.h @@ -38,7 +38,7 @@ class LibSyntaxGenerator { assert(Node.isDeferredToken()); auto Kind = Node.getTokenKind(); - auto Range = Node.getDeferredTokenRange(); + auto Range = Node.getDeferredTokenRangeWithTrivia(); auto LeadingTriviaPieces = Node.getDeferredLeadingTriviaPieces(); auto TrailingTriviaPieces = Node.getDeferredTrailingTriviaPieces(); diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 2e36cc1abbff7..840b0dac37ed1 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1004,23 +1004,12 @@ class Parser { bool delayParsingDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, IterableDeclContext *IDC); - ParsedSyntaxResult - parseTypeInheritanceClauseSyntax(bool allowClassRequirement, - bool allowAnyObject); - - ParsedSyntaxResult - parseDeclAssociatedTypeSyntax(ParseDeclOptions flags, - Optional attrs, - Optional modifiers); - ParserResult parseDeclTypeAlias(ParseDeclOptions Flags, - DeclAttributes &Attributes, - SourceLoc leadingLoc); + DeclAttributes &Attributes); ParserResult parseDeclAssociatedType(ParseDeclOptions Flags, - DeclAttributes &Attributes, - SourceLoc leadingLoc); - + DeclAttributes &Attributes); + /// Parse a #if ... #endif directive. /// Delegate callback function to parse elements in the blocks. ParserResult parseIfConfig( @@ -1102,7 +1091,7 @@ class Parser { ParserResult parseDeclImport(ParseDeclOptions Flags, DeclAttributes &Attributes); - ParserStatus parseInheritance(MutableArrayRef &Inherited, + ParserStatus parseInheritance(SmallVectorImpl &Inherited, bool allowClassRequirement, bool allowAnyObject); ParserStatus parseDeclItem(bool &PreviousHadSemi, diff --git a/include/swift/Parse/SyntaxParsingContext.h b/include/swift/Parse/SyntaxParsingContext.h index 96d4d57924429..6df76bebca037 100644 --- a/include/swift/Parse/SyntaxParsingContext.h +++ b/include/swift/Parse/SyntaxParsingContext.h @@ -279,9 +279,17 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext { } /// Returns the topmost Syntax node. - template SyntaxNode topNode(); + template SyntaxNode topNode() { + ParsedRawSyntaxNode &TopNode = getStorage().back(); + if (TopNode.isRecorded()) { + OpaqueSyntaxNode OpaqueNode = TopNode.getOpaqueNode(); + return getSyntaxCreator().getLibSyntaxNodeFor(OpaqueNode); + } + return getSyntaxCreator().createNode(TopNode.copyDeferred()); + } - template llvm::Optional popIf() { + template + llvm::Optional popIf() { auto &Storage = getStorage(); if (Storage.size() <= Offset) return llvm::None; @@ -368,24 +376,5 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext { "Only meant for use in the debugger"); }; -template -inline SyntaxNode SyntaxParsingContext::topNode() { - ParsedRawSyntaxNode &TopNode = getStorage().back(); - if (TopNode.isRecorded()) { - OpaqueSyntaxNode OpaqueNode = TopNode.getOpaqueNode(); - return getSyntaxCreator().getLibSyntaxNodeFor(OpaqueNode); - } - return getSyntaxCreator().createNode(TopNode.copyDeferred()); -} - -template <> inline TokenSyntax SyntaxParsingContext::topNode() { - ParsedRawSyntaxNode &TopNode = getStorage().back(); - if (TopNode.isRecorded()) { - OpaqueSyntaxNode OpaqueNode = TopNode.getOpaqueNode(); - return getSyntaxCreator().getLibSyntaxNodeFor(OpaqueNode); - } - return getSyntaxCreator().createToken(TopNode.copyDeferred()); -} - } // namespace swift #endif // SWIFT_SYNTAX_PARSING_CONTEXT_H diff --git a/include/swift/Syntax/Syntax.h b/include/swift/Syntax/Syntax.h index 31fac98aa9a16..c4b2d8f227dc3 100644 --- a/include/swift/Syntax/Syntax.h +++ b/include/swift/Syntax/Syntax.h @@ -83,7 +83,7 @@ class Syntax { SyntaxKind getKind() const; /// Get the shared raw syntax. - const RC &getRaw() const; + RC getRaw() const; /// Get an ID for this node that is stable across incremental parses SyntaxNodeId getId() const { return getRaw()->getId(); } diff --git a/include/swift/Syntax/SyntaxData.h b/include/swift/Syntax/SyntaxData.h index 6159f2e01e2d8..aa6a69f1369ee 100644 --- a/include/swift/Syntax/SyntaxData.h +++ b/include/swift/Syntax/SyntaxData.h @@ -186,7 +186,7 @@ class SyntaxData final CursorIndex IndexInParent = 0); /// Returns the raw syntax node for this syntax node. - const RC &getRaw() const { + const RC getRaw() const { return Raw; } diff --git a/lib/Parse/ASTGen.cpp b/lib/Parse/ASTGen.cpp index b9def85ea3a9f..8ff9a94f7f174 100644 --- a/lib/Parse/ASTGen.cpp +++ b/lib/Parse/ASTGen.cpp @@ -12,7 +12,6 @@ #include "swift/Parse/ASTGen.h" -#include "DebuggerContextChange.h" #include "swift/Basic/SourceManager.h" #include "swift/Parse/CodeCompletionCallbacks.h" #include "swift/Parse/Parser.h" @@ -24,132 +23,6 @@ SourceLoc ASTGen::generate(const TokenSyntax &Tok, const SourceLoc Loc) { return advanceLocBegin(Loc, Tok); } -SourceLoc ASTGen::generateIdentifierDeclName(const syntax::TokenSyntax &Tok, - const SourceLoc Loc, - Identifier &Id) { - StringRef text; - if (Tok.getText() == "Any") - // Special handle 'Any' because we don't want to accidantaly declare 'Any' - // type in any way. - text = "#Any"; - else - text = Tok.getIdentifierText(); - - Id = Context.getIdentifier(text); - return advanceLocBegin(Loc, Tok); -} - -Decl *ASTGen::generate(const DeclSyntax &D, const SourceLoc Loc) { - Decl *DeclAST = nullptr; - - if (auto associatedTypeDecl = D.getAs()) { - DeclAST = generate(*associatedTypeDecl, Loc); - } else { - llvm_unreachable("unsupported decl kind"); - } - - return DeclAST; -} - -DeclAttributes -ASTGen::generateDeclAttributes(const DeclSyntax &D, - const Optional &attrs, - const Optional &modifiers, - SourceLoc Loc, bool includeComments) { - SourceLoc attrsLoc; - if (attrs) { - attrsLoc = advanceLocBegin(Loc, *attrs->getFirstToken()); - } else if (modifiers) { - attrsLoc = advanceLocBegin(Loc, *modifiers->getFirstToken()); - } else { - // We might have comment attributes. - attrsLoc = advanceLocBegin(Loc, *D.getFirstToken()); - } - if (hasDeclAttributes(attrsLoc)) - return getDeclAttributes(attrsLoc); - return DeclAttributes(); -} - -MutableArrayRef -ASTGen::generate(const TypeInheritanceClauseSyntax &clause, SourceLoc Loc, - bool allowClassRequirement) { - SmallVector inherited; - - bool hasClass = false; - for (const auto elem : clause.getInheritedTypeCollection()) { - const auto &tySyntax = elem.getTypeName(); - if (tySyntax.is()) { - // Accept 'class' only if it's allowed and it's the first one. - if (!allowClassRequirement || hasClass) - continue; - hasClass = true; - } - if (auto ty = generate(tySyntax, Loc)) - inherited.emplace_back(ty); - } - - return Context.AllocateCopy(inherited); -} - -TypeDecl *ASTGen::generate(const AssociatedtypeDeclSyntax &D, - const SourceLoc Loc) { - if (!isa(P.CurDeclContext)) { - // This is already diagnosed in Parser. - return nullptr; - } - - auto idToken = D.getIdentifier(); - if (idToken.isMissing()) - return nullptr; - - auto keywordLoc = advanceLocBegin(Loc, D.getAssociatedtypeKeyword()); - auto name = Context.getIdentifier(idToken.getIdentifierText()); - auto nameLoc = advanceLocBegin(Loc, idToken); - - DeclAttributes attrs = - generateDeclAttributes(D, D.getAttributes(), D.getModifiers(), Loc, true); - - DebuggerContextChange DCC(P, name, DeclKind::AssociatedType); - - ArrayRef inherited; - if (const auto inheritanceClause = D.getInheritanceClause()) - inherited = - generate(*inheritanceClause, Loc, /*allowClassRequirement=*/true); - - TypeRepr *defaultTy = nullptr; - if (const auto init = D.getInitializer()) - defaultTy = generate(init->getValue(), Loc); - - TrailingWhereClause *trailingWhere = nullptr; - if (auto whereClause = D.getGenericWhereClause()) - trailingWhere = generate(*whereClause, Loc); - - auto assocType = new (Context) - AssociatedTypeDecl(P.CurDeclContext, keywordLoc, name, nameLoc, defaultTy, - trailingWhere); - assocType->getAttrs() = attrs; - if (!inherited.empty()) - assocType->setInherited(Context.AllocateCopy(inherited)); - addToScope(assocType); - return assocType; -} - -TrailingWhereClause *ASTGen::generate(const GenericWhereClauseSyntax &syntax, - const SourceLoc Loc) { - SourceLoc whereLoc = advanceLocBegin(Loc, syntax.getWhereKeyword()); - - SmallVector requirements; - requirements.reserve(syntax.getRequirementList().size()); - for (auto elem : syntax.getRequirementList()) { - if (auto req = generate(elem, Loc)) - requirements.push_back(*req); - } - - if (requirements.empty()) - return nullptr; - return TrailingWhereClause::create(Context, whereLoc, requirements); -} - Expr *ASTGen::generate(const IntegerLiteralExprSyntax &Expr, const SourceLoc Loc) { auto Digits = Expr.getDigits(); @@ -251,8 +124,6 @@ TypeRepr *ASTGen::generate(const TypeSyntax &Type, const SourceLoc Loc) { TypeAST = generate(*Unwrapped, Loc); else if (auto Attributed = Type.getAs()) TypeAST = generate(*Attributed, Loc); - else if (auto ClassRestriction = Type.getAs()) - TypeAST = generate(*ClassRestriction, Loc); else if (auto CompletionTy = Type.getAs()) TypeAST = generate(*CompletionTy, Loc); else if (auto Unknown = Type.getAs()) @@ -513,6 +384,11 @@ TypeRepr *ASTGen::generate(const SimpleTypeIdentifierSyntax &Type, auto AnyLoc = advanceLocBegin(Loc, Type.getName()); return CompositionTypeRepr::createEmptyComposition(Context, AnyLoc); } + if (Type.getName().getText() == "class") { + auto classLoc = advanceLocBegin(Loc, Type.getName()); + return new (Context) + SimpleIdentTypeRepr(classLoc, Context.getIdentifier("AnyObject")); + } return generateSimpleOrMemberIdentifier(Type, Loc); } @@ -572,13 +448,6 @@ TypeRepr *ASTGen::generate(const ImplicitlyUnwrappedOptionalTypeSyntax &Type, ImplicitlyUnwrappedOptionalTypeRepr(WrappedType, ExclamationLoc); } -TypeRepr * -ASTGen::generate(const ClassRestrictionTypeSyntax &Type, const SourceLoc Loc) { - auto classLoc = advanceLocBegin(Loc, Type); - return new (Context) - SimpleIdentTypeRepr(classLoc, Context.getIdentifier("AnyObject")); -} - TypeRepr *ASTGen::generate(const CodeCompletionTypeSyntax &Type, const SourceLoc Loc) { auto base = Type.getBase(); @@ -720,7 +589,7 @@ GenericParamList *ASTGen::generate(const GenericParameterClauseSyntax &clause, if (auto inherited = elem.getInheritedType()) { if (auto ty = generate(*inherited, Loc)) { - SmallVector constraints = {ty}; + SmallVector constraints = {generate(*inherited, Loc)}; param->setInherited(Context.AllocateCopy(constraints)); } } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 0a87abbbb67e8..15ff71a34df9d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2692,7 +2692,6 @@ Parser::parseDecl(ParseDeclOptions Flags, SyntaxParsingContext DeclParsingContext(SyntaxContext, SyntaxContextKind::Decl); - SourceLoc leadingLoc = leadingTriviaLoc(); // Note that we're parsing a declaration. StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(), @@ -2710,13 +2709,6 @@ Parser::parseDecl(ParseDeclOptions Flags, StaticSpellingKind StaticSpelling = StaticSpellingKind::None; parseDeclModifierList(Attributes, StaticLoc, StaticSpelling); - if (!Attributes.isEmpty()) { - auto startLoc = Attributes.getStartLoc(); - if (startLoc.isInvalid()) - startLoc = Tok.getLoc(); - Generator.addDeclAttributes(Attributes, startLoc); - } - // We emit diagnostics for 'try let ...' in parseDeclVar(). SourceLoc tryLoc; if (Tok.is(tok::kw_try) && peekToken().isAny(tok::kw_let, tok::kw_var)) @@ -2768,11 +2760,12 @@ Parser::parseDecl(ParseDeclOptions Flags, } case tok::kw_typealias: DeclParsingContext.setCreateSyntax(SyntaxKind::TypealiasDecl); - DeclResult = parseDeclTypeAlias(Flags, Attributes, leadingLoc); + DeclResult = parseDeclTypeAlias(Flags, Attributes); MayNeedOverrideCompletion = true; break; case tok::kw_associatedtype: - DeclResult = parseDeclAssociatedType(Flags, Attributes, leadingLoc); + DeclParsingContext.setCreateSyntax(SyntaxKind::AssociatedtypeDecl); + DeclResult = parseDeclAssociatedType(Flags, Attributes); break; case tok::kw_enum: DeclParsingContext.setCreateSyntax(SyntaxKind::EnumDecl); @@ -3311,107 +3304,100 @@ ParserResult Parser::parseDeclImport(ParseDeclOptions Flags, /// 'class' /// type-identifier /// \endverbatim +ParserStatus Parser::parseInheritance(SmallVectorImpl &Inherited, + bool allowClassRequirement, + bool allowAnyObject) { + SyntaxParsingContext InheritanceContext(SyntaxContext, + SyntaxKind::TypeInheritanceClause); -ParsedSyntaxResult -Parser::parseTypeInheritanceClauseSyntax(bool allowClassRequirement, - bool allowAnyObject) { - ParsedTypeInheritanceClauseSyntaxBuilder builder(*SyntaxContext); - ParserStatus status; + Scope S(this, ScopeKind::InheritanceClause); + consumeToken(tok::colon); - builder.useColon(consumeTokenSyntax(tok::colon)); + SyntaxParsingContext TypeListContext(SyntaxContext, + SyntaxKind::InheritedTypeList); + SourceLoc classRequirementLoc; - SourceLoc startLoc = Tok.getLoc(); - SourceLoc classRequirementLoc, prevCommaLoc; - bool hasNext = true; + ParserStatus Status; + SourceLoc prevComma; + bool HasNextType; do { - ParsedInheritedTypeSyntaxBuilder elemBuilder(*SyntaxContext); - + SyntaxParsingContext TypeContext(SyntaxContext, SyntaxKind::InheritedType); + SWIFT_DEFER { + // Check for a ',', which indicates that there are more protocols coming. + HasNextType = consumeIf(tok::comma, prevComma); + }; // Parse the 'class' keyword for a class requirement. if (Tok.is(tok::kw_class)) { - auto classLoc = Tok.getLoc(); - auto classTok = consumeTokenSyntax(tok::kw_class); - auto restriction = ParsedSyntaxRecorder::makeClassRestrictionType( - std::move(classTok), *SyntaxContext); - elemBuilder.useTypeName(std::move(restriction)); - + SyntaxParsingContext ClassTypeContext(SyntaxContext, + SyntaxKind::ClassRestrictionType); + // If we aren't allowed to have a class requirement here, complain. + auto classLoc = consumeToken(); if (!allowClassRequirement) { - // If we aren't allowed to have a class requirement here, complain. diagnose(classLoc, diag::unexpected_class_constraint); - // Note that it makes no sense to suggest fixing 'struct S : class' to - // 'struct S : AnyObject' for example; in that case we just complain - // about 'class' being invalid here. + // Note that it makes no sense to suggest fixing + // 'struct S : class' to 'struct S : AnyObject' for + // example; in that case we just complain about + // 'class' being invalid here. if (allowAnyObject) { diagnose(classLoc, diag::suggest_anyobject) - .fixItReplace(classLoc, "AnyObject"); + .fixItReplace(classLoc, "AnyObject"); } + continue; + } - } else if (classRequirementLoc.isValid()) { - // If we already saw a class requirement, complain. - diagnose(Tok.getLoc(), diag::redundant_class_requirement) + // If we already saw a class requirement, complain. + if (classRequirementLoc.isValid()) { + diagnose(classLoc, diag::redundant_class_requirement) .highlight(classRequirementLoc) - .fixItRemove(SourceRange(prevCommaLoc, classLoc)); + .fixItRemove(SourceRange(prevComma, classLoc)); + continue; + } - } else if (prevCommaLoc.isValid()) { - // If the class requirement was not the first requirement, complain. + // If the class requirement was not the first requirement, complain. + if (!Inherited.empty()) { + SourceLoc properLoc = Inherited[0].getSourceRange().Start; diagnose(classLoc, diag::late_class_requirement) - .fixItInsert(startLoc, "class, ") - .fixItRemove(SourceRange(prevCommaLoc, classLoc)); + .fixItInsert(properLoc, "class, ") + .fixItRemove(SourceRange(prevComma, classLoc)); } // Record the location of the 'class' keyword. - if (!classRequirementLoc.isValid()) - classRequirementLoc = classLoc; - } else { - // Parse inherited type. - auto inheritedType = parseTypeSyntax(); - status |= inheritedType.getStatus(); - if (!inheritedType.isNull()) - elemBuilder.useTypeName(inheritedType.get()); - else - elemBuilder.useTypeName( - ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext)); - } + classRequirementLoc = classLoc; - // Parse ','. - if (Tok.is(tok::comma)) { - prevCommaLoc = Tok.getLoc(); - elemBuilder.useTrailingComma(consumeTokenSyntax(tok::comma)); - } else { - hasNext = false; + // Add 'AnyObject' to the inherited list. + Inherited.push_back( + new (Context) SimpleIdentTypeRepr(classLoc, + Context.getIdentifier("AnyObject"))); + continue; } - builder.addInheritedTypeCollectionMember(elemBuilder.build()); - } while (hasNext); + auto ParsedTypeResult = parseType(); + Status |= ParsedTypeResult; - return makeParsedResult(builder.build(), status); -} + // Record the type if its a single type. + if (ParsedTypeResult.isNonNull()) + Inherited.push_back(ParsedTypeResult.get()); + } while (HasNextType); -ParserStatus Parser::parseInheritance(MutableArrayRef &Inherited, - bool allowClassRequirement, - bool allowAnyObject) { - auto leadingLoc = leadingTriviaLoc(); - auto parsed = parseTypeInheritanceClauseSyntax(allowClassRequirement, - allowAnyObject); - SyntaxContext->addSyntax(parsed.get()); - auto clause = SyntaxContext->topNode(); - Inherited = Generator.generate(clause, leadingLoc, allowClassRequirement); - return parsed.getStatus(); + return Status; } -static ParsedSyntaxResult -parseIdentifierDeclNameSyntax(Parser &P, StringRef DeclKindName, - llvm::function_ref canRecover) { +static ParserStatus +parseIdentifierDeclName(Parser &P, Identifier &Result, SourceLoc &Loc, + StringRef DeclKindName, + llvm::function_ref canRecover) { if (P.Tok.is(tok::identifier)) { - auto text = P.Tok.getText(); - auto loc = P.Tok.getLoc(); + Loc = P.consumeIdentifier(&Result); - auto tok = P.consumeIdentifierSyntax(); + // We parsed an identifier for the declaration. If we see another + // identifier, it might've been a single identifier that got broken by a + // space or newline accidentally. if (P.Tok.isIdentifierOrUnderscore() && !P.Tok.isContextualDeclKeyword()) - P.diagnoseConsecutiveIDs(text, loc, DeclKindName); + P.diagnoseConsecutiveIDs(Result.str(), Loc, DeclKindName); // Return success anyway - return makeParsedResult(std::move(tok)); + return makeParserSuccess(); } P.checkForInputIncomplete(); @@ -3425,8 +3411,12 @@ parseIdentifierDeclNameSyntax(Parser &P, StringRef DeclKindName, // Pretend this works as an identifier, which shouldn't be observable since // actual uses of it will hit random other errors, e.g. `1()` won't be // callable. - P.Tok.setKind(tok::identifier); - return makeParsedResult(P.consumeTokenSyntax()); + Result = P.Context.getIdentifier(P.Tok.getText()); + Loc = P.Tok.getLoc(); + P.consumeToken(); + + // We recovered, so this is a success. + return makeParserSuccess(); } if (P.Tok.isKeyword()) { @@ -3436,8 +3426,14 @@ parseIdentifierDeclNameSyntax(Parser &P, StringRef DeclKindName, // Recover if the next token is one of the expected tokens. if (canRecover(P.peekToken())) { - P.Tok.setKind(tok::identifier); - return makeParsedResult(P.consumeTokenSyntax()); + llvm::SmallString<32> Name(P.Tok.getText()); + // Append an invalid character so that nothing can resolve to this name. + Name += "#"; + Result = P.Context.getIdentifier(Name.str()); + Loc = P.Tok.getLoc(); + P.consumeToken(); + // Return success because we recovered. + return makeParserSuccess(); } return makeParserError(); } @@ -3446,20 +3442,6 @@ parseIdentifierDeclNameSyntax(Parser &P, StringRef DeclKindName, return makeParserError(); } -static ParserStatus -parseIdentifierDeclName(Parser &P, Identifier &Result, SourceLoc &Loc, - StringRef DeclKindName, - llvm::function_ref canRecover) { - auto leadingLoc = P.leadingTriviaLoc(); - auto parsed = parseIdentifierDeclNameSyntax(P, DeclKindName, canRecover); - if (!parsed.isNull()) { - P.SyntaxContext->addSyntax(parsed.get()); - auto syntax = P.SyntaxContext->topNode(); - Loc = P.Generator.generateIdentifierDeclName(syntax, leadingLoc, Result); - } - return parsed.getStatus(); -} - /// Add a fix-it to remove the space in consecutive identifiers. /// Add a camel-cased option if it is different than the first option. void Parser::diagnoseConsecutiveIDs(StringRef First, SourceLoc FirstLoc, @@ -3668,7 +3650,7 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) { status |= extendedType; // Parse optional inheritance clause. - MutableArrayRef Inherited; + SmallVector Inherited; if (Tok.is(tok::colon)) status |= parseInheritance(Inherited, /*allowClassRequirement=*/false, @@ -3695,7 +3677,7 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) { ExtensionDecl *ext = ExtensionDecl::create(Context, ExtensionLoc, extendedType.getPtrOrNull(), - Inherited, + Context.AllocateCopy(Inherited), CurDeclContext, trailingWhereClause); ext->getAttrs() = Attributes; @@ -3965,9 +3947,8 @@ ParserStatus Parser::parseLineDirective(bool isLine) { /// decl-typealias: /// 'typealias' identifier generic-params? '=' type requirement-clause? /// \endverbatim -ParserResult -Parser::parseDeclTypeAlias(Parser::ParseDeclOptions Flags, - DeclAttributes &Attributes, SourceLoc leadingLoc) { +ParserResult Parser:: +parseDeclTypeAlias(Parser::ParseDeclOptions Flags, DeclAttributes &Attributes) { ParserPosition startPosition = getParserPosition(); llvm::Optional TmpCtxt; TmpCtxt.emplace(SyntaxContext); @@ -3986,7 +3967,7 @@ Parser::parseDeclTypeAlias(Parser::ParseDeclOptions Flags, TmpCtxt->setTransparent(); return nullptr; } - + DebuggerContextChange DCC(*this, Id, DeclKind::TypeAlias); Optional GenericsScope; @@ -4015,7 +3996,7 @@ Parser::parseDeclTypeAlias(Parser::ParseDeclOptions Flags, // If we're in a protocol and don't see an '=' this looks like leftover Swift 2 // code intending to be an associatedtype. backtrackToPosition(startPosition); - return parseDeclAssociatedType(Flags, Attributes, leadingLoc); + return parseDeclAssociatedType(Flags, Attributes); } TmpCtxt->setTransparent(); TmpCtxt.reset(); @@ -4074,116 +4055,95 @@ Parser::parseDeclTypeAlias(Parser::ParseDeclOptions Flags, /// Parse an associatedtype decl. /// +/// \verbatim /// decl-associatedtype: -/// 'associatedtype' identifier type-inheritance-clause? -/// ('=' type)? where-clause? -ParsedSyntaxResult -Parser::parseDeclAssociatedTypeSyntax(ParseDeclOptions flags, - Optional attrs, - Optional modifiers) { - ParsedAssociatedtypeDeclSyntaxBuilder builder(*SyntaxContext); - ParserStatus status; - - if (attrs) - builder.useAttributes(std::move(*attrs)); - if (modifiers) - builder.useModifiers(std::move(*modifiers)); +/// 'associatedtype' identifier inheritance? ('=' type)? where-clause? +/// \endverbatim - // Parse 'associatedtype' keyword. - // Look for 'typealias' here and diagnose a fixit because parseDeclTypeAlias - // can ask us to fix up leftover Swift 2 code intending to be an - // associatedtype. - auto keywordLoc = Tok.getLoc(); +ParserResult Parser::parseDeclAssociatedType(Parser::ParseDeclOptions Flags, + DeclAttributes &Attributes) { + SourceLoc AssociatedTypeLoc; + ParserStatus Status; + Identifier Id; + SourceLoc IdLoc; + + // Look for 'typealias' here and diagnose a fixit because parseDeclTypeAlias can + // ask us to fix up leftover Swift 2 code intending to be an associatedtype. if (Tok.is(tok::kw_typealias)) { - diagnose(Tok.getLoc(), diag::typealias_inside_protocol_without_type) - .fixItReplace(Tok.getLoc(), "associatedtype"); - ignoreToken(tok::kw_typealias); + AssociatedTypeLoc = consumeToken(tok::kw_typealias); + diagnose(AssociatedTypeLoc, diag::typealias_inside_protocol_without_type) + .fixItReplace(AssociatedTypeLoc, "associatedtype"); } else { - builder.useAssociatedtypeKeyword( - consumeTokenSyntax(tok::kw_associatedtype)); + AssociatedTypeLoc = consumeToken(tok::kw_associatedtype); } - // Parse the name. - auto name = parseIdentifierDeclNameSyntax( - *this, "associatedtype", - [&](const Token &next) { return next.isAny(tok::colon, tok::equal); }); - if (name.isNull()) - return makeParsedResult(builder.build(), name.getStatus()); - assert(name.isSuccess()); - builder.useIdentifier(name.get()); - - // Diagnose generic parameters. + Status = parseIdentifierDeclName( + *this, Id, IdLoc, "associatedtype", + [](const Token &next) { return next.isAny(tok::colon, tok::equal); }); + if (Status.isError()) + return nullptr; + + DebuggerContextChange DCC(*this, Id, DeclKind::AssociatedType); + + // Reject generic parameters with a specific error. if (startsWithLess(Tok)) { - auto loc = Tok.getLoc(); - ignoreToken(); - if (ignoreUntilGreaterInTypeList()) - ignoreToken(); + // Introduce a throwaway scope to capture the generic parameters. We + // don't want them visible anywhere! + Scope S(this, ScopeKind::Generics); - diagnose(loc, diag::associated_type_generic_parameter_list) - .fixItRemove({loc, PreviousLoc}); + if (auto genericParams = parseGenericParameters().getPtrOrNull()) { + diagnose(genericParams->getLAngleLoc(), + diag::associated_type_generic_parameter_list) + .fixItRemove(genericParams->getSourceRange()); + } } - + // Parse optional inheritance clause. - if (Tok.is(tok::colon)) { - auto inheritance = parseTypeInheritanceClauseSyntax( - /*allowClassRequirement=*/false, /*allowAnyObject=*/true); - status |= inheritance.getStatus(); - if (!inheritance.isNull()) - builder.useInheritanceClause(inheritance.get()); - } - - // Parse optional default type. + // FIXME: Allow class requirements here. + SmallVector Inherited; + if (Tok.is(tok::colon)) + Status |= parseInheritance(Inherited, + /*allowClassRequirement=*/false, + /*allowAnyObject=*/true); + + ParserResult UnderlyingTy; if (Tok.is(tok::equal)) { - ParsedTypeInitializerClauseSyntaxBuilder initBuilder(*SyntaxContext); - initBuilder.useEqual(consumeTokenSyntax(tok::equal)); - - // Parse type. - auto type = parseTypeSyntax(diag::expected_type_in_associatedtype); - status |= type.getStatus(); - if (!type.isNull()) - initBuilder.useValue(type.get()); - else - initBuilder.useValue( - ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext)); - - builder.useInitializer(initBuilder.build()); + SyntaxParsingContext InitContext(SyntaxContext, + SyntaxKind::TypeInitializerClause); + consumeToken(tok::equal); + UnderlyingTy = parseType(diag::expected_type_in_associatedtype); + Status |= UnderlyingTy; + if (UnderlyingTy.isNull()) + return Status; } - // Parse optional 'where' clause. + TrailingWhereClause *TrailingWhere = nullptr; + // Parse a 'where' clause if present. if (Tok.is(tok::kw_where)) { - bool firstTypeInComplete = false; - auto where = parseGenericWhereClauseSyntax(firstTypeInComplete); - status |= where.getStatus(); - if (!where.isNull()) - builder.useGenericWhereClause(where.get()); - } - - // Diagnose if it's not in protocol decl. - // TODO: Move this to ASTGen. - if (!flags.contains(PD_InProtocol)) { - diagnose(keywordLoc, diag::associatedtype_outside_protocol) - .fixItReplace(keywordLoc, "typealias"); - status.setIsParseError(); + auto whereStatus = parseProtocolOrAssociatedTypeWhereClause( + TrailingWhere, /*isProtocol=*/false); + Status |= whereStatus; + if (whereStatus.hasCodeCompletion() && !CodeCompletion) { + // Trigger delayed parsing, no need to continue. + return whereStatus; + } } - return makeParsedResult(builder.build(), status); -} + if (!Flags.contains(PD_InProtocol)) { + diagnose(AssociatedTypeLoc, diag::associatedtype_outside_protocol) + .fixItReplace(AssociatedTypeLoc, "typealias"); + Status.setIsParseError(); + return Status; + } -ParserResult -Parser::parseDeclAssociatedType(Parser::ParseDeclOptions Flags, - DeclAttributes &Attributes, - SourceLoc leadingLoc) { - auto modifiers = SyntaxContext->popIf(); - auto attrs = SyntaxContext->popIf(); - - auto parsed = parseDeclAssociatedTypeSyntax(Flags, std::move(attrs), - std::move(modifiers)); - assert(!parsed.isNull()); - - SyntaxContext->addSyntax(parsed.get()); - auto syntax = SyntaxContext->topNode(); - auto result = Generator.generate(syntax, leadingLoc); - return makeParserResult(parsed.getStatus(), result); + auto assocType = new (Context) + AssociatedTypeDecl(CurDeclContext, AssociatedTypeLoc, Id, IdLoc, + UnderlyingTy.getPtrOrNull(), TrailingWhere); + assocType->getAttrs() = Attributes; + if (!Inherited.empty()) + assocType->setInherited(Context.AllocateCopy(Inherited)); + addToScope(assocType); + return makeParserResult(Status, assocType); } /// This function creates an accessor function (with no body) for a computed @@ -5614,11 +5574,11 @@ ParserResult Parser::parseDeclEnum(ParseDeclOptions Flags, // Parse optional inheritance clause within the context of the enum. if (Tok.is(tok::colon)) { - MutableArrayRef Inherited; + SmallVector Inherited; Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false, /*allowAnyObject=*/false); - ED->setInherited(Inherited); + ED->setInherited(Context.AllocateCopy(Inherited)); } diagnoseWhereClauseInGenericParamList(GenericParams); @@ -5900,11 +5860,11 @@ ParserResult Parser::parseDeclStruct(ParseDeclOptions Flags, // Parse optional inheritance clause within the context of the struct. if (Tok.is(tok::colon)) { - MutableArrayRef Inherited; + SmallVector Inherited; Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false, /*allowAnyObject=*/false); - SD->setInherited(Inherited); + SD->setInherited(Context.AllocateCopy(Inherited)); } diagnoseWhereClauseInGenericParamList(GenericParams); @@ -5993,11 +5953,11 @@ ParserResult Parser::parseDeclClass(ParseDeclOptions Flags, // Parse optional inheritance clause within the context of the class. if (Tok.is(tok::colon)) { - MutableArrayRef Inherited; + SmallVector Inherited; Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false, /*allowAnyObject=*/false); - CD->setInherited(Inherited); + CD->setInherited(Context.AllocateCopy(Inherited)); // Parse python style inheritance clause and replace parentheses with a colon } else if (Tok.is(tok::l_paren)) { @@ -6099,7 +6059,7 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) { DebuggerContextChange DCC (*this); // Parse optional inheritance clause. - MutableArrayRef InheritedProtocols; + SmallVector InheritedProtocols; SourceLoc colonLoc; if (Tok.is(tok::colon)) { colonLoc = Tok.getLoc(); @@ -6119,7 +6079,7 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) { ProtocolDecl *Proto = new (Context) ProtocolDecl(CurDeclContext, ProtocolLoc, NameLoc, ProtocolName, - InheritedProtocols, TrailingWhere); + Context.AllocateCopy(InheritedProtocols), TrailingWhere); // No need to setLocalDiscriminator: protocols can't appear in local contexts. Proto->getAttrs() = Attributes; diff --git a/lib/Parse/ParseGeneric.cpp b/lib/Parse/ParseGeneric.cpp index 7e21c510cdfdd..ee00e32c6aad8 100644 --- a/lib/Parse/ParseGeneric.cpp +++ b/lib/Parse/ParseGeneric.cpp @@ -104,8 +104,9 @@ Parser::parseGenericParameterClauseSyntax() { diagnose(Tok, diag::unexpected_class_constraint); diagnose(Tok, diag::suggest_anyobject) .fixItReplace(Tok.getLoc(), "AnyObject"); - auto ty = ParsedSyntaxRecorder::makeClassRestrictionType( - consumeTokenSyntax(tok::kw_class), *SyntaxContext); + Tok.setKind(tok::identifier); + auto ty = ParsedSyntaxRecorder::makeSimpleTypeIdentifier( + consumeTokenSyntax(), None, *SyntaxContext); paramBuilder.useInheritedType(std::move(ty)); } else { diagnose(Tok, diag::expected_generics_type_restriction, ident); diff --git a/lib/Syntax/Syntax.cpp b/lib/Syntax/Syntax.cpp index 850fb9ecbf082..57aa313597c7b 100644 --- a/lib/Syntax/Syntax.cpp +++ b/lib/Syntax/Syntax.cpp @@ -18,7 +18,7 @@ using namespace swift; using namespace swift::syntax; -const RC &Syntax::getRaw() const { +RC Syntax::getRaw() const { return Data->getRaw(); } diff --git a/test/Syntax/serialize_tupletype.swift.result b/test/Syntax/serialize_tupletype.swift.result index fcccca1cb3731..c186b51c93d6b 100644 --- a/test/Syntax/serialize_tupletype.swift.result +++ b/test/Syntax/serialize_tupletype.swift.result @@ -1,23 +1,23 @@ { - "id": 40, + "id": 39, "kind": "SourceFile", "layout": [ { - "id": 39, + "id": 38, "kind": "CodeBlockItemList", "layout": [ { - "id": 37, + "id": 36, "kind": "CodeBlockItem", "layout": [ { - "id": 36, + "id": 35, "kind": "TypealiasDecl", "layout": [ null, null, { - "id": 34, + "id": 33, "tokenKind": { "kind": "kw_typealias" }, @@ -48,7 +48,7 @@ "presence": "Present" }, { - "id": 35, + "id": 34, "tokenKind": { "kind": "identifier", "text": "x" @@ -64,11 +64,11 @@ }, null, { - "id": 33, + "id": 32, "kind": "TypeInitializerClause", "layout": [ { - "id": 2, + "id": 1, "tokenKind": { "kind": "equal" }, @@ -82,11 +82,11 @@ "presence": "Present" }, { - "id": 32, + "id": 31, "kind": "TupleType", "layout": [ { - "id": 19, + "id": 18, "tokenKind": { "kind": "l_paren" }, @@ -95,16 +95,16 @@ "presence": "Present" }, { - "id": 30, + "id": 29, "kind": "TupleTypeElementList", "layout": [ { - "id": 25, + "id": 24, "kind": "TupleTypeElement", "layout": [ null, { - "id": 20, + "id": 19, "tokenKind": { "kind": "identifier", "text": "b" @@ -115,7 +115,7 @@ }, null, { - "id": 21, + "id": 20, "tokenKind": { "kind": "colon" }, @@ -129,11 +129,11 @@ "presence": "Present" }, { - "id": 23, + "id": 22, "kind": "SimpleTypeIdentifier", "layout": [ { - "id": 22, + "id": 21, "tokenKind": { "kind": "identifier", "text": "Int" @@ -149,7 +149,7 @@ null, null, { - "id": 24, + "id": 23, "tokenKind": { "kind": "comma" }, @@ -166,12 +166,12 @@ "presence": "Present" }, { - "id": 29, + "id": 28, "kind": "TupleTypeElement", "layout": [ null, { - "id": 26, + "id": 25, "tokenKind": { "kind": "kw__" }, @@ -181,7 +181,7 @@ }, null, { - "id": 21, + "id": 20, "tokenKind": { "kind": "colon" }, @@ -195,11 +195,11 @@ "presence": "Present" }, { - "id": 28, + "id": 27, "kind": "SimpleTypeIdentifier", "layout": [ { - "id": 27, + "id": 26, "tokenKind": { "kind": "identifier", "text": "String" @@ -222,7 +222,7 @@ "presence": "Present" }, { - "id": 31, + "id": 30, "tokenKind": { "kind": "r_paren" }, @@ -249,7 +249,7 @@ "presence": "Present" }, { - "id": 38, + "id": 37, "tokenKind": { "kind": "eof", "text": "" diff --git a/utils/gyb_syntax_support/AttributeNodes.py b/utils/gyb_syntax_support/AttributeNodes.py index a663f92fae5d0..c185a1da30031 100644 --- a/utils/gyb_syntax_support/AttributeNodes.py +++ b/utils/gyb_syntax_support/AttributeNodes.py @@ -79,7 +79,6 @@ # attribute-list -> attribute attribute-list? Node('AttributeList', kind='SyntaxCollection', - omit_when_empty=True, element='Syntax', element_name='Attribute', element_choices=[ 'Attribute', diff --git a/utils/gyb_syntax_support/DeclNodes.py b/utils/gyb_syntax_support/DeclNodes.py index 14111b3b45a7c..6741725b51072 100644 --- a/utils/gyb_syntax_support/DeclNodes.py +++ b/utils/gyb_syntax_support/DeclNodes.py @@ -374,7 +374,6 @@ # | 'weak' # mutation-modifier -> 'mutating' | 'nonmutating' Node('ModifierList', kind='SyntaxCollection', - omit_when_empty=True, element='DeclModifier', element_name='Modifier'),