Skip to content

Add CMake build system for SwiftSyntaxBuilder and _SwiftSyntaxMacros #990

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ add_subdirectory(SwiftSyntax)
add_subdirectory(SwiftDiagnostics)
add_subdirectory(SwiftParser)
add_subdirectory(SwiftOperators)
add_subdirectory(SwiftSyntaxBuilder)
add_subdirectory(_SwiftSyntaxMacros)
add_subdirectory(SwiftCompilerSupport)
1 change: 1 addition & 0 deletions Sources/SwiftDiagnostics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

add_library(SwiftDiagnostics STATIC
Diagnostic.swift
DiagnosticsFormatter.swift
FixIt.swift
Message.swift
Note.swift
Expand Down
60 changes: 60 additions & 0 deletions Sources/SwiftSyntaxBuilder/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

add_library(SwiftSyntaxBuilder STATIC
BuildBuildable.swift
HasTrailingComma.swift
Indenter.swift
Syntax+StringInterpolation.swift

ConvenienceInitializers/BinaryOperatorExprConvenienceInitializers.swift
ConvenienceInitializers/BooleanLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/CatchClauseConvenienceInitializer.swift
ConvenienceInitializers/CustomAttributeConvenienceInitializers.swift
ConvenienceInitializers/DictionaryExprConvenienceInitializers.swift
ConvenienceInitializers/FloatLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/FunctionCallExprConvenienceInitializers.swift
ConvenienceInitializers/IdentifierExprConvenienceInitializers.swift
ConvenienceInitializers/IdentifierPatternConvenienceInitializers.swift
ConvenienceInitializers/IfStmtConvenienceInitializers.swift
ConvenienceInitializers/IntegerLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/MemberAccessExprConvenienceInitializers.swift
ConvenienceInitializers/PrefixOperatorExprConvenienceInitializers.swift
ConvenienceInitializers/SimpleTypeIdentifierConvenienceInitializers.swift
ConvenienceInitializers/StringConvenienceInitializers.swift
ConvenienceInitializers/StringLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/TernaryExprConvenienceInitializers.swift
ConvenienceInitializers/TupleExprElementConvenienceInitializers.swift
ConvenienceInitializers/TypeAnnotationConvenienceInitializers.swift
ConvenienceInitializers/VariableDeclConvenienceInitializers.swift
generated/BuildableBaseProtocols.swift
generated/BuildableCollectionNodes.swift
generated/BuildableNodes.swift
generated/ExpressibleAsProtocols.swift
generated/ResultBuildersFile.swift
generated/Token.swift
gyb_generated/SyntaxExpressibleByStringInterpolationConformances.swift
)

target_link_libraries(SwiftSyntaxBuilder PUBLIC
SwiftParser
SwiftSyntax
)

set_property(GLOBAL APPEND PROPERTY SWIFTSYNTAX_EXPORTS SwiftSyntaxBuilder)

# NOTE: workaround for CMake not setting up include flags yet
set_target_properties(SwiftSyntaxBuilder PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${CMAKE_Swift_MODULE_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR}")

install(TARGETS SwiftSyntaxBuilder
EXPORT SwiftSyntaxTargets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
36 changes: 36 additions & 0 deletions Sources/_SwiftSyntaxMacros/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

add_library(_SwiftSyntaxMacros STATIC
ExpressionMacro.swift
Macro.swift
MacroEvaluationContext.swift
MacroResult.swift
MacroSystem+Builtin.swift
MacroSystem+Examples.swift
MacroSystem.swift
Syntax+MacroEvaluation.swift
)

target_link_libraries(_SwiftSyntaxMacros PUBLIC
SwiftParser
SwiftSyntaxBuilder
)

set_property(GLOBAL APPEND PROPERTY SWIFTSYNTAX_EXPORTS _SwiftSyntaxMacros)

# NOTE: workaround for CMake not setting up include flags yet
set_target_properties(_SwiftSyntaxMacros PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${CMAKE_Swift_MODULE_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR}")

install(TARGETS _SwiftSyntaxMacros
EXPORT SwiftSyntaxTargets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
254 changes: 254 additions & 0 deletions Sources/_SwiftSyntaxMacros/MacroSystem+Builtin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
import SwiftSyntax
import SwiftSyntaxBuilder

struct ColumnMacro: ExpressionMacro {
static var name: String { "column" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let line = macro.startLocation(
converter: context.sourceLocationConverter
).column ?? 0
return .init("\(line)")
}
}

struct LineMacro: ExpressionMacro {
static var name: String { "line" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let line = macro.startLocation(
converter: context.sourceLocationConverter
).line ?? 0
return .init("\(line)")
}
}

extension PatternBindingSyntax {
/// When the variable is declaring a single binding, produce the name of
/// that binding.
fileprivate var singleBindingName: String? {
if let identifierPattern = pattern.as(IdentifierPatternSyntax.self) {
return identifierPattern.identifier.text
}

return nil
}
}

struct FunctionMacro: ExpressionMacro {
static var name: String { "function" }

/// Form a function name.
private static func formFunctionName(
_ baseName: String, _ parameters: ParameterClauseSyntax?,
isSubscript: Bool = false
) -> String {
let argumentNames: [String] = parameters?.parameterList.map { param in
if let argumentName = param.firstName?.text,
!isSubscript || param.secondName != nil {
return "\(argumentName):"
}

return "_:"
} ?? []

return "\(baseName)(\(argumentNames.joined(separator: "")))"
}

private static func findEnclosingName(
_ macro: MacroExpansionExprSyntax
) -> String? {
var currentNode = Syntax(macro)
while let parent = currentNode.parent {
switch parent.as(SyntaxEnum.self) {
case .accessorDecl(let accessor):
if let accessorList = accessor.parent?.as(AccessorListSyntax.self),
let accessorBlock = accessorList.parent?.as(AccessorBlockSyntax.self),
let binding = accessorBlock.parent?.as(PatternBindingSyntax.self),
let varName = binding.singleBindingName {
return varName
}

break

case .functionDecl(let function):
return formFunctionName(
function.identifier.text, function.signature.input
)

case .initializerDecl(let initializer):
return formFunctionName("init", initializer.signature.input)

case .subscriptDecl(let subscriptDecl):
return formFunctionName(
"subscript", subscriptDecl.indices, isSubscript: true
)

case .enumCaseElement(let enumCase):
return formFunctionName(
enumCase.identifier.text, enumCase.associatedValue
)

case .structDecl(let structDecl):
return structDecl.identifier.text

case .enumDecl(let enumDecl):
return enumDecl.identifier.text

case .classDecl(let classDecl):
return classDecl.identifier.text

case .actorDecl(let actorDecl):
return actorDecl.identifier.text

case .protocolDecl(let protocolDecl):
return protocolDecl.identifier.text

case .extensionDecl(let extensionDecl):
// FIXME: It would be nice to be able to switch on type syntax...
let extendedType = extensionDecl.extendedType
if let simple = extendedType.as(SimpleTypeIdentifierSyntax.self) {
return simple.name.text
}

if let member = extendedType.as(MemberTypeIdentifierSyntax.self) {
return member.name.text
}

return nil

default:
break
}

currentNode = parent
}

return nil
}

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let name = findEnclosingName(macro) ?? context.moduleName
let literal: ExprSyntax = #""\#(name)""#
if let leadingTrivia = macro.leadingTrivia {
return .init(literal.withLeadingTrivia(leadingTrivia))
}

return .init(literal)
}
}

struct ColorLiteralMacro: ExpressionMacro {
static var name: String { "colorLiteral" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let initSyntax: ExprSyntax = ".init(\(macro.argumentList))"
if let leadingTrivia = macro.leadingTrivia {
return MacroResult(initSyntax.withLeadingTrivia(leadingTrivia))
}
return MacroResult(initSyntax)
}
}

struct FileLiteralMacro: ExpressionMacro {
static var name: String { "fileLiteral" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let initSyntax: ExprSyntax = ".init(\(macro.argumentList))"
if let leadingTrivia = macro.leadingTrivia {
return MacroResult(initSyntax.withLeadingTrivia(leadingTrivia))
}
return MacroResult(initSyntax)
}
}

struct ImageLiteralMacro: ExpressionMacro {
static var name: String { "imageLiteral" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let initSyntax: ExprSyntax = ".init(\(macro.argumentList))"
if let leadingTrivia = macro.leadingTrivia {
return MacroResult(initSyntax.withLeadingTrivia(leadingTrivia))
}
return MacroResult(initSyntax)
}
}

struct FilePathMacro: ExpressionMacro {
static var name: String { "filePath" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
let fileName = context.sourceLocationConverter.location(
for: .init(utf8Offset: 0)
).file ?? "<unknown file>"
let fileLiteral: ExprSyntax = #""\#(fileName)""#
if let leadingTrivia = macro.leadingTrivia {
return MacroResult(fileLiteral.withLeadingTrivia(leadingTrivia))
}
return MacroResult(fileLiteral)
}
}

struct FileIDMacro: ExpressionMacro {
static var name: String { "fileID" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
var fileName = context.sourceLocationConverter.location(
for: .init(utf8Offset: 0)
).file ?? "<unknown file>"

// Only keep everything after the last slash.
if let lastSlash = fileName.lastIndex(of: "/") {
fileName = String(fileName[fileName.index(after: lastSlash)...])
}

let fileLiteral: ExprSyntax = #""\#(context.moduleName)/\#(fileName)""#
if let leadingTrivia = macro.leadingTrivia {
return MacroResult(fileLiteral.withLeadingTrivia(leadingTrivia))
}
return MacroResult(fileLiteral)
}
}

struct FileMacro: ExpressionMacro {
static var name: String { "file" }

static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax> {
// FIXME: Macro evaluation context needs to know the semantics of #file,
// which is a feature check.
return FilePathMacro.apply(macro, in: context)
}
}

extension MacroSystem {
public static var builtinMacroSystem: MacroSystem = {
var macroSystem = MacroSystem()
try! macroSystem.add(ColorLiteralMacro.self)
try! macroSystem.add(ColumnMacro.self)
try! macroSystem.add(FileIDMacro.self)
try! macroSystem.add(FileLiteralMacro.self)
try! macroSystem.add(FilePathMacro.self)
try! macroSystem.add(FunctionMacro.self)
try! macroSystem.add(ImageLiteralMacro.self)
try! macroSystem.add(LineMacro.self)
return macroSystem
}()
}
Loading