Skip to content

Commit

Permalink
Set autocorrect as a formatter
Browse files Browse the repository at this point in the history
It allows to run autocorrect even for not existing files (new buffers).
It doesn't clean the history of changes.
rubocop.autocorrect command is an alias for format document.
  • Loading branch information
sergey-kintsel committed Jan 3, 2018
1 parent 053a484 commit 7500a04
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 42 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@
"title": "Ruby: lint by rubocop"
},
{
"command": "ruby.rubocopAutocorrect",
"command": "editor.action.formatDocument",
"title": "Ruby: autocorrect by rubocop"
}
],
"keybindings": [
{
"key": "shift+ctrl+r",
"command": "ruby.rubocopAutocorrect",
"command": "editor.action.formatDocument",
"when": "editorLangId == 'ruby'"
}
],
Expand Down
2 changes: 1 addition & 1 deletion src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vs from 'vscode';
import * as fs from 'fs';
import * as cp from 'child_process';
import * as path from 'path';
import Rubocop from './rubocop';
import { Rubocop } from './rubocop';

export interface RubocopConfig {
command: string;
Expand Down
18 changes: 3 additions & 15 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@

import * as vscode from 'vscode';
import Rubocop from './rubocop';
import { Rubocop, RubocopAutocorrectProvider } from './rubocop';
import { onDidChangeConfiguration } from './configuration';

// entry point of extension
export function activate(context: vscode.ExtensionContext): void {
'use strict';

const diag = vscode.languages.createDiagnosticCollection('ruby');
const rubocopAutocorrect = new Rubocop(diag, ['--auto-correct']);

vscode.commands.registerCommand('ruby.rubocopAutocorrect', () => {
const document = vscode.window.activeTextEditor.document;

if (document.languageId !== 'ruby') {
return;
}

document.save().then(() => {
rubocopAutocorrect.execute(document, () => rubocop.execute(document));
});
});

context.subscriptions.push(diag);

const rubocop = new Rubocop(diag);
Expand Down Expand Up @@ -53,4 +39,6 @@ export function activate(context: vscode.ExtensionContext): void {
ws.onDidCloseTextDocument((e: vscode.TextDocument) => {
rubocop.clear(e);
});
const formattingProvider = new RubocopAutocorrectProvider;
vscode.languages.registerDocumentFormattingEditProvider('ruby', formattingProvider);
}
86 changes: 63 additions & 23 deletions src/rubocop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,72 @@ import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import { getConfig, RubocopConfig } from './configuration';
import * as os from 'os';

const tmpFileName = path.join(os.tmpdir(), '_rubocop.rb');

export class RubocopAutocorrectProvider implements vscode.DocumentFormattingEditProvider {
public provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.TextEdit[] {
const config = getConfig();
fs.writeFileSync(tmpFileName, document.getText());
const onSuccess = () => {
const newText = fs.readFileSync(tmpFileName).toString();
fs.unlink(tmpFileName);
return [new vscode.TextEdit(this.getFullRange(document), newText)];
};
try {
cp.execFileSync(
config.command,
[tmpFileName, ...getCommandArguments(tmpFileName), '--auto-correct'],
{ cwd: getCurrentPath(document.fileName) },
);
} catch (e) {
// if there are still some offences not fixed rubocop will return status 1
if (e.status !== 1) {
vscode.window.showWarningMessage('An error occured during autocorrection');
console.log(e);
fs.unlink(tmpFileName);
return [];
} else {
return onSuccess();
}
}
return onSuccess();
}

private getFullRange(document: vscode.TextDocument): vscode.Range {
return new vscode.Range(
new vscode.Position(0, 0),
document.lineAt(document.lineCount - 1).range.end,
);
}
}

function isFileUri(uri: vscode.Uri): boolean {
return uri.scheme === 'file';
}

export default class Rubocop {
function getCurrentPath(fileName: string): string {
return vscode.workspace.rootPath || path.dirname(fileName);
}

// extract argument to an array
function getCommandArguments(fileName: string): string[] {
let commandArguments = [fileName, '--format', 'json', '--force-exclusion'];
const extensionConfig = getConfig();
if (extensionConfig.configFilePath !== '') {
if (fs.existsSync(extensionConfig.configFilePath)) {
const config = ['--config', extensionConfig.configFilePath];
commandArguments = commandArguments.concat(config);
} else {
vscode.window.showWarningMessage(`${extensionConfig.configFilePath} file does not exist. Ignoring...`);
}
}

return commandArguments;
}

export class Rubocop {
public config: RubocopConfig;
private diag: vscode.DiagnosticCollection;
private additionalArguments: string[];
Expand All @@ -33,10 +93,7 @@ export default class Rubocop {

const fileName = document.fileName;
const uri = document.uri;
let currentPath = vscode.workspace.rootPath;
if (!currentPath) {
currentPath = path.dirname(fileName);
}
let currentPath = getCurrentPath(fileName);

let onDidExec = (error: Error, stdout: string, stderr: string) => {
if (this.hasError(error, stderr)) {
Expand Down Expand Up @@ -69,7 +126,7 @@ export default class Rubocop {
this.diag.set(entries);
};

const args = this.commandArguments(fileName);
const args = getCommandArguments(fileName).concat(this.additionalArguments);

let task = new Task(uri, token => {
let process = this.executeRubocop(args, { cwd: currentPath }, (error, stdout, stderr) => {
Expand Down Expand Up @@ -99,22 +156,6 @@ export default class Rubocop {
}
}

// extract argument to an array
protected commandArguments(fileName: string): string[] {
let commandArguments = [fileName, '--format', 'json', '--force-exclusion'];

if (this.config.configFilePath !== '') {
if (fs.existsSync(this.config.configFilePath)) {
const config = ['--config', this.config.configFilePath];
commandArguments = commandArguments.concat(config);
} else {
vscode.window.showWarningMessage(`${this.config.configFilePath} file does not exist. Ignoring...`);
}
}

return commandArguments.concat(this.additionalArguments);
}

// execute rubocop
private executeRubocop(
args: string[],
Expand Down Expand Up @@ -180,5 +221,4 @@ export default class Rubocop {
default: return vscode.DiagnosticSeverity.Error;
}
}

}
2 changes: 1 addition & 1 deletion test/rubocop.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import * as vscode from 'vscode';
import Rubocop from '../src/rubocop';
import { Rubocop } from '../src/rubocop';

describe('Rubocop', () => {
let instance: Rubocop;
Expand Down

0 comments on commit 7500a04

Please sign in to comment.