Skip to content

Commit 968ceb3

Browse files
committed
[SourceKit] Include generated macro buffers in diagnostic responses
Introduce a new key `generated_buffers`, which stores an array of generated buffers. These include the buffer text, as well as its original location and any parent buffers. While here, also fix rdar://107281079 such that only apply the filename fallback logic to the pretty-printed Decl case. We ought to remove this fallback once the editor can handle it though. rdar://107281079 rdar://107952288
1 parent 1856b5e commit 968ceb3

File tree

15 files changed

+978
-144
lines changed

15 files changed

+978
-144
lines changed

lib/Frontend/SerializedDiagnosticConsumer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ unsigned SerializedDiagnosticConsumer::getEmitFile(
231231
// NOTE: Using Filename.data() here relies on SourceMgr using
232232
// const char* as buffer identifiers. This is fast, but may
233233
// be brittle. We can always switch over to using a StringMap.
234+
// Note that the logic in EditorDiagConsumer::getBufferInfo
235+
// will also need changing.
234236
unsigned &existingEntry = State->Files[Filename.data()];
235237
if (existingEntry)
236238
return existingEntry;

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,15 @@ public struct InvalidMacro: PeerMacro, DeclarationMacro {
916916
}
917917
}
918918

919+
public struct CoerceToIntMacro: ExpressionMacro {
920+
public static func expansion(
921+
of node: some FreestandingMacroExpansionSyntax,
922+
in context: some MacroExpansionContext
923+
) -> ExprSyntax {
924+
"\(node.argumentList.first!.expression) as Int"
925+
}
926+
}
927+
919928
public struct WrapInType: PeerMacro {
920929
public static func expansion(
921930
of node: AttributeSyntax,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %sourcekitd-test -req=diags %t/main.swift -- %t/main.swift -I %t | %FileCheck %s
4+
5+
//--- Header.h
6+
#define FOO(x) #x
7+
8+
//--- module.modulemap
9+
module HeaderWithMacro {
10+
header "Header.h"
11+
}
12+
13+
//--- main.swift
14+
import HeaderWithMacro
15+
16+
_ = FOO(5)
17+
18+
// rdar://107281079 – Make sure the note points in the .h file
19+
// CHECK: key.diagnostics: [
20+
// CHECK-NEXT: {
21+
// CHECK-NEXT: key.line: 3,
22+
// CHECK-NEXT: key.column: 5,
23+
// CHECK-NEXT: key.filepath: "{{.*}}main.swift",
24+
// CHECK-NEXT: key.severity: source.diagnostic.severity.error,
25+
// CHECK-NEXT: key.id: "cannot_find_in_scope",
26+
// CHECK-NEXT: key.description: "cannot find 'FOO' in scope",
27+
// CHECK-NEXT: key.ranges: [
28+
// CHECK-NEXT: {
29+
// CHECK-NEXT: key.offset: 28,
30+
// CHECK-NEXT: key.length: 3
31+
// CHECK-NEXT: }
32+
// CHECK-NEXT: ],
33+
// CHECK-NEXT: key.diagnostics: [
34+
// CHECK-NEXT: {
35+
// CHECK-NEXT: key.line: 1,
36+
// CHECK-NEXT: key.column: 9,
37+
// CHECK-NEXT: key.filepath: "{{.*}}Header.h",
38+
// CHECK-NEXT: key.severity: source.diagnostic.severity.note,
39+
// CHECK-NEXT: key.id: "macro_not_imported_function_like",
40+
// CHECK-NEXT: key.description: "macro 'FOO' unavailable: function like macros not supported"
41+
// CHECK-NEXT: }
42+
// CHECK-NEXT: ]
43+
// CHECK-NEXT: }
44+
// CHECK-NEXT: ]

test/SourceKit/Inputs/sourcekitd_path_sanitize.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,35 @@
1212
import re
1313
import sys
1414

15-
SWIFTMODULE_BUNDLE_RE = re.compile(
16-
r'key.filepath: ".*[/\\](.*)\.swiftmodule[/\\].*\.swiftmodule"')
17-
SWIFTMODULE_RE = re.compile(r'key.filepath: ".*[/\\](.*)\.swiftmodule"')
18-
SWIFT_RE = re.compile(r'key.filepath: ".*[/\\](.*)\.swift"')
19-
PCM_RE = re.compile(r'key.filepath: ".*[/\\](.*)-[0-9A-Z]*\.pcm"')
20-
HEADER_RE = re.compile(r' file=\\".*[/\\](.*)\.h\\"')
15+
# I'm sorry dear reader, unfortunately my knowledge of regex trumps my knowledge of
16+
# Python. This pattern allows us to clean up file paths by stripping them down to
17+
# just the relevant file name.
18+
RE = re.compile(
19+
# The key can either be 'filepath' or 'buffer_name'. Also apply this logic to
20+
# the file name in XML, which is written 'file=\"...\"'.
21+
r'(key\.(?:filepath|buffer_name): |file=)'
22+
23+
# Open delimiter with optional escape.
24+
r'\\?"'
25+
26+
# Lazily match characters until we hit a slash, then match any non-slash that
27+
# ends in the right file extension, capturing the result.
28+
r'.*?[/\\]+([^/\\]*\.(?:swiftmodule|swift|pcm|h))'
29+
30+
# For swiftmodule bundles, we want to match against the directory name, so
31+
# optionally match the .swiftmodule filename here. The lazy matching of the
32+
# previous logic means we'll prefer to match the previous '.swiftmodule' as the
33+
# directory.
34+
r'(?:[/\\]+[^/\\]*\.swiftmodule)?'
35+
36+
# Close delimiter with optional escape.
37+
r'\\?"'
38+
)
2139

2240
try:
2341
for line in sys.stdin.readlines():
24-
line = re.sub(SWIFTMODULE_BUNDLE_RE,
25-
r'key.filepath: \1.swiftmodule', line)
26-
line = re.sub(SWIFTMODULE_RE, r'key.filepath: \1.swiftmodule', line)
27-
line = re.sub(SWIFT_RE, r'key.filepath: \1.swift', line)
28-
line = re.sub(PCM_RE, r'key.filepath: \1.pcm', line)
29-
line = re.sub(HEADER_RE, r' file=\1.h', line)
42+
# We substitute in both the key and the matched filename.
43+
line = re.sub(RE, r'\1\2', line)
3044
sys.stdout.write(line)
3145
except KeyboardInterrupt:
3246
sys.stdout.flush()

test/SourceKit/Macros/diags.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@freestanding(expression)
2+
macro coerceToInt<T>(_: T) -> Int = #externalMacro(module: "MacroDefinition", type: "CoerceToIntMacro")
3+
4+
@freestanding(expression)
5+
macro stringify<T>(_: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
6+
7+
@attached(peer)
8+
macro Invalid() = #externalMacro(module: "MacroDefinition", type: "InvalidMacro")
9+
10+
func foo() {
11+
let _ = #coerceToInt("a")
12+
let _ = #coerceToInt("b")
13+
let _ = #stringify(#coerceToInt("c"))
14+
}
15+
16+
@Invalid
17+
struct Bad {}
18+
19+
// REQUIRES: swift_swift_parser
20+
21+
// RUN: %empty-directory(%t)
22+
23+
//##-- Prepare the macro plugin.
24+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/../../Macros/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
25+
26+
// RUN: %sourcekitd-test -req=diags %s -- -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser %s | %sed_clean > %t.response
27+
// RUN: %diff -u %s.response %t.response

0 commit comments

Comments
 (0)