Skip to content

Commit c9e3699

Browse files
authored
Merge pull request #41500 from rintaro/swiftcompiler-ast
[SwiftCompiler] Add DiagnosticEngine bridging
2 parents b2ed8a2 + 4d9b65d commit c9e3699

File tree

12 files changed

+431
-0
lines changed

12 files changed

+431
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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 http://swift.org/LICENSE.txt for license information
7+
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
8+
9+
add_swift_compiler_module(AST
10+
DEPENDS
11+
Basic
12+
SOURCES
13+
DiagnosticEngine.swift)
14+
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//===--- DiagnosticEngine.swift -------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 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+
import ASTBridging
14+
15+
import Basic
16+
17+
public typealias DiagID = BridgedDiagID
18+
19+
extension BridgedDiagnosticArgument {
20+
init(stringRef val: BridgedStringRef) {
21+
self.init(kind: .stringRef, value: .init(stringRefValue: val))
22+
}
23+
init(int val: Int) {
24+
self.init(kind: .int, value: .init(intValue: val))
25+
}
26+
}
27+
28+
public protocol DiagnosticArgument {
29+
func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void)
30+
}
31+
extension String: DiagnosticArgument {
32+
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
33+
withBridgedStringRef { fn(BridgedDiagnosticArgument(stringRef: $0)) }
34+
}
35+
}
36+
extension Int: DiagnosticArgument {
37+
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
38+
fn(BridgedDiagnosticArgument(int: self))
39+
}
40+
}
41+
42+
public struct DiagnosticFixIt {
43+
public let start: SourceLoc
44+
public let byteLength: Int
45+
public let text: String
46+
47+
public init(start: SourceLoc, byteLength: Int, replacement text: String) {
48+
self.start = start
49+
self.byteLength = byteLength
50+
self.text = text
51+
}
52+
53+
func withBridgedDiagnosticFixIt(_ fn: (BridgedDiagnosticFixIt) -> Void) {
54+
text.withBridgedStringRef { bridgedTextRef in
55+
let bridgedDiagnosticFixIt = BridgedDiagnosticFixIt(
56+
start: start.bridged,
57+
byteLength: byteLength,
58+
text: bridgedTextRef)
59+
fn(bridgedDiagnosticFixIt)
60+
}
61+
}
62+
}
63+
64+
public struct DiagnosticEngine {
65+
private let bridged: BridgedDiagnosticEngine
66+
67+
public init(bridged: BridgedDiagnosticEngine) {
68+
self.bridged = bridged
69+
}
70+
71+
public func diagnose(_ position: SourceLoc?,
72+
_ id: DiagID,
73+
_ args: [DiagnosticArgument],
74+
highlight: CharSourceRange? = nil,
75+
fixIts: [DiagnosticFixIt] = []) {
76+
77+
let bridgedSourceLoc: BridgedSourceLoc = position.bridged
78+
let bridgedHighlightRange: BridgedCharSourceRange = highlight.bridged
79+
var bridgedArgs: [BridgedDiagnosticArgument] = []
80+
var bridgedFixIts: [BridgedDiagnosticFixIt] = []
81+
82+
// Build a higher-order function to wrap every 'withBridgedXXX { ... }'
83+
// calls, so we don't escape anything from the closure. 'bridgedArgs' and
84+
// 'bridgedFixIts' are temporary storage to store bridged values. So they
85+
// should not be used after the closue is executed.
86+
87+
var closure: () -> Void = {
88+
bridgedArgs.withBridgedArrayRef { bridgedArgsRef in
89+
bridgedFixIts.withBridgedArrayRef { bridgedFixItsRef in
90+
DiagnosticEngine_diagnose(bridged, bridgedSourceLoc,
91+
id, bridgedArgsRef,
92+
bridgedHighlightRange, bridgedFixItsRef)
93+
}
94+
}
95+
}
96+
for arg in args {
97+
closure = { [closure, arg] in
98+
arg._withBridgedDiagnosticArgument { bridgedArg in
99+
bridgedArgs.append(bridgedArg)
100+
closure()
101+
}
102+
}
103+
}
104+
for fixIt in fixIts {
105+
closure = { [closure, fixIt] in
106+
fixIt.withBridgedDiagnosticFixIt { bridgedFixIt in
107+
bridgedFixIts.append(bridgedFixIt)
108+
closure()
109+
}
110+
}
111+
}
112+
113+
closure()
114+
}
115+
116+
public func diagnose(_ position: SourceLoc?,
117+
_ id: DiagID,
118+
_ args: DiagnosticArgument...,
119+
highlight: CharSourceRange? = nil,
120+
fixIts: DiagnosticFixIt...) {
121+
diagnose(position, id, args, highlight: highlight, fixIts: fixIts)
122+
}
123+
}

