Skip to content

Commit

Permalink
enh(scala) add Scala 3 end and extension soft keywords (#3327)
Browse files Browse the repository at this point in the history
* enh(scala) add Scala 3 extension soft keyword

Based on https://github.com/scala/vscode-scala-syntax/blob/57e0829cd46980699570101a68c320a20330d36c/src/typescript/Scala.tmLanguage.ts#L1134.
Also see https://docs.scala-lang.org/scala3/reference/contextual/extension-methods.html#syntax.

* enh(scala) add Scala 3 end soft keyword

Add Scala 3 end of definition or expression.

Simplified verion of https://github.com/scala/vscode-scala-syntax/blob/main/src/typescript/Scala.tmLanguage.ts#L599-L634. Here we only need one kind of keyword.
  • Loading branch information
nicolasstucki committed Sep 9, 2021
1 parent c3c04d6 commit 32bde79
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -18,6 +18,8 @@ Grammars:
- enh(scala) add missing `do` and `then` keyword (#3323) [Nicolas Stucki][]
- enh(scala) add missing `enum`, `export` and `given` keywords (#3328) [Nicolas Stucki][]
- enh(scala) remove symbol syntax and fix quoted code syntax (#3324) [Nicolas Stucki][]
- enh(scala) add Scala 3 `extension` soft keyword (#3326) [Nicolas Stucki][]
- enh(scala) add Scala 3 `end` soft keyword (#3327) [Nicolas Stucki][]
- enh(scala) add `inline` soft keyword (#3329) [Nicolas Stucki][]

[Austin Schick]: https://github.com/austin-schick
Expand Down
26 changes: 26 additions & 0 deletions src/languages/scala.js
Expand Up @@ -112,6 +112,30 @@ export default function(hljs) {
contains: [ NAME ]
};

const EXTENSION = {
begin: [
/^\s*/, // Is first token on the line
'extension',
/\s+(?=[[(])/, // followed by at least one space and `[` or `(`
],
beginScope: {
2: "keyword",
}
};

const END = [{
begin: [
/^\s*/, // Is first token on the line
/end/,
/\s+/,
/(extension\b)?/, // `extension` is the only marker that follows an `end` that cannot be captured by another rule.
],
beginScope: {
2: "keyword",
4: "keyword",
}
}];

// TODO: use negative look-behind in future
// /(?<!\.)\binline(?=\s)/
const INLINE_MODES = [{
Expand All @@ -136,6 +160,8 @@ export default function(hljs) {
METHOD,
CLASS,
hljs.C_NUMBER_MODE,
EXTENSION,
END,
...INLINE_MODES,
ANNOTATION
]
Expand Down
41 changes: 41 additions & 0 deletions test/markup/scala/end.expect.txt
@@ -0,0 +1,41 @@
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">foo</span> </span>=
<span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>)
()
<span class="hljs-keyword">else</span>
()
<span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>

<span class="hljs-keyword">while</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">do</span>
()
<span class="hljs-keyword">end</span> <span class="hljs-keyword">while</span>

<span class="hljs-keyword">for</span> x &lt;- xs <span class="hljs-keyword">do</span>
()
<span class="hljs-keyword">end</span> <span class="hljs-keyword">for</span>

x <span class="hljs-keyword">match</span>
<span class="hljs-keyword">case</span> _ =&gt;
<span class="hljs-keyword">end</span> <span class="hljs-keyword">match</span>
<span class="hljs-keyword">end</span> foo

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bar</span> </span>=
<span class="hljs-keyword">new</span> <span class="hljs-type">Foo</span>:
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= ()
<span class="hljs-keyword">end</span> <span class="hljs-keyword">new</span>
<span class="hljs-keyword">end</span>

<span class="hljs-keyword">val</span> baz =
()
<span class="hljs-keyword">end</span> <span class="hljs-keyword">val</span>

<span class="hljs-keyword">var</span> baz2 =
()
<span class="hljs-keyword">end</span> <span class="hljs-keyword">var</span>

<span class="hljs-keyword">extension</span> (x: <span class="hljs-type">Int</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= <span class="hljs-number">1</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= <span class="hljs-number">2</span>
<span class="hljs-keyword">end</span> <span class="hljs-keyword">extension</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span></span>:
<span class="hljs-keyword">end</span> <span class="hljs-type">Foo</span>
41 changes: 41 additions & 0 deletions test/markup/scala/end.txt
@@ -0,0 +1,41 @@
def foo =
if (true)
()
else
()
end if

while true do
()
end while

for x <- xs do
()
end for

x match
case _ =>
end match
end foo

def bar =
new Foo:
def f = ()
end new
end

val baz =
()
end val

var baz2 =
()
end var

extension (x: Int)
def f = 1
def f = 2
end extension

class Foo:
end Foo
19 changes: 19 additions & 0 deletions test/markup/scala/extension.expect.txt
@@ -0,0 +1,19 @@
<span class="hljs-keyword">extension</span> (x: <span class="hljs-type">Int</span>) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">plus</span></span>(y: <span class="hljs-type">Int</span>) = x + y

<span class="hljs-keyword">extension</span> [<span class="hljs-type">T</span>](x: <span class="hljs-type">T</span>) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= ()

<span class="hljs-keyword">extension</span> (x: <span class="hljs-type">Int</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= <span class="hljs-number">1</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= <span class="hljs-number">2</span>

<span class="hljs-class"><span class="hljs-keyword">object</span> <span class="hljs-title">Foo</span> </span>{
<span class="hljs-keyword">extension</span> (x: <span class="hljs-type">Int</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= <span class="hljs-number">1</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span> </span>= <span class="hljs-number">2</span>
}

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">extension</span></span>(file: <span class="hljs-type">File</span>) =
file.extension

file
.extension
19 changes: 19 additions & 0 deletions test/markup/scala/extension.txt
@@ -0,0 +1,19 @@
extension (x: Int) def plus(y: Int) = x + y

extension [T](x: T) def f = ()

extension (x: Int)
def f = 1
def f = 2

object Foo {
extension (x: Int)
def f = 1
def f = 2
}

def extension(file: File) =
file.extension

file
.extension

0 comments on commit 32bde79

Please sign in to comment.