@futdevpro/dynamo-eslint 1.14.25 → 1.14.27

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.
Files changed (29) hide show
  1. package/.github/workflows/main.yml +5 -0
  2. package/build/configs/base.js +1 -0
  3. package/build/configs/base.js.map +1 -1
  4. package/build/plugin/index.d.ts +2 -0
  5. package/build/plugin/index.d.ts.map +1 -1
  6. package/build/plugin/index.js +3 -0
  7. package/build/plugin/index.js.map +1 -1
  8. package/build/plugin/rules/no-getter-logic.d.ts +4 -0
  9. package/build/plugin/rules/no-getter-logic.d.ts.map +1 -0
  10. package/build/plugin/rules/no-getter-logic.js +176 -0
  11. package/build/plugin/rules/no-getter-logic.js.map +1 -0
  12. package/build/plugin/rules/no-getter-logic.spec.d.ts +2 -0
  13. package/build/plugin/rules/no-getter-logic.spec.d.ts.map +1 -0
  14. package/build/plugin/rules/no-getter-logic.spec.js +461 -0
  15. package/build/plugin/rules/no-getter-logic.spec.js.map +1 -0
  16. package/build/plugin/rules/require-jsdoc-description.d.ts.map +1 -1
  17. package/build/plugin/rules/require-jsdoc-description.js +53 -10
  18. package/build/plugin/rules/require-jsdoc-description.js.map +1 -1
  19. package/build/plugin/rules/require-jsdoc-description.spec.js +94 -0
  20. package/build/plugin/rules/require-jsdoc-description.spec.js.map +1 -1
  21. package/futdevpro-dynamo-eslint-1.14.27.tgz +0 -0
  22. package/package.json +1 -1
  23. package/src/configs/base.ts +1 -0
  24. package/src/plugin/index.ts +3 -0
  25. package/src/plugin/rules/no-getter-logic.spec.ts +520 -0
  26. package/src/plugin/rules/no-getter-logic.ts +201 -0
  27. package/src/plugin/rules/require-jsdoc-description.spec.ts +111 -0
  28. package/src/plugin/rules/require-jsdoc-description.ts +61 -12
  29. package/futdevpro-dynamo-eslint-1.14.25.tgz +0 -0
@@ -539,4 +539,115 @@ describe('| require-jsdoc-description', () => {
539
539
 
540
540
  rule.FunctionDeclaration(mockNode);
541
541
  });
542
+
543
+ it('| should handle abstract class with multiline JSDoc', () => {
544
+ const mockContext = {
545
+ report: (options: any) => {
546
+ fail('Should not report when abstract class has multiline JSDoc');
547
+ },
548
+ options: [{ scope: 'public' }],
549
+ sourceCode: {
550
+ getCommentsBefore: () => [{
551
+ type: 'Block',
552
+ value: '* Abstract data service osztály a user műveletek kezeléséhez.\n* Kezeli a login, register, validation és egyéb user-rel kapcsolatos műveleteket.',
553
+ loc: { end: { line: 3 } },
554
+ }],
555
+ },
556
+ } as any;
557
+
558
+ const rule = requireJSDocRule.create(mockContext);
559
+
560
+ const mockNode = {
561
+ type: 'ClassDeclaration',
562
+ id: { name: 'FDPNTS_User_DataService' },
563
+ loc: { start: { line: 4 } },
564
+ parent: {
565
+ type: 'ExportNamedDeclaration',
566
+ },
567
+ } as any;
568
+
569
+ rule.ClassDeclaration(mockNode);
570
+ });
571
+
572
+ it('| should handle multiline JSDoc with empty lines', () => {
573
+ const mockContext = {
574
+ report: (options: any) => {
575
+ fail('Should not report when JSDoc has multiline description with empty lines');
576
+ },
577
+ options: [{ scope: 'public' }],
578
+ sourceCode: {
579
+ getCommentsBefore: () => [{
580
+ type: 'Block',
581
+ value: '* This is a multiline description\n*\n* with empty lines in between\n* that should still be valid',
582
+ loc: { end: { line: 4 } },
583
+ }],
584
+ },
585
+ } as any;
586
+
587
+ const rule = requireJSDocRule.create(mockContext);
588
+
589
+ const mockNode = {
590
+ type: 'FunctionDeclaration',
591
+ id: { name: 'testFunction' },
592
+ loc: { start: { line: 5 } },
593
+ } as any;
594
+
595
+ rule.FunctionDeclaration(mockNode);
596
+ });
597
+
598
+ it('| should handle multiline JSDoc followed by @tags', () => {
599
+ const mockContext = {
600
+ report: (options: any) => {
601
+ fail('Should not report when JSDoc has description before @tags');
602
+ },
603
+ options: [{ scope: 'public' }],
604
+ sourceCode: {
605
+ getCommentsBefore: () => [{
606
+ type: 'Block',
607
+ value: '* This is a description\n* that spans multiple lines\n* @param {string} name The name parameter',
608
+ loc: { end: { line: 2 } },
609
+ }],
610
+ },
611
+ } as any;
612
+
613
+ const rule = requireJSDocRule.create(mockContext);
614
+
615
+ const mockNode = {
616
+ type: 'FunctionDeclaration',
617
+ id: { name: 'testFunction' },
618
+ loc: { start: { line: 3 } },
619
+ } as any;
620
+
621
+ rule.FunctionDeclaration(mockNode);
622
+ });
623
+
624
+ it('| should report when abstract class is missing JSDoc', () => {
625
+ let reportCalled = false;
626
+ const mockContext = {
627
+ report: (options: any) => {
628
+ reportCalled = true;
629
+ expect(options.data.type).toBe('Class');
630
+ expect(options.data.name).toBe('AbstractClass');
631
+ },
632
+ options: [{ scope: 'public' }],
633
+ sourceCode: {
634
+ getCommentsBefore: () => [],
635
+ },
636
+ } as any;
637
+
638
+ const rule = requireJSDocRule.create(mockContext);
639
+
640
+ const mockNode = {
641
+ type: 'ClassDeclaration',
642
+ id: { name: 'AbstractClass' },
643
+ loc: { start: { line: 1 } },
644
+ parent: {
645
+ type: 'ExportNamedDeclaration',
646
+ },
647
+ } as any;
648
+
649
+ rule.ClassDeclaration(mockNode);
650
+
651
+ expect(reportCalled).toBe(true);
652
+ });
542
653
  });
