diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 1e338c77d0..2ab681546c 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -34,6 +34,7 @@ This is a {{ site.pmd.release_type }} release. ### External Contributions +* [#2666](https://github.com/pmd/pmd/pull/2666): \[swift] Manage swift5 string literals - [kenji21](https://github.com/kenji21) * [#2959](https://github.com/pmd/pmd/pull/2959): \[apex] New Rule: override equals and hashcode rule - [recdevs](https://github.com/recdevs) * [#2964](https://github.com/pmd/pmd/pull/2964): \[cs] Update C# grammar for additional C# 7 and C# 8 features - [Maikel Steneker](https://github.com/maikelsteneker) * [#2983](https://github.com/pmd/pmd/pull/2983): \[java] LiteralsFirstInComparisons should consider constant fields - [Ozan Gulle](https://github.com/ozangulle) 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..2c44bc62f2 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 | SingleStringLiteral | BooleanLiteral | NilLiteral | RawMultiStringLiteral | RawSingleStringLiteral ; // GRAMMAR OF AN INTEGER LITERAL @@ -1073,11 +1073,16 @@ TRIPLEDQUOTES : '"""' ; MultiStringLiteral : TRIPLEDQUOTES '\n' .*? '\n' TRIPLEDQUOTES ; fragment MultiQuotedText : MultiQuotedTextItem+ ; -fragment MultiQuotedTextItem : MultiInterpolatedString - | ~[\\\u000A\u000D] - ; +fragment MultiQuotedTextItem : MultiInterpolatedString | ~[\\\u000A\u000D] ; fragment MultiInterpolatedString: '\\(' (MultiQuotedTextItem | SingleStringLiteral)* ')'; +// swift 5 extended delimiter, eg ##"abc"## +RawSingleStringLiteral : '#"' RawSingleQuotedTextItem* '"#' | '#' RawSingleStringLiteral '#'; +fragment RawSingleQuotedTextItem : ~[\u000A\u000D] ; + +RawMultiStringLiteral : '#"""' RawMultiQuotedTextItem* '"""#' | '#' RawMultiStringLiteral '#'; +fragment RawMultiQuotedTextItem : . ; + // 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..85bd015309 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,16 @@ 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)"## + } +} + +let rawMultiString = ###"a\###"### +let rawMultiString2 = ###"""a\### +""hey"" +"""### 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..cb66d0c607 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,42 @@ 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 + [##"