aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMats Larsen <me@supergrecko.com>2022-05-31 03:30:04 +0200
committerMats Larsen <me@supergrecko.com>2022-05-31 03:30:04 +0200
commit2f0c1453951db63e003c6a44c7e0031de16166e4 (patch)
tree7728e071bdfdc680ca8a1235e597730201a717a3
parentea92e0c4d53ae468e4b4779508925fccc6897c97 (diff)
downloadcompiler-explorer-gh-3180.tar.gz
compiler-explorer-gh-3180.zip
Move "View Assembly Documentation" action out of compiler.jsgh-3182gh-3180
-rw-r--r--static/compiler-service.js3
-rw-r--r--static/extensions/view-assembly-documentation.ts133
-rw-r--r--static/panes/compiler.js147
-rw-r--r--types/features/assembly-documentation.interfaces.ts4
4 files changed, 158 insertions, 129 deletions
diff --git a/static/compiler-service.js b/static/compiler-service.js
index 02089123b..91de2de34 100644
--- a/static/compiler-service.js
+++ b/static/compiler-service.js
@@ -35,9 +35,6 @@ function CompilerService(eventHub) {
this.allowStoreCodeDebug = true;
this.cache = new LruCache({
max: 200 * 1024,
- length: function (n) {
- return JSON.stringify(n).length;
- },
});
this.compilersByLang = {};
_.each(
diff --git a/static/extensions/view-assembly-documentation.ts b/static/extensions/view-assembly-documentation.ts
new file mode 100644
index 000000000..def21cef0
--- /dev/null
+++ b/static/extensions/view-assembly-documentation.ts
@@ -0,0 +1,133 @@
+import * as monaco from 'monaco-editor';
+import {ga} from '../analytics';
+import LRUCache from 'lru-cache';
+import {getAssemblyDocumentation} from '../api/api';
+import {AssemblyInstructionInfo} from '../../lib/asm-docs/base';
+import {InstructionSet} from '../../types/features/assembly-documentation.interfaces';
+import {Alert} from '../alert';
+
+type OpcodeCacheEntry =
+ | {
+ found: true;
+ body: AssemblyInstructionInfo;
+ }
+ | {
+ found: false;
+ error: string;
+ };
+
+const VIEW_ASSEMBLY_DOCUMENTATION_ID = 'viewasmdoc';
+const ASSEMBLY_OPCODE_CACHE = new LRUCache<string, OpcodeCacheEntry>({
+ max: 64 * 1024,
+});
+
+/**
+ * Add an extension to the monaco editor which allows to view the assembly documentation for the instruction the
+ * cursor is currently on.
+ */
+export const createViewAssemblyDocumentationAction = (
+ editor: monaco.editor.IStandaloneCodeEditor,
+ instructionSet: InstructionSet
+) => {
+ editor.addAction({
+ id: VIEW_ASSEMBLY_DOCUMENTATION_ID,
+ label: 'View assembly documentation',
+ keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.F8],
+ precondition: 'isAsmKeyword',
+ contextMenuGroupId: 'help',
+ contextMenuOrder: 1.5,
+ run: onAssemblyAction(editor, instructionSet),
+ });
+};
+
+const onAssemblyAction = (editor: monaco.editor.IStandaloneCodeEditor, instructionSet: InstructionSet) => async () => {
+ ga.proxy('send', {
+ hitType: 'event',
+ eventCategory: 'OpenModalPane',
+ eventAction: 'AsmDocs',
+ });
+
+ const position = editor.getPosition();
+ const model = editor.getModel();
+ if (position === null || model === null) return;
+
+ const word = model.getWordAtPosition(position);
+ if (word === null || word.word === '') return;
+
+ const opcode = word.word.toUpperCase();
+ const alertSystem = new Alert();
+
+ try {
+ const response = await getAssemblyInfo(opcode, instructionSet);
+ if (response.found) {
+ alertSystem.alert(
+ opcode + ' help',
+ response.body.html + createDisplayableHtml(response.body.url, opcode),
+ () => {
+ editor.focus();
+ editor.setPosition(position);
+ }
+ );
+ } else {
+ alertSystem.notify('This token was not found in the documentation. Sorry!', {
+ group: 'notokenindocs',
+ alertClass: 'notification-error',
+ dismissTime: 5000,
+ });
+ }
+ } catch (error) {
+ alertSystem.notify('There was a network error fetching the documentation for this opcode (' + error + ').', {
+ group: 'notokenindocs',
+ alertClass: 'notification-error',
+ dismissTime: 5000,
+ });
+ }
+};
+
+export const getAssemblyInfo = async (opcode: string, instructionSet: InstructionSet): Promise<OpcodeCacheEntry> => {
+ const entryName = `asm/${instructionSet}/${opcode}`;
+
+ if (ASSEMBLY_OPCODE_CACHE.has(entryName)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- logically sound
+ return ASSEMBLY_OPCODE_CACHE.get(entryName)!;
+ }
+
+ try {
+ const response = await getAssemblyDocumentation({opcode, instructionSet});
+ const json = await response.json();
+ if (response.status === 200) {
+ ASSEMBLY_OPCODE_CACHE.set(entryName, {found: true, body: json});
+ } else {
+ // TODO(supergrecko): make prettier with XOR type
+ const jsonWithError = json as unknown as {error: string};
+ ASSEMBLY_OPCODE_CACHE.set(entryName, {found: false, error: jsonWithError.error});
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- logically sound
+ return ASSEMBLY_OPCODE_CACHE.get(entryName)!;
+ } catch (error) {
+ throw new Error('Fetch Assembly Documentation failed: ' + error);
+ }
+};
+
+const createDisplayableHtml = (url: string, opcode: string) => {
+ const title = encodeURI(`[BUG] Problem with ${opcode} opcode documentation`);
+ const github = `https://github.com/compiler-explorer/compiler-explorer/issues/new?title=${title}`;
+ return `
+<br><br>
+For more information, visit
+<a href='${url}' target='_blank' rel='noopener noreferrer'>the ${opcode} documentation
+ <sup>
+ <small class='fas fa-external-link-alt opens-new-window' title='Opens in a new window'>
+ </small>
+ </sup>
+<a/>.
+If the documentation for this opcode is wrong or broken in some way, please feel free to
+<a href="${github}">
+ open an issue on GitHub
+ <sup>
+ <small class='fas fa-external-link-alt opens-new-window' title='Opens in a new window'>
+ </small>
+ </sup>
+</a>`;
+};
diff --git a/static/panes/compiler.js b/static/panes/compiler.js
index f36a5bf8d..166d3597d 100644
--- a/static/panes/compiler.js
+++ b/static/panes/compiler.js
@@ -31,7 +31,7 @@ var Toggles = require('../widgets/toggles').Toggles;
var FontScale = require('../widgets/fontscale').FontScale;
var Promise = require('es6-promise').Promise;
var Components = require('../components');
-var LruCache = require('lru-cache');
+require('lru-cache');
var options = require('../options').options;
var monaco = require('monaco-editor');
var Alert = require('../alert').Alert;
@@ -44,16 +44,12 @@ var CompilerPicker = require('../compiler-picker').CompilerPicker;
var Settings = require('../settings').Settings;
var utils = require('../utils');
var LibUtils = require('../lib-utils');
-var getAssemblyDocumentation = require('../api/api').getAssemblyDocumentation;
+// eslint-disable-next-line max-len
+var createViewAssemblyDocumentationAction =
+ require('../extensions/view-assembly-documentation').createViewAssemblyDocumentationAction;
+var getAssemblyInfo = require('../extensions/view-assembly-documentation').getAssemblyInfo;
var PaneRenaming = require('../widgets/pane-renaming').PaneRenaming;
-var OpcodeCache = new LruCache({
- max: 64 * 1024,
- length: function (n) {
- return JSON.stringify(n).length;
- },
-});
-
function patchOldFilters(filters) {
if (filters === undefined) return undefined;
// Filters are of the form {filter: true|false¸ ...}. In older versions, we used
@@ -808,16 +804,7 @@ Compiler.prototype.initEditorActions = function () {
}, this),
});
- this.outputEditor.addAction({
- id: 'viewasmdoc',
- label: 'View assembly documentation',
- keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.F8],
- keybindingContext: null,
- precondition: 'isAsmKeyword',
- contextMenuGroupId: 'help',
- contextMenuOrder: 1.5,
- run: _.bind(this.onAsmToolTip, this),
- });
+ createViewAssemblyDocumentationAction(this.outputEditor, this.compiler.instructionSet || 'amd64');
this.outputEditor.addAction({
id: 'toggleColourisation',
@@ -981,38 +968,39 @@ Compiler.prototype.compileFromTree = function (options, bypassCache) {
files: tree.multifileService.getFiles(),
};
- const fetches = [];
+ var fetches = [];
fetches.push(
- this.compilerService.expand(request.source).then(contents => {
+ this.compilerService.expand(request.source).then(function (contents) {
request.source = contents;
})
);
- for (let file of request.files) {
+ for (var i = 0; i < request.files.length; i++) {
fetches.push(
- this.compilerService.expand(file.contents).then(contents => {
- file.contents = contents;
+ this.compilerService.expand(request.files[i].contents).then(function (contents) {
+ request.files[i].contents = contents;
})
);
}
- Promise.all(fetches).then(() => {
+ var self = this;
+ Promise.all(fetches).then(function () {
var treeState = tree.currentState();
var cmakeProject = tree.multifileService.isACMakeProject();
if (bypassCache) request.bypassCache = true;
- if (!this.compiler) {
- this.onCompileResponse(request, errorResult('<Please select a compiler>'), false);
+ if (!self.compiler) {
+ self.onCompileResponse(request, errorResult('<Please select a compiler>'), false);
} else if (cmakeProject && request.source === '') {
- this.onCompileResponse(request, errorResult('<Please supply a CMakeLists.txt>'), false);
+ self.onCompileResponse(request, errorResult('<Please supply a CMakeLists.txt>'), false);
} else {
if (cmakeProject) {
request.options.compilerOptions.cmakeArgs = treeState.cmakeArgs;
request.options.compilerOptions.customOutputFilename = treeState.customOutputFilename;
- this.sendCMakeCompile(request);
+ self.sendCMakeCompile(request);
} else {
- this.sendCompile(request);
+ self.sendCompile(request);
}
}
});
@@ -2385,8 +2373,9 @@ function htmlEncode(rawStr) {
Compiler.prototype.checkForHints = function (result) {
if (result.hints) {
- result.hints.forEach(hint => {
- this.alertSystem.notify(htmlEncode(hint), {
+ var self = this;
+ result.hints.forEach(function (hint) {
+ self.alertSystem.notify(htmlEncode(hint), {
group: 'hints',
collapseSimilar: false,
});
@@ -2815,34 +2804,6 @@ function getNumericToolTip(value) {
return result;
}
-function getAsmInfo(opcode, instructionSet) {
- var cacheName = 'asm/' + (instructionSet ? instructionSet + '/' : '') + opcode;
- var cached = OpcodeCache.get(cacheName);
- if (cached) {
- if (cached.found) {
- return Promise.resolve(cached.data);
- }
- return Promise.reject(cached.data);
- }
- return new Promise(function (resolve, reject) {
- getAssemblyDocumentation({opcode: opcode, instructionSet: instructionSet})
- .then(function (response) {
- response.json().then(function (body) {
- if (response.status === 200) {
- OpcodeCache.set(cacheName, {found: true, data: body});
- resolve(body);
- } else {
- OpcodeCache.set(cacheName, {found: false, data: body.error});
- reject(body.error);
- }
- });
- })
- .catch(function (error) {
- reject('Fetch error: ' + error);
- });
- });
-}
-
Compiler.prototype.onDidChangeCursorSelection = function (e) {
if (this.awaitingInitialResults) {
this.selection = e.selection;
@@ -2933,7 +2894,7 @@ Compiler.prototype.onMouseMove = function (e) {
}
var hoverShowAsmDoc = this.settings.hoverShowAsmDoc === true;
if (hoverShowAsmDoc && this.compiler && this.compiler.supportsAsmDocs && this.isWordAsmKeyword(currentWord)) {
- getAsmInfo(currentWord.word, this.compiler.instructionSet).then(
+ getAssemblyInfo(currentWord.word.toUpperCase(), this.compiler.instructionSet).then(
_.bind(function (response) {
if (!response) return;
this.decorations.asmToolTip = {
@@ -2969,70 +2930,6 @@ Compiler.prototype.isWordAsmKeyword = function (word) {
});
};
-Compiler.prototype.onAsmToolTip = function (ed) {
- ga.proxy('send', {
- hitType: 'event',
- eventCategory: 'OpenModalPane',
- eventAction: 'AsmDocs',
- });
- var pos = ed.getPosition();
- if (!pos || !ed.getModel()) return;
- var word = ed.getModel().getWordAtPosition(pos);
- if (!word || !word.word) return;
- var opcode = word.word.toUpperCase();
-
- function newGitHubIssueUrl() {
- return (
- 'https://github.com/compiler-explorer/compiler-explorer/issues/new?title=' +
- encodeURIComponent('[BUG] Problem with ' + opcode + ' opcode')
- );
- }
-
- function appendInfo(url) {
- return (
- '<br><br>For more information, visit <a href="' +
- url +
- '" target="_blank" rel="noopener noreferrer">the ' +
- opcode +
- ' documentation <sup><small class="fas fa-external-link-alt opens-new-window"' +
- ' title="Opens in a new window"></small></sup></a>.' +
- '<br>If the documentation for this opcode is wrong or broken in some way, ' +
- 'please feel free to <a href="' +
- newGitHubIssueUrl() +
- '" target="_blank" rel="noopener noreferrer">' +
- 'open an issue on GitHub <sup><small class="fas fa-external-link-alt opens-new-window" ' +
- 'title="Opens in a new window"></small></sup></a>.'
- );
- }
-
- getAsmInfo(word.word, this.compiler.instructionSet).then(
- _.bind(function (asmHelp) {
- if (asmHelp) {
- this.alertSystem.alert(opcode + ' help', asmHelp.html + appendInfo(asmHelp.url), function () {
- ed.focus();
- ed.setPosition(pos);
- });
- } else {
- this.alertSystem.notify('This token was not found in the documentation. Sorry!', {
- group: 'notokenindocs',
- alertClass: 'notification-error',
- dismissTime: 5000,
- });
- }
- }, this),
- _.bind(function (rejection) {
- this.alertSystem.notify(
- 'There was an error fetching the documentation for this opcode (' + rejection + ').',
- {
- group: 'notokenindocs',
- alertClass: 'notification-error',
- dismissTime: 5000,
- }
- );
- }, this)
- );
-};
-
Compiler.prototype.handleCompilationStatus = function (status) {
this.compilerService.handleCompilationStatus(this.statusLabel, this.statusIcon, status);
};
diff --git a/types/features/assembly-documentation.interfaces.ts b/types/features/assembly-documentation.interfaces.ts
index 4d0359623..4ccde2830 100644
--- a/types/features/assembly-documentation.interfaces.ts
+++ b/types/features/assembly-documentation.interfaces.ts
@@ -24,9 +24,11 @@
import {AssemblyInstructionInfo} from '../../lib/asm-docs/base';
+export type InstructionSet = 'amd64' | 'arm32' | 'avr' | 'java' | 'llvm' | 'mos6502';
+
export interface AssemblyDocumentationRequest {
/** Specifies which instruction set to look for */
- instructionSet: 'amd64' | 'arm32' | 'java';
+ instructionSet: InstructionSet;
/** Instruction set opcode to look for */
opcode: string;
}