Skip to content

Commit

Permalink
Merge pull request #11 from ValentinVignal/support-nested-analysis-op…
Browse files Browse the repository at this point in the history
…tions

feat:  Support nested analysis options
  • Loading branch information
ValentinVignal authored Aug 14, 2023
2 parents 852844f + 8ec1fb6 commit daef594
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.16

- :sparkles: Supports nested analysis options.

## 0.15

- :arrow_up: Upgrade to node 16.
Expand Down
61 changes: 55 additions & 6 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17090,29 +17090,78 @@ var __importStar = (this && this.__importStar) || function (mod) {
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.IgnoredFiles = void 0;
const fs = __importStar(__nccwpck_require__(5747));
const yaml = __importStar(__nccwpck_require__(1917));
const minimatch = __importStar(__nccwpck_require__(3973));
const minimatch_1 = __importDefault(__nccwpck_require__(3973));
const path = __importStar(__nccwpck_require__(5622));
const ActionOptions_1 = __nccwpck_require__(3615);
/**
* The ignore files in the analysis_options.yaml
*/
class IgnoredFiles {
constructor() {
var _a, _b;
let patterns;
try {
const yamlFile = yaml.load(fs.readFileSync(path.resolve(ActionOptions_1.actionOptions.workingDirectory, 'analysis_options.yaml'), 'utf8'));
patterns = (_b = (_a = yamlFile === null || yamlFile === void 0 ? void 0 : yamlFile.analyzer) === null || _a === void 0 ? void 0 : _a.exclude) !== null && _b !== void 0 ? _b : [];
const yamlPath = IgnoredFiles.findClosestYamlFile(ActionOptions_1.actionOptions.workingDirectory);
if (!yamlPath) {
throw new Error(`Could not find any "analysis_options.yaml" in the parent directories of "${ActionOptions_1.actionOptions.workingDirectory}"`);
}
patterns = IgnoredFiles.getIgnoredPatterns(yamlPath);
}
catch (error) {
console.log('Could not load analysis_options.yaml:\n', error);
console.error('Could not load analysis_options.yaml:\n', error);
}
patterns !== null && patterns !== void 0 ? patterns : (patterns = []);
this.patterns = patterns.map((pattern) => new minimatch.Minimatch(pattern));
this.patterns = patterns.map((pattern) => new minimatch_1.default.Minimatch(pattern));
}
/**
*
* @param path
*/
static findClosestYamlFile(directoryPath) {
const yamlPath = path.resolve(directoryPath, 'analysis_options.yaml');
if (fs.existsSync(yamlPath)) {
return yamlPath;
}
else {
const parentDirectoryPath = path.resolve(directoryPath, '..');
if (parentDirectoryPath === directoryPath) {
return null;
}
else {
return IgnoredFiles.findClosestYamlFile(parentDirectoryPath);
}
}
}
static getIgnoredPatterns(yamlPath) {
var _a;
const yamlFile = yaml.load(fs.readFileSync(yamlPath, 'utf8'));
const exclude = (_a = yamlFile === null || yamlFile === void 0 ? void 0 : yamlFile.analyzer) === null || _a === void 0 ? void 0 : _a.exclude;
let patterns;
if (exclude) {
if (Array.isArray(exclude)) {
patterns = exclude;
}
else if (typeof exclude === 'string') {
patterns = [exclude];
}
}
patterns !== null && patterns !== void 0 ? patterns : (patterns = []);
if (yamlFile === null || yamlFile === void 0 ? void 0 : yamlFile.include) {
const newPath = path.resolve(path.dirname(yamlPath), yamlFile.include);
if (fs.existsSync(newPath)) {
return [
...IgnoredFiles.getIgnoredPatterns(newPath),
...patterns,
];
}
}
return patterns;
}
/**
* Whether a file is ignored
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "action-dart-analyze",
"version": "0.15.0",
"version": "0.16.0",
"description": "",
"main": "index.js",
"scripts": {
Expand Down
45 changes: 45 additions & 0 deletions src/utils/IgnoredFiles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ jest.mock('path', () => mockPath);

const mockFs = {
readFileSync: jest.fn(),
existsSync: jest.fn(),
};


jest.mock('fs', () => mockFs);

const mockYaml = {
Expand All @@ -44,6 +46,7 @@ describe('IgnoredFiles', () => {
} as ActionOptions;

mockPath.resolve.mockReturnValue('path/to/yaml');
mockFs.existsSync.mockReturnValue(true);
mockFs.readFileSync.mockReturnValue('yamlContent');
mockYaml.load.mockReturnValue({
analyzer: {
Expand All @@ -65,6 +68,48 @@ describe('IgnoredFiles', () => {
['yamlContent'],
]);

expect(ignoredFiles.has('lib/path/to/generated/file.g.dart')).toBe(true);
expect(ignoredFiles.has('lib/path/to/normal/file')).toBe(false);
expect(ignoredFiles.has('lib/main.dart')).toBe(false);
expect(ignoredFiles.has('lib/excluded.dart')).toBe(true);
});
test('It should return the ignored files of the closest analysis_options.yaml file', () => {
mockActionOptions.actionOptions = {
workingDirectory: 'working/directory',
} as ActionOptions;

mockPath.resolve.mockReturnValueOnce('working/directory/analysis_options.yaml');
mockFs.existsSync.mockReturnValueOnce(false); // The file is not found.
mockPath.resolve.mockReturnValueOnce('working'); // Returns the parent
mockPath.resolve.mockReturnValueOnce('working/analysis_options.yaml'); // Yaml higher in the file tree.
mockFs.existsSync.mockReturnValueOnce(true); // The file is not found.
mockFs.readFileSync.mockReturnValue('yamlContent');
mockYaml.load.mockReturnValue({
analyzer: {
exclude: [
'**/*.g.dart',
'lib/excluded.dart'
],
}
});
const ignoredFiles = new IgnoredFiles();

