diff --git a/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/antlr4/Swift.g4 b/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/antlr4/Swift.g4 index 01ee4ad84c..c71b5fbda7 100644 --- a/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/antlr4/Swift.g4 +++ b/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/antlr4/Swift.g4 @@ -1018,7 +1018,7 @@ ImplicitParameterName : '$' DecimalLiteral ; // TODO: don't allow '_' here // GRAMMAR OF A LITERAL booleanLiteral: BooleanLiteral ; -literal : numericLiteral | MultiStringLiteral | SingleStringLiteral | BooleanLiteral | NilLiteral ; +literal : numericLiteral | MultiStringLiteral | DashedSingleStringLiteral | SingleStringLiteral | BooleanLiteral | NilLiteral ; // GRAMMAR OF AN INTEGER LITERAL @@ -1078,6 +1078,13 @@ fragment MultiQuotedTextItem : MultiInterpolatedString ; fragment MultiInterpolatedString: '\\(' (MultiQuotedTextItem | SingleStringLiteral)* ')'; +DashedSingleStringLiteral : '#"' DashedMultiQuotedText? '"#' ; +fragment DashedMultiQuotedText : DashedMultiQuotedTextItem+ ; +fragment DashedMultiQuotedTextItem : EscapedCharacter | DashedMultiInterpolatedString + | ~[\\\u000A\u000D] + ; +fragment DashedMultiInterpolatedString: '\\#(' (DashedMultiQuotedTextItem | DashedSingleStringLiteral)* ')'; + // StringLiteral : '"' QuotedText? '"' ; SingleStringLiteral : '"' QuotedText? '"' ; fragment SingleDoubleQuote : '"' | ~["] ; diff --git a/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.swift b/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.swift index 6e77f1dd29..cf326c21c7 100644 --- a/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.swift +++ b/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.swift @@ -38,3 +38,11 @@ var x = 2 print(x[keyPath: id]) // prints 2 x[keyPath: id] = 3 print(x[keyPath: id]) // prints 3 + +// https://www.swiftbysundell.com/articles/string-literals-in-swift/ +let rawString = #"Press "Continue" to close this dialog."# +extension URL { + func html(withTitle title: String) -> String { + return #"\#(title)"# + } +} diff --git a/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.txt b/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.txt index 5eaa13610c..0a89406a83 100644 --- a/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.txt +++ b/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/cpd/testdata/Swift5.0.txt @@ -197,4 +197,37 @@ L40 [id] 18 19 [\]] 20 20 [)] 21 21 +L43 + [let] 1 3 + [rawString] 5 13 + [=] 15 15 + [#"Press "Continue" to close this d[ 17 58 +L44 + [extension] 1 9 + [URL] 11 13 + [{] 15 15 +L45 + [func] 5 8 + [html] 10 13 + [(] 14 14 + [withTitle] 15 23 + [title] 25 29 + [:] 30 30 + [String] 32 37 + [)] 38 38 + [->] 40 41 + [String] 43 48 + [{] 50 50 +L46 + [return] 9 14 + [#"\\[ 16 61 +L47 + [}] 5 5 +L48 + [}] 1 1 +L49 + [let] 1 3 + [regex] 5 9 + [=] 11 11 + [#"w+"#] 13 18 EOF