Skip to main content

Scope test format

We have a custom format we use to test that our scopes are correct. The format is automatically generated, so you shouldn't need to edit it yourself. See Step 6 of the adding a new scope guide for more information.

Example

Example of .scope file for the javascript statement scope.

const value = 0;
---
[Content] =
[Removal] =
[Domain] = 0:0-0:16
>----------------<
0| const value = 0;

[Insertion delimiter] = "\n"

Understanding the format

General layout of a .scope file is:

Source code
---
Scopes

Source code

The code that you want to generate scopes for. We try to keep this as short and simple as possible while still containing the syntax you want to test.

Scopes

One or more scopes found in the source code. Each scope is a collection of ranges as well as an insertion delimiter.

A description of the different ranges and how they are used is available in our glossary.

Scope ranges

The below example indicates that the content range, removal range, and domain range was the same. Line 0, column 0, to line 0, column 16.

[Content] =
[Removal] =
[Domain] = 0:0-2:1

These ranges could also be different and in that case each show up as a separate range.

[Removal] =
[Content] = 0:0-0:6

[Domain] = 0:0-2:1

Each range is also visualized:

Single line range

  >------------<
0| if (true) {}

Multi line range

  >-----------
0| if (true) {
1|
2| }
-<

On the left hand side we first have the line numbers, a pipe separator, and finally the source code. The range is visualized by starting after > and ending before <. Note that > and < is excluded from the range. That means a range of length one is >-< and an empty range is ><.

Style guidelines

For ease of readability we want all scope test to follow the recommended style guidelines.

Naming convention and values

  • For classes, functions and variables we use the classic: foo, bar, baz, bongo. Language specific formatting still applies. eg Foo for a class in Java, IFoo for an interface in C# etc.
  • For arguments and parameters we use: aaa, bbb, ccc and so on.
  • For data type we use int or number.
  • For value we use 0, 1, 2 and so on.

Examples:

class Foo {}
int foo = 0;
foo(aaa, bbb);

Keep it compact

Don't add more lines than the example actually needs. For example if the test is about the class name, the facet name.class: there is no point having a lot of code in the class body or having it span multiple lines. Keep the code single line and with an empty body if possible.

class Foo {}

There are exceptions to this rule:

  1. Sometimes we actually need a body, but that doesn't mean that we need it to be multiple lines. The facet interior.class can look like this:
class Foo { }
  1. When testing a facet inside a code block. eg a method in a class or a field in a interface multiple lines are prefered.
class Foo {
bar() {}
}
  1. If you're doing a *.iteration.document test we want to include a leading and trailing new line. eg:

int foo;

Examples of good fixtures

These are examples of scope facets and appropriate source code.

// statement.variable.initialized
// name.variable.initialized
// type.variable.initialized
// value.variable
int foo = 0;

// class
// name.class
// statement.class
// type.class
class Foo {}

// class
// name.class
// statement.class
// type.class
@bar
class Foo {}

// interior.class
// statement.iteration.class
// namedFunction.iteration.class
// name.iteration.class
// value.iteration.class
// type.iteration.class
// class.iteration.class
class Foo { }

// functionCall
// functionCallee
// statement.functionCall
// argumentList.actual.empty
foo();

// argument.actual.singleLine
// argument.actual.iteration
// argumentList.actual.singleLine
foo(aaa, bbb);

// namedFunction
// name.function
// statement.function
// argumentList.formal.empty
void bar() {}

// type.return
int bar() {}

// argument.formal.singleLine
// argument.formal.iteration
// argumentList.formal.singleLine
// name.argument.formal
// name.argument.formal.iteration
// type.argument.formal
// type.argument.formal.iteration
void bar(int aaa, int bbb) {}

// argument.actual.multiLine
// argumentList.actual.multiLine
foo(
aaa,
bbb
);

// argument.formal.multiLine
// argument.formal.iteration
// argumentList.formal.multiLine
void bar(
int aaa,
int bbb
) {}

// namedFunction.method
// statement.method
// name.method
// argumentList.formal.method.empty
class Foo {
void bar() {}
}

// namedFunction.constructor
// statement.constructor
// name.constructor
// argumentList.formal.constructor.empty
class Foo {
Foo() {}
}

// statement.field.class
// name.field.class
// value.field.class
// type.field.class
class Foo {
int bar;
int baz = 0;
@An int bongo = 0;
}

// string.singleLine
// textFragment.string.singleLine
"Hello world"

// string.multiLine
// textFragment.string.multiLine
"""
Hello
world
"""

// statement.while
// condition.while
while (true) {}

// interior.while
while (true) { }

// condition.ternary
// branch.ternary
// branch.ternary.iteration
true ? 0 : 1;

// branch.if.else
if (true) {}
else {}

// ifStatement
// statement.if
// condition.if
// branch.if.elif.else
// branch.if.iteration
if (true) {}
else if (false) {}
else {}

// interior.if
if (true) { }
else if (false) { }
else { }