Skip to content

Show CLI warnings & improve ER diagram generation #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 3, 2023
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
9 changes: 1 addition & 8 deletions sample_dotnet/ExampleAPI/Context/BloggingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,9 @@ public class BloggingContext : DbContext

public DbSet<Tag> Tags { get; set; }

public string DbPath { get; private set; }

public BloggingContext()
{
DbPath = $"blogging.db";
}

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite($"Data Source={DbPath}");
options.UseSqlite($"Data Source=blogging.db");
options.LogTo(Console.WriteLine);
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
Expand Down
Binary file modified sample_dotnet/ExampleAPI/blogging.db
Binary file not shown.
10 changes: 4 additions & 6 deletions src/actions/DBContextInfoCommandAction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as vscode from 'vscode';

import { CLI } from '../cli/CLI';
import { EFOutputParser } from '../cli/EFOutputParser';
import { getCommandsConfig } from '../config/config';
import { TREE_VIEW_ID } from '../constants/constants';

Expand Down Expand Up @@ -42,14 +42,12 @@ export class DBContextInfoCommandAction extends TerminalAction {
removeDataFromOutput: true,
asJson: true,
});
const output = CLI.getDataFromStdOut(await this.getOutput());
const uri = vscode.Uri.parse(
`${TextDocumentProvider.scheme}:${output}`,
);
const { data } = EFOutputParser.parse(await this.getOutput());
const uri = vscode.Uri.parse(`${TextDocumentProvider.scheme}:${data}`);
const doc = await vscode.workspace.openTextDocument(uri);
await vscode.languages.setTextDocumentLanguage(doc, 'json');
await vscode.window.showTextDocument(doc, { preview: false });
return output;
return data;
},
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/actions/GenerateERDAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import path from 'path';
import fs from 'fs';
import util from 'util';

import { CLI } from '../cli/CLI';
import { getCommandsConfig, getERDConfig } from '../config/config';
import { TerminalAction } from './TerminalAction';
import { DEFAULT_EFCORE_PROVIDERS, TREE_VIEW_ID } from '../constants/constants';
Expand All @@ -18,6 +17,7 @@ import type { Logger } from '../util/Logger';

// @ts-ignore
import mermaidTemplate from '../templates/DbContext.Mermaid.t4';
import { EFOutputParser } from '../cli/EFOutputParser';

const copyFile = util.promisify(fs.copyFile);
const rename = util.promisify(fs.rename);
Expand Down Expand Up @@ -162,7 +162,7 @@ export class GenerateERDAction extends TerminalAction {
},
);
const output = await this.getOutput();
const data = CLI.getDataFromStdOut(await this.getOutput());
const { data } = EFOutputParser.parse(output);
const result = JSON.parse(data) as ScaffoldResult;

const fileContents = fs.readFileSync(result.contextFile, 'utf-8');
Expand Down
4 changes: 2 additions & 2 deletions src/actions/GenerateScriptAction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as vscode from 'vscode';

import { CLI } from '../cli/CLI';
import { EFOutputParser } from '../cli/EFOutputParser';
import { getCommandsConfig } from '../config/config';
import { TREE_VIEW_ID } from '../constants/constants';
import type { TerminalProvider } from '../terminal/TerminalProvider';
Expand Down Expand Up @@ -40,7 +40,7 @@ export class GenerateScriptAction extends TerminalAction {
removeDataFromOutput: true,
});
const output = await this.getOutput();
const data = CLI.getDataFromStdOut(output);
const { data } = EFOutputParser.parse(output);
const uri = vscode.Uri.parse(`${TextDocumentProvider.scheme}:${data}`);
const doc = await vscode.workspace.openTextDocument(uri);
await vscode.languages.setTextDocumentLanguage(doc, 'sql');
Expand Down
7 changes: 3 additions & 4 deletions src/actions/ScaffoldAction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Project } from 'nuget-deps-tree';
import * as vscode from 'vscode';
import { CLI } from '../cli/CLI';
import { EFOutputParser } from '../cli/EFOutputParser';
import { CommandProvider } from '../commands/CommandProvider';
import { RefreshTreeCommand } from '../commands/RefreshTreeCommand';
import { getCommandsConfig } from '../config/config';
Expand Down Expand Up @@ -136,10 +136,9 @@ export class ScaffoldAction extends TerminalAction {
asJson: true,
},
);
const output = JSON.parse(
CLI.getDataFromStdOut(await this.getOutput()),
) as ScaffoldResult;

