syntax-highlighter: Add snapshot test for Groovy (#60819)

Updates the docs to mention how to run one test specifically.
This commit is contained in:
Varun Gandhi 2024-03-05 03:29:07 +08:00 committed by GitHub
parent aa53b8cff0
commit 8c1bb283a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 341 additions and 7 deletions

View File

@ -47,6 +47,18 @@ By default on startup, `syntect_server` will list all file types it supports. Th
2. Use `cargo run --bin syntect_server` to run the server locally.
3. You can change the `SRC_SYNTECT_SERVER` option in your `sg.config.yaml` to point to whatever port you're running on (usually 8000) and test against that without building the docker image.
### Testing syntect -> SCIP grammar mappings
<!-- NOTE(id: only-flag) -->
You can run a subset of tests for `syntect_scip` using the `ONLY` environment variable.
Example:
```bash
cd crates/syntax-analysis
ONLY=.java cargo test test_all_files -- --nocapture
```
## Building docker image
`./build.sh` will build your current repository checkout into a final Docker image. You **DO NOT** need to do this when you push to get it publish. But, you should do this to make sure that it is possible to build the image :smile:.

View File

@ -0,0 +1,250 @@
---
source: crates/syntax-analysis/src/highlighting/syntect_scip.rs
expression: "snapshot_sciptect_documents(&document, &contents)"
---
def name = "John"
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^^^^^ StringLiteral string.quoted.double.groovy
String greeting = "Hello"
//^^^^^^ IdentifierType storage.type.class.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^^^^^^ StringLiteral string.quoted.double.groovy
int age = 30
//^^^ IdentifierType storage.type.primitive.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^ NumericLiteral constant.numeric.groovy
def list = [1, 2, 3]
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^ PunctuationBracket punctuation.definition.structure.begin.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.structure.end.groovy
def map = [name: "John", age: 30]
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^ PunctuationBracket punctuation.definition.structure.begin.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^^^^^ StringLiteral string.quoted.double.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.structure.end.groovy
def code = { "Inside closure" }
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
// ^^^^^^^^^^^^^^^^ StringLiteral string.quoted.double.groovy
// ^ PunctuationBracket punctuation.section.block.end.groovy
def message = name ?: "Default"
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^ IdentifierOperator keyword.operator.elvis.groovy
// ^^^^^^^^^ StringLiteral string.quoted.double.groovy
def str = "hello 123 world"
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^^^^^^^^^^^^^^^^ StringLiteral string.quoted.double.groovy
def regex = /\d+/
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^ PunctuationBracket punctuation.definition.string.regexp.begin.groovy
// ^^^ StringLiteral punctuation.definition.string.regexp.end.groovy
// ^ PunctuationBracket punctuation.definition.string.regexp.end.groovy
def transformed = [1, 2, 3, 4, 5].collect{ it * 2 }
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^ PunctuationBracket punctuation.definition.structure.begin.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.structure.end.groovy
// ^ PunctuationBracket punctuation.accessor.dot.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
// ^ IdentifierOperator keyword.operator.arithmetic.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.section.block.end.groovy
assert name instanceof String
//^^^^^^ Keyword keyword.control.assert.groovy
// ^^^^^^^^^^ IdentifierOperator keyword.operator.instanceof.groovy
// ^^^^^^ IdentifierType storage.type.class.groovy
new File("data.txt")
//^^^ Keyword keyword.other.new.groovy
// ^^^^ IdentifierType storage.type.class.groovy
// ^^^^^^^^^^ StringLiteral string.quoted.double.groovy
name.reverse()
// ^ PunctuationBracket punctuation.accessor.dot.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.end.groovy
for(i in 1..5) {
//^^^ Keyword keyword.control.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^^ IdentifierOperator keyword.operator.range.groovy
// ^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
println i
// ^^^^^^^ IdentifierFunction support.function.print.groovy
}
//^ PunctuationBracket punctuation.section.block.end.groovy
class Person {
//^^^^^ IdentifierType storage.type.class.groovy
// ^^^^^^ IdentifierType entity.name.type.class.groovy
String name
// ^^^^^^ IdentifierType storage.type.class.groovy
int age
// ^^^ IdentifierType storage.type.primitive.groovy
String greeting() {
// ^^^^^^ IdentifierType storage.type.return-type.class.groovy
// ^^^^^^^^ IdentifierFunction entity.name.function.groovy
// ^ PunctuationBracket punctuation.definition.parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.parameters.end.groovy
"Hello, $name!"
// ^^^^^^^^ StringLiteral variable.other.interpolated.groovy
// ^^^^^ Identifier variable.other.interpolated.groovy
// ^^ StringLiteral string.quoted.double.groovy
}
}
def person = new Person(name: "John", age: 30)
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^^ Keyword keyword.other.new.groovy
// ^^^^^^ IdentifierType storage.type.class.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^^^^^ StringLiteral string.quoted.double.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^ NumericLiteral constant.numeric.groovy
class Employee extends Person {
//^^^^^ IdentifierType storage.type.class.groovy
// ^^^^^^^^ IdentifierType entity.name.type.class.groovy
// ^^^^^^^ Keyword storage.modifier.extends.groovy
// ^^^^^^ Identifier entity.other.inherited-class.groovy
double salary
// ^^^^^^ IdentifierType storage.type.primitive.groovy
String greeting() {
// ^^^^^^ IdentifierType storage.type.return-type.class.groovy
// ^^^^^^^^ IdentifierFunction entity.name.function.groovy
// ^ PunctuationBracket punctuation.definition.parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.parameters.end.groovy
"${super.greeting()} My salary is $salary."
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ StringLiteral variable.other.interpolated.groovy
// ^^ PunctuationBracket punctuation.section.embedded.groovy
// ^^^^^ Identifier variable.language.groovy
// ^ PunctuationBracket punctuation.accessor.dot.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.end.groovy
// ^ PunctuationBracket punctuation.section.embedded.groovy
// ^^^^^^^ Identifier variable.other.interpolated.groovy
// ^^ StringLiteral string.quoted.double.groovy
}
}
def employee = new Employee(name: "Jane", age: 28, salary: 60000)
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^^ Keyword keyword.other.new.groovy
// ^^^^^^^^ IdentifierType storage.type.class.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^^^^^ StringLiteral string.quoted.double.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^^^^ NumericLiteral constant.numeric.groovy
interface Singer {
// ^^^^^^ IdentifierType storage.type.class.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
void sing()
// ^ PunctuationBracket punctuation.definition.method-parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.end.groovy
}
//^ PunctuationBracket punctuation.section.block.end.groovy
class LeadSinger implements Singer {
//^^^^^ IdentifierType storage.type.class.groovy
// ^^^^^^^^^^ IdentifierType entity.name.type.class.groovy
// ^^^^^^^^^^ Keyword storage.modifier.implements.groovy
// ^^^^^^ Identifier entity.other.inherited-class.interface.groovy
@Override
// ^^^^^^^^^ IdentifierType storage.type.annotation.groovy
void sing() {
// ^^^^ IdentifierType storage.type.return-type.void.groovy
// ^^^^ IdentifierFunction entity.name.function.groovy
// ^ PunctuationBracket punctuation.definition.parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.parameters.end.groovy
println "Singing a song!"
// ^^^^^^^ IdentifierFunction support.function.print.groovy
// ^^^^^^^^^^^^^^^^^ StringLiteral string.quoted.double.groovy
}
}
trait Guitarist {
// ^^^^^^^^^ IdentifierType storage.type.class.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
void playGuitar() {
// ^ PunctuationBracket punctuation.definition.method-parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.end.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
println "Playing guitar riff"
// ^^^^^^^ IdentifierFunction support.function.print.groovy
// ^^^^^^^^^^^^^^^^^^^^^ StringLiteral string.quoted.double.groovy
}
// ^ PunctuationBracket punctuation.section.block.end.groovy
}
//^ PunctuationBracket punctuation.section.block.end.groovy
class RockSinger extends Person implements Singer, Guitarist { }
//^^^^^ IdentifierType storage.type.class.groovy
// ^^^^^^^^^^ IdentifierType entity.name.type.class.groovy
// ^^^^^^^ Keyword storage.modifier.extends.groovy
// ^^^^^^ Identifier entity.other.inherited-class.groovy
// ^^^^^^^^^^ Keyword storage.modifier.implements.groovy
// ^^^^^^ Identifier entity.other.inherited-class.interface.groovy
// ^ PunctuationBracket punctuation.definition.implemented.interfaces.separator.groovy
// ^^^^^^^^^ Identifier entity.other.inherited-class.interface.groovy
def singer = new RockSinger(name: "Ross", age: 25).with {
//^^^ IdentifierType storage.type.def.groovy
// ^ IdentifierOperator keyword.operator.assignment.groovy
// ^^^ Keyword keyword.other.new.groovy
// ^^^^^^^^^^ IdentifierType storage.type.class.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^^^^^ StringLiteral string.quoted.double.groovy
// ^ PunctuationBracket punctuation.definition.separator.key-value.groovy
// ^^ NumericLiteral constant.numeric.groovy
// ^ PunctuationBracket punctuation.accessor.dot.groovy
// ^^^^ IdentifierFunction support.function.other.groovy
// ^ PunctuationBracket punctuation.section.block.begin.groovy
sing()
// ^ PunctuationBracket punctuation.definition.method-parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.end.groovy
playGuitar()
// ^ PunctuationBracket punctuation.definition.method-parameters.begin.groovy
// ^ PunctuationBracket punctuation.definition.method-parameters.end.groovy
}
//^ PunctuationBracket punctuation.section.block.end.groovy

View File

@ -0,0 +1,71 @@
def name = "John"
String greeting = "Hello"
int age = 30
def list = [1, 2, 3]
def map = [name: "John", age: 30]
def code = { "Inside closure" }
def message = name ?: "Default"
def str = "hello 123 world"
def regex = /\d+/
def transformed = [1, 2, 3, 4, 5].collect{ it * 2 }
assert name instanceof String
new File("data.txt")
name.reverse()
for(i in 1..5) {
println i
}
class Person {
String name
int age
String greeting() {
"Hello, $name!"
}
}
def person = new Person(name: "John", age: 30)
class Employee extends Person {
double salary
String greeting() {
"${super.greeting()} My salary is $salary."
}
}
def employee = new Employee(name: "Jane", age: 28, salary: 60000)
interface Singer {
void sing()
}
class LeadSinger implements Singer {
@Override
void sing() {
println "Singing a song!"
}
}
trait Guitarist {
void playGuitar() {
println "Playing guitar riff"
}
}
class RockSinger extends Person implements Singer, Guitarist { }
def singer = new RockSinger(name: "Ross", age: 25).with {
sing()
playGuitar()
}

View File

@ -388,8 +388,9 @@ impl<'a> DocumentGenerator<'a> {
match match_scope_to_kind(&scope) {
Some(kind) => {
// Uncomment to debug what scopes are picked up
// println!("SCOPE {row:>3}:{character:<3} {:50} {kind:?}", format!("{}", scope));
// See also NOTE(id: only-flag)
// DEBUG: Print matched scopes here
// eprintln!("SCOPE {row:>3}:{character:<3} {:50} {kind:?}", format!("{}", scope));
let partial_hl =
HighlightStart::some(row, character, kind, scope);
if let Some(partial_hl) = highlight_manager.push_hl(partial_hl)
@ -404,7 +405,9 @@ impl<'a> DocumentGenerator<'a> {
};
}
None => {
// println!("SCOPE {row:>3}:{character:<3} {:50}", format!("{}", scope));
// See also NOTE(id: only-flag)
// DEBUG: Print unknown/unhighlighted scope here
// eprintln!("SCOPE {row:>3}:{character:<3} {:50}", format!("{}", scope));
unhandled_scopes.insert(scope);
highlight_manager.push_empty();
}
@ -584,10 +587,8 @@ mod test {
let dir = read_dir(&input_dir)?;
let filter = env::args()
.last()
.and_then(|x| x.strip_prefix("only=").map(|x| x.to_owned()))
.unwrap_or("".to_owned()); // run everything
// See NOTE(id: only-flag) for exact syntax on how to pass this.
let filter = env::var("ONLY").unwrap_or("".to_owned());
let mut count = 0;
for entry in dir {