mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 10:33:59 -05:00
Refactor handling of Assembly Documentation Providers (#3247)
This commit is contained in:
@@ -7,5 +7,5 @@ out
|
||||
views
|
||||
|
||||
# Autogenerated files
|
||||
lib/handlers/asm-docs-*.js
|
||||
lib/asm-docs/generated/asm-docs-*.js
|
||||
etc/scripts/vendor/jvms.html
|
||||
|
||||
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -1,7 +1,7 @@
|
||||
docs/* linguist-documentation
|
||||
*.s linguist-generated
|
||||
*.asm linguist-generated
|
||||
lib/handlers/asm-docs-amd64.js linguist-generated
|
||||
lib/handlers/asm-docs-arm32.js linguist-generated
|
||||
lib/handlers/asm-docs-java.js linguist-generated
|
||||
lib/asm-docs/generated/asm-docs-amd64.js linguist-generated
|
||||
lib/asm-docs/generated/asm-docs-arm32.js linguist-generated
|
||||
lib/asm-docs/generated/asm-docs-java.js linguist-generated
|
||||
test/*-cases/* linguist-generated
|
||||
|
||||
1
.idea/codeStyles/Project.xml
generated
1
.idea/codeStyles/Project.xml
generated
@@ -26,6 +26,7 @@
|
||||
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
<option name="SPACES_WITHIN_OBJECT_TYPE_BRACES" value="false" />
|
||||
</TypeScriptCodeStyleSettings>
|
||||
<VueCodeStyleSettings>
|
||||
|
||||
@@ -3,7 +3,7 @@ include:
|
||||
- lib/**/*.js
|
||||
- lib/**/*.ts
|
||||
exclude:
|
||||
- lib/handlers/asm-docs-*.js
|
||||
- lib/asm-docs/generated/asm-docs-*.js
|
||||
- lib/compilers/fake-for-test.js
|
||||
report-dir: ./out/coverage
|
||||
reporter:
|
||||
|
||||
@@ -40,7 +40,7 @@ out
|
||||
views
|
||||
|
||||
# Autogenerated files
|
||||
lib/handlers/asm-docs-*.js
|
||||
lib/asm-docs/generated/asm-docs-*.js
|
||||
|
||||
|
||||
#########################
|
||||
|
||||
@@ -12,26 +12,26 @@ To add a new assembly documentation handler, you need to perform the following s
|
||||
|
||||
## 1. Find a data source
|
||||
|
||||
First of all you need to find a data source to get our instruction info from. While it is possible to write down
|
||||
information about every single instruction for an instruction set, it's far from maintainable and it is a lot of work.
|
||||
First you need to find a data source to get our instruction info from. While it is possible to write down
|
||||
information about every single instruction for an instruction set, it's far from maintainable, and it is a lot of work.
|
||||
|
||||
Existing assembly documentation handlers use some sort of established documentation. The arm32 handler uses the
|
||||
developer.arm.com website and the JVM bytecode handler uses Oracle's documentation.
|
||||
|
||||
## 2. Create a tool for collecting the data
|
||||
|
||||
Since we want to go through the automated route, you should write a script or a piece of code to automatically gather the
|
||||
data for us and store it in a nice format that CE expects. The output of the script should be a generated .js file
|
||||
Since we want to go through the automated route, you should write a script or a piece of code to automatically gather
|
||||
the data for us and store it in a nice format that CE expects. The output of the script should be a generated .js file
|
||||
with a single exported function containing a gigantic switch for the instruction opcode. Examples of this generated file
|
||||
can be found in `/lib/handlers/asm-docs-amd64.js`.
|
||||
can be found in `/lib/asm-docs/generated/asm-docs-amd64.js`.
|
||||
|
||||
How you generate this file is completely up to you, just make sure it's easy for others to run the script if needed as
|
||||
well. If you need inspiration on how to write this tool, you can look at the `docenizer-*` scripts found in
|
||||
`/etc/scripts` in the source control tree.
|
||||
|
||||
CE expects the tool to output the file into the `/lib/handlers/` folder with a name following the existing convention.
|
||||
Each case in the switch should return a piece of formatted HTML to insert into the popup, a tooltip text for the
|
||||
on-hover tooltip and a URL to external documentation.
|
||||
CE expects the tool to output the file into the `/lib/asm-docs/generated/` folder with a name following the existing
|
||||
convention. Each case in the switch should return a piece of formatted HTML to insert into the popup, a tooltip text
|
||||
for the on-hover tooltip and a URL to external documentation.
|
||||
|
||||
```js
|
||||
case "CALL":
|
||||
@@ -45,37 +45,32 @@ case "CALL":
|
||||
## 3. Connect your tool output to CE
|
||||
|
||||
Once your tool has generated the JavaScript file, you want to connect it to CE. This is done by editing the files found
|
||||
in `/lib/handlers/assembly-documentation`. You'll want to add a new file named after your instruction set which contains
|
||||
a class extending `BaseAssemblyDocumentationHandler`. The class should implement the `getInstructionInformation` method.
|
||||
in the `/lib/asm-docs` directory which is adjacent to your newly generated JavaScript file.
|
||||
|
||||
First you want to add a new file named after your instruction set which exports a class extending the
|
||||
`BaseAssemblyDocumentationProvider` class. The class should implement the `getInstructionInformation` method which
|
||||
in most cases, delegates to your generated JavaScript. Instruction sets like Arm32 have use code to tweak the output
|
||||
if needed.
|
||||
|
||||
This method is expected to take the instruction opcode in full uppercase and either return the associated data or null
|
||||
if not found.
|
||||
|
||||
```js
|
||||
import { getAsmOpcode } from '../asm-docs-java';
|
||||
import { BaseAssemblyDocumentationHandler } from '../base-assembly-documentation-handler';
|
||||
```ts
|
||||
import { getAsmOpcode } from './generated//asm-docs-java';
|
||||
import { BaseAssemblyDocumentationProvider } from './base';
|
||||
|
||||
export class JavaDocumentationHandler extends BaseAssemblyDocumentationHandler {
|
||||
getInstructionInformation(instruction) {
|
||||
export class JavaDocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
// Return the instruction set name
|
||||
public static get key() { return 'java'; }
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The last thing to do is to associate your instruction set in the CE API with this handler. This is done by modifying the
|
||||
`/lib/handlers/assembly-documentation/router.js` file. Simply add your instruction set name and associate it with a
|
||||
new instance of your class in the mapping object.
|
||||
|
||||
```js
|
||||
const ASSEMBLY_DOCUMENTATION_HANDLERS = {
|
||||
amd64: new Amd64DocumentationHandler(),
|
||||
arm32: new Arm32DocumentationHandler(),
|
||||
java: new JavaDocumentationHandler(),
|
||||
};
|
||||
```
|
||||
|
||||
Finally we want to tell CE that the new documentation provider exists. This is done by re-exporting the class inside
|
||||
`/lib/asm-docs/_all.ts`. Please keep the exports here in alphabetic order.
|
||||
## 4. Testing
|
||||
|
||||
You can ensure your API handler is working as expected by writing a test case for it in the
|
||||
`/test/handlers/assembly-documentation` directory. Simply copy over one of the existing files and modify it to work
|
||||
with the new slug you created in the step above.
|
||||
Testing new assembly documentation providers is really easy. It is just a matter of modifying the `TEST_MATRIX` variable
|
||||
found in the `/test/handlers/asm-docs-tests.js` file.
|
||||
|
||||
29
lib/asm-docs/_all.ts
Normal file
29
lib/asm-docs/_all.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
export { Amd64DocumentationProvider } from './amd64';
|
||||
export { Arm32DocumentationProvider } from './arm32';
|
||||
export { AvrDocumentationProvider } from './avr';
|
||||
export { JavaDocumentationProvider } from './java';
|
||||
export { Mos6502DocumentationProvider } from './mos6502';
|
||||
@@ -22,17 +22,17 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { getAsmOpcode } from '../asm-docs-amd64';
|
||||
import { BaseAssemblyDocumentationHandler } from '../base-assembly-documentation-handler';
|
||||
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base';
|
||||
import { getAsmOpcode } from './generated/asm-docs-amd64';
|
||||
|
||||
const ATT_SUFFIX_REMOVER = /^([a-z]+)[blqw]$/i;
|
||||
|
||||
export class Amd64DocumentationHandler extends BaseAssemblyDocumentationHandler {
|
||||
getInstructionInformation(instruction) {
|
||||
// Try both default and with AT&T suffix removed
|
||||
export class Amd64DocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
private static readonly ATT_SUFFIX_REMOVER = /^([a-z]+)[blqw]$/i;
|
||||
public static get key() { return 'amd64'; }
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
// Try both raw opcode and with AT&T suffix removed
|
||||
let info = getAsmOpcode(instruction);
|
||||
if (!info) {
|
||||
const alternativeInstruction = ATT_SUFFIX_REMOVER.exec(instruction);
|
||||
const alternativeInstruction = Amd64DocumentationProvider.ATT_SUFFIX_REMOVER.exec(instruction);
|
||||
if (alternativeInstruction) {
|
||||
info = getAsmOpcode(alternativeInstruction[1]);
|
||||
}
|
||||
68
lib/asm-docs/arm32.ts
Normal file
68
lib/asm-docs/arm32.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base';
|
||||
import { getAsmOpcode } from './generated/asm-docs-arm32';
|
||||
|
||||
export class Arm32DocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
private static readonly CONDITIONAL_INSTRUCTION_REGEXP = /^([A-Za-z]+?)(EQ|NE|CS|CC|MI|PL|VS|VC|HI|LS|GE|LT|GT|LE|AL)$/;
|
||||
public static get key() { return 'arm32'; }
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
const info = getAsmOpcode(instruction) || Arm32DocumentationProvider.getConditionalOpcode(instruction);
|
||||
return info || null;
|
||||
}
|
||||
|
||||
private static readonly CONDITIONAL_OPCODE_TAGS: Record<string, string> = {
|
||||
EQ: 'If equal, ',
|
||||
NE: 'If not equal, ',
|
||||
CS: 'If carry set, ',
|
||||
CC: 'If carry clear, ',
|
||||
MI: 'If negative, ',
|
||||
PL: 'If positive or zero, ',
|
||||
VS: 'If overflow, ',
|
||||
VC: 'If no overflow, ',
|
||||
HI: 'If unsigned higher, ',
|
||||
LS: 'If unsigned lower or same, ',
|
||||
GE: 'If signed greater than or equal, ',
|
||||
LT: 'If signed less than, ',
|
||||
GT: 'If signed greater than, ',
|
||||
LE: 'If signed less than or equal, ',
|
||||
};
|
||||
|
||||
/** Add additional notes for conditional instructions */
|
||||
private static getConditionalOpcode(instruction: string): AssemblyInstructionInfo | null {
|
||||
// If the instruction is a conditional instruction
|
||||
const isConditionalOpcode = instruction.match(Arm32DocumentationProvider.CONDITIONAL_INSTRUCTION_REGEXP);
|
||||
if (!isConditionalOpcode) {
|
||||
return null;
|
||||
}
|
||||
const information = getAsmOpcode(isConditionalOpcode[1]);
|
||||
const text = Arm32DocumentationProvider.CONDITIONAL_OPCODE_TAGS[isConditionalOpcode[2]] || '';
|
||||
return {
|
||||
...information,
|
||||
tooltip: text + information.tooltip,
|
||||
html: text + information.html,
|
||||
};
|
||||
}
|
||||
}
|
||||
33
lib/asm-docs/avr.ts
Normal file
33
lib/asm-docs/avr.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base';
|
||||
import { getAsmOpcode } from './generated/asm-docs-avr';
|
||||
|
||||
export class AvrDocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
public static get key() { return 'avr'; }
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
@@ -22,38 +22,22 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { propsFor } from '../../properties';
|
||||
|
||||
import { Amd64DocumentationHandler } from './amd64';
|
||||
import { Arm32DocumentationHandler } from './arm32';
|
||||
import { AVRDocumentationHandler } from './avr';
|
||||
import { JavaDocumentationHandler } from './java';
|
||||
import { Mos6502DocumentationHandler } from './mos6502';
|
||||
|
||||
/** @type {Record.<string, BaseAssemblyDocumentationHandler>} */
|
||||
const ASSEMBLY_DOCUMENTATION_HANDLERS = {
|
||||
amd64: new Amd64DocumentationHandler(),
|
||||
arm32: new Arm32DocumentationHandler(),
|
||||
java: new JavaDocumentationHandler(),
|
||||
6502: new Mos6502DocumentationHandler(),
|
||||
avr: new AVRDocumentationHandler(),
|
||||
};
|
||||
|
||||
const MAX_STATIC_AGE = propsFor('asm-docs')('staticMaxAgeSecs', 10);
|
||||
export type AssemblyInstructionInfo = Record<'tooltip' | 'html' | 'url', string>;
|
||||
|
||||
/**
|
||||
* Initialize all Assembly Docs routes
|
||||
* Base class for all assembly documentation generators.
|
||||
*
|
||||
* @param {e.Router} router
|
||||
* Implementations of this class are responsible for providing documentation
|
||||
* about an instruction set's assembly instructions by instruction opcode.
|
||||
*
|
||||
* Each implementor should provide a static `get key()` method that returns
|
||||
* the name of the instruction set.
|
||||
*/
|
||||
export const setup = (router) => router.get('/asm/:arch/:opcode', (req, res) => {
|
||||
if (MAX_STATIC_AGE > 0) {
|
||||
res.setHeader('Cache-Control', `public, max-age=${MAX_STATIC_AGE}`);
|
||||
}
|
||||
const architecture = req.params.arch;
|
||||
const handler = ASSEMBLY_DOCUMENTATION_HANDLERS[architecture];
|
||||
if (handler !== undefined) {
|
||||
return handler.handle(req, res);
|
||||
}
|
||||
res.status(404).json({ error: `No documentation for '${architecture}'` }).send();
|
||||
});
|
||||
export abstract class BaseAssemblyDocumentationProvider {
|
||||
/**
|
||||
* Gather the assembly instruction information by the instruction name.
|
||||
*
|
||||
* Implementors should return null if the instruction is not supported.
|
||||
*/
|
||||
public abstract getInstructionInformation(instruction: string): AssemblyInstructionInfo | null;
|
||||
}
|
||||
@@ -22,11 +22,11 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { getAsmOpcode } from '../asm-docs-java';
|
||||
import { BaseAssemblyDocumentationHandler } from '../base-assembly-documentation-handler';
|
||||
import { makeKeyedTypeGetter } from '../keyed-type';
|
||||
|
||||
export class JavaDocumentationHandler extends BaseAssemblyDocumentationHandler {
|
||||
getInstructionInformation(instruction) {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
import * as all from './_all';
|
||||
|
||||
export { BaseAssemblyDocumentationProvider } from './base';
|
||||
export * from './_all';
|
||||
|
||||
export const getDocumentationProviderTypeByKey = makeKeyedTypeGetter('documentation provider', all);
|
||||
33
lib/asm-docs/java.ts
Normal file
33
lib/asm-docs/java.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base';
|
||||
import { getAsmOpcode } from './generated/asm-docs-java';
|
||||
|
||||
export class JavaDocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
public static get key() { return 'java'; }
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
33
lib/asm-docs/mos6502.ts
Normal file
33
lib/asm-docs/mos6502.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base';
|
||||
import { getAsmOpcode } from './generated/asm-docs-6502';
|
||||
|
||||
export class Mos6502DocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
public static get key() { return '6502'; }
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import { logger } from '../logger';
|
||||
import { getShortenerTypeByKey } from '../shortener';
|
||||
import * as utils from '../utils';
|
||||
|
||||
import * as assemblyDocumentation from './assembly-documentation/router';
|
||||
import { withAssemblyDocumentationProviders } from './assembly-documentation';
|
||||
import { FormattingHandler } from './formatting';
|
||||
|
||||
export class ApiHandler {
|
||||
@@ -61,7 +61,7 @@ export class ApiHandler {
|
||||
this.handle.get('/libraries', this.handleAllLibraries.bind(this));
|
||||
|
||||
// Binding for assembly documentation
|
||||
assemblyDocumentation.setup(this.handle);
|
||||
withAssemblyDocumentationProviders(this.handle);
|
||||
// Legacy binding for old clients.
|
||||
this.handle.get('/asm/:opcode',
|
||||
(req, res) => res.redirect(`amd64/${req.params.opcode}`),
|
||||
|
||||
69
lib/handlers/assembly-documentation.ts
Normal file
69
lib/handlers/assembly-documentation.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { BaseAssemblyDocumentationProvider, getDocumentationProviderTypeByKey } from '../asm-docs';
|
||||
import { propsFor } from '../properties';
|
||||
|
||||
const MAX_STATIC_AGE = propsFor('asm-docs')('staticMaxAgeSecs', 10);
|
||||
|
||||
const onDocumentationProviderRequest = (
|
||||
provider: BaseAssemblyDocumentationProvider,
|
||||
request: express.Request,
|
||||
response: express.Response,
|
||||
) => {
|
||||
// If the request had no opcode parameter, we should fail. This assumes
|
||||
// no assembly language has a __unknown_opcode instruction.
|
||||
const instruction = (request.params.opcode || '__UNKNOWN_OPCODE').toUpperCase();
|
||||
const information = provider.getInstructionInformation(instruction);
|
||||
if (information === null) {
|
||||
return response.status(404).send({ error: `Unknown opcode '${instruction}'` });
|
||||
}
|
||||
// Accept either JSON or Plaintext Content-Type
|
||||
const requestedContentType = request.accepts(['text', 'json']);
|
||||
switch (requestedContentType) {
|
||||
case 'text': response.send(information.html); break;
|
||||
case 'json': response.send(information); break;
|
||||
default: response.status(406).send({ error: 'Not Acceptable' }); break;
|
||||
}
|
||||
};
|
||||
|
||||
/** Initialize API routes for assembly documentation */
|
||||
export const withAssemblyDocumentationProviders = (
|
||||
router: express.Router,
|
||||
) => router.get('/asm/:arch/:opcode', (req, res) => {
|
||||
if (MAX_STATIC_AGE > 0) {
|
||||
res.setHeader('Cache-Control', `public, max-age=${MAX_STATIC_AGE}`);
|
||||
}
|
||||
const arch = req.params.arch;
|
||||
// makeKeyedTypeGetter throws if the key is not found. We do not wish
|
||||
// crash CE if this happens, so we catch the error and return a 404.
|
||||
try {
|
||||
const providerClass = getDocumentationProviderTypeByKey(arch);
|
||||
onDocumentationProviderRequest(new providerClass(), req, res);
|
||||
} catch {
|
||||
res.status(404).json({ error: `No documentation for '${arch}'` }).send();
|
||||
}
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { getAsmOpcode } from '../asm-docs-arm32';
|
||||
import { BaseAssemblyDocumentationHandler } from '../base-assembly-documentation-handler';
|
||||
|
||||
const CONDITIONAL_INSTRUCTION_REGEXP = /^([A-Za-z]+?)(EQ|NE|CS|CC|MI|PL|VS|VC|HI|LS|GE|LT|GT|LE|AL)$/;
|
||||
|
||||
export class Arm32DocumentationHandler extends BaseAssemblyDocumentationHandler {
|
||||
// Notes for conditionals:
|
||||
// https://developer.arm.com/documentation/dui0473/m/condition-codes/condition-code-suffixes-and-related-flags
|
||||
getOpcodeConditional(opcode) {
|
||||
if (!opcode) return;
|
||||
|
||||
const conditionals = {
|
||||
EQ: 'If equal, ',
|
||||
NE: 'If not equal, ',
|
||||
CS: 'If carry set, ',
|
||||
CC: 'If carry clear, ',
|
||||
MI: 'If negative, ',
|
||||
PL: 'If positive or zero, ',
|
||||
VS: 'If overflow, ',
|
||||
VC: 'If no overflow, ',
|
||||
HI: 'If unsigned higher, ',
|
||||
LS: 'If unsigned lower or same, ',
|
||||
GE: 'If signed greater than or equal, ',
|
||||
LT: 'If signed less than, ',
|
||||
GT: 'If signed greater than, ',
|
||||
LE: 'If signed less than or equal, ',
|
||||
};
|
||||
|
||||
const matches = opcode.match(CONDITIONAL_INSTRUCTION_REGEXP);
|
||||
if (matches) {
|
||||
const opcodeDescription = getAsmOpcode(matches[1]);
|
||||
if (!opcodeDescription) return;
|
||||
|
||||
const conditionalText = conditionals[matches[2]] || '';
|
||||
|
||||
opcodeDescription.tooltip = conditionalText + opcodeDescription.tooltip;
|
||||
opcodeDescription.html = conditionalText + opcodeDescription.html;
|
||||
|
||||
return opcodeDescription;
|
||||
}
|
||||
}
|
||||
|
||||
getInstructionInformation(instruction) {
|
||||
const info = getAsmOpcode(instruction) || this.getOpcodeConditional(instruction);
|
||||
return info || null;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { getAsmOpcode } from '../asm-docs-avr';
|
||||
import { BaseAssemblyDocumentationHandler } from '../base-assembly-documentation-handler';
|
||||
|
||||
export class AVRDocumentationHandler extends BaseAssemblyDocumentationHandler {
|
||||
getInstructionInformation(instruction) {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { getAsmOpcode } from '../asm-docs-6502';
|
||||
import { BaseAssemblyDocumentationHandler } from '../base-assembly-documentation-handler';
|
||||
|
||||
export class Mos6502DocumentationHandler extends BaseAssemblyDocumentationHandler {
|
||||
getInstructionInformation(instruction) {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { AssemblyDocumentationResponse } from '../../types/features/assembly-documentation.interfaces';
|
||||
|
||||
export class BaseAssemblyDocumentationHandler {
|
||||
/**
|
||||
* Gather the assembly instruction information by the instruction name.
|
||||
*
|
||||
* Implementors should return null if the instruction is not supported.
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
getInstructionInformation(instruction: string): AssemblyDocumentationResponse | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request for assembly instruction documentation.
|
||||
*
|
||||
* Implementors should not have to override this.
|
||||
*/
|
||||
handle(request: express.Request, response: express.Response) {
|
||||
// If the request had no opcode parameter, we should fail. This assumes
|
||||
// no assembly language has a __unknown_opcode instruction.
|
||||
const instruction = (request.params.opcode || '__UNKNOWN_OPCODE').toUpperCase();
|
||||
const information = this.getInstructionInformation(instruction);
|
||||
if (information === null) {
|
||||
return response.status(404).send({ error: `Unknown opcode '${instruction}'` });
|
||||
}
|
||||
// Accept either JSON or Plaintext Content-Type
|
||||
const requestedContentType = request.accepts(['text', 'json']);
|
||||
switch (requestedContentType) {
|
||||
case 'text': response.send(information.html); break;
|
||||
case 'json': response.send(information); break;
|
||||
default: response.status(406).send({ error: 'Not Acceptable' }); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
package-lock.json
generated
22
package-lock.json
generated
@@ -13007,6 +13007,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
"node_modules/ts-node/node_modules/acorn": {
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz",
|
||||
"integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
>>>>>>> 066865fc (Move Assembly Documentation providers into their own /asm-providers directory under /lib)
|
||||
"node_modules/ts-node/node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
@@ -24172,6 +24186,14 @@
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
"acorn": {
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz",
|
||||
"integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw=="
|
||||
},
|
||||
>>>>>>> 066865fc (Move Assembly Documentation providers into their own /asm-providers directory under /lib)
|
||||
"diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
|
||||
92
test/handlers/asm-docs-tests.js
Normal file
92
test/handlers/asm-docs-tests.js
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { expect } from 'chai';
|
||||
import express from 'express';
|
||||
|
||||
import { withAssemblyDocumentationProviders } from '../../lib/handlers/assembly-documentation';
|
||||
import { chai } from '../utils';
|
||||
|
||||
/** Test matrix of architecture to [opcode, tooptip, html, url] */
|
||||
export const TEST_MATRIX = {
|
||||
6502: ['lda', 'Load Accumulator with Memory', 'data is transferred from memory to the accumulator', 'https://www.pagetable.com/c64ref/6502/'],
|
||||
amd64: ['mov', 'Copies the second operand', 'Copies the second operand', 'www.felixcloutier.com'],
|
||||
arm32: ['mov', 'writes an immediate value', 'writes an immediate value to the destination register', 'https://developer.arm.com/documentation/'],
|
||||
avr: ['mov', 'Copy Register', 'makes a copy of one register into another', 'https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf'],
|
||||
java: ['iload_0', 'Load int from local variable', 'Load int from local variable', 'https://docs.oracle.com/javase/specs/jvms/se16/html/'],
|
||||
};
|
||||
|
||||
describe('Assembly Documentation API', () => {
|
||||
let app;
|
||||
|
||||
before(() => {
|
||||
app = express();
|
||||
const router = express.Router();
|
||||
withAssemblyDocumentationProviders(router);
|
||||
app.use('/api', router);
|
||||
});
|
||||
|
||||
it('should return 404 for unknown architecture', async () => {
|
||||
const res = await chai.request(app).get(`/api/asm/not_an_arch/mov`)
|
||||
.set('Accept', 'application/json');
|
||||
expect(res).to.have.status(404);
|
||||
expect(res).to.be.json;
|
||||
expect(res.body).to.deep.equal({ error: `No documentation for 'not_an_arch'` });
|
||||
});
|
||||
|
||||
for (const [arch, [opcode, tooltip, html, url]] of Object.entries(TEST_MATRIX)) {
|
||||
it(`should process ${arch} text requests`, async () => {
|
||||
const res = await chai.request(app).get(`/api/asm/${arch}/${opcode}`)
|
||||
.set('Accept', 'text/plain');
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.html;
|
||||
expect(res.text).to.contain(html);
|
||||
});
|
||||
|
||||
it(`should process ${arch} json requests`, async () => {
|
||||
const res = await chai.request(app).get(`/api/asm/${arch}/${opcode}`)
|
||||
.set('Accept', 'application/json');
|
||||
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.json;
|
||||
expect(res.body.html).to.contain(html);
|
||||
expect(res.body.tooltip).to.contain(tooltip);
|
||||
expect(res.body.url).to.contain(url);
|
||||
});
|
||||
|
||||
it(`should return 404 for ${arch} unknown opcode requests`, async () => {
|
||||
const res = await chai.request(app).get(`/api/asm/${arch}/not_an_opcode`)
|
||||
.set('Accept', 'application/json');
|
||||
expect(res).to.have.status(404);
|
||||
expect(res).to.be.json;
|
||||
expect(res.body).to.deep.equal({ error: 'Unknown opcode \'NOT_AN_OPCODE\'' });
|
||||
});
|
||||
|
||||
it(`should return 406 for ${arch} bad accept type requests`, async () => {
|
||||
const res = await chai.request(app).get(`/api/asm/${arch}/${opcode}`)
|
||||
.set('Accept', 'application/pdf');
|
||||
expect(res).to.have.status(406);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { Mos6502DocumentationHandler } from '../../../lib/handlers/assembly-documentation/mos6502';
|
||||
import { chai } from '../../utils';
|
||||
|
||||
describe('6502 assembly documentation', () => {
|
||||
let app;
|
||||
before(() => {
|
||||
app = express();
|
||||
const handler = new Mos6502DocumentationHandler();
|
||||
app.use('/asm/:opcode', handler.handle.bind(handler));
|
||||
});
|
||||
|
||||
it('returns 404 for unknown opcodes', () => {
|
||||
return chai.request(app).get('/asm/lda_oh_wait')
|
||||
.then(res => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equal({ error: 'Unknown opcode \'LDA_OH_WAIT\'' });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=text requests', () => {
|
||||
return chai.request(app).get('/asm/lda')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('data is transferred from memory to the accumulator');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=json requests', () => {
|
||||
return chai.request(app).get('/asm/lda')
|
||||
.set('Accept', 'application/json')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.json;
|
||||
res.body.html.should.contain('data is transferred from memory to the accumulator');
|
||||
res.body.tooltip.should.contain('Load Accumulator with Memory');
|
||||
res.body.url.should.contain('https://www.pagetable.com/c64ref/6502/');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should return 406 on bad accept type', () => {
|
||||
return chai.request(app).get('/asm/lda')
|
||||
.set('Accept', 'application/pdf')
|
||||
.then(res => {
|
||||
res.should.have.status(406);
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
});
|
||||
@@ -1,85 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { Amd64DocumentationHandler } from '../../../lib/handlers/assembly-documentation/amd64';
|
||||
import { chai } from '../../utils';
|
||||
|
||||
describe('amd64 assembly documentation', () => {
|
||||
let app;
|
||||
before(() => {
|
||||
app = express();
|
||||
const handler = new Amd64DocumentationHandler();
|
||||
app.use('/asm/:opcode', handler.handle.bind(handler));
|
||||
});
|
||||
|
||||
it('returns 404 for unknown opcodes', () => {
|
||||
return chai.request(app).get('/asm/mov_oh_wait')
|
||||
.then(res => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equal({ error: 'Unknown opcode \'MOV_OH_WAIT\'' });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=text requests', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('Copies the second operand');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=json requests', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.set('Accept', 'application/json')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.json;
|
||||
res.body.html.should.contain('Copies the second operand');
|
||||
res.body.tooltip.should.contain('Copies the second operand');
|
||||
res.body.url.should.contain('www.felixcloutier.com');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should return 406 on bad accept type', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.set('Accept', 'application/pdf')
|
||||
.then(res => {
|
||||
res.should.have.status(406);
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should handle at&t syntax', () => {
|
||||
return chai.request(app)
|
||||
.get('/asm/addq')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('Adds the destination operand');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
});
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express, { Router } from 'express';
|
||||
|
||||
import { setup } from '../../../lib/handlers/assembly-documentation/router';
|
||||
import { chai } from '../../utils';
|
||||
|
||||
describe('Assembly Documentation API', () => {
|
||||
let app;
|
||||
|
||||
before(() => {
|
||||
app = express();
|
||||
/** @type {e.Router} */
|
||||
const router = Router();
|
||||
setup(router);
|
||||
app.use('/api', router);
|
||||
});
|
||||
|
||||
it('should accept requests to the api', () => {
|
||||
return chai.request(app)
|
||||
.get('/api/asm/amd64/mov')
|
||||
.set('Accept', 'application/json')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.json;
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
|
||||
it('should return opcode not found', () => {
|
||||
return chai.request(app).get('/api/asm/amd64/notexistingop')
|
||||
.set('Accept', 'application/json')
|
||||
.then((res) => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equals({ error: `Unknown opcode 'NOTEXISTINGOP'` });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should return architecture not found', () => {
|
||||
return chai.request(app).get('/api/asm/notarch/mov')
|
||||
.set('Accept', 'application/json')
|
||||
.then((res) => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equals({ error: `No documentation for 'notarch'` });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
});
|
||||
@@ -1,105 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { Arm32DocumentationHandler } from '../../../lib/handlers/assembly-documentation/arm32';
|
||||
import { chai } from '../../utils';
|
||||
|
||||
describe('arm32 assembly documentation', () => {
|
||||
let app;
|
||||
before(() => {
|
||||
app = express();
|
||||
const handler = new Arm32DocumentationHandler();
|
||||
app.use('/asm/:opcode', handler.handle.bind(handler));
|
||||
});
|
||||
|
||||
it('returns 404 for unknown opcodes', () => {
|
||||
return chai.request(app).get('/asm/mov_oh_wait')
|
||||
.then(res => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equal({ error: 'Unknown opcode \'MOV_OH_WAIT\'' });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=text requests', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('writes an immediate value to the destination register');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=json requests', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.set('Accept', 'application/json')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.json;
|
||||
res.body.html.should.contain('writes an immediate value');
|
||||
res.body.tooltip.should.contain('writes an immediate value');
|
||||
res.body.url.should.contain('https://developer.arm.com/documentation/');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should return 406 on bad accept type', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.set('Accept', 'application/pdf')
|
||||
.then(res => {
|
||||
res.should.have.status(406);
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should handle opcodes with a conditional type suffix that are not conditionals', () => {
|
||||
return chai.request(app)
|
||||
.get('/asm/adcs')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('adds an immediate value and the Carry flag');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should handle conditional opcodes', () => {
|
||||
return chai.request(app)
|
||||
.get('/asm/beq')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('If equal, <p>Branch causes a branch');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should respond with "unknown opcode" for unknown opcodes that can be parsed as conditional', () => {
|
||||
return chai.request(app)
|
||||
.get('/asm/jne')
|
||||
.then(res => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equal({ error: 'Unknown opcode \'JNE\'' });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
});
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { AVRDocumentationHandler } from '../../../lib/handlers/assembly-documentation/avr';
|
||||
import { chai } from '../../utils';
|
||||
|
||||
describe('AVR assembly documentation', () => {
|
||||
let app;
|
||||
before(() => {
|
||||
app = express();
|
||||
const handler = new AVRDocumentationHandler();
|
||||
app.use('/asm/:opcode', handler.handle.bind(handler));
|
||||
});
|
||||
|
||||
it('returns 404 for unknown opcodes', () => {
|
||||
return chai.request(app).get('/asm/mov_oh_wait')
|
||||
.then(res => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equal({ error: 'Unknown opcode \'MOV_OH_WAIT\'' });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=text requests', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('makes a copy of one register into another');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=json requests', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.set('Accept', 'application/json')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.json;
|
||||
res.body.html.should.contain('makes a copy of one register into another');
|
||||
res.body.tooltip.should.contain('Copy Register');
|
||||
res.body.url.should.contain('https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should return 406 on bad accept type', () => {
|
||||
return chai.request(app).get('/asm/mov')
|
||||
.set('Accept', 'application/pdf')
|
||||
.then(res => {
|
||||
res.should.have.status(406);
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
});
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import express from 'express';
|
||||
|
||||
import { JavaDocumentationHandler } from '../../../lib/handlers/assembly-documentation/java';
|
||||
import { chai } from '../../utils';
|
||||
|
||||
describe('jvm assembly documentation', () => {
|
||||
let app;
|
||||
before(() => {
|
||||
app = express();
|
||||
const handler = new JavaDocumentationHandler();
|
||||
app.use('/asm/:opcode', handler.handle.bind(handler));
|
||||
});
|
||||
|
||||
it('returns 404 for unknown opcodes', () => {
|
||||
return chai.request(app).get('/asm/mov_oh_wait')
|
||||
.then(res => {
|
||||
res.should.have.status(404);
|
||||
res.should.be.json;
|
||||
res.body.should.deep.equal({ error: 'Unknown opcode \'MOV_OH_WAIT\'' });
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=text requests', () => {
|
||||
return chai.request(app).get('/asm/iload_0')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.html;
|
||||
res.text.should.contain('Load int from local variable');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('responds to accept=json requests', () => {
|
||||
return chai.request(app).get('/asm/iload_0')
|
||||
.set('Accept', 'application/json')
|
||||
.then(res => {
|
||||
res.should.have.status(200);
|
||||
res.should.be.json;
|
||||
res.body.html.should.contain('Load int from local variable');
|
||||
res.body.tooltip.should.contain('Load int from local variable');
|
||||
res.body.url.should.contain('https://docs.oracle.com/javase/specs/jvms/se16/html/');
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
|
||||
it('should return 406 on bad accept type', () => {
|
||||
return chai.request(app).get('/asm/iload_0')
|
||||
.set('Accept', 'application/pdf')
|
||||
.then(res => {
|
||||
res.should.have.status(406);
|
||||
}).catch(e => { throw e; });
|
||||
});
|
||||
});
|
||||
@@ -22,6 +22,8 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { AssemblyInstructionInfo } from '../../lib/asm-docs/base';
|
||||
|
||||
export interface AssemblyDocumentationRequest {
|
||||
/** Specifies which instruction set to look for */
|
||||
instructionSet: 'amd64' | 'arm32' | 'java';
|
||||
@@ -29,11 +31,7 @@ export interface AssemblyDocumentationRequest {
|
||||
opcode: string;
|
||||
}
|
||||
|
||||
export interface AssemblyDocumentationResponse {
|
||||
tooltip: string;
|
||||
html: string;
|
||||
url: string;
|
||||
}
|
||||
export type AssemblyDocumentationResponse = AssemblyInstructionInfo;
|
||||
|
||||
export interface AssemblyDocumentationError {
|
||||
/** Explanatory error string */
|
||||
|
||||
Reference in New Issue
Block a user