ParserResult<GenericParamList> Parser::parseGenericParameters(SourceLoc LAngleLoc) { // Parse the generic parameter list. SmallVector<GenericTypeParamDecl *, 4> GenericParams; bool Invalid = false; do { // Note that we're parsing a declaration. StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(), StructureMarkerKind::Declaration); // Parse attributes. DeclAttributes attributes; if (Tok.hasComment()) attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange())); bool foundCCTokenInAttr; parseDeclAttributeList(attributes, foundCCTokenInAttr); // Parse the name of the parameter. Identifier Name; SourceLoc NameLoc; if (parseIdentifier(Name, NameLoc, diag::expected_generics_parameter_name)) { Invalid = true; break; } // Parse the ':' followed by a type. SmallVector<TypeLoc, 1> Inherited; if (Tok.is(tok::colon)) { (void)consumeToken(); ParserResult<TypeRepr> Ty; if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol, tok::kw_Any)) { Ty = parseTypeIdentifierOrTypeComposition(); } else if (Tok.is(tok::kw_class)) { diagnose(Tok, diag::unexpected_class_constraint); diagnose(Tok, diag::suggest_anyobject, Name) .fixItReplace(Tok.getLoc(), "AnyObject"); consumeToken(); Invalid = true; } else { diagnose(Tok, diag::expected_generics_type_restriction, Name); Invalid = true; } if (Ty.hasCodeCompletion()) return makeParserCodeCompletionStatus(); if (Ty.isNonNull()) Inherited.push_back(Ty.get()); } // We always create generic type parameters with a depth of zero. // Semantic analysis fills in the depth when it processes the generic // parameter list. auto Param = new (Context) GenericTypeParamDecl(CurDeclContext, Name, NameLoc, /*Depth=*/0, GenericParams.size()); if (!Inherited.empty()) Param->setInherited(Context.AllocateCopy(Inherited)); GenericParams.push_back(Param); // Attach attributes. Param->getAttrs() = attributes; // Add this parameter to the scope. addToScope(Param); // Parse the comma, if the list continues. } while (consumeIf(tok::comma)); // Parse the optional where-clause. SourceLoc WhereLoc; SmallVector<RequirementRepr, 4> Requirements; bool FirstTypeInComplete; if (Tok.is(tok::kw_where) && parseGenericWhereClause(WhereLoc, Requirements, FirstTypeInComplete).isError()) { Invalid = true; } // Parse the closing '>'. SourceLoc RAngleLoc; if (!startsWithGreater(Tok)) { if (!Invalid) { diagnose(Tok, diag::expected_rangle_generics_param); diagnose(LAngleLoc, diag::opening_angle); Invalid = true; } // Skip until we hit the '>'. skipUntilGreaterInTypeList(); if (startsWithGreater(Tok)) RAngleLoc = consumeStartingGreater(); else RAngleLoc = Tok.getLoc(); } else { RAngleLoc = consumeStartingGreater(); } if (GenericParams.empty()) return nullptr; return makeParserResult(GenericParamList::create(Context, LAngleLoc, GenericParams, WhereLoc, Requirements, RAngleLoc)); }
ParserStatus Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc, SmallVectorImpl<GenericTypeParamDecl *> &GenericParams) { ParserStatus Result; SyntaxParsingContext GPSContext(SyntaxContext, SyntaxKind::GenericParameterList); bool HasNextParam; do { SyntaxParsingContext GParamContext(SyntaxContext, SyntaxKind::GenericParameter); // Note that we're parsing a declaration. StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(), StructureMarkerKind::Declaration); if (ParsingDecl.isFailed()) { return makeParserError(); } // Parse attributes. DeclAttributes attributes; if (Tok.hasComment()) attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange())); bool foundCCTokenInAttr; parseDeclAttributeList(attributes, foundCCTokenInAttr); // Parse the name of the parameter. Identifier Name; SourceLoc NameLoc; if (parseIdentifier(Name, NameLoc, diag::expected_generics_parameter_name)) { Result.setIsParseError(); break; } // Parse the ':' followed by a type. SmallVector<TypeLoc, 1> Inherited; if (Tok.is(tok::colon)) { (void)consumeToken(); ParserResult<TypeRepr> Ty; if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol, tok::kw_Any)) { Ty = parseType(); } else if (Tok.is(tok::kw_class)) { diagnose(Tok, diag::unexpected_class_constraint); diagnose(Tok, diag::suggest_anyobject) .fixItReplace(Tok.getLoc(), "AnyObject"); consumeToken(); Result.setIsParseError(); } else { diagnose(Tok, diag::expected_generics_type_restriction, Name); Result.setIsParseError(); } if (Ty.hasCodeCompletion()) return makeParserCodeCompletionStatus(); if (Ty.isNonNull()) Inherited.push_back(Ty.get()); } // We always create generic type parameters with an invalid depth. // Semantic analysis fills in the depth when it processes the generic // parameter list. auto Param = new (Context) GenericTypeParamDecl(CurDeclContext, Name, NameLoc, GenericTypeParamDecl::InvalidDepth, GenericParams.size()); if (!Inherited.empty()) Param->setInherited(Context.AllocateCopy(Inherited)); GenericParams.push_back(Param); // Attach attributes. Param->getAttrs() = attributes; // Add this parameter to the scope. addToScope(Param); // Parse the comma, if the list continues. HasNextParam = consumeIf(tok::comma); } while (HasNextParam); return Result; }