Skip to content
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
40 changes: 27 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ Thank you for your interest in contributing to Barrel Roll! This document provid
cd barrel-roll
```

2. **Install Dependencies**
1. **Install Dependencies**

```bash
npm install
```

3. **Build the Extension**
1. **Build the Extension**

```bash
npm run compile
```
Expand All @@ -27,9 +28,9 @@ Thank you for your interest in contributing to Barrel Roll! This document provid
### Running the Extension Locally

1. Open the project in VS Code
2. Press F5 to start debugging
3. A new VS Code window will open with the extension loaded
4. Right-click on any folder in the file explorer to test the "Barrel Roll: Generate/Update index.ts" command
1. Press F5 to start debugging
1. A new VS Code window will open with the extension loaded
1. Right-click on any folder in the file explorer to test the "Barrel Roll: Generate/Update index.ts" command

### Making Changes

Expand All @@ -39,24 +40,25 @@ Thank you for your interest in contributing to Barrel Roll! This document provid
git checkout -b feature/your-feature-name
```

2. Make your changes following the code style guidelines
1. Make your changes following the code style guidelines

3. Run linting:
1. Run linting:

```bash
npm run lint
npm run lint:fix # Auto-fix issues
```

4. Run formatting:
1. Run formatting:

```bash
npm run format
```

5. Write tests for your changes (if applicable)
1. Write tests for your changes (if applicable)

1. Run tests:

6. Run tests:
```bash
npm test
```
Expand Down Expand Up @@ -108,10 +110,22 @@ feat: add support for default exports
## Pull Request Process

1. Ensure all tests pass
2. Update documentation if needed
3. Update CHANGELOG.md with your changes
4. Submit a pull request with a clear description of the changes
1. Update documentation if needed
1. Update CHANGELOG.md with your changes
1. Submit a pull request with a clear description of the changes

## Questions?

Feel free to open an issue for any questions or concerns.

## Coding conventions: error handling

- Prefer the shared helpers in `src/utils/errors.ts`:
- `getErrorMessage(error)` — safe extraction of an error message
- `formatErrorForLog(error)` — prefer when logging since it preserves stack when available

- To catch and automatically correct ad-hoc checks like `error instanceof Error ? error.message : String(error)` run:
- `npm run lint:fix` (uses ESLint auto-fix where applicable)
- `npm run fix:instanceof-error` (codemod using `jscodeshift` for larger-scale replacements)

If you want to add more auto-fix patterns, please open an issue or PR so we can review and add targeted rules/codemods.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ This architecture ensures:
- **Dependency Inversion**: High-level modules don't depend on low-level details
- **Testability**: Each component can be tested in isolation

## Known Limitations

- **Bundle size**: The extension uses [ts-morph](https://github.com/dsherret/ts-morph) for robust TypeScript AST parsing. This adds approximately 6 MB to the extension bundle. The trade-off is accurate parsing that correctly ignores export-like text inside strings, comments, and regex literals.

- **Re-exports without aliases**: Passthrough re-exports like `export { foo } from './module'` are intentionally skipped because they don't introduce new named exports—they simply forward exports from other modules. Re-exports **with** aliases (e.g., `export { default as MyClass } from './impl'`) are included because they create a new named export.

- **Dynamic exports**: Exports computed at runtime (e.g., `export default someFactory()`) are captured as default exports, but any dynamically generated named exports cannot be statically detected.

- **Non-TypeScript files**: Only `.ts` and `.tsx` files are scanned. JavaScript files, JSON, and other formats are ignored.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
Expand All @@ -236,4 +246,8 @@ For developer notes on automation, dependency checks, test conventions, and othe

## License

Apache-2.0
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.

## Ownership

This repository is maintained by **Rob "Coderrob" Lindley**. For inquiries, please contact via GitHub.
2 changes: 1 addition & 1 deletion badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import _import from 'eslint-plugin-import';
import jsdoc from 'eslint-plugin-jsdoc';
import prettier from 'eslint-plugin-prettier';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import sonarjs from 'eslint-plugin-sonarjs';
import localPlugin from './scripts/eslint-plugin-local.mjs';
import globals from 'globals';

const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -64,8 +66,10 @@ export default [
plugins: {
'@typescript-eslint': typescriptEslint,
import: _import,
jsdoc,
'simple-import-sort': simpleImportSort,
sonarjs,
local: localPlugin,
},
settings: {
'import/resolver': {
Expand Down Expand Up @@ -98,8 +102,25 @@ export default [
message:
'Avoid using \'typeof import(...)["T"]\' indexed import types; import the type and refer to it directly.',
},
{
selector: "BinaryExpression[operator='instanceof'][right.name='Error']",
message:
"Avoid ad-hoc 'instanceof Error' checks — prefer `getErrorMessage` or `formatErrorForLog` from 'src/utils/errors' for consistent error handling and logging.",
},
{
selector:
"TSTypeReference[typeName.name='ReturnType'] > TSTypeParameterInstantiation > TSIndexedAccessType",
message:
'Avoid ReturnType applied to indexed access types; define a named type/interface instead.',
},
{
selector:
"TSTypeReference[typeName.name='ReturnType'] > TSTypeParameterInstantiation > TSTypeReference[typeName.name='ReturnType']",
message: 'Avoid nested ReturnType chains; define a named type/interface instead.',
},
],
'sonarjs/no-duplicate-string': ['error', { threshold: 3 }],
'local/no-instanceof-error-autofix': 'error',
'sonarjs/no-identical-functions': 'error',
'sonarjs/prefer-immediate-return': 'error',
'sonarjs/pseudo-random': 'warn',
Expand All @@ -111,6 +132,27 @@ export default [
'sonarjs/prefer-single-boolean-return': 'error',

// TypeScript ESLint rules
'@typescript-eslint/explicit-function-return-type': [
'error',
{
allowExpressions: false,
allowTypedFunctionExpressions: false,
allowHigherOrderFunctions: false,
allowDirectConstAssertionInArrowFunctions: false,
},
],
'jsdoc/require-jsdoc': [
'error',
{
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: false,
ArrowFunctionExpression: false,
FunctionExpression: false,
},
},
],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
Expand Down Expand Up @@ -168,6 +210,23 @@ export default [
},
},

// Allow 'instanceof Error' only within guards helper to implement the guard itself
{
files: ['src/utils/guards.ts'],
rules: {
'no-restricted-syntax': 'off',
},
},

// Source files - relax strict return type rules since methods already have explicit return types
{
files: ['src/**/*.ts'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'no-restricted-syntax': 'off',
},
},

// Mocha test suite files (VS Code extension integration tests)
{
files: ['**/src/test/suite/**/*.{ts,tsx}'],
Expand Down Expand Up @@ -225,4 +284,13 @@ export default [
'unicorn/prefer-top-level-await': 'off',
},
},

// Test files - relax strict rules
{
files: ['**/*.test.ts', '**/*.test.js', '**/test/**'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'no-restricted-syntax': 'off',
},
},
];
Loading