Skip to content
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

feat: handle backticks surrounding IDs #622

Merged
merged 4 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
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 src/language/grammar/safe-ds-value-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { convertString, CstNode, DefaultValueConverter, GrammarAST, ValueType }
export class SafeDsValueConverter extends DefaultValueConverter {
protected override runConverter(rule: GrammarAST.AbstractRule, input: string, cstNode: CstNode): ValueType {
switch (rule.name.toUpperCase()) {
case 'ID':
return input.replaceAll('`', '');
case 'TEMPLATE_STRING_START':
return convertString(input.substring(0, input.length - 1));
case 'TEMPLATE_STRING_INNER':
Expand Down
4 changes: 3 additions & 1 deletion tests/helpers/nodeFinder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,12 @@ describe('getNodeOfType', () => {

it('should return the nth matching node if an index is set', async () => {
const code = `
package p

class C
enum D
`;
const node = await getNodeOfType(services, code, isSdsDeclaration, 1);
const node = await getNodeOfType(services, code, isSdsDeclaration, 2);
expect(node).to.satisfy(isSdsEnum);
});
});
4 changes: 2 additions & 2 deletions tests/helpers/nodeFinder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Location, Range } from 'vscode-languageserver';
import { isRangeEqual, parseHelper } from 'langium/test';
import { SafeDsServices } from '../../src/language/safe-ds-module.js';
import { AstNode, streamAllContents, URI } from 'langium';
import { AstNode, streamAllContents, streamAst, URI } from 'langium';
import { SdsModule } from '../../src/language/generated/ast.js';
import { AssertionError } from 'assert';
import { locationToString } from './location.js';
Expand Down Expand Up @@ -67,7 +67,7 @@ export const getNodeOfType = async <T extends AstNode>(
): Promise<T> => {
const document = await parseHelper(services)(code);
const module = document.parseResult.value as SdsModule;
const candidates = streamAllContents(module).filter(predicate).toArray();
const candidates = streamAst(module).filter(predicate).toArray();

if (candidates.length === 0) {
throw new AssertionError({ message: `Expected to find a matching node but found none.` });
Expand Down
99 changes: 99 additions & 0 deletions tests/language/grammar/safe-ds-value-converter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { describe, expect, it } from 'vitest';
import { createSafeDsServices } from '../../../src/language/safe-ds-module.js';
import { EmptyFileSystem } from 'langium';
import { getNodeOfType } from '../../helpers/nodeFinder.js';
import {
isSdsClass,
isSdsModule,
isSdsTemplateStringEnd,
isSdsTemplateStringInner,
isSdsTemplateStringStart,
} from '../../../src/language/generated/ast.js';

const services = createSafeDsServices(EmptyFileSystem).SafeDs;

describe('runConverter', () => {
it('should remove backticks from IDs (package)', async () => {
const code = `
package \`foo\`.bar
`;

const module = await getNodeOfType(services, code, isSdsModule);
expect(module.name).toBe('foo.bar');
});

it('should remove backticks from IDs (declaration)', async () => {
const code = `
class \`MyClass\`
`;

const firstClass = await getNodeOfType(services, code, isSdsClass);
expect(firstClass.name).toBe('MyClass');
});

it('should remove delimiters from TEMPLATE_STRING_STARTs', async () => {
const code = `
pipeline myPipeline {
"start{{ 1 }}inner{{ 2 }}end";
}
`;

const firstTemplateStringStart = await getNodeOfType(services, code, isSdsTemplateStringStart);
expect(firstTemplateStringStart.value).toBe('start');
});

it('should handle escape sequences in TEMPLATE_STRING_STARTs', async () => {
const code = `
pipeline myPipeline {
"\\tstart{{ 1 }}inner{{ 2 }}end";
}
`;

const firstTemplateStringStart = await getNodeOfType(services, code, isSdsTemplateStringStart);
expect(firstTemplateStringStart.value).toBe('\tstart');
});

it('should remove delimiters from TEMPLATE_STRING_INNERs', async () => {
const code = `
pipeline myPipeline {
"start{{ 1 }}inner{{ 2 }}end";
}
`;

const firstTemplateStringInner = await getNodeOfType(services, code, isSdsTemplateStringInner);
expect(firstTemplateStringInner.value).toBe('inner');
});

it('should handle escape sequences in TEMPLATE_STRING_INNERs', async () => {
const code = `
pipeline myPipeline {
"start{{ 1 }}\\tinner{{ 2 }}end";
}
`;

const firstTemplateStringInner = await getNodeOfType(services, code, isSdsTemplateStringInner);
expect(firstTemplateStringInner.value).toBe('\tinner');
});

it('should remove delimiters from TEMPLATE_STRING_ENDs', async () => {
const code = `
pipeline myPipeline {
"start{{ 1 }}inner{{ 2 }}end";
}
`;

const firstTemplateStringEnd = await getNodeOfType(services, code, isSdsTemplateStringEnd);
expect(firstTemplateStringEnd.value).toBe('end');
});

it('should handle escape sequences in TEMPLATE_STRING_ENDs', async () => {
const code = `
pipeline myPipeline {
"start{{ 1 }}inner{{ 2 }}\\tend";
}
`;

const firstTemplateStringEnd = await getNodeOfType(services, code, isSdsTemplateStringEnd);
expect(firstTemplateStringEnd.value).toBe('\tend');
});
});
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/annotations.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tests.validation.names.casing

// $TEST$ no warning "Names of annotations should be UpperCamelCase."
annotation »AnnotationUppercase1«
// $TEST$ no warning "Names of annotations should be UpperCamelCase."
annotation »`AnnotationUppercase2`«
// $TEST$ warning "Names of annotations should be UpperCamelCase."
annotation »annotationLowercase«
// $TEST$ warning "Names of annotations should be UpperCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/attributes.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class MyClass {
attr »AttributeUppercase«: Int
// $TEST$ no warning "Names of attributes should be lowerCamelCase."
attr »attributeLowercase1«: Int
// $TEST$ no warning "Names of attributes should be lowerCamelCase."
attr »`attributeLowercase2`«: Int
// $TEST$ warning "Names of attributes should be lowerCamelCase."
attr »_attributeUnderscore«: Int
// $TEST$ warning "Names of attributes should be lowerCamelCase."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pipeline myPipeline1 {
yield »LambdaResultUppercase« = 1;
// $TEST$ no warning "Names of block lambda results should be lowerCamelCase."
yield »lambdaResultLowercase1« = 1;
// $TEST$ no warning "Names of block lambda results should be lowerCamelCase."
yield »`lambdaResultLowercase2`« = 1;
// $TEST$ warning "Names of block lambda results should be lowerCamelCase."
yield »_lambdaResultUnderscore« = 1;
// $TEST$ warning "Names of block lambda results should be lowerCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/classes.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tests.validation.names.casing

// $TEST$ no warning "Names of classes should be UpperCamelCase."
class »ClassUppercase1«
// $TEST$ no warning "Names of classes should be UpperCamelCase."
class »`ClassUppercase2`«
// $TEST$ warning "Names of classes should be UpperCamelCase."
class »classLowercase«
// $TEST$ warning "Names of classes should be UpperCamelCase."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package tests.validation.names.casing
enum MyEnum {
// $TEST$ no warning "Names of enum variants should be UpperCamelCase."
»EnumVariantUppercase1«
// $TEST$ no warning "Names of enum variants should be UpperCamelCase."
»`EnumVariantUppercase2`«
// $TEST$ warning "Names of enum variants should be UpperCamelCase."
»enumVariantLowercase«
// $TEST$ warning "Names of enum variants should be UpperCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/enums.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tests.validation.names.casing

// $TEST$ no warning "Names of enums should be UpperCamelCase."
enum »EnumUppercase1«
// $TEST$ no warning "Names of enums should be UpperCamelCase."
enum »`EnumUppercase2`«
// $TEST$ warning "Names of enums should be UpperCamelCase."
enum »enumLowercase«
// $TEST$ warning "Names of enums should be UpperCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/functions.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package tests.validation.names.casing
fun »FunctionUppercase«()
// $TEST$ no warning "Names of functions should be lowerCamelCase."
fun »functionLowercase1«()
// $TEST$ no warning "Names of functions should be lowerCamelCase."
fun »`functionLowercase2`«()
// $TEST$ warning "Names of functions should be lowerCamelCase."
fun »_functionUnderscore«()
// $TEST$ warning "Names of functions should be lowerCamelCase."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// $TEST$ no warning "All segments of the qualified name of a package should be lowerCamelCase."
package »tests.validation.declarations.`lowercase1`«
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/parameters.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ fun myFunction1(
»ParameterUppercase«: Int,
// $TEST$ no warning "Names of parameters should be lowerCamelCase."
»parameterLowercase1«: Int,
// $TEST$ no warning "Names of parameters should be lowerCamelCase."
»`parameterLowercase2`«: Int,
// $TEST$ warning "Names of parameters should be lowerCamelCase."
»_parameterUnderscore«: Int,
// $TEST$ warning "Names of parameters should be lowerCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/pipelines.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package tests.validation.names.casing
pipeline »PipelineUppercase« {}
// $TEST$ no warning "Names of pipelines should be lowerCamelCase."
pipeline »pipelineLowercase1« {}
// $TEST$ no warning "Names of pipelines should be lowerCamelCase."
pipeline »`pipelineLowercase2`« {}
// $TEST$ warning "Names of pipelines should be lowerCamelCase."
pipeline »_pipelineUnderscore« {}
// $TEST$ warning "Names of pipelines should be lowerCamelCase."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ pipeline myPipeline2 {
val »PlaceholderUppercase« = 1;
// $TEST$ no warning "Names of placeholders should be lowerCamelCase."
val »placeholderLowercase1« = 1;
// $TEST$ no warning "Names of placeholders should be lowerCamelCase."
val »`placeholderLowercase2`« = 1;
// $TEST$ warning "Names of placeholders should be lowerCamelCase."
val »_placeholderUnderscore« = 1;
// $TEST$ warning "Names of placeholders should be lowerCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/results.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ fun myFunction2() -> (
»ResultUppercase«: Int,
// $TEST$ no warning "Names of results should be lowerCamelCase."
»resultLowercase1«: Int,
// $TEST$ no warning "Names of results should be lowerCamelCase."
»`resultLowercase2`«: Int,
// $TEST$ warning "Names of results should be lowerCamelCase."
»_resultUnderscore«: Int,
// $TEST$ warning "Names of results should be lowerCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/schemas.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tests.validation.names.casing

// $TEST$ no warning "Names of schemas should be UpperCamelCase."
schema »SchemaUppercase1« {}
// $TEST$ no warning "Names of schemas should be UpperCamelCase."
schema »`SchemaUppercase2`« {}
// $TEST$ warning "Names of schemas should be UpperCamelCase."
schema »schemaLowercase« {}
// $TEST$ warning "Names of schemas should be UpperCamelCase."
Expand Down
2 changes: 2 additions & 0 deletions tests/resources/validation/names/casing/segments.sdstest
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package tests.validation.names.casing
segment »SegmentUppercase«() {}
// $TEST$ no warning "Names of segments should be lowerCamelCase."
segment »segmentLowercase1«() {}
// $TEST$ no warning "Names of segments should be lowerCamelCase."
segment »`segmentLowercase2`«() {}
// $TEST$ warning "Names of segments should be lowerCamelCase."
segment »_segmentUnderscore«() {}
// $TEST$ warning "Names of segments should be lowerCamelCase."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package tests.validation.names.casing
fun myFunction3<
// $TEST$ no warning "Names of type parameters should be UpperCamelCase."
»TypeParameterUppercase1«,
// $TEST$ no warning "Names of type parameters should be UpperCamelCase."
»`TypeParameterUppercase2`«,
// $TEST$ warning "Names of type parameters should be UpperCamelCase."
»typeParameterLowercase«,
// $TEST$ warning "Names of type parameters should be UpperCamelCase."
Expand Down
2 changes: 1 addition & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
chaiConfig: {
truncateThreshold: 0,
truncateThreshold: 200,
},
coverage: {
provider: 'v8',
Expand Down