Skip to content

Commit 515260f

Browse files
authored
Merge pull request #2323 from ahoppen/if-config-hints
2 parents abf98b9 + 2ad0236 commit 515260f

File tree

5 files changed

+241
-127
lines changed

5 files changed

+241
-127
lines changed

Sources/LanguageServerProtocol/SupportTypes/InlayHint.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public struct InlayHintKind: RawRepresentable, Codable, Hashable, Sendable {
6868

6969
/// A type annotation.
7070
public static let type: InlayHintKind = InlayHintKind(rawValue: 1)
71-
/// A parameter label. Note that this case is not used by
72-
/// Swift, since Swift already has explicit parameter labels.
71+
72+
/// A parameter label.
7373
public static let parameter: InlayHintKind = InlayHintKind(rawValue: 2)
7474
}
7575

Sources/SwiftLanguageService/CMakeLists.txt

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,51 @@
11
add_library(SwiftLanguageService STATIC
2-
SemanticRefactoring.swift
3-
SwiftTestingScanner.swift
4-
FoldingRange.swift
5-
CMakeLists.txt
6-
SymbolInfo.swift
7-
RefactoringEdit.swift
8-
CodeActions/ConvertStringConcatenationToStringInterpolation.swift
9-
CodeActions/SyntaxRefactoringCodeActionProvider.swift
2+
AdjustPositionToStartOfArgument.swift
3+
AdjustPositionToStartOfIdentifier.swift
4+
ClosureCompletionFormat.swift
5+
CodeActions/AddDocumentation.swift
6+
CodeActions/ConvertIntegerLiteral.swift
107
CodeActions/ConvertJSONToCodableStruct.swift
8+
CodeActions/ConvertStringConcatenationToStringInterpolation.swift
9+
CodeActions/PackageManifestEdits.swift
1110
CodeActions/SyntaxCodeActionProvider.swift
1211
CodeActions/SyntaxCodeActions.swift
13-
CodeActions/ConvertIntegerLiteral.swift
14-
CodeActions/PackageManifestEdits.swift
15-
CodeActions/AddDocumentation.swift
16-
RefactoringResponse.swift
17-
SyntacticSwiftXCTestScanner.swift
12+
CodeActions/SyntaxRefactoringCodeActionProvider.swift
13+
CodeCompletion.swift
14+
CodeCompletionSession.swift
1815
CommentXML.swift
19-
SymbolGraph.swift
20-
ClosureCompletionFormat.swift
21-
SemanticRefactorCommand.swift
22-
DocumentFormatting.swift
16+
CursorInfo.swift
17+
Diagnostic.swift
2318
DiagnosticReportManager.swift
24-
SemanticTokens.swift
19+
DocumentFormatting.swift
20+
DocumentSymbols.swift
2521
ExpandMacroCommand.swift
26-
Diagnostic.swift
27-
CodeCompletion.swift
28-
SwiftCodeLensScanner.swift
29-
SwiftCommand.swift
22+
FoldingRange.swift
23+
GeneratedInterfaceManager.swift
24+
InlayHints.swift
25+
MacroExpansion.swift
26+
OpenInterface.swift
27+
RefactoringEdit.swift
28+
RefactoringResponse.swift
3029
RelatedIdentifiers.swift
31-
VariableTypeInfo.swift
32-
CodeCompletionSession.swift
33-
SyntaxTreeManager.swift
3430
Rename.swift
3531
RewriteSourceKitPlaceholders.swift
32+
SemanticRefactorCommand.swift
33+
SemanticRefactoring.swift
34+
SemanticTokens.swift
35+
SignatureHelp.swift
36+
SwiftCodeLensScanner.swift
37+
SwiftCommand.swift
3638
SwiftLanguageService.swift
37-
TestDiscovery.swift
38-
OpenInterface.swift
39+
SwiftTestingScanner.swift
40+
SymbolGraph.swift
41+
SymbolInfo.swift
42+
SyntacticSwiftXCTestScanner.swift
3943
SyntaxHighlightingToken.swift
40-
MacroExpansion.swift
41-
AdjustPositionToStartOfIdentifier.swift
4244
SyntaxHighlightingTokenParser.swift
43-
CursorInfo.swift
44-
DocumentSymbols.swift
4545
SyntaxHighlightingTokens.swift
46-
GeneratedInterfaceManager.swift
47-
SignatureHelp.swift
48-
AdjustPositionToStartOfArgument.swift
46+
SyntaxTreeManager.swift
47+
TestDiscovery.swift
48+
VariableTypeInfo.swift
4949
)
5050
set_target_properties(SwiftLanguageService PROPERTIES
5151
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
package import LanguageServerProtocol
14+
import SourceKitLSP
15+
import SwiftExtensions
16+
import SwiftSyntax
17+
18+
private class IfConfigCollector: SyntaxVisitor {
19+
private var ifConfigDecls: [IfConfigDeclSyntax] = []
20+
21+
override func visit(_ node: IfConfigDeclSyntax) -> SyntaxVisitorContinueKind {
22+
ifConfigDecls.append(node)
23+
24+
return .visitChildren
25+
}
26+
27+
static func collectIfConfigDecls(in tree: some SyntaxProtocol) -> [IfConfigDeclSyntax] {
28+
let visitor = IfConfigCollector(viewMode: .sourceAccurate)
29+
visitor.walk(tree)
30+
return visitor.ifConfigDecls
31+
}
32+
}
33+
34+
extension SwiftLanguageService {
35+
package func inlayHint(_ req: InlayHintRequest) async throws -> [InlayHint] {
36+
let uri = req.textDocument.uri
37+
let infos = try await variableTypeInfos(uri, req.range)
38+
let typeHints = infos
39+
.lazy
40+
.filter { !$0.hasExplicitType }
41+
.map { info -> InlayHint in
42+
let position = info.range.upperBound
43+
let label = ": \(info.printedType)"
44+
let textEdits: [TextEdit]?
45+
if info.canBeFollowedByTypeAnnotation {
46+
textEdits = [TextEdit(range: position..<position, newText: label)]
47+
} else {
48+
textEdits = nil
49+
}
50+
return InlayHint(
51+
position: position,
52+
label: .string(label),
53+
kind: .type,
54+
textEdits: textEdits
55+
)
56+
}
57+
58+
let snapshot = try await self.latestSnapshot(for: uri)
59+
let syntaxTree = await syntaxTreeManager.syntaxTree(for: snapshot)
60+
let ifConfigDecls = IfConfigCollector.collectIfConfigDecls(in: syntaxTree)
61+
let ifConfigHints = ifConfigDecls.compactMap { (ifConfigDecl) -> InlayHint? in
62+
// Do not show inlay hints for if config clauses that have a `#elseif` of `#else` clause since it is unclear which
63+
// `#if`, `#elseif`, or `#else` clause the `#endif` now refers to.
64+
guard let condition = ifConfigDecl.clauses.only?.condition else {
65+
return nil
66+
}
67+
guard !ifConfigDecl.poundEndif.trailingTrivia.contains(where: { $0.isComment }) else {
68+
// If a comment already exists (eg. because the user inserted it), don't show an inlay hint.
69+
return nil
70+
}
71+
let hintPosition = snapshot.position(of: ifConfigDecl.poundEndif.endPositionBeforeTrailingTrivia)
72+
let label = " // \(condition.trimmedDescription)"
73+
return InlayHint(
74+
position: hintPosition,
75+
label: .string(label),
76+
kind: .type, // For the lack of a better kind, pretend this comment is a type
77+
textEdits: [TextEdit(range: Range(hintPosition), newText: label)],
78+
tooltip: .string("Condition of this conditional compilation clause")
79+
)
80+
}
81+
82+
return Array(typeHints + ifConfigHints)
83+
}
84+
}

Sources/SwiftLanguageService/SwiftLanguageService.swift

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,32 +1032,6 @@ extension SwiftLanguageService {
10321032
return codeActions
10331033
}
10341034

1035-
package func inlayHint(_ req: InlayHintRequest) async throws -> [InlayHint] {
1036-
let uri = req.textDocument.uri
1037-
let infos = try await variableTypeInfos(uri, req.range)
1038-
let hints = infos
1039-
.lazy
1040-
.filter { !$0.hasExplicitType }
1041-
.map { info -> InlayHint in
1042-
let position = info.range.upperBound
1043-
let label = ": \(info.printedType)"
1044-
let textEdits: [TextEdit]?
1045-
if info.canBeFollowedByTypeAnnotation {
1046-
textEdits = [TextEdit(range: position..<position, newText: label)]
1047-
} else {
1048-
textEdits = nil
1049-
}
1050-
return InlayHint(
1051-
position: position,
1052-
label: .string(label),
1053-
kind: .type,
1054-
textEdits: textEdits
1055-
)
1056-
}
1057-
1058-
return Array(hints)
1059-
}
1060-
10611035
package func codeLens(_ req: CodeLensRequest) async throws -> [CodeLens] {
10621036
let snapshot = try documentManager.latestSnapshot(req.textDocument.uri)
10631037
var targetDisplayName: String? = nil

0 commit comments

Comments
 (0)