Skip to content

Commit

Permalink
Refactored eslint-plugin to use typescript-eslint
Browse files Browse the repository at this point in the history
  • Loading branch information
kraenhansen committed Sep 2, 2024
1 parent 0362e09 commit a93689c
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 125 deletions.
99 changes: 99 additions & 0 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,21 @@
"@microsoft/tsdoc": "workspace:*",
"@microsoft/tsdoc-config": "workspace:*"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8",
"eslint": "^8"
},
"devDependencies": {
"@typescript-eslint/rule-tester": "~8.3.0",
"@typescript-eslint/utils": "~8.3.0",
"@rushstack/heft-node-rig": "~2.6.11",
"@rushstack/heft": "^0.66.13",
"@types/eslint": "8.40.1",
"@types/estree": "1.0.1",
"@types/heft-jest": "1.0.3",
"@types/node": "14.18.36",
"eslint": "~8.57.0",
"eslint-plugin-header": "~3.1.1"
"eslint-plugin-header": "~3.1.1",
"typescript": "~5.4.2"
}
}
124 changes: 124 additions & 0 deletions eslint-plugin/src/SyntaxRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.

import { TSDocParser, TextRange, TSDocConfiguration, type ParserContext } from '@microsoft/tsdoc';
import type { TSDocConfigFile } from '@microsoft/tsdoc-config';
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';

const tsdocMessageIds: { [x: string]: string } = {};

const defaultTSDocConfiguration: TSDocConfiguration = new TSDocConfiguration();
defaultTSDocConfiguration.allTsdocMessageIds.forEach((messageId: string) => {
tsdocMessageIds[messageId] = `${messageId}: {{unformattedText}}`;
});

import { Debug } from './Debug';
import { ConfigCache } from './ConfigCache';

import { configMessages, createRule } from './utils';

export const rule: TSESLint.AnyRuleModule = createRule({
name: 'syntax',
meta: {
messages: {
...configMessages,
...tsdocMessageIds
},
type: 'problem',
docs: {
description: 'Validates that TypeScript documentation comments conform to the TSDoc standard',
// This package is experimental
recommended: false
},
schema: []
},
defaultOptions: [],
create: (context: TSESLint.RuleContext<string, unknown[]>) => {
const sourceFilePath: string = context.getFilename();
Debug.log(`Linting: "${sourceFilePath}"`);

const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();

try {
const tsdocConfigFile: TSDocConfigFile = ConfigCache.getForSourceFile(sourceFilePath);
if (!tsdocConfigFile.fileNotFound) {
if (tsdocConfigFile.hasErrors) {
context.report({
loc: { line: 1, column: 1 },
messageId: 'error-loading-config-file',
data: {
details: tsdocConfigFile.getErrorSummary()
}
});
}

try {
tsdocConfigFile.configureParser(tsdocConfiguration);
} catch (e) {
context.report({
loc: { line: 1, column: 1 },
messageId: 'error-applying-config',
data: {
details: e.message
}
});
}
}
} catch (e) {
context.report({
loc: { line: 1, column: 1 },
messageId: 'error-loading-config-file',
data: {
details: `Unexpected exception: ${e.message}`
}
});
}

const tsdocParser: TSDocParser = new TSDocParser(tsdocConfiguration);

const sourceCode: TSESLint.SourceCode = context.sourceCode;
const checkCommentBlocks: (node: TSESTree.Program) => void = function (node: TSESTree.Program) {
for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Block') {
continue;
}
if (!comment.range) {
continue;
}

const textRange: TextRange = TextRange.fromStringRange(
sourceCode.text,
comment.range[0],
comment.range[1]
);

// Smallest comment is "/***/"
if (textRange.length < 5) {
continue;
}
// Make sure it starts with "/**"
if (textRange.buffer[textRange.pos + 2] !== '*') {
continue;
}

const parserContext: ParserContext = tsdocParser.parseRange(textRange);
for (const message of parserContext.log.messages) {
context.report({
loc: {
start: sourceCode.getLocFromIndex(message.textRange.pos),
end: sourceCode.getLocFromIndex(message.textRange.end)
},
messageId: message.messageId,
data: {
unformattedText: message.unformattedText
}
});
}
}
};

return {
Program: checkCommentBlocks
};
}
});
Loading

0 comments on commit a93689c

Please sign in to comment.