-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): add new executor for dotnet-format
Add a new executor to lint and format projects using an external tool. Fixes #13
- Loading branch information
Ben Callaghan
committed
May 19, 2021
1 parent
e2b1cfc
commit 92afd05
Showing
10 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { ExecutorContext } from '@nrwl/devkit'; | ||
|
||
import { promises as fs } from 'fs'; | ||
|
||
import { DotNetClient, mockDotnetFactory } from '@nx-dotnet/dotnet'; | ||
import { rimraf } from '@nx-dotnet/utils'; | ||
|
||
import executor from './executor'; | ||
import { FormatExecutorSchema } from './schema'; | ||
|
||
const options: FormatExecutorSchema = { | ||
check: true, | ||
verbosity: 'minimal', | ||
}; | ||
|
||
const root = process.cwd() + '/tmp'; | ||
|
||
jest.mock('../../../../dotnet/src/lib/core/dotnet.client'); | ||
|
||
describe('Format Executor', () => { | ||
let context: ExecutorContext; | ||
let dotnetClient: DotNetClient; | ||
|
||
beforeEach(() => { | ||
context = { | ||
root: root, | ||
cwd: root, | ||
projectName: 'my-app', | ||
targetName: 'lint', | ||
workspace: { | ||
version: 2, | ||
projects: { | ||
'my-app': { | ||
root: `${root}/apps/my-app`, | ||
sourceRoot: `${root}/apps/my-app`, | ||
targets: { | ||
lint: { | ||
executor: '@nx-dotnet/core:format', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
isVerbose: false, | ||
}; | ||
dotnetClient = new DotNetClient(mockDotnetFactory()); | ||
}); | ||
|
||
afterEach(async () => { | ||
await rimraf(root); | ||
}); | ||
|
||
it('detects no dotnet project', async () => { | ||
expect.assertions(1); | ||
try { | ||
await executor(options, context, dotnetClient); | ||
} catch (e) { | ||
console.log(e.message); | ||
expect(e.message).toMatch( | ||
"Unable to find a build-able project within project's source directory!", | ||
); | ||
} | ||
}); | ||
|
||
it('detects multiple dotnet projects', async () => { | ||
expect.assertions(1); | ||
|
||
try { | ||
const directoryPath = `${root}/apps/my-app`; | ||
await fs.mkdir(directoryPath, { recursive: true }); | ||
await Promise.all([ | ||
fs.writeFile(`${directoryPath}/1.csproj`, ''), | ||
fs.writeFile(`${directoryPath}/2.csproj`, ''), | ||
]); | ||
} catch (e) { | ||
console.warn(e.message); | ||
} | ||
|
||
try { | ||
await executor(options, context, dotnetClient); | ||
} catch (e) { | ||
console.log(e.message); | ||
expect(e.message).toMatch( | ||
"More than one build-able projects are contained within the project's source directory!", | ||
); | ||
} | ||
}); | ||
|
||
it('calls build when 1 project file is found', async () => { | ||
try { | ||
const directoryPath = `${root}/apps/my-app`; | ||
await fs.mkdir(directoryPath, { recursive: true }); | ||
await Promise.all([fs.writeFile(`${directoryPath}/1.csproj`, '')]); | ||
} catch (e) { | ||
console.warn(e.message); | ||
} | ||
|
||
const res = await executor(options, context, dotnetClient); | ||
expect( | ||
(dotnetClient as jest.Mocked<DotNetClient>).format, | ||
).toHaveBeenCalled(); | ||
expect(res.success).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { ExecutorContext } from '@nrwl/devkit'; | ||
import { | ||
DotNetClient, | ||
dotnetFactory, | ||
dotnetFormatFlags, | ||
} from '@nx-dotnet/dotnet'; | ||
import { | ||
getExecutedProjectConfiguration, | ||
getProjectFileForNxProject, | ||
} from '@nx-dotnet/utils'; | ||
import { FormatExecutorSchema } from './schema'; | ||
|
||
function normalizeOptions( | ||
options: FormatExecutorSchema, | ||
): Record<string, string | boolean | undefined> { | ||
const { diagnostics, include, exclude, check, fix, ...flags } = options; | ||
return { | ||
...flags, | ||
diagnostics: Array.isArray(diagnostics) | ||
? diagnostics.join(' ') | ||
: diagnostics, | ||
include: Array.isArray(include) ? include.join(' ') : include, | ||
exclude: Array.isArray(exclude) ? exclude.join(' ') : exclude, | ||
check: fix ? false : check, | ||
}; | ||
} | ||
|
||
export default async function runExecutor( | ||
options: FormatExecutorSchema, | ||
context: ExecutorContext, | ||
dotnetClient: DotNetClient = new DotNetClient(dotnetFactory()), | ||
) { | ||
const nxProjectConfiguration = getExecutedProjectConfiguration(context); | ||
const projectFilePath = await getProjectFileForNxProject( | ||
nxProjectConfiguration, | ||
); | ||
|
||
const normalized = normalizeOptions(options); | ||
|
||
dotnetClient.installTool('dotnet-format'); | ||
dotnetClient.format( | ||
projectFilePath, | ||
Object.keys(options).map((x) => ({ | ||
flag: x as dotnetFormatFlags, | ||
value: normalized[x], | ||
})), | ||
); | ||
|
||
return { | ||
success: true, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
export interface FormatExecutorSchema { | ||
noRestore?: boolean; | ||
fixWhitespace?: boolean; | ||
fixStyle?: string; | ||
diagnostics?: string | string[]; | ||
include?: string[]; | ||
exclude?: string[]; | ||
check: boolean; | ||
report?: string; | ||
binarylog?: string; | ||
verbosity: | ||
| 'q' | ||
| 'quiet' | ||
| 'm' | ||
| 'minimal' | ||
| 'n' | ||
| 'normal' | ||
| 'd' | ||
| 'detailed' | ||
| 'diag' | ||
| 'diagnostic'; | ||
fix?: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
{ | ||
"$schema": "http://json-schema.org/schema", | ||
"cli": "nx", | ||
"title": "Format executor", | ||
"description": "Formats and lints a project using the dotnet-format tool", | ||
"type": "object", | ||
"properties": { | ||
"noRestore": { | ||
"type": "boolean", | ||
"description": "Doesn't execute an implicit restore before formatting" | ||
}, | ||
"fixWhitespace": { | ||
"type": "boolean", | ||
"alias": ["w"], | ||
"description": "Run whitespace formatting. Run by default when not applying fixes." | ||
}, | ||
"fixStyle": { | ||
"type": "string", | ||
"alias": ["s"], | ||
"description": "Run code style analyzers and apply fixes." | ||
}, | ||
"fixAnalyzers": { | ||
"type": "string", | ||
"alias": ["a"], | ||
"description": "Run 3rd party analyzers and apply fixes." | ||
}, | ||
"diagnostics": { | ||
"anyOf": [ | ||
{ | ||
"type": "string", | ||
"description": "A space separated list of diagnostic ids to use as a filter when fixing code style or 3rd party analyzers." | ||
}, | ||
{ | ||
"type": "array", | ||
"description": "A list of diagnostic ids to use as a filter when fixing code style or 3rd party analyzers.", | ||
"items": { | ||
"type": "string" | ||
} | ||
} | ||
] | ||
}, | ||
"include": { | ||
"type": "array", | ||
"description": "A list of relative file or folder paths to include in formatting. All files are formatted if empty", | ||
"items": { | ||
"type": "string" | ||
} | ||
}, | ||
"exclude": { | ||
"type": "array", | ||
"description": "A list of relative file or folder paths to exclude from formatting.", | ||
"items": { | ||
"type": "string" | ||
} | ||
}, | ||
"check": { | ||
"type": "boolean", | ||
"description": "Formats files without saving changes to disk. Terminates with a non-zero exit code if any files were formatted.", | ||
"default": true | ||
}, | ||
"report": { | ||
"type": "string", | ||
"description": "Accepts a file path, which if provided, will produce a json report in the given directory." | ||
}, | ||
"binarylog": { | ||
"type": "string", | ||
"description": "Log all project or solution load information to a binary log file." | ||
}, | ||
"verbosity": { | ||
"type": "string", | ||
"description": "Set the verbosity level.", | ||
"enum": [ | ||
"q", | ||
"quiet", | ||
"m", | ||
"minimal", | ||
"n", | ||
"normal", | ||
"d", | ||
"detailed", | ||
"diag", | ||
"diagnostic" | ||
], | ||
"default": "minimal" | ||
}, | ||
"fix": { | ||
"type": "boolean", | ||
"description": "Formats files and saves changes to disk. Equivalent to setting --check=false." | ||
} | ||
}, | ||
"required": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
packages/dotnet/src/lib/models/dotnet-format/dotnet-format-flags.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export type dotnetFormatFlags = | ||
| 'noRestore' | ||
// Deliberately excluding the folder option, as the csproj file is always used as the workspace. | ||
| 'fixWhitespace' | ||
| 'fixStyle' | ||
| 'fixAnalyzers' | ||
| 'diagnostics' | ||
| 'include' | ||
| 'exclude' | ||
| 'check' | ||
| 'report' | ||
| 'binarylog' | ||
| 'verbosity'; | ||
// Deliberately excluding the version option, as it doesn't perform any actual formatting. | ||
|
||
export const formatKeyMap: Partial<{ [key in dotnetFormatFlags]: string }> = { | ||
noRestore: 'no-restore', | ||
fixWhitespace: 'fix-whitespace', | ||
fixStyle: 'fix-style', | ||
fixAnalyzers: 'fix-analyzers', | ||
}; |
6 changes: 6 additions & 0 deletions
6
packages/dotnet/src/lib/models/dotnet-format/dotnet-format-options.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { dotnetFormatFlags } from './dotnet-format-flags'; | ||
|
||
export type dotnetFormatOptions = { | ||
flag: dotnetFormatFlags; | ||
value?: string | boolean; | ||
}[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './dotnet-format-flags'; | ||
export * from './dotnet-format-options'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters