Skip to content

enh(swift) highlight function and macro call usage #3959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ Core Grammars:
- fix(swift) ensure keyword attributes highlight correctly [Bradley Mackey][]
- fix(types) fix interface LanguageDetail > keywords [Patrick Chiu]
- enh(java) add `goto` to be recognized as a keyword in Java [Alvin Joy][]
- enh(swift) highlight function and macro call usage [Bradley Mackey][]

New Grammars:

88 changes: 65 additions & 23 deletions src/languages/swift.js
Original file line number Diff line number Diff line change
@@ -11,11 +11,17 @@ import * as Swift from './lib/kws_swift.js';
import {
concat,
either,
lookahead
lookahead,
negativeLookahead
} from '../lib/regex.js';

/** @type LanguageFn */
export default function(hljs) {
/**
* Regex for detecting a function call following an identifier.
*/
const TRAILING_PAREN_REGEX = /[^\S\r\n]*\(/;

const WHITESPACE = {
match: /\s+/,
relevance: 0
@@ -40,9 +46,9 @@ export default function(hljs) {
],
className: { 2: "keyword" }
};
const KEYWORD_GUARD = {
// Consume .keyword to prevent highlighting properties and methods as keywords.
match: concat(/\./, either(...Swift.keywords)),
const KEYWORD_PROP_GUARD = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so we don't want the keyword engine to grab these as keywords, true, but if they are essentially "properly access" why wouldnt we scope them as that?

// Consume .keyword to prevent highlighting properties as keywords. .methods are highlighted seperately
match: concat(/\./, either(...Swift.keywords), negativeLookahead(TRAILING_PAREN_REGEX)),
relevance: 0
};
const PLAIN_KEYWORDS = Swift.keywords
@@ -70,24 +76,14 @@ export default function(hljs) {
};
const KEYWORD_MODES = [
DOT_KEYWORD,
KEYWORD_GUARD,
KEYWORD_PROP_GUARD,
KEYWORD
];

// https://github.com/apple/swift/tree/main/stdlib/public/core
const BUILT_IN_GUARD = {
// Consume .built_in to prevent highlighting properties and methods.
match: concat(/\./, either(...Swift.builtIns)),
relevance: 0
};
const BUILT_IN = {
className: 'built_in',
match: concat(/\b/, either(...Swift.builtIns), /(?=\()/)
scope: 'built_in',
match: concat(/\b/, either(...Swift.builtIns), lookahead(TRAILING_PAREN_REGEX)),
};
const BUILT_INS = [
BUILT_IN_GUARD,
BUILT_IN
];

// https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418
const OPERATOR_GUARD = {
@@ -335,7 +331,7 @@ export default function(hljs) {
...COMMENTS,
REGEXP,
...KEYWORD_MODES,
...BUILT_INS,
BUILT_IN,
...OPERATORS,
NUMBER,
STRING,
@@ -390,13 +386,16 @@ export default function(hljs) {
endsParent: true,
illegal: /["']/
};

const FUNCTION_IDENT = either(QUOTED_IDENTIFIER.match, Swift.identifier, Swift.operator);

// https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID362
// https://docs.swift.org/swift-book/documentation/the-swift-programming-language/declarations/#Macro-Declaration
const FUNCTION_OR_MACRO = {
match: [
/(func|macro)/,
/\s+/,
either(QUOTED_IDENTIFIER.match, Swift.identifier, Swift.operator)
FUNCTION_IDENT,
],
className: {
1: "keyword",
@@ -491,14 +490,56 @@ export default function(hljs) {
]
};

function noneOf(list) {
return negativeLookahead(either(...list));
}

const METHODS_ONLY = [...Swift.keywords, ...Swift.builtIns];
const FUNCTION_CALL = {
relevance: 0,
variants: [
{
// Functions and macro calls
scope: "title.function",
keywords: KEYWORDS,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems weird, why would we have keywords popping up in the middle of a function name? Or is this truly to cover "it's a function name that's also a keyword"?

match: concat(
either(/\b/, /#/),
noneOf(METHODS_ONLY.map(x => concat(x, TRAILING_PAREN_REGEX))),
FUNCTION_IDENT,
lookahead(TRAILING_PAREN_REGEX),
),
},
{
// Keywords/built-ins that only can appear as a method call
// e.g. foo.if()
match: [
/\./,
either(...METHODS_ONLY),
TRAILING_PAREN_REGEX,
],
scope: {
2: "title.function",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd call anything that appears to be an object property access a property for consistent highlighting across different grammars.

}
},
{
// Quoted methods calls, e.g. `foo`()
scope: "title.function",
match: concat(
QUOTED_IDENTIFIER.match,
lookahead(TRAILING_PAREN_REGEX),
)
}
]
};

// Add supported submodes to string interpolation.
for (const variant of STRING.variants) {
const interpolation = variant.contains.find(mode => mode.label === "interpol");
// TODO: Interpolation can contain any expression, so there's room for improvement here.
interpolation.keywords = KEYWORDS;
const submodes = [
...KEYWORD_MODES,
...BUILT_INS,
BUILT_IN,
...OPERATORS,
NUMBER,
STRING,
@@ -535,14 +576,15 @@ export default function(hljs) {
},
REGEXP,
...KEYWORD_MODES,
...BUILT_INS,
BUILT_IN,
...OPERATORS,
NUMBER,
STRING,
...IDENTIFIERS,
...ATTRIBUTES,
TYPE,
TUPLE
TUPLE,
FUNCTION_CALL,
...IDENTIFIERS,
]
};
}
8 changes: 8 additions & 0 deletions src/lib/regex.js
Original file line number Diff line number Diff line change
@@ -25,6 +25,14 @@ export function lookahead(re) {
return concat('(?=', re, ')');
}

/**
* @param {RegExp | string } re
* @returns {string}
*/
export function negativeLookahead(re) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome.

return concat('(?!', re, ')');
}

/**
* @param {RegExp | string } re
* @returns {string}
64 changes: 64 additions & 0 deletions test/markup/swift/functions.expect.txt
Original file line number Diff line number Diff line change
@@ -17,6 +17,9 @@
<span class="hljs-params">p5</span>: <span class="hljs-meta">@attribute</span> <span class="hljs-type">String</span>? <span class="hljs-operator">=</span> <span class="hljs-string">&quot;text&quot;</span>
) { }

<span class="hljs-keyword">func</span> <span class="hljs-title function_">`escaped`</span>() {}
<span class="hljs-keyword">func</span> <span class="hljs-title function_">`if`</span>() {}

<span class="hljs-keyword">init</span>&lt;<span class="hljs-type">X</span>: <span class="hljs-type">A</span>&gt;(<span class="hljs-keyword">_</span> <span class="hljs-params">p</span>: <span class="hljs-meta">@attribute</span> <span class="hljs-keyword">inout</span> (x: <span class="hljs-type">Int</span>, var: <span class="hljs-type">Int</span>) <span class="hljs-operator">=</span> (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)) { }
<span class="hljs-keyword">init?</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">p</span>: <span class="hljs-meta">@attribute</span> <span class="hljs-keyword">inout</span> (x: <span class="hljs-type">Int</span>, var: <span class="hljs-type">Int</span>) <span class="hljs-operator">=</span> (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)) { }
<span class="hljs-keyword">init!</span> (<span class="hljs-keyword">_</span> <span class="hljs-params">p</span>: <span class="hljs-meta">@attribute</span> <span class="hljs-keyword">inout</span> (x: <span class="hljs-type">Int</span>, var: <span class="hljs-type">Int</span>) <span class="hljs-operator">=</span> (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)) { }
@@ -30,3 +33,64 @@
<span class="hljs-keyword">static</span> <span class="hljs-keyword">func</span> <span class="hljs-title function_">&gt;</span> (<span class="hljs-params">lhs</span>: <span class="hljs-keyword">Self</span>, <span class="hljs-params">rhs</span>: <span class="hljs-keyword">Self</span>) -&gt; <span class="hljs-type">Bool</span>
<span class="hljs-keyword">static</span> <span class="hljs-keyword">func</span> <span class="hljs-title function_">&gt;=</span> (<span class="hljs-params">lhs</span>: <span class="hljs-keyword">Self</span>, <span class="hljs-params">rhs</span>: <span class="hljs-keyword">Self</span>) -&gt; <span class="hljs-type">Bool</span>
}

<span class="hljs-comment">// paren spacing</span>
obj.<span class="hljs-title function_">fn</span>(<span class="hljs-number">1</span>)
obj.<span class="hljs-title function_">fn</span> (<span class="hljs-number">1</span>)
obj.prop
(<span class="hljs-number">1</span>) <span class="hljs-comment">// newline break, this is no longer a function</span>

<span class="hljs-comment">// builtins</span>
<span class="hljs-built_in">abs</span>(<span class="hljs-number">1</span>)
<span class="hljs-built_in">swap</span>(<span class="hljs-operator">&amp;</span>a, <span class="hljs-operator">&amp;</span>b)
<span class="hljs-built_in">zip</span>(a, b)
obj.<span class="hljs-title function_">abs</span>(<span class="hljs-number">1</span>)
obj.<span class="hljs-title function_">swap</span>(<span class="hljs-operator">&amp;</span>a, <span class="hljs-operator">&amp;</span>b)
obj.<span class="hljs-title function_">zip</span>(a, b)
obj.<span class="hljs-title function_">abs</span> (<span class="hljs-number">1</span>)
obj.abs
(<span class="hljs-number">1</span>)

<span class="hljs-comment">// methods</span>
<span class="hljs-title function_">method</span>()
<span class="hljs-title function_">method</span>(<span class="hljs-number">1</span>)
<span class="hljs-title function_">method</span>(param: <span class="hljs-number">1</span>)
obj.<span class="hljs-title function_">method</span>()
obj .<span class="hljs-title function_">method</span>()
obj.<span class="hljs-title function_">method</span>(<span class="hljs-number">1</span>)
obj.<span class="hljs-title function_">method</span>(param: <span class="hljs-number">1</span>)
obj.prop.<span class="hljs-title function_">method</span>()
obj.prop .<span class="hljs-title function_">method</span>()
obj.prop.<span class="hljs-title function_">method</span>(<span class="hljs-number">1</span>)
obj.prop.<span class="hljs-title function_">method</span>(param: <span class="hljs-number">1</span>)
obj.prop.<span class="hljs-title function_">method</span>(
param: <span class="hljs-number">1</span>
)
obj.prop
.<span class="hljs-title function_">method</span>()

<span class="hljs-comment">// keywords</span>
obj.<span class="hljs-title function_">if</span>(condition: <span class="hljs-literal">true</span>)
obj.if <span class="hljs-comment">// variable</span>
obj .if <span class="hljs-comment">// variable</span>
<span class="hljs-title function_">`if`</span>()
obj.<span class="hljs-title function_">`if`</span>()
obj.<span class="hljs-title function_">`if`</span> ()
<span class="hljs-title function_">`notKeyword`</span>()
obj.<span class="hljs-title function_">`notKeyword`</span>()
obj.<span class="hljs-title function_">`notKeyword`</span> ()

<span class="hljs-comment">// number sign keywords are fine</span>
<span class="hljs-title function_">column</span>()
<span class="hljs-title function_">keyPath</span>()
<span class="hljs-title function_">sourceLocation</span>()
obj.<span class="hljs-title function_">column</span>()
obj.<span class="hljs-title function_">keyPath</span>()
obj.<span class="hljs-title function_">sourceLocation</span>()

<span class="hljs-comment">// attribute keywords are fine</span>
<span class="hljs-title function_">frozen</span>()
<span class="hljs-title function_">discardableResult</span>()
obj.<span class="hljs-title function_">frozen</span>()
obj.<span class="hljs-title function_">discardableResult</span>()

64 changes: 64 additions & 0 deletions test/markup/swift/functions.txt
Original file line number Diff line number Diff line change
@@ -17,6 +17,9 @@ func f3(
p5: @attribute String? = "text"
) { }

func `escaped`() {}
func `if`() {}

init<X: A>(_ p: @attribute inout (x: Int, var: Int) = (0, 0)) { }
init?(_ p: @attribute inout (x: Int, var: Int) = (0, 0)) { }
init! (_ p: @attribute inout (x: Int, var: Int) = (0, 0)) { }
@@ -30,3 +33,64 @@ protocol Comparable: Equatable {
static func > (lhs: Self, rhs: Self) -> Bool
static func >= (lhs: Self, rhs: Self) -> Bool
}

// paren spacing
obj.fn(1)
obj.fn (1)
obj.prop
(1) // newline break, this is no longer a function

// builtins
abs(1)
swap(&a, &b)
zip(a, b)
obj.abs(1)
obj.swap(&a, &b)
obj.zip(a, b)
obj.abs (1)
obj.abs
(1)

// methods
method()
method(1)
method(param: 1)
obj.method()
obj .method()
obj.method(1)
obj.method(param: 1)
obj.prop.method()
obj.prop .method()
obj.prop.method(1)
obj.prop.method(param: 1)
obj.prop.method(
param: 1
)
obj.prop
.method()

// keywords
obj.if(condition: true)
obj.if // variable
obj .if // variable
`if`()
obj.`if`()
obj.`if` ()
`notKeyword`()
obj.`notKeyword`()
obj.`notKeyword` ()

// number sign keywords are fine
column()
keyPath()
sourceLocation()
obj.column()
obj.keyPath()
obj.sourceLocation()

// attribute keywords are fine
frozen()
discardableResult()
obj.frozen()
obj.discardableResult()

21 changes: 17 additions & 4 deletions test/markup/swift/keywords.expect.txt
Original file line number Diff line number Diff line change
@@ -19,10 +19,23 @@ x <span class="hljs-keyword">is</span> <span class="hljs-type">String</span>
<span class="hljs-keyword">isolated</span> <span class="hljs-keyword">nonisolated</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">fileprivate</span> <span class="hljs-keyword">package</span> <span class="hljs-keyword">internal</span> <span class="hljs-keyword">open</span>

<span class="hljs-keyword">#if</span>
<span class="hljs-keyword">#error</span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#if</span> <span class="hljs-type">DEBUG</span>
<span class="hljs-title function_"><span class="hljs-keyword">#error</span></span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#elseif</span> <span class="hljs-title function_">os</span>(macOS)
<span class="hljs-title function_"><span class="hljs-keyword">#error</span></span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#elseif</span> <span class="hljs-title function_">arch</span>(arm64)
<span class="hljs-title function_"><span class="hljs-keyword">#error</span></span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#elseif</span> <span class="hljs-title function_">compiler</span>(<span class="hljs-operator">&gt;=</span><span class="hljs-number">5.0</span>)
<span class="hljs-title function_"><span class="hljs-keyword">#error</span></span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#elseif</span> <span class="hljs-title function_">canImport</span>(<span class="hljs-type">UIKit</span>)
<span class="hljs-title function_"><span class="hljs-keyword">#error</span></span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#elseif</span> <span class="hljs-title function_">targetEnvironment</span>(simulator)
<span class="hljs-title function_"><span class="hljs-keyword">#error</span></span>(<span class="hljs-string">&quot;Error&quot;</span>)
<span class="hljs-keyword">#endif</span>

x.as(y)
x.for(y)
<span class="hljs-title function_"><span class="hljs-keyword">#imageLiteral</span></span>(resourceName: expression)
<span class="hljs-title function_"><span class="hljs-keyword">#fileLiteral</span></span>(resourceName: expression)

x.<span class="hljs-title function_">as</span>(y)
x.<span class="hljs-title function_">for</span>(y)
#notAKeyword
15 changes: 14 additions & 1 deletion test/markup/swift/keywords.txt
Original file line number Diff line number Diff line change
@@ -19,10 +19,23 @@ async await
isolated nonisolated
public private fileprivate package internal open

#if
#if DEBUG
#error("Error")
#elseif os(macOS)
#error("Error")
#elseif arch(arm64)
#error("Error")
#elseif compiler(>=5.0)
#error("Error")
#elseif canImport(UIKit)
#error("Error")
#elseif targetEnvironment(simulator)
#error("Error")
#endif

#imageLiteral(resourceName: expression)
#fileLiteral(resourceName: expression)

x.as(y)
x.for(y)
#notAKeyword
6 changes: 3 additions & 3 deletions test/markup/swift/macro.expect.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<span class="hljs-keyword">macro</span> <span class="hljs-title function_">warning</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">message</span>: <span class="hljs-type">String</span>) <span class="hljs-operator">=</span> #externalMacro(module: <span class="hljs-string">&quot;MyMacros&quot;</span>, type: <span class="hljs-string">&quot;WarningMacro&quot;</span>)
<span class="hljs-keyword">macro</span> <span class="hljs-title function_">warning</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">message</span>: <span class="hljs-type">String</span>) <span class="hljs-operator">=</span> <span class="hljs-title function_">#externalMacro</span>(module: <span class="hljs-string">&quot;MyMacros&quot;</span>, type: <span class="hljs-string">&quot;WarningMacro&quot;</span>)

<span class="hljs-keyword">@freestanding</span>(declaration)
<span class="hljs-keyword">macro</span> <span class="hljs-title function_">error</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">message</span>: <span class="hljs-type">String</span>) <span class="hljs-operator">=</span> #externalMacro(module: <span class="hljs-string">&quot;MyMacros&quot;</span>, type: <span class="hljs-string">&quot;ErrorMacro&quot;</span>)
<span class="hljs-keyword">macro</span> <span class="hljs-title function_">error</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">message</span>: <span class="hljs-type">String</span>) <span class="hljs-operator">=</span> <span class="hljs-title function_">#externalMacro</span>(module: <span class="hljs-string">&quot;MyMacros&quot;</span>, type: <span class="hljs-string">&quot;ErrorMacro&quot;</span>)

<span class="hljs-keyword">@attached</span>(member)
<span class="hljs-keyword">macro</span> <span class="hljs-title function_">OptionSetMembers</span>()

<span class="hljs-keyword">@attached</span>(peer, names: overloaded)
<span class="hljs-keyword">macro</span> <span class="hljs-title function_">OptionSetMembers</span>()

#myMacro()
<span class="hljs-title function_">#myMacro</span>()
4 changes: 2 additions & 2 deletions test/markup/swift/numbers.expect.txt
Original file line number Diff line number Diff line change
@@ -26,11 +26,11 @@
<span class="hljs-operator">+-</span><span class="hljs-number">1</span>
<span class="hljs-number">2</span><span class="hljs-operator">-</span><span class="hljs-number">3</span>
<span class="hljs-operator">-</span><span class="hljs-number">10</span>.magnitude
fn(<span class="hljs-operator">-</span><span class="hljs-number">5</span>)
<span class="hljs-title function_">fn</span>(<span class="hljs-operator">-</span><span class="hljs-number">5</span>)
<span class="hljs-number">0x2</span>.p2

<span class="hljs-comment">// expressions not containing numeric literals</span>
fn(x0.d);
<span class="hljs-title function_">fn</span>(x0.d);

<span class="hljs-comment">// pseudo-expressions containing numeric literals</span>
.<span class="hljs-number">0</span>
10 changes: 5 additions & 5 deletions test/markup/swift/ownership.expect.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<span class="hljs-keyword">consume</span> x
<span class="hljs-keyword">_</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">consume</span> y
doStuffUniquely(with: <span class="hljs-keyword">consume</span> x)
<span class="hljs-title function_">doStuffUniquely</span>(with: <span class="hljs-keyword">consume</span> x)
<span class="hljs-keyword">copy</span> x
<span class="hljs-keyword">_</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">copy</span> x
doStuff(with: <span class="hljs-keyword">copy</span> x)
<span class="hljs-title function_">doStuff</span>(with: <span class="hljs-keyword">copy</span> x)

<span class="hljs-keyword">struct</span> <span class="hljs-title class_">MoveOnly</span>: ~<span class="hljs-title class_ inherited__">Copyable</span> {}

@@ -13,9 +13,9 @@ doStuff(with: <span class="hljs-keyword">copy</span> x)
<span class="hljs-keyword">func</span> <span class="hljs-title function_">foo</span>(<span class="hljs-keyword">_</span>: <span class="hljs-keyword">borrowing</span> <span class="hljs-type">Foo</span>)
<span class="hljs-keyword">func</span> <span class="hljs-title function_">foo</span>(<span class="hljs-keyword">_</span>: <span class="hljs-keyword">consuming</span> <span class="hljs-type">Foo</span>)
<span class="hljs-keyword">func</span> <span class="hljs-title function_">foo</span>(<span class="hljs-keyword">_</span>: <span class="hljs-keyword">inout</span> <span class="hljs-type">Foo</span>)
<span class="hljs-keyword">let</span> f: (<span class="hljs-keyword">borrowing</span> <span class="hljs-type">Foo</span>) -&gt; <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> { a <span class="hljs-keyword">in</span> a.foo() }
<span class="hljs-keyword">let</span> f: (<span class="hljs-keyword">consuming</span> <span class="hljs-type">Foo</span>) -&gt; <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> { a <span class="hljs-keyword">in</span> a.foo() }
<span class="hljs-keyword">let</span> f: (<span class="hljs-keyword">inout</span> <span class="hljs-type">Foo</span>) -&gt; <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> { a <span class="hljs-keyword">in</span> a.foo() }
<span class="hljs-keyword">let</span> f: (<span class="hljs-keyword">borrowing</span> <span class="hljs-type">Foo</span>) -&gt; <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> { a <span class="hljs-keyword">in</span> a.<span class="hljs-title function_">foo</span>() }
<span class="hljs-keyword">let</span> f: (<span class="hljs-keyword">consuming</span> <span class="hljs-type">Foo</span>) -&gt; <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> { a <span class="hljs-keyword">in</span> a.<span class="hljs-title function_">foo</span>() }
<span class="hljs-keyword">let</span> f: (<span class="hljs-keyword">inout</span> <span class="hljs-type">Foo</span>) -&gt; <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> { a <span class="hljs-keyword">in</span> a.<span class="hljs-title function_">foo</span>() }
<span class="hljs-keyword">struct</span> <span class="hljs-title class_">Foo</span> {
<span class="hljs-keyword">consuming</span> <span class="hljs-keyword">func</span> <span class="hljs-title function_">foo</span>()
<span class="hljs-keyword">borrowing</span> <span class="hljs-keyword">func</span> <span class="hljs-title function_">foo</span>()
20 changes: 10 additions & 10 deletions test/markup/swift/regex.expect.txt
Original file line number Diff line number Diff line change
@@ -9,12 +9,12 @@
<span class="hljs-keyword">let</span> n <span class="hljs-operator">=</span> <span class="hljs-regexp">/hello/</span> <span class="hljs-operator">+</span> <span class="hljs-regexp">/world/</span> <span class="hljs-operator">-</span> <span class="hljs-regexp">/nice/</span>
<span class="hljs-keyword">let</span> q <span class="hljs-operator">=</span> <span class="hljs-regexp">/hello/</span> <span class="hljs-operator">/</span> <span class="hljs-number">2</span>
(<span class="hljs-regexp">/hello/</span>)
method(value: <span class="hljs-regexp">/hello/</span>)
method(<span class="hljs-regexp">/hello/</span>, world)
method(<span class="hljs-regexp">/hello/</span>, <span class="hljs-regexp">/world/</span>)
foo(<span class="hljs-regexp">/a, b/</span>) <span class="hljs-comment">// Will become regex literal &#x27;/a, b/&#x27;</span>
qux(<span class="hljs-regexp">/, !/</span>) <span class="hljs-comment">// Will become regex literal &#x27;/, !/&#x27;</span>
qux(<span class="hljs-regexp">/,/</span>) <span class="hljs-comment">// Will become regex literal &#x27;/,/&#x27;</span>
<span class="hljs-title function_">method</span>(value: <span class="hljs-regexp">/hello/</span>)
<span class="hljs-title function_">method</span>(<span class="hljs-regexp">/hello/</span>, world)
<span class="hljs-title function_">method</span>(<span class="hljs-regexp">/hello/</span>, <span class="hljs-regexp">/world/</span>)
<span class="hljs-title function_">foo</span>(<span class="hljs-regexp">/a, b/</span>) <span class="hljs-comment">// Will become regex literal &#x27;/a, b/&#x27;</span>
<span class="hljs-title function_">qux</span>(<span class="hljs-regexp">/, !/</span>) <span class="hljs-comment">// Will become regex literal &#x27;/, !/&#x27;</span>
<span class="hljs-title function_">qux</span>(<span class="hljs-regexp">/,/</span>) <span class="hljs-comment">// Will become regex literal &#x27;/,/&#x27;</span>
<span class="hljs-keyword">let</span> g <span class="hljs-operator">=</span> hasSubscript[<span class="hljs-regexp">/]/</span><span class="hljs-number">2</span> <span class="hljs-comment">// Will become regex literal &#x27;/]/&#x27;</span>
<span class="hljs-keyword">let</span> h <span class="hljs-operator">=</span> <span class="hljs-regexp">/0; let f = 1/</span> <span class="hljs-comment">// Will become the regex literal &#x27;/0; let y = 1/&#x27;</span>
<span class="hljs-keyword">let</span> i <span class="hljs-operator">=</span> <span class="hljs-regexp">/^x/</span> <span class="hljs-comment">// Will become the regex literal &#x27;/^x/&#x27;</span>
@@ -37,9 +37,9 @@ qux(<span class="hljs-regexp">/,/</span>) <span class="hljs-comment">// Will
<span class="hljs-keyword">let</span> n <span class="hljs-operator">=</span> <span class="hljs-regexp">#/hello/#</span> <span class="hljs-operator">+</span> <span class="hljs-regexp">/world/</span> <span class="hljs-operator">-</span> <span class="hljs-regexp">#/nice/#</span>
<span class="hljs-keyword">let</span> q <span class="hljs-operator">=</span> <span class="hljs-regexp">#/hello/#</span> <span class="hljs-operator">/</span> <span class="hljs-number">2</span>
(<span class="hljs-regexp">#/hello/#</span>)
method(value: <span class="hljs-regexp">#/hello/#</span>)
method(<span class="hljs-regexp">#/hello/#</span>, world)
method(<span class="hljs-regexp">#/hello/#</span>, <span class="hljs-regexp">#/world/#</span>)
<span class="hljs-title function_">method</span>(value: <span class="hljs-regexp">#/hello/#</span>)
<span class="hljs-title function_">method</span>(<span class="hljs-regexp">#/hello/#</span>, world)
<span class="hljs-title function_">method</span>(<span class="hljs-regexp">#/hello/#</span>, <span class="hljs-regexp">#/world/#</span>)
<span class="hljs-regexp">#/regex with #not a comment/#</span>

<span class="hljs-comment">// multiline extended literals</span>
@@ -100,4 +100,4 @@ x<span class="hljs-operator">+</span><span class="hljs-regexp">#/y/#</span> <spa
<span class="hljs-comment">// unterminated</span>
<span class="hljs-operator">/</span>something
another line
<span class="hljs-operator">/</span>
<span class="hljs-operator">/</span>
2 changes: 1 addition & 1 deletion test/markup/swift/swiftui.expect.txt
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
<span class="hljs-keyword">struct</span> <span class="hljs-title class_">MyApp</span>: <span class="hljs-title class_ inherited__">App</span> {
<span class="hljs-keyword">var</span> body: <span class="hljs-keyword">some</span> <span class="hljs-type">Scene</span> {
<span class="hljs-type">WindowGroup</span> {
<span class="hljs-keyword">#if</span> os(iOS)
<span class="hljs-keyword">#if</span> <span class="hljs-title function_">os</span>(iOS)
<span class="hljs-type">Text</span>(<span class="hljs-string">&quot;Hello, world from iOS!&quot;</span>)
<span class="hljs-keyword">#else</span>
<span class="hljs-type">Text</span>(<span class="hljs-string">&quot;Hello, world!&quot;</span>)