From b1db35e01021f245749bd6e49acf2002690cf7d6 Mon Sep 17 00:00:00 2001 From: Suren Poghosyan Date: Tue, 27 Aug 2024 20:58:03 +0400 Subject: [PATCH 1/2] [code-duplication-pattern] add functionality which will ignore common patterns like } { ) }); --- README.md | 104 +++++++++++++------- dist/Patterns/CodeDuplicationPattern.js | 14 ++- dist/Patterns/CodeDuplicationPattern.js.map | 2 +- src/Patterns/CodeDuplicationPattern.ts | 17 +++- tests/CodeDuplicationPattern.test.ts | 36 +++++++ 5 files changed, 132 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index b266933..1878bd1 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,95 @@ # Code Diagnose -**Code Diagnose** is a CLI tool for detecting software antipatterns in your TypeScript projects. It helps identify code smells and improve code quality by analyzing your codebase for common design issues. +**Code Diagnose** is a powerful command-line tool designed for developers who work with TypeScript. It helps you keep your code clean and efficient by finding common issues that can make your code messy over time. With **Code Diagnose**, you can easily find and fix problems like repeated code, large classes, and unnecessary code, making your project easier to maintain and scale. -### Installation -To install Code Diagnose, run: +## Why Use Code Diagnose? -`npm install -g code-diagnose` +As your project grows, your code can become hard to manage. Repeated code blocks, large classes, and bad design choices can slow down development and make it harder to add new features. **Code Diagnose** helps you find these problems automatically so you can focus on writing new code instead of fixing old issues. -### Usage -To analyze your TypeScript project, use the following command: +### Key Benefits: +- **Improves Code Quality**: Detects common issues to help you write cleaner, easier-to-maintain code. +- **Saves Time**: Finds problems quickly that would take a lot of time to find manually. +- **Easy to Use**: Works smoothly with your TypeScript projects. -`analyze-project --directory /path/to/your/project` +## Installation -Replace /path/to/your/project with the path to the directory of your TypeScript project. +Installing **Code Diagnose** is simple. Use npm to install it globally on your system: -### Patterns Detected +```bash +npm install -g code-diagnose +``` -**Code Diagnose** can detect the following software antipatterns: +This makes **Code Diagnose** available for use in any of your projects. -- **Code Duplication Pattern**: Identifies repeated code across files. -- **Code Smell Pattern**: Flags general code smells and poor practices. -- **God Object (AST) Pattern**: Detects classes or objects with excessive responsibilities. -- **God Object Pattern**: Similar to AST but without AST-specific context. -- **Magic Numbers Pattern**: Finds hardcoded numeric values that should be constants. -- **Shotgun Surgery Pattern**: Detects cases where a single change requires altering many different parts of the codebase. -- **Large Class Pattern**: Identifies classes that are too large and should be refactored. -- **Lazy Class Pattern**: Flags classes that are not sufficiently utilized and could be removed or merged. -- **Long Parameter List Pattern**: Detects methods or functions with too many parameters. -- **Middle Man Pattern**: Finds classes that only pass requests to other classes. -- **Primitive Obsession Pattern**: Identifies overuse of primitive types instead of using more appropriate types or classes. -- **Speculative Generality Pattern**: Flags code that is overly generalized or anticipates future requirements that might never be needed. -- **Switch Statement Overuse Pattern**: Detects excessive use of switch statements that could be replaced with polymorphism. -- **Dead Code Pattern**: Finds variables or code that is declared but never used. +## How to Use Code Diagnose +After installation, analyzing your project is easy. Go to your project’s directory and run: -### Configuration +```bash +analyze-project --directory /path/to/your/project +``` -**.diagnoseignore** +Replace `/path/to/your/project` with the actual path to your project. **Code Diagnose** will scan your files and create a report showing areas that need attention. -You can exclude specific files or directories from being analyzed by creating a .diagnoseignore file in the root of your project. This file should list the files and directories to ignore, one per line. For example: +### Example Usage: + +```bash +analyze-project --directory ./my-typescript-project +``` + +After running this command, you’ll get a detailed report of any detected issues, along with suggestions on how to fix them. + +## Patterns Detected by Code Diagnose + +**Code Diagnose** can detect a wide range of common issues in TypeScript projects. Here are the patterns it currently supports: + +- **Code Duplication**: Finds repeated code blocks in different files or within the same file. Reducing duplication makes your code easier to maintain. +- **Code Smells**: Detects general bad practices that could lead to bugs or make your code harder to understand. +- **God Object (AST)**: Identifies classes or objects that try to do too much. These should be broken down into smaller, more focused pieces. +- **God Object (Non-AST)**: Similar to the AST version but focuses on non-abstract syntax tree contexts for broader coverage. +- **Magic Numbers**: Finds hardcoded numbers that should be replaced with named constants to improve readability. +- **Shotgun Surgery**: Detects when one change requires you to update many parts of your codebase, a sign that your code might need refactoring. +- **Large Class**: Finds classes that have become too large and should be split into smaller, more manageable pieces. +- **Lazy Class**: Flags classes that don’t do enough to justify their existence, suggesting they could be merged with others or removed. +- **Long Parameter List**: Detects functions or methods with too many parameters, making them hard to use and understand. +- **Middle Man**: Identifies classes that only pass requests to other classes without adding value. These can often be removed to simplify your codebase. +- **Primitive Obsession**: Finds overuse of primitive types (like strings and numbers) where more specific types or classes would make the code clearer. +- **Speculative Generality**: Flags code that’s been over-engineered to handle unlikely cases, adding unnecessary complexity. +- **Switch Statement Overuse**: Detects overuse of switch statements, which can often be replaced with polymorphism for cleaner code. +- **Dead Code**: Finds variables, functions, or entire blocks of code that are declared but never used, which can be safely removed. + +By detecting these patterns, **Code Diagnose** helps you refactor and improve your code, making your project cleaner and more efficient. + +## Configuration Options + +You can customize **Code Diagnose** to meet your needs. Create a `.diagnoseignore` file in your project’s root directory to exclude specific files or directories from analysis. + +### Example .diagnoseignore File: ``` # Ignore all files in the node_modules directory node_modules/ -# Ignore specific files -src/ignore-this-file.ts +# Ignore a specific file +src/legacy-code.ts ``` -### Beta Version +Ignoring files or directories that aren’t relevant lets you focus on the most important parts of your codebase. + +## Beta Version Disclaimer + +**Code Diagnose** is currently in beta, which means it’s still being improved. As a beta user, your feedback is very valuable. If you find any issues or have suggestions for new features, please share them on our GitHub page. + +## Contributing to Code Diagnose -Please note that Code Diagnose is currently in beta and still under development. Features and functionality may change as development progresses. Feedback and contributions are welcome! +We welcome contributions! If you’d like to help improve **Code Diagnose** by reporting bugs, suggesting features, or submitting code, visit our [GitHub repository](https://github.com/surenpoghosian/code-diagnose). -### Contributing +Your input helps us make **Code Diagnose** better, and we appreciate any contributions you can make. -If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on [GitHub](https://github.com/surenpoghosian/code-diagnose) +## License -### License +**Code Diagnose** is open-source software, licensed under the MIT License. You’re free to use, modify, and distribute it as you see fit. For more details, check out the [LICENSE](https://github.com/surenpoghosian/code-diagnose/blob/main/LICENSE) file in the GitHub repository. -This project is licensed under the MIT License - see the [LICENSE](https://github.com/surenpoghosian/code-diagnose/blob/main/LICENSE) file for details. +--- -Feel free to adjust any sections to better fit your project’s specifics or any additional details you’d like to include! \ No newline at end of file +Whether you're an experienced developer or just starting out, **Code Diagnose** is a great tool for keeping your TypeScript code in top shape. Try it out today and see how it can help you write better, cleaner code. \ No newline at end of file diff --git a/dist/Patterns/CodeDuplicationPattern.js b/dist/Patterns/CodeDuplicationPattern.js index 114fc35..baf94e8 100644 --- a/dist/Patterns/CodeDuplicationPattern.js +++ b/dist/Patterns/CodeDuplicationPattern.js @@ -6,8 +6,15 @@ const Hint_1 = require("../Reports/Hint"); class CodeDuplicationPattern extends BasePattern_1.BasePattern { analyze(content) { const hints = []; - // Split the content into lines and group them by their occurrence - const lines = content.split('\n').map(line => line.trim()).filter(line => line.length > 0); + const commonPatterns = [ + /^\}$/, // single closing curly brace + /^\{$/, // single opening curly brace + /^\);$/, // closing parenthesis followed by a semicolon + /^\}\);$/, // closing curly brace followed by closing parenthesis and semicolon + ]; + const lines = content.split('\n') + .map(line => line.trim()) + .filter(line => line.length > 0 && !this.isCommonLine(line, commonPatterns)); const lineCounts = new Map(); lines.forEach(line => { lineCounts.set(line, (lineCounts.get(line) || 0) + 1); @@ -33,6 +40,9 @@ class CodeDuplicationPattern extends BasePattern_1.BasePattern { }); return hints; } + isCommonLine(line, patterns) { + return patterns.some(pattern => pattern.test(line)); + } extractCodeBlocks(content) { // Basic implementation to extract code blocks (e.g., functions) // This needs to be improved based on actual use cases and language syntax diff --git a/dist/Patterns/CodeDuplicationPattern.js.map b/dist/Patterns/CodeDuplicationPattern.js.map index 00cd6ba..428a42d 100644 --- a/dist/Patterns/CodeDuplicationPattern.js.map +++ b/dist/Patterns/CodeDuplicationPattern.js.map @@ -1 +1 @@ -{"version":3,"file":"CodeDuplicationPattern.js","sourceRoot":"","sources":["../../src/Patterns/CodeDuplicationPattern.ts"],"names":[],"mappings":";;;AAAA,+CAA4C;AAC5C,0CAAuC;AAEvC,MAAa,sBAAuB,SAAQ,yBAAW;IACnD,OAAO,CAAC,OAAe;QACnB,MAAM,KAAK,GAAW,EAAE,CAAC;QAEzB,kEAAkE;QAClE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3F,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE7C,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACjB,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,0CAA0C;QAC1C,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,IAAI,WAAI,CAAC,sCAAsC,IAAI,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC;YAChG,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,6EAA6E;QAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE9C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACnB,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAClC,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,mCAAmC;QACnC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACjC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,IAAI,WAAI,CAAC,uCAAuC,KAAK,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC;YAClG,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,iBAAiB,CAAC,OAAe;QACrC,gEAAgE;QAChE,0EAA0E;QAC1E,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,yEAAyE,CAAC;QACxF,IAAI,KAA6B,CAAC;QAElC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ;AAnDD,wDAmDC"} \ No newline at end of file +{"version":3,"file":"CodeDuplicationPattern.js","sourceRoot":"","sources":["../../src/Patterns/CodeDuplicationPattern.ts"],"names":[],"mappings":";;;AAAA,+CAA4C;AAC5C,0CAAuC;AAEvC,MAAa,sBAAuB,SAAQ,yBAAW;IACnD,OAAO,CAAC,OAAe;QACnB,MAAM,KAAK,GAAW,EAAE,CAAC;QAEzB,MAAM,cAAc,GAAG;YACnB,MAAM,EAAU,6BAA6B;YAC7C,MAAM,EAAU,6BAA6B;YAC7C,OAAO,EAAS,8CAA8C;YAC9D,SAAS,EAAO,oEAAoE;SACvF,CAAC;QAEF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;aAC5B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;QAEjF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE7C,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACjB,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,0CAA0C;QAC1C,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,IAAI,WAAI,CAAC,sCAAsC,IAAI,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC;YAChG,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,6EAA6E;QAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE9C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACnB,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAClC,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,mCAAmC;QACnC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACjC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,IAAI,WAAI,CAAC,uCAAuC,KAAK,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC;YAClG,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,YAAY,CAAC,IAAY,EAAE,QAAkB;QACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;IAEO,iBAAiB,CAAC,OAAe;QACrC,gEAAgE;QAChE,0EAA0E;QAC1E,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,yEAAyE,CAAC;QACxF,IAAI,KAA6B,CAAC;QAElC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ;AAhED,wDAgEC"} \ No newline at end of file diff --git a/src/Patterns/CodeDuplicationPattern.ts b/src/Patterns/CodeDuplicationPattern.ts index 7382298..73c7ce6 100644 --- a/src/Patterns/CodeDuplicationPattern.ts +++ b/src/Patterns/CodeDuplicationPattern.ts @@ -5,8 +5,17 @@ export class CodeDuplicationPattern extends BasePattern { analyze(content: string): Hint[] { const hints: Hint[] = []; - // Split the content into lines and group them by their occurrence - const lines = content.split('\n').map(line => line.trim()).filter(line => line.length > 0); + const commonPatterns = [ + /^\}$/, // single closing curly brace + /^\{$/, // single opening curly brace + /^\);$/, // closing parenthesis followed by a semicolon + /^\}\);$/, // closing curly brace followed by closing parenthesis and semicolon + ]; + + const lines = content.split('\n') + .map(line => line.trim()) + .filter(line => line.length > 0 && !this.isCommonLine(line, commonPatterns)); + const lineCounts = new Map(); lines.forEach(line => { @@ -39,6 +48,10 @@ export class CodeDuplicationPattern extends BasePattern { return hints; } + private isCommonLine(line: string, patterns: RegExp[]): boolean { + return patterns.some(pattern => pattern.test(line)); + } + private extractCodeBlocks(content: string): string[] { // Basic implementation to extract code blocks (e.g., functions) // This needs to be improved based on actual use cases and language syntax diff --git a/tests/CodeDuplicationPattern.test.ts b/tests/CodeDuplicationPattern.test.ts index d7d0088..88d48bc 100644 --- a/tests/CodeDuplicationPattern.test.ts +++ b/tests/CodeDuplicationPattern.test.ts @@ -97,4 +97,40 @@ describe('CodeDuplicationPattern', () => { expect(hints.some(hint => hint.message.includes('console.log(\'Hello\')'))).toBe(true); expect(hints.some(hint => hint.message.includes('method() {'))).toBe(true); }); + + test('should ignore lines that match common patterns', () => { + const content = ` + function foo() { + console.log('Hello'); + } + + function bar() { + console.log('Hello'); + } + + } + + { + + }); + + }); + `; + const hints = pattern.analyze(content); + + // Check that the common patterns are ignored and do not trigger duplicate detection + expect(hints.length).toBeGreaterThan(0); // Expecting hints for "console.log('Hello')" + expect(hints.some(hint => hint.message.includes('console.log(\'Hello\')'))).toBe(true); + + // Ensure that none of the hints relate to the common patterns + const commonPatternMessages = [ + 'Possible duplicate code detected: "}"', + 'Possible duplicate code detected: "{"', + 'Possible duplicate code detected: ");"', + 'Possible duplicate code detected: "});"', + ]; + commonPatternMessages.forEach(message => { + expect(hints.some(hint => hint.message === message)).toBe(false); + }); + }); }); \ No newline at end of file From 477b10383d20aaa987c3a87caa1c0f8a11d7e0e1 Mon Sep 17 00:00:00 2001 From: Suren Poghosyan Date: Tue, 27 Aug 2024 21:03:46 +0400 Subject: [PATCH 2/2] [code-duplication-pattern] update readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1878bd1..a669691 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ As your project grows, your code can become hard to manage. Repeated code blocks, large classes, and bad design choices can slow down development and make it harder to add new features. **Code Diagnose** helps you find these problems automatically so you can focus on writing new code instead of fixing old issues. +## Not AI-Based + +**Code Diagnose** uses well-defined patterns and rules to analyze your TypeScript code. It does not use AI or machine learning algorithms. Instead, it relies on proven software engineering principles to detect code issues, ensuring consistent and predictable results. + ### Key Benefits: - **Improves Code Quality**: Detects common issues to help you write cleaner, easier-to-maintain code. - **Saves Time**: Finds problems quickly that would take a lot of time to find manually.