Skip to content

Commit

Permalink
Bitbucket normalizer (#168)
Browse files Browse the repository at this point in the history
Co-authored-by: Lars Hvam <larshp@hotmail.com>
  • Loading branch information
marcellourbani and larshp authored Nov 17, 2024
1 parent 2fa365a commit 8af6299
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 21 deletions.
35 changes: 19 additions & 16 deletions browser.webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@ const browserClientConfig = /** @type WebpackConfig */ {
extensions: ['.ts', '.js'], // support ts-files and js-files
alias: {},
fallback: {
"fs": false,
"path": require.resolve("path-browserify")
},
"fs": false,
"path": require.resolve("path-browserify"),
"crypto": require.resolve("crypto-browserify"),
"vm": require.resolve("vm-browserify")
}
},
plugins: [
new ProvidePlugin({
Buffer: [require.resolve("buffer/"), "Buffer"],
}),
],
plugins: [
new ProvidePlugin({
Buffer: [require.resolve("buffer/"), "Buffer"],
}),
],
module: {
rules: [
{
Expand Down Expand Up @@ -71,16 +73,17 @@ const browserServerConfig = /** @type WebpackConfig */ {
mainFields: ['module', 'main'],
extensions: ['.ts', '.js'], // support ts-files and js-files
alias: {
glob: false,
},
glob: false,
},
fallback: {
"path": require.resolve("path-browserify"),
"crypto": require.resolve("crypto-browserify"),
util: false,
fs: false,
child_process: false,
os: false,
assert: false
"crypto": require.resolve("crypto-browserify"),
"vm": require.resolve("vm-browserify"),
util: false,
fs: false,
child_process: false,
os: false,
assert: false
},
},
module: {
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
"@types/vscode": "^1.91.0",
"buffer": "^6.0.3"
}
}
}
14 changes: 10 additions & 4 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import {Help} from "./help";
import {Config} from "./config";
import {Flows} from "./flows";
import {TestController} from "./test_controller";
import {registerBitbucket} from "./integrations";
import {registerNormalizer} from "./normalize";

let client: BaseLanguageClient;
let myStatusBarItem: vscode.StatusBarItem;
let highlight: Highlight;
let help: Help;
let flows: Flows;
let config: Config;
let disposeAll:()=>void|undefined;

function registerAsFsProvider(client: BaseLanguageClient) {
const toUri = (path: string) => Uri.file(path);
Expand Down Expand Up @@ -43,6 +46,7 @@ function registerAsFsProvider(client: BaseLanguageClient) {
}

export function activate(context: ExtensionContext) {
disposeAll = () => context.subscriptions.forEach(async d => d.dispose());
myStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
myStatusBarItem.text = "abaplint";
myStatusBarItem.show();
Expand Down Expand Up @@ -122,14 +126,16 @@ export function activate(context: ExtensionContext) {
highlight.highlightWritesResponse(data.ranges, data.uri);
});
});

// removed, TODO: what was this used for?
// context.subscriptions.push(await client.start());
registerNormalizer(context, client);
registerBitbucket(client);
}

export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
const stop = client.stop().then(() => client.dispose());
if (disposeAll) {disposeAll();}
return stop;
}

83 changes: 83 additions & 0 deletions client/src/integrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {extensions, Uri, workspace} from "vscode";
import {BaseLanguageClient} from "vscode-languageclient";

export const ATLASCODEDIFF = "atlascode.bbpr";
export interface CodeNormalizer {
isRelevant: (u: Uri) => boolean;
normalize: (code: string, uri: Uri) => Promise<string>;
}

export let integrationIsActive:(u:Uri) => boolean = () => false;
interface BitBucketApi {
registerCodeNormalizer:(n:CodeNormalizer)=>Disposable;
}

const shouldNormalize = (u:Uri) => {
try {
const o = JSON.parse(u.query);
return !! o.normalized;
} catch (error) {
return false;
}
};

const extractname = (u:Uri) => {
if (u.scheme !== ATLASCODEDIFF) {return u.path;}
try {
const details = JSON.parse(u.query);
if (details.path && typeof details.path === "string") {
return details.path;
}
} catch (error) {
return u.fragment;
}
};
const normalizations = ["On by default", "Off by default", "deactivated"] as const;
type Normalization<I extends number> = (typeof normalizations[I]);
const getNormalization = <I extends number>(): Normalization<I> => {
const n = workspace.getConfiguration("abaplint").get("codeNormalization") as any;
if (normalizations.includes(n)) {return n;}
return "Off by default";
};
const isAbap = (u:Uri) => !!(u.fsPath.match(/\.abap$/) || u.fragment.match(/\.abap$/));
export const getAbapCodeNormalizer = (client: BaseLanguageClient):CodeNormalizer => {
const normalization = getNormalization();
const inverted = normalization === "On by default";
const inactive = normalization === "deactivated";
return {
isRelevant:(u) => !inactive && isAbap(u),
normalize:async (source, uri) => {
if (inactive || !isAbap(uri) || (inverted === shouldNormalize(uri))) {
return source;
}
const path = extractname(uri);
try {
const formatted:string = await client.sendRequest("abaplint/normalize", {path, source});
return formatted;
} catch (error) {
return source;
}
},
};
};