SwiftCompilerSources/Sources/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
add_swift_compiler_module(Basic
10+
SourceLoc.swift
1011
Utils.swift)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===--- SourceLoc.swift - SourceLoc bridiging utilities ------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 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+
public struct SourceLoc {
14+
/// Points into a source file.
15+
let locationInFile: UnsafePointer<UInt8>
16+
17+
public init?(locationInFile: UnsafePointer<UInt8>?) {
18+
guard let locationInFile = locationInFile else {
19+
return nil
20+
}
21+
self.locationInFile = locationInFile
22+
}
23+
24+
public init?(bridged: BridgedSourceLoc) {
25+
guard let locationInFile = bridged.pointer else {
26+
return nil
27+
}
28+
self.init(locationInFile: locationInFile)
29+
}
30+
31+
public var bridged: BridgedSourceLoc {
32+
.init(pointer: locationInFile)
33+
}
34+
}
35+
36+
extension Optional where Wrapped == SourceLoc {
37+
public var bridged: BridgedSourceLoc {
38+
self?.bridged ?? .init(pointer: nil)
39+
}
40+
}
41+
42+
public struct CharSourceRange {
43+
private let start: SourceLoc
44+
private let byteLength: Int
45+
46+
public init(start: SourceLoc, byteLength: Int) {
47+
self.start = start
48+
self.byteLength = byteLength
49+
}
50+
51+
public init?(bridged: BridgedCharSourceRange) {
52+
guard let start = SourceLoc(bridged: bridged.start) else {
53+
return nil
54+
}
55+
self.init(start: start, byteLength: bridged.byteLength)
56+
}
57+
58+
public var bridged: BridgedCharSourceRange {
59+
.init(start: start.bridged, byteLength: byteLength)
60+
}
61+
}
62+
63+
extension Optional where Wrapped == CharSourceRange {
64+
public var bridged: BridgedCharSourceRange {
65+
self?.bridged ?? .init(start: .init(pointer: nil), byteLength: 0)
66+
}
67+
}

SwiftCompilerSources/Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# NOTE: Subdirectories must be added in dependency order.
1010

1111
add_subdirectory(Basic)
12+
add_subdirectory(AST)
1213
if(SWIFT_ENABLE_EXPERIMENTAL_STRING_PROCESSING)
1314
add_subdirectory(ExperimentalRegex)
1415
endif()

include/swift/AST/ASTBridging.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===--- ASTBridging.h - header for the swift SILBridging module ----------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 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+
#ifndef SWIFT_AST_ASTBRIDGING_H
14+
#define SWIFT_AST_ASTBRIDGING_H
15+
16+
#include "swift/Basic/BasicBridging.h"
17+
#include "swift/Basic/Compiler.h"
18+
#include <stdbool.h>
19+
#include <stddef.h>
20+
21+
#ifdef __cplusplus
22+
extern "C" {
23+
#endif
24+
25+
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
26+
27+
//===----------------------------------------------------------------------===//
28+
// Diagnostic Engine
29+
//===----------------------------------------------------------------------===//
30+
31+
// TODO: Move this to somewhere common header.
32+
#if __has_attribute(enum_extensibility)
33+
#define ENUM_EXTENSIBILITY_ATTR(arg) __attribute__((enum_extensibility(arg)))
34+
#else
35+
#define ENUM_EXTENSIBILITY_ATTR(arg)
36+
#endif
37+
38+
// NOTE: This must be the same underlying value as C++ 'swift::DiagID' defined
39+
// in 'DiagnosticList.cpp'.
40+
typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedDiagID : uint32_t {
41+
#define DIAG(KIND, ID, Options, Text, Signature) BridgedDiagID_##ID,
42+
#include "swift/AST/DiagnosticsAll.def"
43+
} BridgedDiagID;
44+
45+
typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedDiagnosticArgumentKind {
46+
BridgedDiagnosticArgumentKind_StringRef,
47+
BridgedDiagnosticArgumentKind_Int,
48+
} BridgedDiagnosticArgumentKind;
49+
50+
typedef struct {
51+
BridgedDiagnosticArgumentKind kind;
52+
union {
53+
BridgedStringRef stringRefValue;
54+
SwiftInt intValue;
55+
} value;
56+
} BridgedDiagnosticArgument;
57+
58+
typedef struct {
59+
BridgedSourceLoc start;
60+
SwiftInt byteLength;
61+
BridgedStringRef text;
62+
} BridgedDiagnosticFixIt;
63+
64+
typedef struct {
65+
void * _Nonnull object;
66+
} BridgedDiagnosticEngine;
67+
68+
// FIXME: Can we bridge InFlightDiagnostic?
69+
void DiagnosticEngine_diagnose(BridgedDiagnosticEngine, BridgedSourceLoc loc,
70+
BridgedDiagID diagID, BridgedArrayRef arguments,
71+
BridgedCharSourceRange highlight,
72+
BridgedArrayRef fixIts);
73+
74+
bool DiagnosticEngine_hadAnyError(BridgedDiagnosticEngine);
75+
76+
SWIFT_END_NULLABILITY_ANNOTATIONS
77+
78+
#ifdef __cplusplus
79+
} // extern "C"
80+
#endif
81+
82+
#endif // SWIFT_AST_ASTBRIDGING_H

