eslint-plugin-crisp 1.0.32 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-crisp",
3
- "version": "1.0.32",
3
+ "version": "1.0.33",
4
4
  "description": "Custom EsLint Rules for Crisp",
5
5
  "main": "index.js",
6
6
  "author": "Crisp IM SAS",
@@ -1,3 +1,94 @@
1
+ const PARAM_REGEX = /^\s*\*\s*@param\s*\{\s*(.+?)\s*\}\s*(\S+)/;
2
+ const RETURN_REGEX = /^\s*\*\s*@return\s*\{\s*(.+?)\s*\}\s*(.*)/;
3
+ const SCOPE_REGEX = /^\s*\*\s*@(public|private|protected)/;
4
+
5
+ function parseJSDoc(jsdoc) {
6
+ const lines = jsdoc.split('\n');
7
+ const params = [];
8
+ let returnLine = null;
9
+ let description = '';
10
+ let scope = '';
11
+
12
+ for (let i = 1; i < lines.length; i++) {
13
+ const line = lines[i].trim();
14
+
15
+ // If the line matches any of the regexes, break out of the loop
16
+ if (line.match(PARAM_REGEX) || line.match(RETURN_REGEX) || line.match(SCOPE_REGEX)) {
17
+ break;
18
+ }
19
+
20
+ // Append each line to the description, removing leading " * " if present
21
+ description += line.replace(/^\s*\*/, '').trim() + ' ';
22
+ }
23
+
24
+ description = description.trim();
25
+
26
+ for (const line of lines) {
27
+ const paramMatch = line.match(PARAM_REGEX);
28
+ if (paramMatch) {
29
+ const [, type, name] = paramMatch;
30
+ params.push({ type, name });
31
+ }
32
+
33
+ const returnMatch = line.match(RETURN_REGEX);
34
+ if (returnMatch) {
35
+ const [, type, desc] = returnMatch;
36
+ returnLine = { type, description: desc.trim() };
37
+ }
38
+
39
+ const scopeMatch = line.match(SCOPE_REGEX);
40
+ if (scopeMatch) {
41
+ scope = scopeMatch[1];
42
+ }
43
+ }
44
+
45
+ return { description, scope, params, returnLine };
46
+ }
47
+
48
+ function formatJSDoc(parsedJSDoc, indentation=0) {
49
+ let maxTypeLength = 0;
50
+ let indent = ' '.repeat(indentation);
51
+
52
+ // Calculate the maximum type length from params
53
+ for (const param of parsedJSDoc.params) {
54
+ if (param.type.length > maxTypeLength) {
55
+ maxTypeLength = param.type.length;
56
+ }
57
+ }
58
+
59
+ // Check the return type length if it exists
60
+ if (parsedJSDoc.returnLine && parsedJSDoc.returnLine && parsedJSDoc.returnLine.type.length > maxTypeLength && parsedJSDoc.returnLine.description) {
61
+ maxTypeLength = parsedJSDoc.returnLine.type.length;
62
+ }
63
+
64
+ let jsdoc = '/**\n'
65
+
66
+ jsdoc += indent + '* ' + parsedJSDoc.description + '\n';
67
+
68
+ if (parsedJSDoc.scope) {
69
+ jsdoc += indent + '* @' + parsedJSDoc.scope + '\n';
70
+ }
71
+
72
+ // Format params with padding based on maximum type length
73
+ for (const param of parsedJSDoc.params) {
74
+ const paddingType = ' '.repeat(Math.max(0, maxTypeLength - param.type.length));
75
+ jsdoc += indent + `* @param {${param.type}}${paddingType} ${param.name}\n`;
76
+ }
77
+
78
+ // Format return with padding based on maximum type length
79
+ if (parsedJSDoc.returnLine) {
80
+ const paddingType = ' '.repeat(Math.max(0, maxTypeLength - parsedJSDoc.returnLine.type.length));
81
+ let _return = `* @return {${parsedJSDoc.returnLine.type}}${paddingType} ${parsedJSDoc.returnLine.description}`.trimEnd();
82
+
83
+ jsdoc += indent + _return + "\n";
84
+ }
85
+
86
+ jsdoc += indent + '*/';
87
+
88
+ return jsdoc;
89
+ }
90
+
91
+
1
92
  module.exports = {
2
93
  meta: {
3
94
  type: 'layout',
@@ -8,6 +99,7 @@ module.exports = {
8
99
  },
9
100
  fixable: 'whitespace',
10
101
  },
102
+
11
103
  create: function(context) {
12
104
  return {
13
105
  Program: function(node) {
@@ -17,66 +109,19 @@ module.exports = {
17
109
  .filter(comment => comment.type === 'Block' && comment.value.startsWith('*'))
18
110
  .forEach(jsdocComment => {
19
111
  const lines = jsdocComment.value.split('\n');
20
- let bracePos = -1, descPos = -1;
21
- let lineNum = jsdocComment.loc.start.line;
22
-
23
- for (const line of lines) {
24
- lineNum++;
25
- const paramMatch = line.match(/@param\s*{(\S*)}[\s\t]+(\S+)\s*(.*)/);
26
- const returnMatch = line.match(/@return\s*{(\S*)}\s*(.*)/);
27
-
28
- let match = null;
29
-
30
- if (paramMatch) {
31
- match = paramMatch;
32
- } else if (returnMatch) {
33
- match = returnMatch;
34
- }
35
-
36
- if (match) {
37
- const newBracePos = match.index + match[0].indexOf('{');
38
-
39
- // Check for multiple types, skip alignment if found
40
- const multipleTypes = /\|/.test(match[1]);
41
- if (multipleTypes) {
42
- continue;
43
- }
44
-
45
- let descStart = match[0].substring(match[0].lastIndexOf('}') + 1).search(/\S/);
46
-
47
- // If description is undefined, skip the description alignment check
48
- if (match[match.length - 1] === 'undefined') {
49
- descStart = -1;
50
- }
51
-
52
- if (descStart !== -1) {
53
- const newDescPos = match.index + match[0].lastIndexOf('}') + 1 + descStart + 1; // +1 for ESLint column index
54
-
55
- if (descPos === -1) {
56
- descPos = newDescPos;
57
- } else if (descPos !== newDescPos) {
58
- context.report({
59
- node: jsdocComment,
60
- message: `In JSDoc at line ${lineNum}, the description is misaligned. Found at column ${newDescPos}, but expected column ${descPos}.`,
61
- loc: {
62
- start: { line: lineNum, column: newDescPos },
63
- },
64
- });
65
- }
66
- }
67
-
68
- if (bracePos === -1) {
69
- bracePos = newBracePos;
70
- } else if (bracePos !== newBracePos) {
71
- context.report({
72
- node: jsdocComment,
73
- message: `In JSDoc at line ${lineNum}, the type brace is misaligned. Found at column ${newBracePos + 1}, but expected column ${bracePos + 1}.`,
74
- loc: {
75
- start: { line: lineNum, column: newBracePos + 1 },
76
- },
77
- });
78
- }
79
- }
112
+ const jsdocString = `/*${jsdocComment.value}*/`;
113
+ const parsedJSDoc = parseJSDoc(jsdocString);
114
+ const indentation = lines.length > 2 ? lines[1].match(/^\s*/)[0].length : 0; // Capture indentation from the first line
115
+ const formattedJSDoc = formatJSDoc(parsedJSDoc, indentation);
116
+
117
+ if (jsdocString !== formattedJSDoc && parsedJSDoc.description && parsedJSDoc.scope) {
118
+ context.report({
119
+ node,
120
+ message: 'JSDoc alignment issue',
121
+ fix(fixer) {
122
+ return fixer.replaceText(jsdocComment, formattedJSDoc);
123
+ },
124
+ });
80
125
  }
81
126
  });
82
127
  },