mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Add LSP support
This commit is contained in:
parent
747f4b9d20
commit
66c244f540
1
.gitignore
vendored
1
.gitignore
vendored
@ -71,3 +71,4 @@ submodules/OpenSSLEncryptionProvider/SharedHeaders/*
|
|||||||
submodules/TelegramCore/FlatSerialization/Sources/*
|
submodules/TelegramCore/FlatSerialization/Sources/*
|
||||||
buildServer.json
|
buildServer.json
|
||||||
.build/**
|
.build/**
|
||||||
|
Telegram.LSP.json
|
||||||
|
@ -547,7 +547,7 @@ def generate_project(bazel, arguments):
|
|||||||
|
|
||||||
call_executable(['killall', 'Xcode'], check_result=False)
|
call_executable(['killall', 'Xcode'], check_result=False)
|
||||||
|
|
||||||
generate(
|
xcodeproj_path = generate(
|
||||||
build_environment=bazel_command_line.build_environment,
|
build_environment=bazel_command_line.build_environment,
|
||||||
disable_extensions=disable_extensions,
|
disable_extensions=disable_extensions,
|
||||||
disable_provisioning_profiles=disable_provisioning_profiles,
|
disable_provisioning_profiles=disable_provisioning_profiles,
|
||||||
@ -558,6 +558,22 @@ def generate_project(bazel, arguments):
|
|||||||
target_name=target_name
|
target_name=target_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if target_name == "Telegram":
|
||||||
|
run_executable_with_output('swift', arguments=[
|
||||||
|
'run',
|
||||||
|
'-c',
|
||||||
|
'release',
|
||||||
|
'--package-path',
|
||||||
|
'build-system/XcodeParse',
|
||||||
|
'XcodeParse',
|
||||||
|
'--project-path',
|
||||||
|
xcodeproj_path,
|
||||||
|
'--output-path',
|
||||||
|
'Telegram/Telegram.LSP.json'
|
||||||
|
], check_result=True)
|
||||||
|
|
||||||
|
call_executable(['open', xcodeproj_path])
|
||||||
|
|
||||||
|
|
||||||
def build(bazel, arguments):
|
def build(bazel, arguments):
|
||||||
bazel_command_line = BazelCommandLine(
|
bazel_command_line = BazelCommandLine(
|
||||||
|
@ -51,8 +51,8 @@ def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions,
|
|||||||
call_executable(bazel_generate_arguments)
|
call_executable(bazel_generate_arguments)
|
||||||
|
|
||||||
xcodeproj_path = '{}.xcodeproj'.format(app_target_spec.replace(':', '/'))
|
xcodeproj_path = '{}.xcodeproj'.format(app_target_spec.replace(':', '/'))
|
||||||
call_executable(['open', xcodeproj_path])
|
return xcodeproj_path
|
||||||
|
|
||||||
|
|
||||||
def generate(build_environment: BuildEnvironment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name):
|
def generate(build_environment: BuildEnvironment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name) -> str:
|
||||||
generate_xcodeproj(build_environment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name)
|
return generate_xcodeproj(build_environment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name)
|
||||||
|
8
build-system/XcodeParse/.gitignore
vendored
Normal file
8
build-system/XcodeParse/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
@ -0,0 +1,88 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1620"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "XcodeParse"
|
||||||
|
BuildableName = "XcodeParse"
|
||||||
|
BlueprintName = "XcodeParse"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "XcodeParse"
|
||||||
|
BuildableName = "XcodeParse"
|
||||||
|
BlueprintName = "XcodeParse"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<CommandLineArguments>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "-p /Users/ali/build/telegram/telegram-ios/Telegram/Telegram.xcodeproj"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "-o /Users/ali/build/telegram/telegram-ios/Telegram/Telegram.LSP.json"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
</CommandLineArguments>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "XcodeParse"
|
||||||
|
BuildableName = "XcodeParse"
|
||||||
|
BlueprintName = "XcodeParse"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
51
build-system/XcodeParse/Package.resolved
Normal file
51
build-system/XcodeParse/Package.resolved
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "17beff37a9aac4bf93a9e4b944ed029007695fe907b5a4eaa87576689f695b1b",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "aexml",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/tadija/AEXML.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "db806756c989760b35108146381535aec231092b",
|
||||||
|
"version" : "4.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "pathkit",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/kylef/PathKit.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "3bfd2737b700b9a36565a8c94f4ad2b050a5e574",
|
||||||
|
"version" : "1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "spectre",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/kylef/Spectre.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "26cc5e9ae0947092c7139ef7ba612e34646086c7",
|
||||||
|
"version" : "0.10.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-argument-parser",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-argument-parser.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "41982a3656a71c768319979febd796c6fd111d5c",
|
||||||
|
"version" : "1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "xcodeproj",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/tuist/XcodeProj.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "128d90e4633a8e6941586dea75426e177dfb92e6",
|
||||||
|
"version" : "9.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
22
build-system/XcodeParse/Package.swift
Normal file
22
build-system/XcodeParse/Package.swift
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// swift-tools-version: 6.0
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "XcodeParse",
|
||||||
|
platforms: [.macOS(.v11)],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://github.com/tuist/XcodeProj.git", exact: "9.0.0"),
|
||||||
|
.package(url: "https://github.com/apple/swift-argument-parser.git", exact: "1.5.0"),
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
.executableTarget(
|
||||||
|
name: "XcodeParse",
|
||||||
|
dependencies: [
|
||||||
|
"XcodeProj",
|
||||||
|
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
288
build-system/XcodeParse/Sources/main.swift
Normal file
288
build-system/XcodeParse/Sources/main.swift
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
import Foundation
|
||||||
|
import Darwin
|
||||||
|
import XcodeProj
|
||||||
|
import PathKit
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
// Custom error types for the command
|
||||||
|
enum XcodeParseError: Error, LocalizedError {
|
||||||
|
case missingBuildSetting(String)
|
||||||
|
case unresolvableBuildSetting(String, String)
|
||||||
|
case swiftFlagProcessingError(String, Error)
|
||||||
|
case unresolvableSwiftFlag(String, String)
|
||||||
|
|
||||||
|
var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .missingBuildSetting(let setting):
|
||||||
|
return "Project does not contain required build setting: \(setting)"
|
||||||
|
case .unresolvableBuildSetting(let name, let value):
|
||||||
|
return "Could not resolve build setting value: \(name) = \(value)"
|
||||||
|
case .swiftFlagProcessingError(let target, let error):
|
||||||
|
return "Error processing swift flags for \(target): \(error)"
|
||||||
|
case .unresolvableSwiftFlag(let target, let flag):
|
||||||
|
return "Unresolved variable in swift flags for \(target): \(flag)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct XcodeParse: ParsableCommand {
|
||||||
|
static let configuration = CommandConfiguration(
|
||||||
|
commandName: "xcodeparse",
|
||||||
|
abstract: "Extract file sets and Swift flags from an Xcode project",
|
||||||
|
version: "1.0.0"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Extract all variable references like $(VARIABLE_NAME)
|
||||||
|
// private static let variablePatternRegex = try! NSRegularExpression(pattern: "\\$\\(([^)]+)\\)", options: [])
|
||||||
|
|
||||||
|
// Update the class-level regex to handle simple variables
|
||||||
|
private static let simpleVariableRegex = try! NSRegularExpression(pattern: "\\$\\(([^$)]+)\\)", options: [])
|
||||||
|
|
||||||
|
// Add another regex for variables that contain exactly one nested variable
|
||||||
|
private static let nestedVariableRegex = try! NSRegularExpression(pattern: "\\$\\(([^$)]*\\$\\([^)]+\\)[^)]*)\\)", options: [])
|
||||||
|
|
||||||
|
@Option(name: .shortAndLong, help: "Path to the Xcode project (.xcodeproj) file")
|
||||||
|
var projectPath: String
|
||||||
|
|
||||||
|
@Option(name: .shortAndLong, help: "Output path for the JSON file")
|
||||||
|
var outputPath: String
|
||||||
|
|
||||||
|
func run() throws {
|
||||||
|
let projectPathObj = Path(projectPath)
|
||||||
|
|
||||||
|
let xcodeproj = try XcodeProj(path: projectPathObj)
|
||||||
|
|
||||||
|
func absolutePath(file: PBXFileElement) -> String? {
|
||||||
|
guard let path = file.path else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if let parent = file.parent {
|
||||||
|
if let parentPath = absolutePath(file: parent) {
|
||||||
|
return parentPath + "/" + path
|
||||||
|
} else {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func localPath(projectRoot: String, file: PBXFileElement) -> String? {
|
||||||
|
guard let path = absolutePath(file: file) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if path.hasPrefix(projectRoot) {
|
||||||
|
return String(path[path.index(path.startIndex, offsetBy: projectRoot.count)...])
|
||||||
|
} else {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawVariables: [String: String] = [:]
|
||||||
|
let requiredBuildSettings: [String] = ["SRCROOT", "PROJECT_DIR", "BAZEL_OUT"]
|
||||||
|
for buildConfiguration in xcodeproj.pbxproj.buildConfigurations {
|
||||||
|
if buildConfiguration.name == "Debug" {
|
||||||
|
for name in requiredBuildSettings {
|
||||||
|
if let value = buildConfiguration.buildSettings[name]?.stringValue {
|
||||||
|
rawVariables[name] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name in requiredBuildSettings {
|
||||||
|
if rawVariables[name] == nil {
|
||||||
|
throw XcodeParseError.missingBuildSetting(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while true {
|
||||||
|
var hasSubstitutions: Bool = false
|
||||||
|
inner: for (name, value) in rawVariables {
|
||||||
|
for (otherName, otherValue) in rawVariables {
|
||||||
|
if name == otherName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if value.contains("$(\(otherName))") {
|
||||||
|
rawVariables[name] = value.replacingOccurrences(of: "$(\(otherName))", with: otherValue)
|
||||||
|
hasSubstitutions = true
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasSubstitutions {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name, value) in rawVariables {
|
||||||
|
if value.contains("$(") {
|
||||||
|
throw XcodeParseError.unresolvableBuildSetting(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rawVariables["ENABLE_PREVIEWS"] = ""
|
||||||
|
|
||||||
|
let variables = rawVariables
|
||||||
|
|
||||||
|
let projectRoot = variables["SRCROOT"]! + "/"
|
||||||
|
|
||||||
|
enum ShlexError: Error {
|
||||||
|
case unmatchedQuote
|
||||||
|
}
|
||||||
|
|
||||||
|
func shlexSplit(_ input: String) throws -> [String] {
|
||||||
|
var tokens = [String]()
|
||||||
|
var current = ""
|
||||||
|
var inSingleQuote = false
|
||||||
|
var inDoubleQuote = false
|
||||||
|
var escapeNext = false
|
||||||
|
|
||||||
|
for char in input {
|
||||||
|
if escapeNext {
|
||||||
|
current.append(char)
|
||||||
|
escapeNext = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if char == "\\" {
|
||||||
|
// In single quotes, backslashes are taken literally.
|
||||||
|
if inSingleQuote {
|
||||||
|
current.append(char)
|
||||||
|
} else {
|
||||||
|
escapeNext = true
|
||||||
|
}
|
||||||
|
} else if char == "'" && !inDoubleQuote {
|
||||||
|
inSingleQuote.toggle()
|
||||||
|
} else if char == "\"" && !inSingleQuote {
|
||||||
|
inDoubleQuote.toggle()
|
||||||
|
} else if char.isWhitespace && !inSingleQuote && !inDoubleQuote {
|
||||||
|
if !current.isEmpty {
|
||||||
|
tokens.append(current)
|
||||||
|
current = ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
current.append(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if escapeNext {
|
||||||
|
// A trailing backslash is taken as a literal backslash.
|
||||||
|
current.append("\\")
|
||||||
|
}
|
||||||
|
|
||||||
|
if inSingleQuote || inDoubleQuote {
|
||||||
|
throw ShlexError.unmatchedQuote
|
||||||
|
}
|
||||||
|
|
||||||
|
if !current.isEmpty {
|
||||||
|
tokens.append(current)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FileSet {
|
||||||
|
var files: [String]
|
||||||
|
var swiftFlags: [String]
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileSets: [FileSet] = []
|
||||||
|
|
||||||
|
for target in xcodeproj.pbxproj.nativeTargets {
|
||||||
|
var files: [String] = []
|
||||||
|
for sourceFile in try target.sourceFiles() {
|
||||||
|
if let path = localPath(projectRoot: projectRoot, file: sourceFile) {
|
||||||
|
files.append(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var swiftFlags: [String] = []
|
||||||
|
if let buildConfigurationList = target.buildConfigurationList {
|
||||||
|
for buildConfiguration in buildConfigurationList.buildConfigurations {
|
||||||
|
if buildConfiguration.name == "Debug" {
|
||||||
|
if let swiftFlagsString = buildConfiguration.buildSettings["OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]"]?.stringValue {
|
||||||
|
do {
|
||||||
|
swiftFlags = try shlexSplit(swiftFlagsString)
|
||||||
|
} catch let error {
|
||||||
|
throw XcodeParseError.swiftFlagProcessingError(target.name, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0 ..< swiftFlags.count {
|
||||||
|
if swiftFlags[i].contains("$(") {
|
||||||
|
var flag = swiftFlags[i]
|
||||||
|
var madeProgress = true
|
||||||
|
|
||||||
|
// Keep resolving variables until no more progress can be made
|
||||||
|
while flag.contains("$(") && madeProgress {
|
||||||
|
madeProgress = false
|
||||||
|
|
||||||
|
let nsString = flag as NSString
|
||||||
|
let matches = XcodeParse.simpleVariableRegex.matches(in: flag, options: [], range: NSRange(location: 0, length: nsString.length))
|
||||||
|
|
||||||
|
// Try to resolve variables that don't contain other variables
|
||||||
|
for match in matches.reversed() {
|
||||||
|
let variableRange = match.range(at: 1)
|
||||||
|
let variableName = nsString.substring(with: variableRange)
|
||||||
|
|
||||||
|
// Skip this variable if it contains another variable reference
|
||||||
|
// (we'll get it in a later iteration after inner variables are resolved)
|
||||||
|
if variableName.contains("$(") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up the variable directly by name
|
||||||
|
var variableValue: String? = variables[variableName]
|
||||||
|
|
||||||
|
// If not found in variables, check build settings
|
||||||
|
if variableValue == nil, let value = buildConfiguration.buildSettings[variableName]?.stringValue {
|
||||||
|
variableValue = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// If variable found, do the replacement
|
||||||
|
if let value = variableValue {
|
||||||
|
let fullRange = match.range(at: 0) // The full $(VARIABLE_NAME) pattern
|
||||||
|
flag = (flag as NSString).replacingCharacters(in: fullRange, with: value)
|
||||||
|
madeProgress = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are still unresolved variables
|
||||||
|
if flag.contains("$(") {
|
||||||
|
throw XcodeParseError.unresolvableSwiftFlag(target.name, flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
swiftFlags[i] = flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !files.isEmpty && !swiftFlags.isEmpty {
|
||||||
|
fileSets.append(FileSet(
|
||||||
|
files: files,
|
||||||
|
swiftFlags: swiftFlags
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let fileSetDicts = fileSets.map { fileSet -> [String: Any] in
|
||||||
|
return [
|
||||||
|
"files": fileSet.files,
|
||||||
|
"swiftFlags": fileSet.swiftFlags
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let jsonData = try JSONSerialization.data(withJSONObject: fileSetDicts, options: .prettyPrinted)
|
||||||
|
try jsonData.write(to: URL(fileURLWithPath: outputPath))
|
||||||
|
print("Successfully wrote output to \(outputPath)")
|
||||||
|
} catch let error {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XcodeParse.main()
|
Loading…
x
Reference in New Issue
Block a user