Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

- Syntax highlighting for `Feature`, `Rule` `Scenario`, and `Scenario Outline` keywords ([#249](https://github.com/cucumber/language-service/pull/249))

## [1.7.0] - 2025-05-18
### Added
- Syntax highlighting for comments (`#`) ([#245](https://github.com/cucumber/language-service/pull/245))
16 changes: 12 additions & 4 deletions src/service/getGherkinSemanticTokens.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,10 @@ import { parseGherkinDocument } from '../gherkin/parseGherkinDocument.js'
// The default vs theme can only highlight certain tokens. See the list of those tokens in
// https://microsoft.github.io/monaco-editor/monarch.html
export const semanticTokenTypes: SemanticTokenTypes[] = [
SemanticTokenTypes.keyword, // Feature, Scenario, Given etc
SemanticTokenTypes.keyword, // Background, Given, When, Then, etc.
SemanticTokenTypes.namespace, // Feature keyword
SemanticTokenTypes.class, // Rule keyword
SemanticTokenTypes.function, // Scenario keyword
SemanticTokenTypes.parameter, // step parameters
SemanticTokenTypes.string, // DocString content and ``` delimiter, table cells (except example table header rows)
SemanticTokenTypes.type, // @tags and DocString ```type
@@ -77,10 +80,10 @@ export function getGherkinSemanticTokens(
return makeLocationToken(tag.location, tag.name, SemanticTokenTypes.type, arr)
},
feature(feature, arr) {
return makeLocationToken(feature.location, feature.keyword, SemanticTokenTypes.keyword, arr)
return makeLocationToken(feature.location, feature.keyword, SemanticTokenTypes.namespace, arr)
},
rule(rule, arr) {
return makeLocationToken(rule.location, rule.keyword, SemanticTokenTypes.keyword, arr)
return makeLocationToken(rule.location, rule.keyword, SemanticTokenTypes.class, arr)
},
background(background, arr) {
return makeLocationToken(
@@ -92,7 +95,12 @@ export function getGherkinSemanticTokens(
},
scenario(scenario, arr) {
inScenarioOutline = (scenario.examples || []).length > 0
return makeLocationToken(scenario.location, scenario.keyword, SemanticTokenTypes.keyword, arr)
return makeLocationToken(
scenario.location,
scenario.keyword,
SemanticTokenTypes.function,
arr
)
},
examples(examples, arr) {
inExamples = true
60 changes: 32 additions & 28 deletions test/service/getGherkinSemanticTokens.test.ts
Original file line number Diff line number Diff line change
@@ -21,26 +21,27 @@ Feature: a
This is a description
and so is this

Background:
Given a repeating step
Rule:
Background:
Given a repeating step

Scenario: b
Given I have 42 cukes in my belly
"""sometype
hello
world
"""
And a table
| a | bbb |
| cc | dd |
And I should be on the map
Scenario: b
Given I have 42 cukes in my belly
"""sometype
hello
world
"""
And a table
| a | bbb |
| cc | dd |
And I should be on the map

Scenario Outline: c
Given a <foo> and <bar>
Scenario Outline: c
Given a <foo> and <bar>

Examples:
| foo | bar |
| a | b |
Examples:
| foo | bar |
| a | b |
`
const parameterTypeRegistry = new ParameterTypeRegistry()
const cucumberExpression = new CucumberExpression(
@@ -61,10 +62,11 @@ Feature: a
['# some comment', SemanticTokenTypes.comment],
['@foo', SemanticTokenTypes.type],
['@bar', SemanticTokenTypes.type],
['Feature', SemanticTokenTypes.keyword],
['Feature', SemanticTokenTypes.namespace],
['Rule', SemanticTokenTypes.class],
['Background', SemanticTokenTypes.keyword],
['Given ', SemanticTokenTypes.keyword],
['Scenario', SemanticTokenTypes.keyword],
['Scenario', SemanticTokenTypes.function],
['Given ', SemanticTokenTypes.keyword],
['42', SemanticTokenTypes.parameter],
['belly', SemanticTokenTypes.parameter],
@@ -79,7 +81,7 @@ Feature: a
['cc', SemanticTokenTypes.string],
['dd', SemanticTokenTypes.string],
['And ', SemanticTokenTypes.keyword],
['Scenario Outline', SemanticTokenTypes.keyword],
['Scenario Outline', SemanticTokenTypes.function],
['Given ', SemanticTokenTypes.keyword],
['<foo>', SemanticTokenTypes.variable],
['<bar>', SemanticTokenTypes.variable],
@@ -96,18 +98,20 @@ Feature: a
// Note that 'When' step uses two spaces, to align the text with 'Given'
const gherkinSource = `
Feature: making drinks
Scenario Outline:
Given a <ingredient>
When I make <drink>
Examples:
| ingredient | drink |
| apple | apple juice |
Rule:
Scenario Outline:
Given a <ingredient>
When I make <drink>
Examples:
| ingredient | drink |
| apple | apple juice |
`
const semanticTokens = getGherkinSemanticTokens(gherkinSource, [])
const actual = tokenize(gherkinSource, semanticTokens.data)
const expected: TokenWithType[] = [
['Feature', SemanticTokenTypes.keyword],
['Scenario Outline', SemanticTokenTypes.keyword],
['Feature', SemanticTokenTypes.namespace],
['Rule', SemanticTokenTypes.class],
['Scenario Outline', SemanticTokenTypes.function],
['Given ', SemanticTokenTypes.keyword],
['<ingredient>', SemanticTokenTypes.variable],
['When ', SemanticTokenTypes.keyword],