Skip to content

Commit 00555b6

Browse files
authored
SE-0356: Snippet slice parsing (#20)
Rewrite the snippet parser to support slicing. See: https://github.com/apple/swift-evolution/blob/main/proposals/0356-swift-snippets.md#slices Adopt SymbolKit model changes related to slicing. Remove experimental guard flag for snippet functionality, but guard snippet functionality on Swift 5.7. rdar://95220356
1 parent 0fdcbf1 commit 00555b6

File tree

14 files changed

+635
-266
lines changed

14 files changed

+635
-266
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// This source file is part of the Swift.org open source project
2+
//
3+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
4+
// Licensed under Apache License v2.0 with Runtime Library Exception
5+
//
6+
// See https://swift.org/LICENSE.txt for license information
7+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
8+
9+
// This snippet is in a subdirectory.
10+
11+
func foo() {}

IntegrationTests/Tests/Fixtures/PackageWithSnippets/_Snippets/TestTest.swift renamed to IntegrationTests/Tests/Fixtures/PackageWithSnippets/Snippets/TestTest.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
// Create a foo.
1010
import Library
1111

12+
// snippet.best
1213
let best = BestStruct()
1314
best.best()
15+
// snippet.end
1416

1517
// snippet.hide
1618

IntegrationTests/Tests/Fixtures/PackageWithSnippets/Sources/Library/Library.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
///
1111
/// Is best.
1212
public struct BestStruct {
13+
public init() {}
1314
public func best() {}
1415
}

IntegrationTests/Tests/SnippetDocumentationGenerationTests.swift

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import XCTest
1111
final class SnippetDocumentationGenerationTests: XCTestCase {
1212
func testGenerateDocumentationForPackageWithSnippets() throws {
1313
let result = try swiftPackage(
14-
"generate-documentation", "--enable-experimental-snippet-support",
14+
"generate-documentation",
15+
"--target", "Library",
1516
workingDirectory: try setupTemporaryDirectoryForFixture(named: "PackageWithSnippets")
1617
)
1718

@@ -25,12 +26,9 @@ final class SnippetDocumentationGenerationTests: XCTestCase {
2526
XCTAssertEqual(
2627
Set(dataDirectoryContents.map(\.lastTwoPathComponents)),
2728
[
28-
// REMOVEME: "documentation/packagewithsnippets.json"
29-
// should disappear once the fix for
30-
// https://github.com/apple/swift-docc/pull/116 is available in CI.
31-
"documentation/packagewithsnippets.json",
3229
"documentation/library.json",
3330
"library/beststruct.json",
31+
"beststruct/init().json",
3432
"beststruct/best().json",
3533
]
3634
)
@@ -49,34 +47,6 @@ final class SnippetDocumentationGenerationTests: XCTestCase {
4947
)
5048
}
5149

52-
func testGenerateDocumentationForPackageWithSnippetsWithoutExperimentalFlag() throws {
53-
let result = try swiftPackage(
54-
"generate-documentation",
55-
workingDirectory: try setupTemporaryDirectoryForFixture(named: "PackageWithSnippets")
56-
)
57-
58-
result.assertExitStatusEquals(0)
59-
XCTAssertEqual(result.referencedDocCArchives.count, 1)
60-
61-
let doccArchiveURL = try XCTUnwrap(result.referencedDocCArchives.first)
62-
63-
let dataDirectoryContents = try filesIn(.dataSubdirectory, of: doccArchiveURL)
64-
65-
XCTAssertEqual(
66-
Set(dataDirectoryContents.map(\.lastTwoPathComponents)),
67-
[
68-
"documentation/library.json",
69-
"library/beststruct.json",
70-
"beststruct/best().json",
71-
]
72-
)
73-
74-
XCTAssertFalse(
75-
FileManager.default.fileExists(atPath: result.symbolGraphsDirectory.path),
76-
"Unified symbol graph directory created when experimental snippet support flag was not passed."
77-
)
78-
}
79-
8050
func testPreviewDocumentationWithSnippets() throws {
8151
let outputDirectory = try temporaryDirectory().appendingPathComponent("output")
8252

@@ -87,9 +57,9 @@ final class SnippetDocumentationGenerationTests: XCTestCase {
8757
"--disable-sandbox",
8858
"--allow-writing-to-directory", outputDirectory.path,
8959
"preview-documentation",
60+
"--target", "Library",
9061
"--port", port,
9162
"--output-path", outputDirectory.path,
92-
"--enable-experimental-snippet-support"
9363
],
9464
workingDirectory: try setupTemporaryDirectoryForFixture(named: "PackageWithSnippets")
9565
)

Plugins/Swift-DocC Convert/SwiftDocCConvert.swift

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ import PackagePlugin
3131

3232
let verbose = argumentExtractor.extractFlag(named: "verbose") > 0
3333

34-
let experimentalSnippetSupportIsEnabled = argumentExtractor.extractFlag(
35-
named: "enable-experimental-snippet-support"
36-
) > 0
37-
3834
// Parse the given command-line arguments
3935
let parsedArguments = ParsedArguments(argumentExtractor.remainingArguments)
4036

@@ -50,16 +46,16 @@ import PackagePlugin
5046
return
5147
}
5248

53-
let snippetBuilder: SnippetBuilder?
54-
if experimentalSnippetSupportIsEnabled {
55-
let snippetBuildTool = try context.tool(named: "snippet-build")
56-
snippetBuilder = SnippetBuilder(
57-
snippetTool: URL(fileURLWithPath: snippetBuildTool.path.string, isDirectory: false),
58-
workingDirectory: URL(fileURLWithPath: context.pluginWorkDirectory.string, isDirectory: true)
59-
)
60-
} else {
61-
snippetBuilder = nil
62-
}
49+
#if swift(>=5.7)
50+
let snippetBuildTool = try context.tool(named: "snippet-build")
51+
let snippetBuilder = SnippetBuilder(
52+
snippetTool: URL(fileURLWithPath: snippetBuildTool.path.string, isDirectory: false),
53+
workingDirectory: URL(fileURLWithPath: context.pluginWorkDirectory.string, isDirectory: true)
54+
)
55+
#else
56+
let snippetBuilder: SnippetBuilder? = nil
57+
#endif
58+
6359

6460
// Iterate over the Swift source module targets we were given.
6561
for (index, target) in swiftSourceModuleTargets.enumerated() {

Plugins/Swift-DocC Preview/SwiftDocCPreview.swift

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ import PackagePlugin
2727

2828
let verbose = argumentExtractor.extractFlag(named: "verbose") > 0
2929

30-
let experimentalSnippetSupportIsEnabled = argumentExtractor.extractFlag(
31-
named: "enable-experimental-snippet-support"
32-
) > 0
33-
3430
// Parse the given command-line arguments
3531
let parsedArguments = ParsedArguments(argumentExtractor.remainingArguments)
3632

@@ -70,16 +66,15 @@ import PackagePlugin
7066
return
7167
}
7268

73-
let snippetBuilder: SnippetBuilder?
74-
if experimentalSnippetSupportIsEnabled {
75-
let snippetBuildTool = try context.tool(named: "snippet-build")
76-
snippetBuilder = SnippetBuilder(
77-
snippetTool: URL(fileURLWithPath: snippetBuildTool.path.string, isDirectory: false),
78-
workingDirectory: URL(fileURLWithPath: context.pluginWorkDirectory.string, isDirectory: true)
79-
)
80-
} else {
81-
snippetBuilder = nil
82-
}
69+
#if swift(>=5.7)
70+
let snippetBuildTool = try context.tool(named: "snippet-build")
71+
let snippetBuilder = SnippetBuilder(
72+
snippetTool: URL(fileURLWithPath: snippetBuildTool.path.string, isDirectory: false),
73+
workingDirectory: URL(fileURLWithPath: context.pluginWorkDirectory.string, isDirectory: true)
74+
)
75+
#else
76+
let snippetBuilder: SnippetBuilder? = nil
77+
#endif
8378

8479
let symbolGraphs = try packageManager.doccSymbolGraphs(
8580
for: target,

Sources/Snippets/Model/Snippet.swift

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,23 @@ public struct Snippet {
1717

1818
/// A short abstract explaining what the snippet does.
1919
public var explanation: String
20+
21+
/// The ``presentationLines`` joined with a newline `"\n"` separator.
22+
public var presentationCode: String {
23+
return presentationLines.joined(separator: "\n")
24+
}
2025

2126
/// The code to display as the snippet.
22-
public var presentationCode: String
23-
24-
/// The identifier of the snippet.
25-
public var identifier: String {
26-
return sourceFile.deletingPathExtension().lastPathComponent
27-
}
27+
public var presentationLines: [String]
28+
29+
/// Named line ranges in the snippet.
30+
public var slices: [String: Range<Int>]
2831

2932
init(parsing source: String, sourceFile: URL) {
30-
let extractor = PlainTextSnippetExtractor(source: source)
31-
self.explanation = extractor.explanation
32-
self.presentationCode = extractor.presentationCode
33+
let extractor = SnippetParser(source: source)
34+
self.explanation = extractor.explanationLines.joined(separator: "\n")
35+
self.presentationLines = extractor.presentationLines.map(String.init)
36+
self.slices = extractor.slices
3337
self.sourceFile = sourceFile
3438
}
3539

@@ -41,4 +45,11 @@ public struct Snippet {
4145
let source = try String(contentsOf: sourceFile)
4246
self.init(parsing: source, sourceFile: sourceFile)
4347
}
48+
49+
subscript(sliceIdentifier: String) -> String? {
50+
guard let slice = slices[sliceIdentifier] else {
51+
return nil
52+
}
53+
return presentationLines[slice].joined(separator: "\n")
54+
}
4455
}

Sources/Snippets/Parsing/PlainTextSnippetExtractor.swift

Lines changed: 0 additions & 130 deletions
This file was deleted.

0 commit comments

Comments
 (0)