//===--- GenericSyntax.cpp - Swift Generic Syntax Implementation ----------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift/Syntax/GenericSyntax.h" #include "swift/Syntax/RawSyntax.h" #include "swift/Syntax/SyntaxFactory.h" #include "swift/Syntax/TypeSyntax.h" using llvm::Optional; using llvm::None; using namespace swift; using namespace swift::syntax; #pragma mark - conformance-requirement Data ConformanceRequirementSyntaxData:: ConformanceRequirementSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : GenericRequirementSyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::ConformanceRequirement); syntax_assert_child_kind(Raw, ConformanceRequirementSyntax::Cursor::LeftTypeIdentifier, SyntaxKind::TypeIdentifier); syntax_assert_child_token_text(Raw, ConformanceRequirementSyntax::Cursor::Colon, tok::colon, ":"); syntax_assert_child_kind(Raw, ConformanceRequirementSyntax::Cursor::RightTypeIdentifier, SyntaxKind::TypeIdentifier); } RC ConformanceRequirementSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new ConformanceRequirementSyntaxData { Raw, Parent, IndexInParent } }; } RC ConformanceRequirementSyntaxData::makeBlank() { auto Raw = RawSyntax::make(SyntaxKind::ConformanceRequirement, { RawSyntax::missing(SyntaxKind::TypeIdentifier), TokenSyntax::missingToken(tok::colon, ":"), RawSyntax::missing(SyntaxKind::TypeIdentifier), }, SourcePresence::Present); return make(Raw); } #pragma mark - generic-parameter Data GenericParameterSyntaxData:: GenericParameterSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::GenericParameter); } RC GenericParameterSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new GenericParameterSyntaxData { Raw, Parent, IndexInParent } }; } RC GenericParameterSyntaxData::makeBlank() { return make(RawSyntax::make(SyntaxKind::GenericParameter, { TokenSyntax::missingToken(tok::identifier, ""), TokenSyntax::missingToken(tok::colon, ":"), RawSyntax::missing(SyntaxKind::MissingType), }, SourcePresence::Present)); } #pragma mark - generic-parameter API GenericParameterSyntax:: GenericParameterSyntax(RC Root, const GenericParameterSyntaxData *Data) : Syntax(Root, Data) {} #pragma mark - generic-parameter-list Data GenericParameterListSyntaxData:: GenericParameterListSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::GenericParameterList); } RC GenericParameterListSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new GenericParameterListSyntaxData { Raw, Parent, IndexInParent } }; } RC GenericParameterListSyntaxData::makeBlank() { auto Raw = RawSyntax::make(SyntaxKind::GenericParameterList, {}, SourcePresence::Present); return make(Raw); } #pragma mark - #pragma mark generic-parameter-clause Data GenericParameterClauseSyntaxData:: GenericParameterClauseSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) { syntax_assert_child_token_text(Raw, GenericParameterClauseSyntax::Cursor::LeftAngleBracketToken, tok::l_angle, "<"); syntax_assert_child_kind(Raw, GenericParameterClauseSyntax::Cursor::GenericParameterList, SyntaxKind::GenericParameterList); syntax_assert_child_token_text(Raw, GenericParameterClauseSyntax::Cursor::RightAngleBracketToken, tok::r_angle, ">"); } RC GenericParameterClauseSyntaxData::make(const RC Raw, const SyntaxData *Parent, const CursorIndex IndexInParent) { return RC { new GenericParameterClauseSyntaxData { Raw, Parent, IndexInParent, } }; } RC GenericParameterClauseSyntaxData::makeBlank() { return make(RawSyntax::make(SyntaxKind::GenericParameterClause, { TokenSyntax::missingToken(tok::l_angle, "<"), RawSyntax::missing(SyntaxKind::GenericParameterList), TokenSyntax::missingToken(tok::r_angle, ">"), }, SourcePresence::Present)); } #pragma mark - generic-parameter-clause API GenericParameterClauseSyntax:: GenericParameterClauseSyntax(const RC Root, const GenericParameterClauseSyntaxData *Data) : Syntax(Root, Data) {} #pragma mark - generic-parameter-clause Builder GenericParameterClauseBuilder::GenericParameterClauseBuilder() : LeftAngleToken(TokenSyntax::missingToken(tok::l_angle, "<")), ParameterListLayout(RawSyntax::missing(SyntaxKind::GenericParameterList) ->Layout), RightAngleToken(TokenSyntax::missingToken(tok::r_angle, ">")) {} GenericParameterClauseBuilder &GenericParameterClauseBuilder:: useLeftAngleBracket(RC LeftAngle) { syntax_assert_token_is(LeftAngle, tok::l_angle, "<"); LeftAngleToken = LeftAngle; return *this; } GenericParameterClauseBuilder &GenericParameterClauseBuilder:: addParameter(llvm::Optional> MaybeComma, GenericParameterSyntax Parameter) { if (MaybeComma.hasValue()) { syntax_assert_token_is(MaybeComma.getValue(), tok::comma, ","); ParameterListLayout.push_back(MaybeComma.getValue()); } else { ParameterListLayout.push_back(TokenSyntax::missingToken(tok::comma, ",")); } ParameterListLayout.push_back(Parameter.getRaw()); return *this; } GenericParameterClauseBuilder &GenericParameterClauseBuilder:: useRightAngleBracket(RC RightAngle) { syntax_assert_token_is(RightAngle, tok::r_angle, ">"); RightAngleToken = RightAngle; return *this; } GenericParameterClauseSyntax GenericParameterClauseBuilder::build() const { auto ListRaw = RawSyntax::make(SyntaxKind::GenericParameterList, ParameterListLayout, SourcePresence::Present); auto Raw = RawSyntax::make(SyntaxKind::GenericParameterClause, { LeftAngleToken, ListRaw, RightAngleToken, }, SourcePresence::Present); auto Data = GenericParameterClauseSyntaxData::make(Raw); return { Data, Data.get() }; } #pragma mark - generic-where-clause Data GenericWhereClauseSyntaxData:: GenericWhereClauseSyntaxData(const RC Raw, const SyntaxData *Parent, const CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::GenericWhereClause); syntax_assert_child_token_text(Raw, GenericWhereClauseSyntax::Cursor::WhereKeyword, tok::kw_where, "where"); syntax_assert_child_kind(Raw, GenericWhereClauseSyntax::Cursor::RequirementList, SyntaxKind::GenericRequirementList); } RC GenericWhereClauseSyntaxData::make(const RC Raw, const SyntaxData *Parent, const CursorIndex IndexInParent) { return RC { new GenericWhereClauseSyntaxData { Raw, Parent, IndexInParent } }; } RC GenericWhereClauseSyntaxData::makeBlank() { return make(RawSyntax::make(SyntaxKind::GenericWhereClause, { TokenSyntax::missingToken(tok::kw_where, "where"), RawSyntax::missing(SyntaxKind::GenericRequirementList), }, SourcePresence::Present)); } #pragma mark - generic-where-clause API GenericWhereClauseSyntax:: GenericWhereClauseSyntax(RC Root, const GenericWhereClauseSyntaxData *Data) : Syntax(Root, Data) {} GenericWhereClauseSyntax GenericWhereClauseSyntax:: withWhereKeyword(RC NewWhereKeyword) const { syntax_assert_token_is(NewWhereKeyword, tok::kw_where, "where"); return Data->replaceChild(NewWhereKeyword, Cursor::WhereKeyword); } GenericWhereClauseSyntax GenericWhereClauseSyntax:: withRequirementList(GenericRequirementListSyntax NewRequirements) const { return Data->replaceChild(NewRequirements.getRaw(), Cursor::RequirementList); } #pragma mark - same-type-requirement Data SameTypeRequirementSyntaxData:: SameTypeRequirementSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : GenericRequirementSyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::SameTypeRequirement); assert(Raw->Layout.size() == 3); syntax_assert_child_kind(Raw, SameTypeRequirementSyntax::Cursor::LeftTypeIdentifier, SyntaxKind::TypeIdentifier); syntax_assert_child_token_text(Raw, SameTypeRequirementSyntax::Cursor::EqualityToken, tok::oper_binary_spaced, "=="); assert(Raw->getChild(SameTypeRequirementSyntax::Cursor::RightType)->isType()); } RC SameTypeRequirementSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new SameTypeRequirementSyntaxData { Raw, Parent, IndexInParent } }; } RC SameTypeRequirementSyntaxData::makeBlank() { return make(RawSyntax::make(SyntaxKind::SameTypeRequirement, { RawSyntax::missing(SyntaxKind::TypeIdentifier), TokenSyntax::missingToken(tok::equal, "="), RawSyntax::missing(SyntaxKind::MissingType), }, SourcePresence::Present)); } #pragma mark - same-type-requirement API SameTypeRequirementSyntax:: SameTypeRequirementSyntax(RC Root, const SameTypeRequirementSyntaxData *Data) : Syntax(Root, Data) {} #pragma mark - generic-argument-list Data GenericArgumentListSyntaxData:: GenericArgumentListSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::GenericArgumentList); } RC GenericArgumentListSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new GenericArgumentListSyntaxData { Raw, Parent, IndexInParent } }; } RC GenericArgumentListSyntaxData::makeBlank() { auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentList, {}, SourcePresence::Present); return make(Raw); } #pragma mark - generic-argument-list API (TODO) #pragma mark - generic-argument-clause Data GenericArgumentClauseSyntaxData:: GenericArgumentClauseSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) {} RC GenericArgumentClauseSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new GenericArgumentClauseSyntaxData { Raw, Parent, IndexInParent } }; } RC GenericArgumentClauseSyntaxData::makeBlank() { auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentClause, { TokenSyntax::missingToken(tok::l_angle, "<"), RawSyntax::missing(SyntaxKind::TypeArgumentList), TokenSyntax::missingToken(tok::r_angle, ">"), }, SourcePresence::Present); return make(Raw); } #pragma mark - generic-argument-clause API GenericArgumentClauseSyntax:: GenericArgumentClauseSyntax(RC Root, const GenericArgumentClauseSyntaxData *Data) : Syntax(Root, Data) {} GenericArgumentClauseSyntax GenericArgumentClauseSyntax:: withLeftAngleBracket(RC NewLeftAngleBracket) const { syntax_assert_token_is(NewLeftAngleBracket, tok::l_angle, "<"); return Data->replaceChild( NewLeftAngleBracket, Cursor::LeftAngleBracketToken); } GenericArgumentClauseSyntax GenericArgumentClauseSyntax:: withRightAngleBracket(RC NewRightAngleBracket) const { syntax_assert_token_is(NewRightAngleBracket, tok::r_angle, ">"); return Data->replaceChild( NewRightAngleBracket, Cursor::RightAngleBracketToken); } #pragma mark - generic-argument-clause Builder GenericArgumentClauseBuilder::GenericArgumentClauseBuilder() : ArgumentListLayout( SyntaxFactory::makeBlankGenericArgumentClause().getRaw()->Layout) {} GenericArgumentClauseBuilder &GenericArgumentClauseBuilder:: useLeftAngleBracket(RC LeftAngle) { syntax_assert_token_is(LeftAngle, tok::l_angle, "<"); LeftAngleToken = LeftAngle; return *this; } GenericArgumentClauseBuilder &GenericArgumentClauseBuilder:: addGenericArgument(llvm::Optional> MaybeComma, TypeSyntax ArgumentTypeSyntax) { if (MaybeComma.hasValue()) { syntax_assert_token_is(MaybeComma.getValue(), tok::comma, ","); ArgumentListLayout.push_back(MaybeComma.getValue()); } else { ArgumentListLayout.push_back(TokenSyntax::missingToken(tok::comma, ",")); } ArgumentListLayout.push_back(ArgumentTypeSyntax.getRaw()); return *this; } GenericArgumentClauseBuilder &GenericArgumentClauseBuilder:: useRightAngleBracket(RC RightAngle) { syntax_assert_token_is(RightAngle, tok::r_angle, ">"); RightAngleToken = RightAngle; return *this; } GenericArgumentClauseSyntax GenericArgumentClauseBuilder::build() const { auto ArgListRaw = RawSyntax::make(SyntaxKind::TypeArgumentList, ArgumentListLayout, SourcePresence::Present); auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentClause, { LeftAngleToken, ArgListRaw, RightAngleToken }, SourcePresence::Present); auto Data = GenericArgumentClauseSyntaxData::make(Raw); return { Data, Data.get() }; }