Skip to content

Commit 40e4da9

Browse files
DRY’d the throws diagnostics and kept behavior: added shared helpers for JSException notes and clause construction, reused in JSFunction/JSSetter. JSSetter now uses its own propagation note text via the helper. All macro tests still green: swift test --package-path ./Plugins/BridgeJS --filter BridgeJSMacrosTests.
If you want, I can similarly centralize any other repeated note/fix-it strings or run the full plugin suite.
1 parent 66f585a commit 40e4da9

2 files changed

Lines changed: 37 additions & 28 deletions

File tree

Plugins/BridgeJS/Sources/BridgeJSMacros/JSMacroSupport.swift

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ struct JSMacroFixItMessage: FixItMessage {
2929
var fixItID: MessageID { MessageID(domain: "JavaScriptKitMacros", id: message) }
3030
}
3131

32+
enum JSMacroText {
33+
static let jsExceptionPropagation = "@JSFunction must propagate JavaScript errors as JSException."
34+
static let jsSetterExceptionPropagation = "@JSSetter must propagate JavaScript errors as JSException."
35+
}
36+
3237
struct JSMacroWarningMessage: DiagnosticMessage {
3338
let message: String
3439
var diagnosticID: MessageID { MessageID(domain: "JavaScriptKitMacros", id: message) }
@@ -211,28 +216,15 @@ enum JSMacroHelper {
211216
guard !isJSException else { return }
212217
guard !isAllowedGenericError else { return }
213218

214-
let throwsSpecifier = throwsClause.throwsSpecifier.with(\.trailingTrivia, .spaces(0))
215-
let leftParen = throwsClause.leftParen ?? .leftParenToken()
216-
let rightParen = (throwsClause.rightParen ?? .rightParenToken())
217-
.with(\.trailingTrivia, throwsClause.rightParen?.trailingTrivia ?? .space)
218-
let newThrowsClause = throwsClause
219-
.with(\.throwsSpecifier, throwsSpecifier)
220-
.with(\.leftParen, leftParen)
221-
.with(\.type, TypeSyntax(IdentifierTypeSyntax(name: .identifier("JSException"))))
222-
.with(\.rightParen, rightParen)
219+
let newThrowsClause = jsExceptionThrowsClause(from: throwsClause)
223220

224221
let fixIt = FixIt(
225222
message: JSMacroFixItMessage(message: "Declare throws(JSException)"),
226223
changes: [.replace(oldNode: Syntax(throwsClause), newNode: Syntax(newThrowsClause))]
227224
)
228225

229226
var notes: [Note] = [
230-
Note(
231-
node: node,
232-
message: JSMacroNoteMessage(
233-
message: "@JSFunction must propagate JavaScript errors as JSException."
234-
)
235-
)
227+
jsExceptionPropagationNote(on: node)
236228
]
237229
notes.append(contentsOf: additionalNotes)
238230

@@ -276,4 +268,29 @@ enum JSMacroHelper {
276268
guard let base = setterPropertyBase(from: firstParameter) else { return nil }
277269
return "set" + capitalizingFirstLetter(base)
278270
}
271+
272+
/// Build a typed throws(JSException) clause preserving trivia when possible.
273+
static func jsExceptionThrowsClause(from throwsClause: ThrowsClauseSyntax?) -> ThrowsClauseSyntax {
274+
let throwsSpecifier = (throwsClause?.throwsSpecifier ?? .keyword(.throws, leadingTrivia: .space))
275+
.with(\.trailingTrivia, .spaces(0))
276+
let leftParen = throwsClause?.leftParen ?? .leftParenToken()
277+
let rightParen = (throwsClause?.rightParen ?? .rightParenToken())
278+
.with(\.trailingTrivia, throwsClause?.rightParen?.trailingTrivia ?? .space)
279+
280+
return ThrowsClauseSyntax(
281+
throwsSpecifier: throwsSpecifier,
282+
leftParen: leftParen,
283+
type: TypeSyntax(IdentifierTypeSyntax(name: .identifier("JSException"))),
284+
rightParen: rightParen
285+
)
286+
}
287+
288+
static func jsExceptionPropagationNote(on node: Syntax, message: String = JSMacroText.jsExceptionPropagation) -> Note {
289+
Note(
290+
node: node,
291+
message: JSMacroNoteMessage(
292+
message: message
293+
)
294+
)
295+
}
279296
}

Plugins/BridgeJS/Sources/BridgeJSMacros/JSSetterMacro.swift

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,8 @@ extension JSSetterMacro: BodyMacro {
195195
let hasAnyThrows = functionDecl.signature.effectSpecifiers?.throwsClause != nil
196196

197197
if !hasTypedJSException {
198-
let existingLeadingTrivia = functionDecl.signature.effectSpecifiers?.throwsClause?.throwsSpecifier
199-
.leadingTrivia
200-
let throwsLeadingTrivia = existingLeadingTrivia ?? .space
201-
let throwsClause = ThrowsClauseSyntax(
202-
throwsSpecifier: .keyword(.throws, leadingTrivia: throwsLeadingTrivia),
203-
leftParen: .leftParenToken(),
204-
type: IdentifierTypeSyntax(name: .identifier("JSException")),
205-
rightParen: .rightParenToken()
198+
let throwsClause = JSMacroHelper.jsExceptionThrowsClause(
199+
from: functionDecl.signature.effectSpecifiers?.throwsClause
206200
)
207201
let newEffects = (functionDecl.signature.effectSpecifiers
208202
?? FunctionEffectSpecifiersSyntax(asyncSpecifier: nil, throwsClause: nil))
@@ -213,11 +207,9 @@ extension JSSetterMacro: BodyMacro {
213207
changes: [.replace(oldNode: Syntax(functionDecl.signature), newNode: Syntax(newSignature))]
214208
)
215209
var notes: [Note] = [
216-
Note(
217-
node: Syntax(functionDecl),
218-
message: JSMacroNoteMessage(
219-
message: "@JSSetter must propagate JavaScript errors as JSException."
220-
)
210+
JSMacroHelper.jsExceptionPropagationNote(
211+
on: Syntax(functionDecl),
212+
message: JSMacroText.jsSetterExceptionPropagation
221213
)
222214
]
223215
if let wrapperNote {

0 commit comments

Comments
 (0)