const { data } = EFOutputParser.parse(await this.getOutput());
const output = JSON.parse(data) as ScaffoldResult;
const uri = vscode.Uri.file(output.contextFile);
const doc = await vscode.workspace.openTextDocument(uri);
await vscode.window.showTextDocument(doc);
Expand Down
76 changes: 8 additions & 68 deletions src/cli/CLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ import type { ChildProcess } from 'child_process';
import { spawn } from 'child_process';

import { getEnvConfig } from '../config/config';
import { TerminalColors } from '../terminal/TerminalColors';
import type { Logger } from '../util/Logger';

const NEWLINE_SEPARATOR = /\r\n|\r|\n/;
const OUTPUT_PREFIX = /^([a-z]+:([\s]{4}|[\s]{3}))/;
import { EFOutputParser } from './EFOutputParser';

export type ExecOpts = {
cmdArgs: string[];
Expand All @@ -29,67 +26,6 @@ export type ExecProcess = {
export class CLI {
constructor(private readonly logger: Logger) {}

public static getDataFromStdOut(output: string): string {
return this.stripPrefixFromStdOut(
output
.split(NEWLINE_SEPARATOR)
.filter(line => line.startsWith('data:'))
.join('\n'),
);
}

public static getErrorsFromStdOut(output: string): string {
return this.stripPrefixFromStdOut(
output
.split(NEWLINE_SEPARATOR)
.filter(line => line.startsWith('error:'))
.join('\n'),
);
}

private static filter(out: string, prefix: string) {
return out
.split(NEWLINE_SEPARATOR)
.filter(line => !line.trim().startsWith(prefix))
.join('\n');
}

public static filterInfoFromOutput(out: string): string {
return this.filter(out, 'info:');
}

public static filterDataFromOutput(out: string): string {
return this.filter(out, 'data:');
}

public static colorizeOutput(output: string): string {
return output
.split(NEWLINE_SEPARATOR)
.map(line => {
if (line.startsWith('warn:')) {
return (
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.yellow}`) +
TerminalColors.reset
);
}
if (line.startsWith('error:')) {
return (
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.red}`) +
TerminalColors.reset
);
}
return line;
})
.join('\n');
}

public static stripPrefixFromStdOut(output: string): string {
return output
.split(NEWLINE_SEPARATOR)
.map(line => line.replace(OUTPUT_PREFIX, ''))
.join('\n');
}

private getInterpolatedArgs(
args: string[],
params: { [key: string]: string },
Expand Down Expand Up @@ -117,12 +53,14 @@ export class CLI {

const args = interpolatedArgs.concat(additionalArgs);

const envConfig = getEnvConfig();

const cmd = spawn(args[0], args.slice(1), {
cwd,
shell: true,
env: {
...process.env,
...getEnvConfig(),
...envConfig,
},
});

Expand All @@ -149,10 +87,12 @@ export class CLI {
});

cmd?.on('exit', async code => {
const error = stderr || CLI.getErrorsFromStdOut(stdout);
const error = stderr || EFOutputParser.parse(stdout).errors;
if (error || code !== 0) {
handlers?.onStdOut?.(`Exited with code ${code}\n`);
const finalError = CLI.filterInfoFromOutput(error || stdout);
const finalError = EFOutputParser.filterInfoFromOutput(
error || stdout,
);
rej(new Error(finalError));
} else {
res(stdout);
Expand Down
89 changes: 89 additions & 0 deletions src/cli/EFOutputParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { TerminalColors } from '../terminal/TerminalColors';

const NEWLINE_SEPARATOR = /\r\n|\r|\n/;
const OUTPUT_PREFIX = /^([a-z]+:([\s]{1,4}))/;

export class EFOutputParser {
private static filter(out: string, prefix: string) {
return out
.split(NEWLINE_SEPARATOR)
.filter(line => !line.trim().startsWith(prefix))
.join('\n');
}

public static filterInfoFromOutput(out: string): string {
return this.filter(out, 'info:');
}

public static filterDataFromOutput(out: string): string {
return this.filter(out, 'data:');
}

public static stripPrefixFromStdOut(output: string): string {
return output
.split(NEWLINE_SEPARATOR)
.map(line => line.replace(OUTPUT_PREFIX, ''))
.join('\n');
}

public static colorizeOutput(output: string): string {
return output
.split(NEWLINE_SEPARATOR)
.map(line => {
if (line.startsWith('warn:')) {
return (
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.yellow}`) +
TerminalColors.reset
);
}
if (line.startsWith('error:')) {
return (
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.red}`) +
TerminalColors.reset
);
}
return line;
})
.join('\n');
}

public static parse(output: string) {
let warnings = '';
let data = '';
let errors = '';
let matchedWarning = false;
let matchedError = false;

output.split(NEWLINE_SEPARATOR).forEach(line => {
if (matchedWarning && !OUTPUT_PREFIX.test(line)) {
matchedWarning = true;
} else {
matchedWarning = line.startsWith('warn:');
}

if (matchedError && !OUTPUT_PREFIX.test(line)) {
matchedError = true;
} else {
matchedError = line.startsWith('error:');
}

const matchedData = line.startsWith('data:');

const lineWithoutPrefix = line.replace(OUTPUT_PREFIX, '');

if (matchedWarning) {
warnings += lineWithoutPrefix;
} else if (matchedError) {
errors += lineWithoutPrefix;
} else if (matchedData) {
data += lineWithoutPrefix;
}
});

return {
warnings,
errors,
data,
};
}
}
9 changes: 5 additions & 4 deletions src/terminal/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import type { ChildProcess } from 'child_process';

import { EventWaiter } from '../util/EventWaiter';
import type { ExecOpts, ExecProcess } from '../cli/CLI';
import { CLI } from '../cli/CLI';
import type { CLI } from '../cli/CLI';
import { TerminalColors } from './TerminalColors';
import { EFOutputParser } from '../cli/EFOutputParser';

const NL = '\n';
const CR = '\r';
Expand Down Expand Up @@ -39,11 +40,11 @@ export class Terminal implements vscode.Pseudoterminal {
} else {
let line = lineBuffer + buffer;
lineBuffer = '';
line = CLI.colorizeOutput(line);
line = EFOutputParser.colorizeOutput(line);
if (removeDataFromOutput) {
line = CLI.filterDataFromOutput(line);
line = EFOutputParser.filterDataFromOutput(line);
}
this.write(CLI.stripPrefixFromStdOut(line));
this.write(EFOutputParser.stripPrefixFromStdOut(line));
}
};
}
Expand Down
13 changes: 9 additions & 4 deletions src/treeView/DbContextTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import type { Migration } from '../types/Migration';
import { getIconPath } from './iconProvider';
import { MigrationTreeItem } from './MigrationTreeItem';
import { TreeItem } from './TreeItem';
import { CLI } from '../cli/CLI';
import type { CLI } from '../cli/CLI';
import { TreeItemCache } from './TreeItemCache';
import { ContextValues } from './ContextValues';
import type { ProjectFile } from '../types/ProjectFile';
import { getCommandsConfig } from '../config/config';
import type { Logger } from '../util/Logger';
import { EFOutputParser } from '../cli/EFOutputParser';

export const dbContextsCache = new TreeItemCache<MigrationTreeItem[]>();

Expand Down Expand Up @@ -58,10 +59,14 @@ export class DbContextTreeItem extends TreeItem {
project: this.projectFile.name,
},
});
const stdOut = await output;
const { data, warnings } = EFOutputParser.parse(stdOut);

const migrations = JSON.parse(
CLI.getDataFromStdOut(await output),
) as Migration[];
if (warnings) {
void vscode.window.showWarningMessage(warnings);
}

const migrations = JSON.parse(data) as Migration[];

const children = migrations.map(
migration =>
Expand Down
Loading