mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* Refactor Tuple Type Syntax This patch: - Refactors TypeArgumentListSyntax and TypeArgumentListSyntaxData to use the SyntaxCollection and SyntaxCollectionData APIs. - Refactors TupleTypeElementSyntax to own its trailing comma, and updates the tests accordingly. - Provides an infrastructure for promoting types to use the SyntaxCollection APIs * Addressed comments. * Renamed makeBlankTypeArgumentList() * Update makeTupleType * Changed makeTupleType to take an element list. * Updated comment. * Improved API for creating TupleTypeElementListSyntax'es * Added round-trip test * Removed last TypeArgumentList holdovers. * Fixed round-trip test invocation
455 lines
16 KiB
C++
455 lines
16 KiB
C++
//===--- 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<RawSyntax> 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>
|
|
ConformanceRequirementSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<ConformanceRequirementSyntaxData> {
|
|
new ConformanceRequirementSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<ConformanceRequirementSyntaxData>
|
|
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<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: SyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Kind == SyntaxKind::GenericParameter);
|
|
}
|
|
|
|
RC<GenericParameterSyntaxData>
|
|
GenericParameterSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<GenericParameterSyntaxData> {
|
|
new GenericParameterSyntaxData { Raw, Parent, IndexInParent }
|
|
};
|
|
}
|
|
|
|
RC<GenericParameterSyntaxData> 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<SyntaxData> Root,
|
|
const GenericParameterSyntaxData *Data)
|
|
: Syntax(Root, Data) {}
|
|
|
|
#pragma mark - generic-parameter-list Data
|
|
|
|
GenericParameterListSyntaxData::
|
|
GenericParameterListSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: SyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Kind == SyntaxKind::GenericParameterList);
|
|
}
|
|
|
|
RC<GenericParameterListSyntaxData>
|
|
GenericParameterListSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<GenericParameterListSyntaxData> {
|
|
new GenericParameterListSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<GenericParameterListSyntaxData> GenericParameterListSyntaxData::makeBlank() {
|
|
auto Raw = RawSyntax::make(SyntaxKind::GenericParameterList,
|
|
{}, SourcePresence::Present);
|
|
return make(Raw);
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark generic-parameter-clause Data
|
|
|
|
GenericParameterClauseSyntaxData::
|
|
GenericParameterClauseSyntaxData(RC<RawSyntax> 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>
|
|
GenericParameterClauseSyntaxData::make(const RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
const CursorIndex IndexInParent) {
|
|
return RC<GenericParameterClauseSyntaxData> {
|
|
new GenericParameterClauseSyntaxData {
|
|
Raw, Parent, IndexInParent,
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<GenericParameterClauseSyntaxData>
|
|
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<SyntaxData> 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<TokenSyntax> LeftAngle) {
|
|
syntax_assert_token_is(LeftAngle, tok::l_angle, "<");
|
|
LeftAngleToken = LeftAngle;
|
|
return *this;
|
|
}
|
|
|
|
GenericParameterClauseBuilder &GenericParameterClauseBuilder::
|
|
addParameter(llvm::Optional<RC<TokenSyntax>> 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<TokenSyntax> 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<RawSyntax> 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>
|
|
GenericWhereClauseSyntaxData::make(const RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
const CursorIndex IndexInParent) {
|
|
return RC<GenericWhereClauseSyntaxData> {
|
|
new GenericWhereClauseSyntaxData { Raw, Parent, IndexInParent }
|
|
};
|
|
}
|
|
|
|
RC<GenericWhereClauseSyntaxData> 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<SyntaxData> Root,
|
|
const GenericWhereClauseSyntaxData *Data)
|
|
: Syntax(Root, Data) {}
|
|
|
|
GenericWhereClauseSyntax GenericWhereClauseSyntax::
|
|
withWhereKeyword(RC<TokenSyntax> NewWhereKeyword) const {
|
|
syntax_assert_token_is(NewWhereKeyword, tok::kw_where, "where");
|
|
return Data->replaceChild<GenericWhereClauseSyntax>(NewWhereKeyword,
|
|
Cursor::WhereKeyword);
|
|
}
|
|
|
|
GenericWhereClauseSyntax GenericWhereClauseSyntax::
|
|
withRequirementList(GenericRequirementListSyntax NewRequirements) const {
|
|
return Data->replaceChild<GenericWhereClauseSyntax>(NewRequirements.getRaw(),
|
|
Cursor::RequirementList);
|
|
}
|
|
|
|
#pragma mark - same-type-requirement Data
|
|
|
|
SameTypeRequirementSyntaxData::
|
|
SameTypeRequirementSyntaxData(RC<RawSyntax> 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>
|
|
SameTypeRequirementSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<SameTypeRequirementSyntaxData> {
|
|
new SameTypeRequirementSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<SameTypeRequirementSyntaxData> 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<SyntaxData> Root,
|
|
const SameTypeRequirementSyntaxData *Data)
|
|
: Syntax(Root, Data) {}
|
|
|
|
#pragma mark - generic-argument-list Data
|
|
|
|
GenericArgumentListSyntaxData::
|
|
GenericArgumentListSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: SyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Kind == SyntaxKind::GenericArgumentList);
|
|
}
|
|
|
|
RC<GenericArgumentListSyntaxData>
|
|
GenericArgumentListSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<GenericArgumentListSyntaxData> {
|
|
new GenericArgumentListSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<GenericArgumentListSyntaxData> 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<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: SyntaxData(Raw, Parent, IndexInParent) {}
|
|
|
|
RC<GenericArgumentClauseSyntaxData>
|
|
GenericArgumentClauseSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<GenericArgumentClauseSyntaxData> {
|
|
new GenericArgumentClauseSyntaxData { Raw, Parent, IndexInParent }
|
|
};
|
|
}
|
|
|
|
RC<GenericArgumentClauseSyntaxData>
|
|
GenericArgumentClauseSyntaxData::makeBlank() {
|
|
auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentClause,
|
|
{
|
|
TokenSyntax::missingToken(tok::l_angle, "<"),
|
|
RawSyntax::missing(SyntaxKind::GenericArgumentList),
|
|
TokenSyntax::missingToken(tok::r_angle, ">"),
|
|
},
|
|
SourcePresence::Present);
|
|
return make(Raw);
|
|
}
|
|
|
|
#pragma mark - generic-argument-clause API
|
|
|
|
GenericArgumentClauseSyntax::
|
|
GenericArgumentClauseSyntax(RC<SyntaxData> Root,
|
|
const GenericArgumentClauseSyntaxData *Data)
|
|
: Syntax(Root, Data) {}
|
|
|
|
GenericArgumentClauseSyntax GenericArgumentClauseSyntax::
|
|
withLeftAngleBracket(RC<TokenSyntax> NewLeftAngleBracket) const {
|
|
syntax_assert_token_is(NewLeftAngleBracket, tok::l_angle, "<");
|
|
return Data->replaceChild<GenericArgumentClauseSyntax>(
|
|
NewLeftAngleBracket, Cursor::LeftAngleBracketToken);
|
|
}
|
|
|
|
|
|
|
|
GenericArgumentClauseSyntax GenericArgumentClauseSyntax::
|
|
withRightAngleBracket(RC<TokenSyntax> NewRightAngleBracket) const {
|
|
syntax_assert_token_is(NewRightAngleBracket, tok::r_angle, ">");
|
|
return Data->replaceChild<GenericArgumentClauseSyntax>(
|
|
NewRightAngleBracket, Cursor::RightAngleBracketToken);
|
|
}
|
|
|
|
#pragma mark - generic-argument-clause Builder
|
|
|
|
GenericArgumentClauseBuilder::GenericArgumentClauseBuilder()
|
|
: ArgumentListLayout(
|
|
SyntaxFactory::makeBlankGenericArgumentClause().getRaw()->Layout) {}
|
|
|
|
GenericArgumentClauseBuilder &GenericArgumentClauseBuilder::
|
|
useLeftAngleBracket(RC<TokenSyntax> LeftAngle) {
|
|
syntax_assert_token_is(LeftAngle, tok::l_angle, "<");
|
|
LeftAngleToken = LeftAngle;
|
|
return *this;
|
|
}
|
|
|
|
GenericArgumentClauseBuilder &GenericArgumentClauseBuilder::
|
|
addGenericArgument(llvm::Optional<RC<TokenSyntax>> 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<TokenSyntax> RightAngle) {
|
|
syntax_assert_token_is(RightAngle, tok::r_angle, ">");
|
|
RightAngleToken = RightAngle;
|
|
return *this;
|
|
}
|
|
|
|
|
|
GenericArgumentClauseSyntax GenericArgumentClauseBuilder::build() const {
|
|
auto ArgListRaw = RawSyntax::make(SyntaxKind::GenericParameterList,
|
|
ArgumentListLayout,
|
|
SourcePresence::Present);
|
|
auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentClause,
|
|
{
|
|
LeftAngleToken,
|
|
ArgListRaw,
|
|
RightAngleToken
|
|
},
|
|
SourcePresence::Present);
|
|
auto Data = GenericArgumentClauseSyntaxData::make(Raw);
|
|
return { Data, Data.get() };
|
|
}
|