include/swift/AST/BridgingUtils.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===--- BridgingUtils.h - utilities for swift bridging -------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 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+
#ifndef SWIFT_AST_BRIDGINGUTILS_H
14+
#define SWIFT_AST_BRIDGINGUTILS_H
15+
16+
#include "swift/AST/ASTBridging.h"
17+
#include "swift/AST/DiagnosticEngine.h"
18+
19+
namespace swift {
20+
21+
inline BridgedDiagnosticEngine getBridgedDiagnosticEngine(DiagnosticEngine *D) {
22+
return {(void *)D};
23+
}
24+
25+
} // namespace swift
26+
27+
#endif
28+

include/swift/Basic/BasicBridging.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ void OStream_write(BridgedOStream os, BridgedStringRef str);
4343

4444
void freeBridgedStringRef(BridgedStringRef str);
4545

46+
//===----------------------------------------------------------------------===//
47+
// Source location
48+
//===----------------------------------------------------------------------===//
49+
50+
typedef struct {
51+
const unsigned char * _Nullable pointer;
52+
} BridgedSourceLoc;
53+
54+
typedef struct {
55+
BridgedSourceLoc start;
56+
SwiftInt byteLength;
57+
} BridgedCharSourceRange;
58+
4659
SWIFT_END_NULLABILITY_ANNOTATIONS
4760

4861
#ifdef __cplusplus

include/swift/Basic/BridgingUtils.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ inline llvm::ArrayRef<T> getArrayRef(BridgedArrayRef bridged) {
3636
return {static_cast<const T *>(bridged.data), bridged.numElements};
3737
}
3838

39+
inline SourceLoc getSourceLoc(const BridgedSourceLoc &bridged) {
40+
return SourceLoc(
41+
llvm::SMLoc::getFromPointer((const char *)bridged.pointer));
42+
}
43+
44+
inline BridgedSourceLoc getBridgedSourceLoc(const SourceLoc &loc) {
45+
return {static_cast<const unsigned char *>(loc.getOpaquePointerValue())};
46+
}
47+
48+
inline CharSourceRange
49+
getCharSourceRange(const BridgedCharSourceRange &bridged) {
50+
auto start = getSourceLoc(bridged.start);
51+
return CharSourceRange(start, bridged.byteLength);
52+
}
53+
54+
inline BridgedCharSourceRange
55+
getBridgedCharSourceRange(const CharSourceRange &range) {
56+
auto start = getBridgedSourceLoc(range.getStart());
57+
return {start, range.getByteLength()};
58+
}
59+
3960
/// Copies the string in an malloc'ed memory and the caller is responsible for
4061
/// freeing it. 'freeBridgedStringRef()' is available in 'BasicBridging.h'
4162
inline BridgedStringRef

include/swift/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ module BasicBridging {
44
export *
55
}
66

7+
module ASTBridging {
8+
header "AST/ASTBridging.h"
9+
export *
10+
}
11+
712
module SILBridging {
813
header "SIL/SILBridging.h"
914
export *

0 commit comments

Comments
 (0)