@@ -125,6 +125,7 @@ const rule: Rule.RuleModule = {
125
125
  }
126
126
 
127
127
  // JSDoc should be on the line immediately before (no blank lines)
128
+ // For multi-line comments, check if the last line of the comment is immediately before the node
128
129
  return commentEnd === nodeStart - 1;
129
130
  } catch (error) {
130
131
  console.error('[require-jsdoc-description] Error in isJSDocOnPreviousLine:', error);
@@ -142,24 +143,27 @@ const rule: Rule.RuleModule = {
142
143
  return '';
143
144
  }
144
145
 
146
+ // The comment.value contains the text between /** and */
147
+ // It may start with * and include newlines with * at the beginning of each line
145
148
  const lines = jsdocComment.value.split('\n');
146
149
  let description = '';
147
150
 
148
151
  for (const line of lines) {
149
- // Remove leading * and whitespace
150
- const cleanLine = line.replace(/^\s*\*\s?/, '').trim();
152
+ // Remove leading whitespace and * character (JSDoc format: " * text" or "* text")
153
+ // Handle both formats: " * text" and "* text" and " *text"
154
+ const cleanLine = line.replace(/^\s*\*+\s?/, '').trim();
151
155
 
152
- // Skip empty lines
156
+ // Skip empty lines (after removing * and whitespace)
153
157
  if (!cleanLine) {
154
158
  continue;
155
159
  }
156
160
 
157
- // Stop at @tags
161
+ // Stop at @tags (JSDoc tags like @param, @returns, etc.)
158
162
  if (cleanLine.startsWith('@')) {
159
163
  break;
160
164
  }
161
165
 
162
- // Add to description
166
+ // Add to description with space separator
163
167
  if (description) {
164
168
  description += ' ';
165
169
  }
@@ -182,10 +186,18 @@ const rule: Rule.RuleModule = {
182
186
  const comments = sourceCode.getCommentsBefore(node);
183
187
 
184
188
  // Find JSDoc comment (/** ... */)
185
- const jsdocComment = comments.find((comment: any) =>
186
- comment.type === 'Block' &&
187
- comment.value.startsWith('*')
188
- );
189
+ // JSDoc comments are Block comments where the value (content between /** and */) starts with *
190
+ const jsdocComment = comments.find((comment: any) => {
191
+ if (comment.type !== 'Block') {
192
+ return false;
193
+ }
194
+
195
+ const value = comment.value || '';
196
+
197
+ // JSDoc comment value should start with * (the first character after /**)
198
+ // Handle cases where there might be whitespace before the *
199
+ return value.trim().startsWith('*');
200
+ });
189
201
 
190
202
  if (!jsdocComment) {
191
203
  return { hasJSDoc: false, isValid: false, isOnPreviousLine: false };
@@ -228,6 +240,39 @@ const rule: Rule.RuleModule = {
228
240
  }
229
241
  }
230
242
 
243
+ /**
244
+ * Get node name location for error reporting
245
+ */
246
+ function getNodeNameLoc(node: any): { start: { line: number; column: number }; end: { line: number; column: number } } | null {
247
+ try {
248
+ // For MethodDefinition, use key.loc
249
+ if (node.key && node.key.loc) {
250
+ return node.key.loc;
251
+ }
252
+
253
+ // For declarations with id (FunctionDeclaration, ClassDeclaration, etc.)
254
+ if (node.id && node.id.loc) {
255
+ return node.id.loc;
256
+ }
257
+
258
+ // For VariableDeclarator
259
+ if (node.id && node.id.loc) {
260
+ return node.id.loc;
261
+ }
262
+
263
+ // Fallback to node location if name location not found
264
+ if (node.loc) {
265
+ return node.loc;
266
+ }
267
+
268
+ return null;
269
+ } catch (error) {
270
+ console.error('[require-jsdoc-description] Error in getNodeNameLoc:', error);
271
+
272
+ return null;
273
+ }
274
+ }
275
+
231
276
  /**
232
277
  * Get node type for error messages
233
278
  */
@@ -299,22 +344,26 @@ const rule: Rule.RuleModule = {
299
344
  try {
300
345
  const name = getNodeName(node);
301
346
  const type = getNodeType(node);
347
+ const nameLoc = getNodeNameLoc(node);
348
+
349
+ // Fallback to node location if name location not found
350
+ const reportLoc = nameLoc || node.loc;
302
351
 
303
352
  if (!jsdocResult.hasJSDoc) {
304
353
  context.report({
305
- node,
354
+ loc: reportLoc,
306
355
  messageId: 'missingJSDoc',
307
356
  data: { type, name },
308
357
  });
309
358
  } else if (!jsdocResult.isOnPreviousLine) {
310
359
  context.report({
311
- node,
360
+ loc: reportLoc,
312
361
  messageId: 'invalidJSDocPosition',
313
362
  data: { type, name },
314
363
  });
315
364
  } else if (!jsdocResult.isValid) {
316
365
  context.report({
317
- node,
366
+ loc: reportLoc,
318
367
  messageId: 'emptyJSDoc',
319
368
  data: { type, name },
320
369
  });
Binary file