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: customize rendering of @param, @result, and @typeParam tags #764

Merged
merged 1 commit into from
Nov 12, 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
10 changes: 10 additions & 0 deletions packages/safe-ds-lang/src/helpers/stringUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/**
* Normalizes line breaks to `\n`.
*
* @param text The text to normalize.
* @return The normalized text.
*/
export const normalizeLineBreaks = (text: string | undefined): string => {
return text?.replace(/\r\n?/gu, '\n') ?? '';
};

/**
* Based on the given count, returns the singular or plural form of the given word.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
JSDocComment,
JSDocDocumentationProvider,
JSDocRenderOptions,
type JSDocTag,
parseJSDoc,
} from 'langium';
import {
Expand All @@ -17,6 +18,10 @@ import {
SdsTypeParameter,
} from '../generated/ast.js';

const PARAM_TAG = 'param';
const RESULT_TAG = 'result';
const TYPE_PARAM_TAG = 'typeParam';

export class SafeDsDocumentationProvider extends JSDocDocumentationProvider {
override getDocumentation(node: AstNode): string | undefined {
if (isSdsParameter(node) || isSdsResult(node) || isSdsTypeParameter(node)) {
Expand All @@ -39,6 +44,16 @@ export class SafeDsDocumentationProvider extends JSDocDocumentationProvider {
}
}

protected override documentationTagRenderer(node: AstNode, tag: JSDocTag): string | undefined {
if (tag.name === PARAM_TAG || tag.name === RESULT_TAG || tag.name === TYPE_PARAM_TAG) {
const contentMd = tag.content.toMarkdown();
const [paramName, description] = contentMd.split(/\s(.*)/su);
return `**@${tag.name}** *${paramName}* — ${(description ?? '').trim()}`;
} else {
return super.documentationTagRenderer(node, tag);
}
}

private getJSDocComment(node: AstNode): JSDocComment | undefined {
const comment = this.commentProvider.getComment(node);
if (comment && isJSDoc(comment)) {
Expand Down Expand Up @@ -70,11 +85,11 @@ export class SafeDsDocumentationProvider extends JSDocDocumentationProvider {

private getTagName(node: SdsParameter | SdsResult | SdsTypeParameter): string {
if (isSdsParameter(node)) {
return 'param';
return PARAM_TAG;
} else if (isSdsResult(node)) {
return 'result';
return RESULT_TAG;
} else {
return 'typeParam';
return TYPE_PARAM_TAG;
}
}

Expand All @@ -83,6 +98,10 @@ export class SafeDsDocumentationProvider extends JSDocDocumentationProvider {
renderLink: (link, display) => {
return this.documentationLinkRenderer(node, link, display);
},
tag: 'bold',
renderTag: (tag: JSDocTag) => {
return this.documentationTagRenderer(node, tag);
},
};
}
}
29 changes: 28 additions & 1 deletion packages/safe-ds-lang/tests/helpers/stringUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
import { describe, expect, it } from 'vitest';
import { pluralize } from '../../src/helpers/stringUtils.js';
import { normalizeLineBreaks, pluralize } from '../../src/helpers/stringUtils.js';

describe('normalizeLineBreaks', () => {
it.each([
{
text: undefined,
expected: '',
},
{
text: '',
expected: '',
},
{
text: 'foo\nbar',
expected: 'foo\nbar',
},
{
text: 'foo\rbar',
expected: 'foo\nbar',
},
{
text: 'foo\r\nbar',
expected: 'foo\nbar',
},
])(`should normalize line breaks (%#)`, ({ text, expected }) => {
expect(normalizeLineBreaks(text)).toBe(expected);
});
});

describe('pluralize', () => {
it.each([
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { afterEach, describe, expect, it } from 'vitest';
import { createSafeDsServices } from '../../../src/language/safe-ds-module.js';
import { AstNode, EmptyFileSystem } from 'langium';
import { AstNode, EmptyFileSystem, expandToString } from 'langium';
import { clearDocuments } from 'langium/test';
import { getNodeOfType } from '../../helpers/nodeFinder.js';
import { afterEach, describe, expect, it } from 'vitest';
import { normalizeLineBreaks } from '../../../src/helpers/stringUtils.js';
import {
isSdsAnnotation,
isSdsFunction,
isSdsParameter,
isSdsResult,
isSdsTypeParameter,
} from '../../../src/language/generated/ast.js';
import { createSafeDsServices } from '../../../src/language/index.js';
import { getNodeOfType } from '../../helpers/nodeFinder.js';

const services = createSafeDsServices(EmptyFileSystem).SafeDs;
const documentationProvider = services.documentation.DocumentationProvider;
Expand Down Expand Up @@ -166,11 +167,39 @@ describe('SafeDsDocumentationProvider', () => {
predicate: isSdsTypeParameter,
expectedDocumentation: undefined,
},
{
testName: 'custom tag rendering',
code: `
/**
* ${testDocumentation}
*
* @param param ${testDocumentation}
* @result result ${testDocumentation}
* @typeParam T ${testDocumentation}
* @since 1.0.0
*/
fun myFunction<T>(param: String) -> result: String
`,
predicate: isSdsFunction,
expectedDocumentation: expandToString`
Lorem ipsum.

**@param** *param* — Lorem ipsum.

**@result** *result* — Lorem ipsum.

**@typeParam** *T* — Lorem ipsum.

**@since** — 1.0.0
`,
},
];

it.each(testCases)('$testName', async ({ code, predicate, expectedDocumentation }) => {
const node = await getNodeOfType(services, code, predicate);
expect(documentationProvider.getDocumentation(node)).toStrictEqual(expectedDocumentation);
const normalizedActual = normalizeLineBreaks(documentationProvider.getDocumentation(node));
const normalizedExpected = normalizeLineBreaks(expectedDocumentation);
expect(normalizedActual).toStrictEqual(normalizedExpected);
});

it('should resolve links', async () => {
Expand Down
11 changes: 1 addition & 10 deletions packages/safe-ds-lang/tests/language/lsp/formatting/creator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs';
import { EmptyFileSystem, URI } from 'langium';
import { Diagnostic } from 'vscode-languageserver';
import { normalizeLineBreaks } from '../../../../src/helpers/stringUtils.js';
import { createSafeDsServices } from '../../../../src/language/index.js';
import { getSyntaxErrors } from '../../../helpers/diagnostics.js';
import { TestDescription, TestDescriptionError } from '../../../helpers/testDescription.js';
Expand Down Expand Up @@ -64,16 +65,6 @@ const invalidTest = (error: TestDescriptionError): FormattingTest => {
};
};

/**
* Normalizes line breaks to `\n`.
*
* @param code The code to normalize.
* @return The normalized code.
*/
const normalizeLineBreaks = (code: string): string => {
return code.replace(/\r\n?/gu, '\n');
};

/**
* A description of a formatting test.
*/
Expand Down