Skip to content

Commit 2eaace3

Browse files
Make formatting use config file by default
1 parent fdf1368 commit 2eaace3

File tree

11 files changed

+131
-19
lines changed

11 files changed

+131
-19
lines changed

Sources/SourceKit/sourcekitd/SwiftLanguageServer.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,11 +694,20 @@ extension SwiftLanguageServer {
694694
}
695695
let options = req.params.options
696696
self.queue.async {
697-
var config = SwiftFormatConfiguration.Configuration()
698-
config.indentation = options.insertSpaces ? .spaces(options.tabSize) : .tabs(1)
699-
config.tabWidth = options.tabSize
697+
let configuration: SwiftFormatConfiguration.Configuration
698+
// try to load swift-format configuration from a ".swift-format" file
699+
// if it fails, use values provided by the lsp
700+
if let configUrl = Configuration.url(forConfigurationFileApplyingTo: file),
701+
let config = try? Configuration(contentsOf: configUrl) {
702+
configuration = config
703+
} else {
704+
var config = SwiftFormatConfiguration.Configuration()
705+
config.indentation = options.insertSpaces ? .spaces(options.tabSize) : .tabs(1)
706+
config.tabWidth = options.tabSize
707+
configuration = config
708+
}
700709

701-
let formatter = SwiftFormat.SwiftFormatter(configuration: config)
710+
let formatter = SwiftFormat.SwiftFormatter(configuration: configuration)
702711
do {
703712
let lines = try LineTable(String(contentsOf: file))
704713
guard let lastLine = lines.last else {

Tests/INPUTS/Formatting/.swift-format

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
This file is intentionally an invalid swift-format configuration file. It is used to test
2+
the behavior when program cannot find a valid file. We cannot just left this directory blank,
3+
because swift-format searches for the configuration in parent directories, and it's possible
4+
that user has another configuration file somewhere outside the Tests.

Tests/INPUTS/Formatting/Root.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/*Root*/
2+
struct Root {
3+
var bar = 123
4+
}

Tests/INPUTS/Formatting/a.swift

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": 1,
3+
"indentation": {
4+
"spaces": 1
5+
},
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/*Directory*/
2+
struct Directory {
3+
var bar = 123
4+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": 1,
3+
"indentation": {
4+
"spaces": 4
5+
},
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/*NestedWithConfig*/
2+
struct NestedWithConfig {
3+
var bar = 123
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/*NestedWithoutConfig*/
2+
struct NestedWithoutConfig {
3+
var bar = 123
4+
}

Tests/INPUTS/Formatting/project.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
{"sources": ["a.swift"]}
1+
{
2+
"sources": [
3+
"Root.swift",
4+
"Directory/Directory.swift",
5+
"Directory/NestedWithConfig/NestedWithConfig.swift",
6+
"Directory/NestedWithoutConfig/NestedWithoutConfig.swift"
7+
]
8+
}

Tests/SourceKitTests/FormattingTests.swift

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,46 @@ import SKTestSupport
1515
import XCTest
1616
import ISDBTestSupport
1717

18+
19+
// Note that none of the indentation values choosen are equal to the default
20+
// indentation level, which is two spaces.
1821
final class FormattingTests: XCTestCase {
1922
var workspace: SKTibsTestWorkspace! = nil
2023

2124
func initialize() throws {
22-
workspace = try staticSourceKitTibsWorkspace(name: "Formatting")!
25+
workspace = try XCTUnwrap(staticSourceKitTibsWorkspace(name: "Formatting"))
2326
try workspace.buildAndIndex()
24-
try workspace.openDocument(workspace.testLoc("a.swift").url, language: .swift)
27+
try workspace.openDocument(workspace.testLoc("Root").url, language: .swift)
28+
try workspace.openDocument(workspace.testLoc("Directory").url, language: .swift)
29+
try workspace.openDocument(workspace.testLoc("NestedWithConfig").url, language: .swift)
30+
try workspace.openDocument(workspace.testLoc("NestedWithoutConfig").url, language: .swift)
2531
}
2632
override func tearDown() {
2733
workspace = nil
2834
}
2935

30-
func performFormattingRequest(file url: URL, options: FormattingOptions) -> [TextEdit]? {
36+
func performFormattingRequest(file url: URL, options: FormattingOptions) throws -> [TextEdit]? {
3137
let request = DocumentFormattingRequest(
3238
textDocument: TextDocumentIdentifier(url),
3339
options: options
3440
)
35-
return try! workspace.sk.sendSync(request)!
41+
return try workspace.sk.sendSync(request)
3642
}
3743

3844
func testSpaces() throws {
3945
XCTAssertNoThrow(try initialize())
40-
let url = workspace.testLoc("a.swift").url
46+
let url = workspace.testLoc("Root").url
4147
let options = FormattingOptions(tabSize: 3, insertSpaces: true)
4248
let edits = try XCTUnwrap(performFormattingRequest(file: url, options: options))
4349
XCTAssertEqual(edits.count, 1)
4450
let firstEdit = try XCTUnwrap(edits.first)
4551
XCTAssertEqual(firstEdit.range.lowerBound, Position(line: 0, utf16index: 0))
4652
XCTAssertEqual(firstEdit.range.upperBound, Position(line: 3, utf16index: 1))
4753
// var bar needs to be indented with three spaces
54+
// which is the value from lsp
4855
XCTAssertEqual(firstEdit.newText, #"""
49-
/*a.swift*/
50-
struct Foo {
56+
/*Root*/
57+
struct Root {
5158
var bar = 123
5259
}
5360
@@ -56,20 +63,81 @@ final class FormattingTests: XCTestCase {
5663

5764
func testTabs() throws {
5865
try initialize()
59-
let url = workspace.testLoc("a.swift").url
66+
let url = workspace.testLoc("Root").url
6067
let options = FormattingOptions(tabSize: 3, insertSpaces: false)
6168
let edits = try XCTUnwrap(performFormattingRequest(file: url, options: options))
6269
XCTAssertEqual(edits.count, 1)
6370
let firstEdit = try XCTUnwrap(edits.first)
6471
XCTAssertEqual(firstEdit.range.lowerBound, Position(line: 0, utf16index: 0))
6572
XCTAssertEqual(firstEdit.range.upperBound, Position(line: 3, utf16index: 1))
6673
// var bar needs to be indented with a tab
74+
// which is the value from lsp
6775
XCTAssertEqual(firstEdit.newText, #"""
68-
/*a.swift*/
69-
struct Foo {
76+
/*Root*/
77+
struct Root {
7078
\#tvar bar = 123
7179
}
7280
7381
"""#)
7482
}
83+
84+
func testConfigFile() throws {
85+
XCTAssertNoThrow(try initialize())
86+
let url = workspace.testLoc("Directory").url
87+
let options = FormattingOptions(tabSize: 3, insertSpaces: true)
88+
let edits = try XCTUnwrap(performFormattingRequest(file: url, options: options))
89+
XCTAssertEqual(edits.count, 1)
90+
let firstEdit = try XCTUnwrap(edits.first)
91+
XCTAssertEqual(firstEdit.range.lowerBound, Position(line: 0, utf16index: 0))
92+
XCTAssertEqual(firstEdit.range.upperBound, Position(line: 3, utf16index: 1))
93+
// var bar needs to be indented with one space
94+
// which is the value from ".swift-format" in "Directory"
95+
XCTAssertEqual(firstEdit.newText, #"""
96+
/*Directory*/
97+
struct Directory {
98+
var bar = 123
99+
}
100+
101+
"""#)
102+
}
103+
104+
func testConfigFileInParentDirectory() throws {
105+
XCTAssertNoThrow(try initialize())
106+
let url = workspace.testLoc("NestedWithoutConfig").url
107+
let options = FormattingOptions(tabSize: 3, insertSpaces: true)
108+
let edits = try XCTUnwrap(performFormattingRequest(file: url, options: options))
109+
XCTAssertEqual(edits.count, 1)
110+
let firstEdit = try XCTUnwrap(edits.first)
111+
XCTAssertEqual(firstEdit.range.lowerBound, Position(line: 0, utf16index: 0))
112+
XCTAssertEqual(firstEdit.range.upperBound, Position(line: 3, utf16index: 1))
113+
// var bar needs to be indented with one space
114+
// which is the value from ".swift-format" in "Directory"
115+
XCTAssertEqual(firstEdit.newText, #"""
116+
/*NestedWithoutConfig*/
117+
struct NestedWithoutConfig {
118+
var bar = 123
119+
}
120+
121+
"""#)
122+
}
123+
124+
func testConfigFileInNestedDirectory() throws {
125+
XCTAssertNoThrow(try initialize())
126+
let url = workspace.testLoc("NestedWithConfig").url
127+
let options = FormattingOptions(tabSize: 3, insertSpaces: true)
128+
let edits = try XCTUnwrap(performFormattingRequest(file: url, options: options))
129+
XCTAssertEqual(edits.count, 1)
130+
let firstEdit = try XCTUnwrap(edits.first)
131+
XCTAssertEqual(firstEdit.range.lowerBound, Position(line: 0, utf16index: 0))
132+
XCTAssertEqual(firstEdit.range.upperBound, Position(line: 3, utf16index: 1))
133+
// var bar needs to be indented with four spaces
134+
// which is the value from ".swift-format" in "NestedWithConfig"
135+
XCTAssertEqual(firstEdit.newText, #"""
136+
/*NestedWithConfig*/
137+
struct NestedWithConfig {
138+
var bar = 123
139+
}
140+
141+
"""#)
142+
}
75143
}

0 commit comments

Comments
 (0)