diff --git a/CHANGES.md b/CHANGES.md index ceb04d4ac3..3dfc86202f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,19 @@ New Languages: - Added 3rd party Laravel Blade grammar to SUPPORTED_LANGUAGES (#2944) [Michael Newton][] +Language grammar improvements: + +- enh(swift) Improved highlighting for operator and precedencegroup declarations. (#2938) [Steven Van Impe][] + +Parser: + +- add `modes.MATCH_NOTHING_RE` that will never match + - This can be used with `end` to hold a mode open (it must then be ended with + `endsParent` in one of it's children modes) [Josh Goebel][] + [Michael Newton]: https://github.com/miken32 +[Steven Van Impe]: https://github.com/svanimpe/ +[Josh Goebel]: https://github.com/joshgoebel ## Version 10.5.0 diff --git a/src/languages/lib/kws_swift.js b/src/languages/lib/kws_swift.js index a52ca459bc..b349c52603 100644 --- a/src/languages/lib/kws_swift.js +++ b/src/languages/lib/kws_swift.js @@ -117,10 +117,6 @@ export const keywords = [ // NOTE: Contextual keywords are reserved only in specific contexts. // Ideally, these should be matched using modes to avoid false positives. -// TODO: Create a PRECEDENCE_GROUP mode to match the remaining contextual keywords: -// assignment associativity higherThan left lowerThan none right -// These aren't included in the list because they result in mostly false positives. - // Literals. export const literals = [ 'false', @@ -128,6 +124,17 @@ export const literals = [ 'true' ]; +// Keywords used in precedence groups. +export const precedencegroupKeywords = [ + 'assignment', + 'associativity', + 'higherThan', + 'left', + 'lowerThan', + 'none', + 'right' +]; + // Keywords that start with a number sign (#). // #available is handled separately. export const numberSignKeywords = [ diff --git a/src/languages/swift.js b/src/languages/swift.js index 5f8e1a7389..f499d1a9a7 100644 --- a/src/languages/swift.js +++ b/src/languages/swift.js @@ -413,6 +413,43 @@ export default function(hljs) { ], illegal: /\[|%/ }; + // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380 + const OPERATOR_DECLARATION = { + beginKeywords: 'operator', + end: hljs.MATCH_NOTHING_RE, + contains: [ + { + className: 'title', + match: Swift.operator, + endsParent: true, + relevance: 0 + } + ] + }; + + // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID550 + const PRECEDENCEGROUP = { + beginKeywords: 'precedencegroup', + end: hljs.MATCH_NOTHING_RE, + contains: [ + { + className: 'title', + match: Swift.typeIdentifier, + relevance: 0 + }, + { + begin: /{/, + end: /}/, + relevance: 0, + endsParent: true, + keywords: [ + ...Swift.precedencegroupKeywords, + ...Swift.literals + ].join(' '), + contains: [ TYPE ] + } + ] + }; // Add supported submodes to string interpolation. for (const variant of STRING.variants) { @@ -460,6 +497,8 @@ export default function(hljs) { ...KEYWORD_MODES ] }, + OPERATOR_DECLARATION, + PRECEDENCEGROUP, { beginKeywords: 'import', end: /$/, diff --git a/src/lib/modes.js b/src/lib/modes.js index eb4c7f137d..e4d2ab45b9 100644 --- a/src/lib/modes.js +++ b/src/lib/modes.js @@ -2,6 +2,7 @@ import { inherit } from './utils.js'; import * as regex from './regex.js'; // Common regexps +export const MATCH_NOTHING_RE = /\b\B/; export const IDENT_RE = '[a-zA-Z]\\w*'; export const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; export const NUMBER_RE = '\\b\\d+(\\.\\d+)?'; diff --git a/test/markup/swift/operator-declarations.expect.txt b/test/markup/swift/operator-declarations.expect.txt new file mode 100644 index 0000000000..3330ebfcbb --- /dev/null +++ b/test/markup/swift/operator-declarations.expect.txt @@ -0,0 +1,3 @@ +prefix operator +++ +postfix operator +++ +infix operator +-: AdditionPrecedence diff --git a/test/markup/swift/operator-declarations.txt b/test/markup/swift/operator-declarations.txt new file mode 100644 index 0000000000..695156346a --- /dev/null +++ b/test/markup/swift/operator-declarations.txt @@ -0,0 +1,3 @@ +prefix operator +++ +postfix operator +++ +infix operator +-: AdditionPrecedence diff --git a/test/markup/swift/precedencegroup.expect.txt b/test/markup/swift/precedencegroup.expect.txt new file mode 100644 index 0000000000..4cb8ebe3f1 --- /dev/null +++ b/test/markup/swift/precedencegroup.expect.txt @@ -0,0 +1,8 @@ +precedencegroup MyGroup { + higherThan: OtherGroup, AnotherGroup + lowerThan: OtherGroup, AnotherGroup + assignment: true + associativity: left + associativity: right + associativity: none +} diff --git a/test/markup/swift/precedencegroup.txt b/test/markup/swift/precedencegroup.txt new file mode 100644 index 0000000000..fdadf9889b --- /dev/null +++ b/test/markup/swift/precedencegroup.txt @@ -0,0 +1,8 @@ +precedencegroup MyGroup { + higherThan: OtherGroup, AnotherGroup + lowerThan: OtherGroup, AnotherGroup + assignment: true + associativity: left + associativity: right + associativity: none +} diff --git a/types/index.d.ts b/types/index.d.ts index e572abae87..223aa3e0c1 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -58,6 +58,7 @@ interface ModesAPI { // built in regex IDENT_RE: string UNDERSCORE_IDENT_RE: string + MATCH_NOTHING_RE: string NUMBER_RE: string C_NUMBER_RE: string BINARY_NUMBER_RE: string