// registers a code formatter for bitbucket using an API which will probably never be merged
// for now it's available on my fork of atlascode:
// https://bitbucket.org/marcellourbani/atlascode/branch/issue-%235433-Add-hook-to-pretty-print-code-to-show-in-diff-in-atlascode
// allows to:
// - normalize the code by default
// - get bitbucket functionality (i.e. comments) to work after normalizing
export const registerBitbucket = async (client: BaseLanguageClient) => {
const ext = extensions.getExtension<BitBucketApi>("atlassian.atlascode");
if (!ext) {
return;
}
if (!ext.isActive) {
await ext.activate();
}
if (ext.exports?.registerCodeNormalizer) {
const norm = getAbapCodeNormalizer(client);
integrationIsActive = (u) => u.scheme === ATLASCODEDIFF && norm.isRelevant(u);
ext.exports.registerCodeNormalizer(norm);
}
};
58 changes: 58 additions & 0 deletions client/src/normalize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {commands, ExtensionContext, TabInputTextDiff, TextEditor, Uri, window, TextDocumentContentProvider, Event, workspace} from "vscode";
import {BaseLanguageClient} from "vscode-languageclient";
import {ATLASCODEDIFF, CodeNormalizer, getAbapCodeNormalizer, integrationIsActive} from "./integrations";
const ABAPGITSCHEME = "abapgit.normalized";

const originalUri = (u:Uri) => {
if (u.scheme !== ABAPGITSCHEME) {return u;}
const {scheme, query} = JSON.parse(u.query);
return u.with({scheme, query});
};

class NormalizedProvider implements TextDocumentContentProvider {
private readonly normalizer: CodeNormalizer;
public constructor(client: BaseLanguageClient) {
this.normalizer = getAbapCodeNormalizer(client);
};
public onDidChange?: Event<Uri> | undefined;
public async provideTextDocumentContent(uri: Uri): Promise<string> {
const origUri = originalUri(uri);
if (uri.scheme === origUri.scheme) {throw new Error("invalid URL"); };
const raw = await workspace.openTextDocument(origUri);
return this.normalizer.normalize(raw.getText(), origUri);
}
}

const shouldActivate = (e: TextEditor | undefined) => {
const curtab = window.tabGroups.activeTabGroup;
const uri = e?.document.uri;
const isdiff = curtab.activeTab?.input instanceof TabInputTextDiff;
if (!(isdiff && uri)) {return false;}
const relevant =
uri.path.match(/\.abap$/) ||
uri.scheme === ATLASCODEDIFF && uri.fragment.match(/\.abap$/);
return relevant && !integrationIsActive(uri);
};

const activateNormalizer = (e: TextEditor | undefined) => {
commands.executeCommand("setContext", "abaplint.IsNormalizerEnabled", shouldActivate(e));
};
const toggleUrlNormalizer = (u:Uri) => {
if (u.scheme === ABAPGITSCHEME) { return originalUri(u);};
const query = JSON.stringify({scheme:u.scheme, query:u.query});
return u.with({scheme:ABAPGITSCHEME, query});
};

const toggleNormalizer = () => {
const curtab = window.tabGroups.activeTabGroup.activeTab;
if (!(curtab?.input instanceof TabInputTextDiff)) {return;}
const {original, modified} = curtab.input;
return commands.executeCommand<void>("vscode.diff", toggleUrlNormalizer(original), toggleUrlNormalizer(modified), curtab.label);
};

export const registerNormalizer = (context:ExtensionContext, client: BaseLanguageClient) => {
const onchg = window.onDidChangeActiveTextEditor(activateNormalizer);
const normalize = commands.registerCommand("abaplint.togglediffNormalize", toggleNormalizer);
const provider = workspace.registerTextDocumentContentProvider(ABAPGITSCHEME, new NormalizedProvider(client));
context.subscriptions.push(onchg, normalize, provider);
};
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@
"command": "abaplint.create.default-config",
"title": "Create Default Config",
"category": "abaplint"
},
{
"command": "abaplint.togglediffNormalize",
"title": "Normalize files",
"icon": "$(law)",
"category": "abaplint"
}
],
"jsonValidation": [
Expand Down Expand Up @@ -117,6 +123,11 @@
"when": "editorLangId == 'abap'",
"command": "abaplint.show",
"group": "navigation"
},
{
"command": "abaplint.togglediffNormalize",
"group": "navigation",
"when": "isInDiffEditor && abaplint.IsNormalizerEnabled"
}
],
"file/newFile": [
Expand Down Expand Up @@ -231,6 +242,22 @@
"description": "List of rules that should not be triggered on formatting"
}
}
},
{
"order": 50,
"id": "codenormalization",
"title": "Diff code normalization for bitbucket",
"properties": {
"abaplint.codeNormalization": {
"type": "string",
"enum": [
"On by default",
"Off by default",
"deactivated"
],
"default": "Off by default"
}
}
}
]
},
Expand Down Expand Up @@ -271,6 +298,7 @@
"path-browserify": "^1.0.1",
"ts-loader": "^9.5.1",
"typescript": "^5.6.3",
"vm-browserify": "^1.1.2",
"webpack": "^5.96.1",
"webpack-cli": "^5.1.4"
}
Expand Down
Loading

0 comments on commit 8af6299

Please sign in to comment.