expect(mockPath.resolve.mock.calls).toEqual([
['working/directory', 'analysis_options.yaml'],
['working/directory', '..'],
['working', 'analysis_options.yaml'],
]);
expect(mockFs.existsSync.mock.calls).toEqual([
['working/directory/analysis_options.yaml'],
['working/analysis_options.yaml'],
]);
expect(mockFs.readFileSync.mock.calls).toEqual([
['working/analysis_options.yaml', 'utf8'],
]);
expect(mockYaml.load.mock.calls).toEqual([
['yamlContent'],
]);

expect(ignoredFiles.has('lib/path/to/generated/file.g.dart')).toBe(true);
expect(ignoredFiles.has('lib/path/to/normal/file')).toBe(false);
expect(ignoredFiles.has('lib/main.dart')).toBe(false);
Expand Down
61 changes: 57 additions & 4 deletions src/utils/IgnoredFiles.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import * as fs from 'fs';
import * as yaml from 'js-yaml';
import * as minimatch from 'minimatch';
import minimatch from 'minimatch';
import * as path from 'path';
import { actionOptions } from './ActionOptions';

type AnalysisOptions = {
include?: string;
analyzer?: {
exclude?: string[] | string;
}
}

/**
* The ignore files in the analysis_options.yaml
*/
Expand All @@ -12,15 +19,61 @@ export class IgnoredFiles {
constructor() {
let patterns: string[];
try {
const yamlFile = yaml.load(fs.readFileSync(path.resolve(actionOptions.workingDirectory, 'analysis_options.yaml'), 'utf8')) as { analyzer?: { exclude?: string[] } };
patterns = yamlFile?.analyzer?.exclude ?? [];
const yamlPath = IgnoredFiles.findClosestYamlFile(actionOptions.workingDirectory);
if (!yamlPath) {
throw new Error(`Could not find any "analysis_options.yaml" in the parent directories of "${actionOptions.workingDirectory}"`);
}
patterns = IgnoredFiles.getIgnoredPatterns(yamlPath);
} catch (error) {
console.log('Could not load analysis_options.yaml:\n', error);
console.error('Could not load analysis_options.yaml:\n', error);
}
patterns ??= [];
this.patterns = patterns.map((pattern) => new minimatch.Minimatch(pattern));
}

/**
*
* @param path
*/
private static findClosestYamlFile(directoryPath: string): string | null {
const yamlPath = path.resolve(directoryPath, 'analysis_options.yaml');
if (fs.existsSync(yamlPath)) {
return yamlPath;
} else {
const parentDirectoryPath = path.resolve(directoryPath, '..');
if (parentDirectoryPath === directoryPath) {
return null;
} else {
return IgnoredFiles.findClosestYamlFile(parentDirectoryPath);
}
}
}

private static getIgnoredPatterns(yamlPath: string): string[] {
const yamlFile = yaml.load(fs.readFileSync(yamlPath, 'utf8')) as AnalysisOptions;
const exclude = yamlFile?.analyzer?.exclude;
let patterns: string[];
if (exclude) {
if (Array.isArray(exclude)) {
patterns = exclude;
} else if (typeof exclude === 'string') {
patterns = [exclude];
}
}
patterns ??= [];

if (yamlFile?.include) {
const newPath = path.resolve(path.dirname(yamlPath), yamlFile.include);
if (fs.existsSync(newPath)) {
return [
...IgnoredFiles.getIgnoredPatterns(newPath),
...patterns,
];
}
}
return patterns;
}

/**
* Whether a file is ignored
*/
Expand Down

0 comments on commit daef594

Please sign in to comment.