diff options
-rw-r--r-- | .eslintrc.yml | 6 | ||||
-rw-r--r-- | .idea/codeStyles/Project.xml | 33 | ||||
-rwxr-xr-x | app.js | 270 | ||||
-rw-r--r-- | lib/base-compiler.js | 648 | ||||
-rw-r--r-- | lib/buildenvsetup/ceconan.js | 20 | ||||
-rw-r--r-- | lib/clientstate-normalizer.js | 202 | ||||
-rw-r--r-- | lib/compiler-arguments.js | 22 | ||||
-rw-r--r-- | lib/compiler-finder.js | 168 | ||||
-rw-r--r-- | lib/compilers/ada.js | 18 | ||||
-rw-r--r-- | lib/compilers/clean.js | 45 | ||||
-rw-r--r-- | lib/compilers/dotnet.ts | 69 | ||||
-rw-r--r-- | lib/compilers/erlang.js | 14 | ||||
-rw-r--r-- | lib/compilers/nim.js | 39 | ||||
-rw-r--r-- | lib/demangler/base.js | 41 | ||||
-rw-r--r-- | lib/exec.js | 108 | ||||
-rw-r--r-- | lib/handlers/api.js | 68 | ||||
-rw-r--r-- | lib/handlers/assembly-documentation.ts | 53 | ||||
-rw-r--r-- | lib/logger.js | 33 | ||||
-rw-r--r-- | lib/tooling/clang-tidy-tool.js | 13 | ||||
-rw-r--r-- | lib/tooling/pvs-studio-tool.js | 40 | ||||
-rw-r--r-- | package.json | 6 | ||||
-rw-r--r-- | test/demangler-tests.js | 139 | ||||
-rw-r--r-- | test/exec-tests.js | 251 | ||||
-rw-r--r-- | test/java-tests.js | 72 | ||||
-rw-r--r-- | test/storage/storage-s3-tests.js | 83 | ||||
-rw-r--r-- | test/tool-tests.js | 62 |
26 files changed, 1269 insertions, 1254 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml index 906901e75..68cefa995 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -25,7 +25,11 @@ env: rules: comma-dangle: - error - - always-multiline + - arrays: always-multiline + objects: always-multiline + imports: always-multiline + exports: always-multiline + functions: never eol-last: - error - always diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 702f69c0f..054d53a0d 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -2,15 +2,16 @@ <code_scheme name="Project" version="173"> <HTMLCodeStyleSettings> <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" /> + <option name="HTML_QUOTE_STYLE" value="Single" /> <option name="HTML_ENFORCE_QUOTES" value="true" /> </HTMLCodeStyleSettings> <JSCodeStyleSettings version="0"> <option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> + <option name="USE_DOUBLE_QUOTES" value="false" /> <option name="FORCE_QUOTE_STYlE" value="true" /> - <option name="ENFORCE_TRAILING_COMMA" value="Remove" /> - <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" /> - <option name="SPACES_WITHIN_IMPORTS" value="true" /> + <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" /> + <option name="SPACES_WITHIN_OBJECT_TYPE_BRACES" value="false" /> <option name="IMPORT_SORT_MODULE_NAME" value="true" /> </JSCodeStyleSettings> <JetCodeStyleSettings> @@ -22,21 +23,19 @@ <TypeScriptCodeStyleSettings version="0"> <option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> + <option name="USE_DOUBLE_QUOTES" value="false" /> <option name="FORCE_QUOTE_STYlE" value="true" /> - <option name="ENFORCE_TRAILING_COMMA" value="Remove" /> - <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" /> - <option name="SPACES_WITHIN_IMPORTS" value="true" /> + <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" /> + <option name="SPACES_WITHIN_OBJECT_TYPE_BRACES" value="false" /> </TypeScriptCodeStyleSettings> <VueCodeStyleSettings> <option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" /> <option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" /> </VueCodeStyleSettings> <codeStyleSettings language="HTML"> - <option name="SOFT_MARGINS" value="80" /> + <option name="SOFT_MARGINS" value="120" /> <indentOptions> - <option name="INDENT_SIZE" value="2" /> - <option name="CONTINUATION_INDENT_SIZE" value="2" /> - <option name="TAB_SIZE" value="2" /> + <option name="CONTINUATION_INDENT_SIZE" value="4" /> </indentOptions> </codeStyleSettings> <codeStyleSettings language="Jade"> @@ -48,20 +47,10 @@ <codeStyleSettings language="JavaScript"> <option name="ALIGN_MULTILINE_PARAMETERS" value="false" /> <option name="ALIGN_MULTILINE_FOR" value="false" /> - <option name="SOFT_MARGINS" value="80" /> - <indentOptions> - <option name="INDENT_SIZE" value="2" /> - <option name="CONTINUATION_INDENT_SIZE" value="2" /> - <option name="TAB_SIZE" value="2" /> - </indentOptions> + <option name="SOFT_MARGINS" value="120" /> </codeStyleSettings> <codeStyleSettings language="TypeScript"> - <option name="SOFT_MARGINS" value="80" /> - <indentOptions> - <option name="INDENT_SIZE" value="2" /> - <option name="CONTINUATION_INDENT_SIZE" value="2" /> - <option name="TAB_SIZE" value="2" /> - </indentOptions> + <option name="SOFT_MARGINS" value="120" /> </codeStyleSettings> <codeStyleSettings language="Vue"> <option name="SOFT_MARGINS" value="80" /> @@ -45,25 +45,25 @@ import urljoin from 'url-join'; import * as aws from './lib/aws'; import * as normalizer from './lib/clientstate-normalizer'; -import { CompilationEnvironment } from './lib/compilation-env'; -import { CompilationQueue } from './lib/compilation-queue'; -import { CompilerFinder } from './lib/compiler-finder'; +import {CompilationEnvironment} from './lib/compilation-env'; +import {CompilationQueue} from './lib/compilation-queue'; +import {CompilerFinder} from './lib/compiler-finder'; // import { policy as csp } from './lib/csp'; -import { initialiseWine } from './lib/exec'; -import { CompileHandler } from './lib/handlers/compile'; +import {initialiseWine} from './lib/exec'; +import {CompileHandler} from './lib/handlers/compile'; import * as healthCheck from './lib/handlers/health-check'; -import { NoScriptHandler } from './lib/handlers/noscript'; -import { RouteAPI } from './lib/handlers/route-api'; -import { SourceHandler } from './lib/handlers/source'; -import { languages as allLanguages } from './lib/languages'; -import { logger, logToLoki, logToPapertrail, suppressConsoleLog } from './lib/logger'; -import { setupMetricsServer } from './lib/metrics-server'; -import { ClientOptionsHandler } from './lib/options-handler'; +import {NoScriptHandler} from './lib/handlers/noscript'; +import {RouteAPI} from './lib/handlers/route-api'; +import {SourceHandler} from './lib/handlers/source'; +import {languages as allLanguages} from './lib/languages'; +import {logger, logToLoki, logToPapertrail, suppressConsoleLog} from './lib/logger'; +import {setupMetricsServer} from './lib/metrics-server'; +import {ClientOptionsHandler} from './lib/options-handler'; import * as props from './lib/properties'; -import { ShortLinkResolver } from './lib/shortener/google'; -import { sources } from './lib/sources'; -import { loadSponsorsFromString } from './lib/sponsors'; -import { getStorageTypeByKey } from './lib/storage'; +import {ShortLinkResolver} from './lib/shortener/google'; +import {sources} from './lib/sources'; +import {loadSponsorsFromString} from './lib/sponsors'; +import {getStorageTypeByKey} from './lib/storage'; import * as utils from './lib/utils'; // Parse arguments from command line 'node ./app.js args...' @@ -182,7 +182,8 @@ const propHierarchy = [ _.map(defArgs.env, e => `${e}.${process.platform}`), process.platform, os.hostname(), - 'local'].flat(); + 'local', +].flat(); logger.info(`properties hierarchy: ${propHierarchy.join(', ')}`); // Propagate debug mode if need be @@ -199,9 +200,11 @@ let languages = allLanguages; if (defArgs.wantedLanguage) { const filteredLangs = {}; _.each(languages, lang => { - if (lang.id === defArgs.wantedLanguage || + if ( + lang.id === defArgs.wantedLanguage || lang.name === defArgs.wantedLanguage || - (lang.alias && lang.alias.includes(defArgs.wantedLanguage))) { + (lang.alias && lang.alias.includes(defArgs.wantedLanguage)) + ) { filteredLangs[lang.id] = lang; } }); @@ -237,7 +240,7 @@ function contentPolicyHeader(/*res*/) { } function measureEventLoopLag(delayMs) { - return new Promise((resolve) => { + return new Promise(resolve => { const start = process.hrtime.bigint(); setTimeout(() => { const elapsed = process.hrtime.bigint() - start; @@ -291,12 +294,14 @@ async function setupWebPackDevMiddleware(router) { /* eslint-enable */ const webpackCompiler = webpack(webpackConfig); - router.use(webpackDevMiddleware(webpackCompiler, { - publicPath: '/static', - stats: 'errors-only', - })); + router.use( + webpackDevMiddleware(webpackCompiler, { + publicPath: '/static', + stats: 'errors-only', + }) + ); - pugRequireHandler = (path) => urljoin(httpRoot, 'static', path); + pugRequireHandler = path => urljoin(httpRoot, 'static', path); } async function setupStaticMiddleware(router) { @@ -307,12 +312,15 @@ async function setupStaticMiddleware(router) { } else { const staticPath = path.join(distPath, 'static'); logger.info(` serving static files from '${staticPath}'`); - router.use('/static', express.static(staticPath, { - maxAge: staticMaxAgeSecs * 1000, - })); + router.use( + '/static', + express.static(staticPath, { + maxAge: staticMaxAgeSecs * 1000, + }) + ); } - pugRequireHandler = (path) => { + pugRequireHandler = path => { if (Object.prototype.hasOwnProperty.call(staticManifest, path)) { return urljoin(staticRoot, staticManifest[path]); } else { @@ -336,7 +344,8 @@ const googleShortUrlResolver = new ShortLinkResolver(); function oldGoogleUrlHandler(req, res, next) { const id = req.params.id; const googleUrl = `https://goo.gl/${encodeURIComponent(id)}`; - googleShortUrlResolver.resolve(googleUrl) + googleShortUrlResolver + .resolve(googleUrl) .then(resultObj => { const parsed = new url.URL(resultObj.longUrl); const allowedRe = new RegExp(ceProps('allowedShortUrlHostRe')); @@ -419,9 +428,7 @@ function setupSentry(sentryDsn, expressApp) { release: releaseBuildNumber || gitReleaseName, environment: sentryEnv || defArgs.env[0], beforeSend(event) { - if (event.request - && event.request.data - && shouldRedactRequestData(event.request.data)) { + if (event.request && event.request.data && shouldRedactRequestData(event.request.data)) { event.request.data = JSON.stringify({redacted: true}); } return event; @@ -434,12 +441,10 @@ function setupSentry(sentryDsn, expressApp) { ], tracesSampler: samplingContext => { // always inherit - if (samplingContext.parentSampled !== undefined) - return samplingContext.parentSampled; + if (samplingContext.parentSampled !== undefined) return samplingContext.parentSampled; // never sample healthcheck - if (samplingContext.transactionContext.name === 'GET /healthcheck') - return 0; + if (samplingContext.transactionContext.name === 'GET /healthcheck') return 0; // default sample rate of 10% return 0.1; @@ -491,8 +496,7 @@ async function main() { if (opts.discoveryonly) { for (const compiler of initialCompilers) { - if (compiler.buildenvsetup && compiler.buildenvsetup.id === '') - delete compiler.buildenvsetup; + if (compiler.buildenvsetup && compiler.buildenvsetup.id === '') delete compiler.buildenvsetup; const compilerInstance = compilerFinder.compileHandler.findCompiler(compiler.lang, compiler.id); if (compilerInstance) { @@ -504,7 +508,8 @@ async function main() { process.exit(0); } - const webServer = express(), router = express.Router(); + const webServer = express(), + router = express.Router(); setupSentry(aws.getConfig('sentryDsn'), webServer); const healthCheckFilePath = ceProps('healthCheckFilePath', false); @@ -545,8 +550,10 @@ async function main() { const rescanCompilerSecs = ceProps('rescanCompilerSecs', 0); if (rescanCompilerSecs && !opts.prediscovered) { logger.info(`Rescanning compilers every ${rescanCompilerSecs} secs`); - setInterval(() => compilerFinder.find().then(result => onCompilerChange(result.compilers)), - rescanCompilerSecs * 1000); + setInterval( + () => compilerFinder.find().then(result => onCompilerChange(result.compilers)), + rescanCompilerSecs * 1000 + ); } const sentrySlowRequestMs = ceProps('sentrySlowRequestMs', 0); @@ -561,19 +568,23 @@ async function main() { .set('view engine', 'pug') .on('error', err => logger.error('Caught error in web handler; continuing:', err)) // sentry request handler must be the first middleware on the app - .use(Sentry.Handlers.requestHandler({ - ip: true, - })) + .use( + Sentry.Handlers.requestHandler({ + ip: true, + }) + ) .use(Sentry.Handlers.tracingHandler()) // eslint-disable-next-line no-unused-vars - .use(responseTime((req, res, time) => { - if (sentrySlowRequestMs > 0 && time >= sentrySlowRequestMs) { - Sentry.withScope(scope => { - scope.setExtra('duration_ms', time); - Sentry.captureMessage('SlowRequest', 'warning'); - }); - } - })) + .use( + responseTime((req, res, time) => { + if (sentrySlowRequestMs > 0 && time >= sentrySlowRequestMs) { + Sentry.withScope(scope => { + scope.setExtra('duration_ms', time); + Sentry.captureMessage('SlowRequest', 'warning'); + }); + } + }) + ) // Handle healthchecks at the root, as they're not expected from the outside world .use('/healthcheck', new healthCheck.HealthCheckHandler(compilationQueue, healthCheckFilePath).handle) .use(httpRoot, router) @@ -585,11 +596,7 @@ async function main() { // eslint-disable-next-line no-unused-vars .use((err, req, res, next) => { const status = - err.status || - err.statusCode || - err.status_code || - (err.output && err.output.statusCode) || - 500; + err.status || err.statusCode || err.status_code || (err.output && err.output.statusCode) || 500; const message = err.message || 'Internal Server Error'; res.status(status); res.render('error', renderConfig({error: {code: status, message: message}})); @@ -601,12 +608,8 @@ async function main() { const sponsorConfig = loadSponsorsFromString(fs.readFileSync(configDir + '/sponsors.yaml', 'utf-8')); function renderConfig(extra, urlOptions) { - const urlOptionsAllowed = [ - 'readOnly', 'hideEditorToolbars', 'language', - ]; - const filteredUrlOptions = _.mapObject( - _.pick(urlOptions, urlOptionsAllowed), - val => utils.toProperty(val)); + const urlOptionsAllowed = ['readOnly', 'hideEditorToolbars', 'language']; + const filteredUrlOptions = _.mapObject(_.pick(urlOptions, urlOptionsAllowed), val => utils.toProperty(val)); const allExtraOptions = _.extend({}, filteredUrlOptions, extra); if (allExtraOptions.mobileViewer && allExtraOptions.config) { @@ -640,26 +643,38 @@ async function main() { const embedded = req.query.embedded === 'true' ? true : false; - res.render(embedded ? 'embed' : 'index', renderConfig({ - embedded: embedded, - mobileViewer: isMobileViewer(req), - config: config, - metadata: metadata, - storedStateId: req.params.id ? req.params.id : false, - }, req.query)); + res.render( + embedded ? 'embed' : 'index', + renderConfig( + { + embedded: embedded, + mobileViewer: isMobileViewer(req), + config: config, + metadata: metadata, + storedStateId: req.params.id ? req.params.id : false, + }, + req.query + ) + ); } const embeddedHandler = function (req, res) { staticHeaders(res); contentPolicyHeader(res); - res.render('embed', renderConfig({ - embedded: true, - mobileViewer: isMobileViewer(req), - }, req.query)); + res.render( + 'embed', + renderConfig( + { + embedded: true, + mobileViewer: isMobileViewer(req), + }, + req.query + ) + ); }; await (isDevMode() ? setupWebPackDevMiddleware(router) : setupStaticMiddleware(router)); - morgan.token('gdpr_ip', req => req.ip ? utils.anonymizeIp(req.ip) : ''); + morgan.token('gdpr_ip', req => (req.ip ? utils.anonymizeIp(req.ip) : '')); // Based on combined format, but: GDPR compliant IP, no timestamp & no unused fields for our usecase const morganFormat = isDevMode() ? 'dev' : ':gdpr_ip ":method :url" :status'; @@ -700,29 +715,41 @@ async function main() { }); router - .use(morgan(morganFormat, { - stream: logger.stream, - // Skip for non errors (2xx, 3xx) - skip: (req, res) => res.statusCode >= 400, - })) - .use(morgan(morganFormat, { - stream: logger.warnStream, - // Skip for non user errors (4xx) - skip: (req, res) => res.statusCode < 400 || res.statusCode >= 500, - })) - .use(morgan(morganFormat, { - stream: logger.errStream, - // Skip for non server errors (5xx) - skip: (req, res) => res.statusCode < 500, - })) + .use( + morgan(morganFormat, { + stream: logger.stream, + // Skip for non errors (2xx, 3xx) + skip: (req, res) => res.statusCode >= 400, + }) + ) + .use( + morgan(morganFormat, { + stream: logger.warnStream, + // Skip for non user errors (4xx) + skip: (req, res) => res.statusCode < 400 || res.statusCode >= 500, + }) + ) + .use( + morgan(morganFormat, { + stream: logger.errStream, + // Skip for non server errors (5xx) + skip: (req, res) => res.statusCode < 500, + }) + ) .use(compression()) .get('/', (req, res) => { staticHeaders(res); contentPolicyHeader(res); - res.render('index', renderConfig({ - embedded: false, - mobileViewer: isMobileViewer(req), - }, req.query)); + res.render( + 'index', + renderConfig( + { + embedded: false, + mobileViewer: isMobileViewer(req), + }, + req.query + ) + ); }) .get('/e', embeddedHandler) // legacy. not a 301 to prevent any redirect loops between old e links and embed.html @@ -730,11 +757,17 @@ async function main() { .get('/embed-ro', (req, res) => { staticHeaders(res); contentPolicyHeader(res); - res.render('embed', renderConfig({ - embedded: true, - readOnly: true, - mobileViewer: isMobileViewer(req), - }, req.query)); + res.render( + 'embed', + renderConfig( + { + embedded: true, + readOnly: true, + mobileViewer: isMobileViewer(req), + }, + req.query + ) + ); }) .get('/robots.txt', (req, res) => { staticHeaders(res); @@ -754,10 +787,16 @@ async function main() { .use('/bits/:bits(\\w+).html', (req, res) => { staticHeaders(res); contentPolicyHeader(res); - res.render('bits/' + req.params.bits, renderConfig({ - embedded: false, - mobileViewer: isMobileViewer(req), - }, req.query)); + res.render( + 'bits/' + req.params.bits, + renderConfig( + { + embedded: false, + mobileViewer: isMobileViewer(req), + }, + req.query + ) + ); }) .use(bodyParser.json({limit: ceProps('bodyParserLimit', maxUploadSize)})) .use('/source', sourceHandler.handle.bind(sourceHandler)) @@ -789,17 +828,16 @@ process.on('SIGTERM', terminationHandler('SIGTERM', 0)); process.on('SIGQUIT', terminationHandler('SIGQUIT', 0)); function terminationHandler(name, code) { - return (error) => { - logger.info(`stopping process: ${name}`); - if (error && error instanceof Error) { - logger.error(error); - } - process.exit(code); - }; + return error => { + logger.info(`stopping process: ${name}`); + if (error && error instanceof Error) { + logger.error(error); + } + process.exit(code); + }; } -main() - .catch(err => { - logger.error('Top-level error (shutting down):', err); - process.exit(1); - }); +main().catch(err => { + logger.error('Top-level error (shutting down):', err); + process.exit(1); +}); diff --git a/lib/base-compiler.js b/lib/base-compiler.js index aa517cdea..1f5c1e781 100644 --- a/lib/base-compiler.js +++ b/lib/base-compiler.js @@ -29,22 +29,22 @@ import fs from 'fs-extra'; import temp from 'temp'; import _ from 'underscore'; -import { BuildEnvSetupBase, getBuildEnvTypeByKey } from './buildenvsetup'; +import {BuildEnvSetupBase, getBuildEnvTypeByKey} from './buildenvsetup'; import * as cfg from './cfg'; -import { CompilerArguments } from './compiler-arguments'; -import { ClangParser, GCCParser } from './compilers/argument-parsers'; -import { getDemanglerTypeByKey } from './demangler'; +import {CompilerArguments} from './compiler-arguments'; +import {ClangParser, GCCParser} from './compilers/argument-parsers'; +import {getDemanglerTypeByKey} from './demangler'; import * as exec from './exec'; -import { FormattingHandler } from './handlers/formatting'; -import { InstructionSets } from './instructionsets'; -import { languages } from './languages'; -import { LlvmAstParser } from './llvm-ast'; -import { LlvmIrParser } from './llvm-ir'; -import { logger } from './logger'; -import { getObjdumperTypeByKey } from './objdumper'; -import { Packager } from './packager'; -import { AsmParser } from './parsers/asm-parser'; -import { getToolchainPath } from './toolchain-utils'; +import {FormattingHandler} from './handlers/formatting'; +import {InstructionSets} from './instructionsets'; +import {languages} from './languages'; +import {LlvmAstParser} from './llvm-ast'; +import {LlvmIrParser} from './llvm-ir'; +import {logger} from './logger'; +import {getObjdumperTypeByKey} from './objdumper'; +import {Packager} from './packager'; +import {AsmParser} from './parsers/asm-parser'; +import {getToolchainPath} from './toolchain-utils'; import * as utils from './utils'; export class BaseCompiler { @@ -71,8 +71,7 @@ export class BaseCompiler { if (!this.compiler.optArg) this.compiler.optArg = ''; if (!this.compiler.supportsOptOutput) this.compiler.supportsOptOutput = false; - if (!this.compiler.disabledFilters) - this.compiler.disabledFilters = []; + if (!this.compiler.disabledFilters) this.compiler.disabledFilters = []; else if (typeof this.compiler.disabledFilters === 'string') this.compiler.disabledFilters = this.compiler.disabledFilters.split(','); @@ -108,14 +107,16 @@ export class BaseCompiler { if (!this.compiler.instructionSet) { const isets = new InstructionSets(); if (this.buildenvsetup) { - isets.getCompilerInstructionSetHint(this.buildenvsetup.compilerArch, this.compiler.exe).then( - (res) => this.compiler.instructionSet = res, - ).catch(() => {}); + isets + .getCompilerInstructionSetHint(this.buildenvsetup.compilerArch, this.compiler.exe) + .then(res => (this.compiler.instructionSet = res)) + .catch(() => {}); } else { const temp = new BuildEnvSetupBase(this.compiler, this.env); - isets.getCompilerInstructionSetHint(temp.compilerArch, this.compiler.exe).then( - (res) => this.compiler.instructionSet = res, - ).catch(() => {}); + isets + .getCompilerInstructionSetHint(temp.compilerArch, this.compiler.exe) + .then(res => (this.compiler.instructionSet = res)) + .catch(() => {}); } } @@ -125,7 +126,7 @@ export class BaseCompiler { } copyAndFilterLibraries(allLibraries, filter) { - const filterLibAndVersion = _.map(filter, (lib) => { + const filterLibAndVersion = _.map(filter, lib => { const match = lib.match(/([\w-]*)\.([\w-]*)/i); if (match) { return { @@ -141,7 +142,7 @@ export class BaseCompiler { }); const filterLibIds = new Set(); - _.each(filterLibAndVersion, (lib) => { + _.each(filterLibAndVersion, lib => { filterLibIds.add(lib.id); }); @@ -209,10 +210,8 @@ export class BaseCompiler { newTempDir() { return new Promise((resolve, reject) => { temp.mkdir({prefix: 'compiler-explorer-compiler', dir: process.env.tmpDir}, (err, dirPath) => { - if (err) - reject(`Unable to open temp file: ${err}`); - else - resolve(dirPath); + if (err) reject(`Unable to open temp file: ${err}`); + else resolve(dirPath); }); }); } @@ -222,8 +221,7 @@ export class BaseCompiler { } getRemote() { - if (this.compiler.exe === null && this.compiler.remote) - return this.compiler.remote; + if (this.compiler.exe === null && this.compiler.remote) return this.compiler.remote; return false; } @@ -251,7 +249,8 @@ export class BaseCompiler { if (!result) { result = await this.env.enqueue(async () => exec.execute(compiler, args, options)); if (result.okToCache) { - this.env.compilerCachePut(key, result) + this.env + .compilerCachePut(key, result) .then(() => { // Do nothing, but we don't await here. }) @@ -323,7 +322,7 @@ export class BaseCompiler { async objdump(outputFilename, result, maxSize, intelAsm, demangle) { outputFilename = this.getObjdumpOutputFilename(outputFilename); - if (!await utils.fileExists(outputFilename)) { + if (!(await utils.fileExists(outputFilename))) { result.asm = '<No output file ' + outputFilename + '>'; return result; } @@ -422,7 +421,7 @@ export class BaseCompiler { // really created. This is currently only possible with regular GCC, not // for compilers that us libgccjit. The later can't easily move dump // files outside of the tempdir created on the fly. - if (this.compiler.removeEmptyGccDump){ + if (this.compiler.removeEmptyGccDump) { if (gccDumpOptions.treeDump !== false) { addOpts.push('-fdump-tree-all' + flags); } @@ -447,11 +446,10 @@ export class BaseCompiler { // Returns a list of additional options that may be required by some backend options. // Meant to be overloaded by compiler classes. // Default handles the GCC compiler with some debug dump enabled. - optionsForBackend(backendOptions, outputFilename){ + optionsForBackend(backendOptions, outputFilename) { const addOpts = []; - if (backendOptions.produceGccDump && backendOptions.produceGccDump.opened - && this.compiler.supportsGccDump) { + if (backendOptions.produceGccDump && backendOptions.produceGccDump.opened && this.compiler.supportsGccDump) { addOpts.push.apply(addOpts, this.getGccDumpOptions(backendOptions.produceGccDump, outputFilename)); } @@ -471,17 +469,21 @@ export class BaseCompiler { const foundLib = _.find(this.supportedLibraries, (o, libId) => libId === selectedLib.id); if (!foundLib) return false; - const result = _.find(foundLib.versions, (o, versionId) => ( - versionId === selectedLib.version || (o.alias && o.alias.includes(selectedLib.version)) - )); + const result = _.find( + foundLib.versions, + (o, versionId) => versionId === selectedLib.version || (o.alias && o.alias.includes(selectedLib.version)) + ); result.name = foundLib.name; return result; } findAutodetectStaticLibLink(linkname) { - const foundLib = _.findKey(this.supportedLibraries, (lib) => { - return (lib.versions.autodetect && lib.versions.autodetect.staticliblink && - lib.versions.autodetect.staticliblink.includes(linkname)); + const foundLib = _.findKey(this.supportedLibraries, lib => { + return ( + lib.versions.autodetect && + lib.versions.autodetect.staticliblink && + lib.versions.autodetect.staticliblink.includes(linkname) + ); }); if (!foundLib) return false; @@ -493,54 +495,68 @@ export class BaseCompiler { getSortedStaticLibraries(libraries) { const dictionary = {}; - const links = _.uniq(_.flatten(_.map(libraries, (selectedLib) => { - const foundVersion = this.findLibVersion(selectedLib); - if (!foundVersion) return false; - - return _.map(foundVersion.staticliblink, (lib) => { - if (lib) { - dictionary[lib] = foundVersion; - return [lib, foundVersion.dependencies]; - } else { - return false; - } - }); - }))); + const links = _.uniq( + _.flatten( + _.map(libraries, selectedLib => { + const foundVersion = this.findLibVersion(selectedLib); + if (!foundVersion) return false; + + return _.map(foundVersion.staticliblink, lib => { + if (lib) { + dictionary[lib] = foundVersion; + return [lib, foundVersion.dependencies]; + } else { + return false; + } + }); + }) + ) + ); let sortedlinks = []; - _.each(links, (libToInsertName) => { + _.each(links, libToInsertName => { const libToInsertObj = dictionary[libToInsertName]; let idxToInsert = sortedlinks.length; for (const [idx, libCompareName] of sortedlinks.entries()) { const libCompareObj = dictionary[libCompareName]; - if (libToInsertObj && libCompareObj && - _.intersection(libToInsertObj.dependencies, libCompareObj.staticliblink).length > 0) { + if ( + libToInsertObj && + libCompareObj && + _.intersection(libToInsertObj.dependencies, libCompareObj.staticliblink).length > 0 + ) { idxToInsert = idx; break; - } else if (libToInsertObj && - libToInsertObj.dependencies.includes(libCompareName)) { + } else if (libToInsertObj && libToInsertObj.dependencies.includes(libCompareName)) { idxToInsert = idx; break; - } else if (libCompareObj && - libCompareObj.dependencies.includes(libToInsertName)) { + } else if (libCompareObj && libCompareObj.dependencies.includes(libToInsertName)) { continue; - } else if (libToInsertObj && + } else if ( + libToInsertObj && libToInsertObj.staticliblink.includes(libToInsertName) && - libToInsertObj.staticliblink.includes(libCompareName)) { - if (libToInsertObj.staticliblink.indexOf(libToInsertName) > - libToInsertObj.staticliblink.indexOf(libCompareName)) { + libToInsertObj.staticliblink.includes(libCompareName) + ) { + if ( + libToInsertObj.staticliblink.indexOf(libToInsertName) > + libToInsertObj.staticliblink.indexOf(libCompareName) + ) { continue; } else { idxToInsert = idx; } break; - } else if (libCompareObj && libCompareObj.staticliblink.includes(libToInsertName) && - libCompareObj.staticliblink.includes(libCompareName)) { - if (libCompareObj.staticliblink.indexOf(libToInsertName) > - libCompareObj.staticliblink.indexOf(libCompareName)) { + } else if ( + libCompareObj && + libCompareObj.staticliblink.includes(libToInsertName) && + libCompareObj.staticliblink.includes(libCompareName) + ) { + if ( + libCompareObj.staticliblink.indexOf(libToInsertName) > + libCompareObj.staticliblink.indexOf(libCompareName) + ) { continue; } else { idxToInsert = idx; @@ -562,7 +578,7 @@ export class BaseCompiler { getStaticLibraryLinks(libraries) { const linkFlag = this.compiler.linkFlag || '-l'; - return _.map(this.getSortedStaticLibraries(libraries), (lib) => { + return _.map(this.getSortedStaticLibraries(libraries), lib => { if (lib) { return linkFlag + lib; } else { @@ -574,27 +590,31 @@ export class BaseCompiler { getSharedLibraryLinks(libraries) { const linkFlag = this.compiler.linkFlag || '-l'; - return _.flatten(_.map(libraries, (selectedLib) => { - const foundVersion = this.findLibVersion(selectedLib); - if (!foundVersion) return false; + return _.flatten( + _.map(libraries, selectedLib => { + const foundVersion = this.findLibVersion(selectedLib); + if (!foundVersion) return false; - return _.map(foundVersion.liblink, (lib) => { - if (lib) { - return linkFlag + lib; - } else { - return false; - } - }); - })); + return _.map(foundVersion.liblink, lib => { + if (lib) { + return linkFlag + lib; + } else { + return false; + } + }); + }) + ); } getSharedLibraryPaths(libraries) { - return _.flatten(_.map(libraries, (selectedLib) => { - const foundVersion = this.findLibVersion(selectedLib); - if (!foundVersion) return false; + return _.flatten( + _.map(libraries, selectedLib => { + const foundVersion = this.findLibVersion(selectedLib); + if (!foundVersion) return false; - return foundVersion.libpath; - })); + return foundVersion.libpath; + }) + ); } getSharedLibraryPathsAsArguments(libraries, libDownloadPath) { @@ -603,10 +623,7 @@ export class BaseCompiler { let toolchainLibraryPaths = []; if (this.toolchainPath) { - toolchainLibraryPaths = [ - path.join(this.toolchainPath, '/lib64'), - path.join(this.toolchainPath, '/lib32'), - ]; + toolchainLibraryPaths = [path.join(this.toolchainPath, '/lib64'), path.join(this.toolchainPath, '/lib32')]; } if (!libDownloadPath) { @@ -619,7 +636,8 @@ export class BaseCompiler { this.compiler.libPath.map(path => pathFlag + path), toolchainLibraryPaths.map(path => pathFlag + path), this.getSharedLibraryPaths(libraries).map(path => pathFlag + path), - this.getSharedLibraryPaths(libraries).map(path => libPathFlag + path)); + this.getSharedLibraryPaths(libraries).map(path => libPathFlag + path) + ); } getSharedLibraryPathsAsLdLibraryPaths(libraries) { @@ -627,9 +645,7 @@ export class BaseCompiler { if (!this.alwaysResetLdPath) { paths = process.env.LD_LIBRARY_PATH ? process.env.LD_LIBRARY_PATH : []; } - return _.union(paths, - this.compiler.ldPath, - this.getSharedLibraryPaths(libraries)); + return _.union(paths, this.compiler.ldPath, this.getSharedLibraryPaths(libraries)); } getSharedLibraryPathsAsLdLibraryPathsForExecution(libraries) { @@ -637,30 +653,31 @@ export class BaseCompiler { if (!this.alwaysResetLdPath) { paths = process.env.LD_LIBRARY_PATH ? process.env.LD_LIBRARY_PATH : []; } - return _.union(paths, - this.compiler.ldPath, - this.compiler.libPath, - this.getSharedLibraryPaths(libraries)); + return _.union(paths, this.compiler.ldPath, this.compiler.libPath, this.getSharedLibraryPaths(libraries)); } getIncludeArguments(libraries) { const includeFlag = this.compiler.includeFlag || '-I'; - return _.flatten(_.map(libraries, (selectedLib) => { - const foundVersion = this.findLibVersion(selectedLib); - if (!foundVersion) return false; + return _.flatten( + _.map(libraries, selectedLib => { + const foundVersion = this.findLibVersion(selectedLib); + if (!foundVersion) return false; - return _.map(foundVersion.path, (path) => includeFlag + path); - })); + return _.map(foundVersion.path, path => includeFlag + path); + }) + ); } getLibraryOptions(libraries) { - return _.flatten(_.map(libraries, (selectedLib) => { - const foundVersion = this.findLibVersion(selectedLib); - if (!foundVersion) return false; + return _.flatten( + _.map(libraries, selectedLib => { + const foundVersion = this.findLibVersion(selectedLib); + if (!foundVersion) return false; - return foundVersion.options; - })); + return foundVersion.options; + }) + ); } orderArguments(options, inputFilename, libIncludes, libOptions, libPaths, libLinks, userOptions, staticLibLinks) { @@ -671,7 +688,7 @@ export class BaseCompiler { libOptions, libPaths, libLinks, - staticLibLinks, + staticLibLinks ); } @@ -702,14 +719,15 @@ export class BaseCompiler { } userOptions = this.filterUserOptions(userOptions) || []; - return this.orderArguments(options, + return this.orderArguments( + options, inputFilename, libIncludes, libOptions, libPaths, libLinks, userOptions, - staticLibLinks, + staticLibLinks ); } @@ -719,15 +737,19 @@ export class BaseCompiler { async generateAST(inputFilename, options) { // These options make Clang produce an AST dump - const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics') - .concat(['-Xclang', '-ast-dump', '-fsyntax-only']); + const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics').concat([ + '-Xclang', + '-ast-dump', + '-fsyntax-only', + ]); const execOptions = this.getDefaultExecOptions(); // A higher max output is needed for when the user includes headers execOptions.maxOutput = 1024 * 1024 * 1024; return this.llvmAst.processAst( - await this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions)); + await this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions) + ); } async generatePP(inputFilename, compilerOptions, rawPpOptions) { @@ -737,16 +759,23 @@ export class BaseCompiler { compilerOptions.splice(compilerOptions.indexOf('-o'), 2); } - let ppOptions = _.extend({ - 'filter-headers': false, - 'clang-format': false, - }, rawPpOptions); - + let ppOptions = _.extend( + { + 'filter-headers': false, + 'clang-format': false, + }, + rawPpOptions + ); + const execOptions = this.getDefaultExecOptions(); // A higher max output is needed for when the user includes headers execOptions.maxOutput = 1024 * 1024 * 1024; - let result = await this.runCompilerRawOutput(this.compiler.exe, compilerOptions, - this.filename(inputFilename), execOptions); + let result = await this.runCompilerRawOutput( + this.compiler.exe, + compilerOptions, + this.filename(inputFilename), + execOptions + ); let output = result.stdout; let numberOfLinesFiltered = 0; @@ -787,8 +816,13 @@ export class BaseCompiler { } } else { let path = match[1]; - if (path.trim() === '' || path === '<source>' || path === '<stdin>' - || path.endsWith('.c') || path.endsWith('.cpp')) { + if ( + path.trim() === '' || + path === '<source>' || + path === '<stdin>' || + path.endsWith('.c') || + path.endsWith('.cpp') + ) { isInSourceRegion = true; } else { isInSourceRegion = false; @@ -815,8 +849,7 @@ export class BaseCompiler { async generateIR(inputFilename, options, filters) { // These options make Clang produce an IR - const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics') - .concat(this.compiler.irArg); + const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics').concat(this.compiler.irArg); const execOptions = this.getDefaultExecOptions(); // A higher max output is needed for when the user includes headers @@ -858,21 +891,20 @@ export class BaseCompiler { // Currently called for getting macro expansion and HIR. // It returns the content of the output file created after using -Z unpretty=<unprettyOpt>. // The outputFriendlyName is a free form string used in case of error. - async generateRustUnprettyOutput(inputFilename, options, unprettyOpt, outputFilename, outputFriendlyName){ + async generateRustUnprettyOutput(inputFilename, options, unprettyOpt, outputFilename, outputFriendlyName) { const execOptions = this.getDefaultExecOptions(); const rustcOptions = [...options]; rustcOptions.splice(options.indexOf('-o', 2)); rustcOptions.push(inputFilename, '-o', outputFilename, `-Zunpretty=${unprettyOpt}`); - const output = await this.runCompiler(this.compiler.exe, rustcOptions, inputFilename, - execOptions); + const output = await this.runCompiler(this.compiler.exe, rustcOptions, inputFilename, execOptions); if (output.code !== 0) { return [{text: `Failed to run compiler to get Rust ${outputFriendlyName}`}]; } if (await fs.exists(outputFilename)) { const content = await fs.readFile(outputFilename, 'utf-8'); - return content.split('\n').map((line) => ({ + return content.split('\n').map(line => ({ text: line, })); } @@ -896,7 +928,7 @@ export class BaseCompiler { } if (await fs.exists(mirPath)) { const content = await fs.readFile(mirPath, 'utf-8'); - return content.split('\n').map((line) => ({ + return content.split('\n').map(line => ({ text: line, })); } @@ -964,7 +996,7 @@ export class BaseCompiler { if (isInExpandedCode) { contentDebugExpanded.push(obj); - } else if (isInTree){ + } else if (isInTree) { contentDebugTree.push(obj); } else { keep_stdout.push(obj); @@ -979,8 +1011,9 @@ export class BaseCompiler { if (result.code !== 0) { contentDebugExpanded.push({text: 'GNAT exited with an error and did not create the expanded code'}); } else { - contentDebugExpanded.push( - {text: 'GNAT exited successfully but the expanded code is missing, something is wrong'}); + contentDebugExpanded.push({ + text: 'GNAT exited successfully but the expanded code is missing, something is wrong', + }); } if (contentDebugTree.length === 0) @@ -1007,10 +1040,9 @@ export class BaseCompiler { * created using a targeted option (eg. -fdump-rtl-expand) */ fromInternalGccDumpName(internalDumpName, selectedPasses) { - if (!selectedPasses) - selectedPasses = ['ipa', 'tree', 'rtl']; + if (!selectedPasses) selectedPasses = ['ipa', 'tree', 'rtl']; - const internalNameRe = new RegExp('^\\s*(' + selectedPasses.join('|') +')-([\\w_-]+).*ON$'); + const internalNameRe = new RegExp('^\\s*(' + selectedPasses.join('|') + ')-([\\w_-]+).*ON$'); const match = internalDumpName.match(internalNameRe); if (match) return { @@ -1018,8 +1050,7 @@ export class BaseCompiler { name: match[2] + ' (' + match[1] + ')', command_prefix: `-fdump-${match[1]}-${match[2]}`, }; - else - return null; + else return null; } async checkOutputFileAndDoPostProcess(asmResult, outputFilename, filters) { @@ -1037,13 +1068,17 @@ export class BaseCompiler { if (tools) { for (const tool of tools) { const matches = this.possibleTools.find(possibleTool => { - return possibleTool.getId() === tool.id && - possibleTool.getType() === type; + return possibleTool.getId() === tool.id && possibleTool.getType() === type; }); if (matches) { - const toolPromise = matches.runTool(compilationInfo, - compilationInfo.inputFilename, tool.args, tool.stdin, this.supportedLibraries); + const toolPromise = matches.runTool( + compilationInfo, + compilationInfo.inputFilename, + tool.args, + tool.stdin, + this.supportedLibraries + ); tooling.push(toolPromise); } } @@ -1059,7 +1094,7 @@ export class BaseCompiler { async getRequiredLibraryVersions(libraries) { const libraryDetails = {}; - _.each(libraries, (selectedLib) => { + _.each(libraries, selectedLib => { const foundVersion = this.findLibVersion(selectedLib); if (foundVersion) libraryDetails[selectedLib.id] = foundVersion; }); @@ -1133,16 +1168,21 @@ export class BaseCompiler { buildFilters.execute = true; const compilerArguments = _.compact( - this.prepareArguments(key.options, buildFilters, key.backendOptions, - inputFilename, outputFilename, key.libraries), + this.prepareArguments( + key.options, + buildFilters, + key.backendOptions, + inputFilename, + outputFilename, + key.libraries + ) ); const execOptions = this.getDefaultExecOptions(); execOptions.ldPath = this.getSharedLibraryPathsAsLdLibraryPaths(key.libraries); const downloads = await buildEnvironment; - const result = await this.buildExecutable(key.compiler.exe, compilerArguments, inputFilename, - execOptions); + const result = await this.buildExecutable(key.compiler.exe, compilerArguments, inputFilename, execOptions); result.downloads = downloads; @@ -1253,8 +1293,7 @@ export class BaseCompiler { } async handleExecution(key, executeParameters) { - if (this.compiler.interpreted) - return this.handleInterpreting(key, executeParameters); + if (this.compiler.interpreted) return this.handleInterpreting(key, executeParameters); const buildResult = await this.getOrBuildExecutable(key); if (buildResult.code !== 0) { return { @@ -1265,7 +1304,7 @@ export class BaseCompiler { stdout: [], }; } else { - if (!await utils.fileExists(buildResult.executableFilename)) { + if (!(await utils.fileExists(buildResult.executableFilename))) { const verboseResult = { code: -1, didExecute: false, @@ -1317,9 +1356,15 @@ export class BaseCompiler { getCompilationInfo(key, result, customBuildPath) { const compilationinfo = Object.assign({}, key, result); compilationinfo.outputFilename = this.getOutputFilename( - customBuildPath || result.dirPath, this.outputFilebase, key); + customBuildPath || result.dirPath, + this.outputFilebase, + key + ); compilationinfo.executableFilename = this.getExecutableFilename( - customBuildPath || result.dirPath, this.outputFilebase, key); + customBuildPath || result.dirPath, + this.outputFilebase, + key + ); compilationinfo.asmParser = this.asm; return compilationinfo; } @@ -1329,7 +1374,7 @@ export class BaseCompiler { const detectedLibs = []; const foundlibOptions = []; - _.each(libsAndOptions.options, (option) => { + _.each(libsAndOptions.options, option => { if (option.indexOf(linkFlag) === 0) { const libVersion = this.findAutodetectStaticLibLink(option.substr(linkFlag.length).trim()); if (libVersion) { @@ -1340,7 +1385,7 @@ export class BaseCompiler { }); if (detectedLibs.length > 0) { - libsAndOptions.options = _.filter(libsAndOptions.options, (option) => !foundlibOptions.includes(option)); + libsAndOptions.options = _.filter(libsAndOptions.options, option => !foundlibOptions.includes(option)); libsAndOptions.libraries = _.union(libsAndOptions.libraries, detectedLibs); return true; @@ -1360,7 +1405,7 @@ export class BaseCompiler { const outputFilename = this.getOutputFilename(dirPath, this.outputFilebase, key); options = _.compact( - this.prepareArguments(options, filters, backendOptions, inputFilename, outputFilename, libraries), + this.prepareArguments(options, filters, backendOptions, inputFilename, outputFilename, libraries) ); const execOptions = this.getDefaultExecOptions(); @@ -1374,46 +1419,45 @@ export class BaseCompiler { const makeRustMir = backendOptions.produceRustMir && this.compiler.supportsRustMirView; const makeRustMacroExp = backendOptions.produceRustMacroExp && this.compiler.supportsRustMacroExpView; const makeRustHir = backendOptions.produceRustHir && this.compiler.supportsRustHirView; - const makeGccDump = backendOptions.produceGccDump && backendOptions.produceGccDump.opened - && this.compiler.supportsGccDump; + const makeGccDump = + backendOptions.produceGccDump && backendOptions.produceGccDump.opened && this.compiler.supportsGccDump; const downloads = await buildEnvironment; - const [ - asmResult, - astResult, - ppResult, - irResult, - rustHirResult, - rustMacroExpResult, - toolsResult, - ] = await Promise.all([ - this.runCompiler(this.compiler.exe, options, inputFilenameSafe, execOptions), - (makeAst ? this.generateAST(inputFilename, options) : ''), - (makePp ? this.generatePP(inputFilename, options, backendOptions.producePp) : ''), - (makeIr ? this.generateIR(inputFilename, options, filters) : ''), - (makeRustHir ? this.generateRustHir(inputFilename, options) : ''), - (makeRustMacroExp ? this.generateRustMacroExpansion(inputFilename, options) : ''), - Promise.all(this.runToolsOfType(tools, 'independent', this.getCompilationInfo(key, { - inputFilename, - dirPath, - outputFilename, - }))), - ]); + const [asmResult, astResult, ppResult, irResult, rustHirResult, rustMacroExpResult, toolsResult] = + await Promise.all([ + this.runCompiler(this.compiler.exe, options, inputFilenameSafe, execOptions), + makeAst ? this.generateAST(inputFilename, options) : '', + makePp ? this.generatePP(inputFilename, options, backendOptions.producePp) : '', + makeIr ? this.generateIR(inputFilename, options, filters) : '', + makeRustHir ? this.generateRustHir(inputFilename, options) : '', + makeRustMacroExp ? this.generateRustMacroExpansion(inputFilename, options) : '', + Promise.all( + this.runToolsOfType( + tools, + 'independent', + this.getCompilationInfo(key, { + inputFilename, + dirPath, + outputFilename, + }) + ) + ), + ]); // GNAT, GCC and rustc can produce their extra output files along // with the main compilation command. - const gnatDebugResults = ((makeGnatDebug || makeGnatDebugTree)? - await this.processGnatDebugOutput(inputFilenameSafe, asmResult) - : ''); - - const gccDumpResult = (makeGccDump ? - await this.processGccDumpOutput(backendOptions.produceGccDump, - asmResult, this.compiler.removeEmptyGccDump, - outputFilename) - : ''); - const rustMirResult = (makeRustMir ? - await this.processRustMirOutput(outputFilename, asmResult) - : ''); + const gnatDebugResults = + makeGnatDebug || makeGnatDebugTree ? await this.processGnatDebugOutput(inputFilenameSafe, asmResult) : ''; + + const gccDumpResult = makeGccDump + ? await this.processGccDumpOutput( + backendOptions.produceGccDump, + asmResult, + this.compiler.removeEmptyGccDump, + outputFilename + ) + : ''; + const rustMirResult = makeRustMir ? await this.processRustMirOutput(outputFilename, asmResult) : ''; asmResult.dirPath = dirPath; asmResult.compilationOptions = options; @@ -1492,11 +1536,11 @@ export class BaseCompiler { getCompilerEnvironmentVariables(compilerflags) { if (this.lang.id === 'c++') { - return { ...this.cmakeBaseEnv, CXXFLAGS: compilerflags }; + return {...this.cmakeBaseEnv, CXXFLAGS: compilerflags}; } else if (this.lang.id === 'fortran') { - return { ...this.cmakeBaseEnv, FFLAGS: compilerflags }; + return {...this.cmakeBaseEnv, FFLAGS: compilerflags}; } else { - return { ...this.cmakeBaseEnv, CFLAGS: compilerflags }; + return {...this.cmakeBaseEnv, CFLAGS: compilerflags}; } } @@ -1514,7 +1558,7 @@ export class BaseCompiler { code: -1, asm: [{text: `<${error.message}>`}], stdout: [], - stderr: [{text: `<${error.message}>` }], + stderr: [{text: `<${error.message}>`}], }; } @@ -1563,7 +1607,7 @@ export class BaseCompiler { stdout: [], }; - errorResult.stderr.push({text:'Compiler does not support compiling to binaries'}); + errorResult.stderr.push({text: 'Compiler does not support compiling to binaries'}); return errorResult; } @@ -1618,8 +1662,13 @@ export class BaseCompiler { const cmakeArgs = utils.splitArguments(key.backendOptions.cmakeArgs); const fullArgs = [toolchainparam, ...cmakeArgs, '..']; - const cmakeStepResult = await this.doBuildstepAndAddToResult(fullResult, 'cmake', this.env.ceProps('cmake'), - fullArgs, makeExecParams); + const cmakeStepResult = await this.doBuildstepAndAddToResult( + fullResult, + 'cmake', + this.env.ceProps('cmake'), + fullArgs, + makeExecParams + ); if (cmakeStepResult.code !== 0) { fullResult.result = { @@ -1631,8 +1680,13 @@ export class BaseCompiler { return fullResult; } - const makeStepResult = await this.doBuildstepAndAddToResult(fullResult, 'make', this.env.ceProps('make'), - [], execParams); + const makeStepResult = await this.doBuildstepAndAddToResult( + fullResult, + 'make', + this.env.ceProps('make'), + [], + execParams + ); if (makeStepResult.code !== 0) { fullResult.result = { @@ -1650,7 +1704,10 @@ export class BaseCompiler { }; const [asmResult] = await this.checkOutputFileAndDoPostProcess( - fullResult.result, outputFilename, cacheKey.filters); + fullResult.result, + outputFilename, + cacheKey.filters + ); fullResult.result = asmResult; if (this.lang.id === 'c++') { @@ -1683,8 +1740,18 @@ export class BaseCompiler { } const optOutput = undefined; - await this.afterCompilation(fullResult.result, false, cacheKey, [], key.tools, cacheKey.backendOptions, - cacheKey.filters, libsAndOptions.options, optOutput, path.join(dirPath, 'build')); + await this.afterCompilation( + fullResult.result, + false, + cacheKey, + [], + key.tools, + cacheKey.backendOptions, + cacheKey.filters, + libsAndOptions.options, + optOutput, + path.join(dirPath, 'build') + ); delete fullResult.result.dirPath; @@ -1698,9 +1765,7 @@ export class BaseCompiler { const joined = path.join(dirPath, filename); const normalized = path.normalize(joined); if (process.platform === 'win32') { - if (!normalized.replace(/\\/g, '/').startsWith( - dirPath.replace(/\\/g, '/')) - ) { + if (!normalized.replace(/\\/g, '/').startsWith(dirPath.replace(/\\/g, '/'))) { throw new Error('Invalid filename'); } } else { @@ -1750,8 +1815,10 @@ export class BaseCompiler { const result = await this.env.cacheGet(key); if (result) { const cacheRetreiveTimeEnd = process.hrtime.bigint(); - result.retreivedFromCacheTime = ((cacheRetreiveTimeEnd - cacheRetreiveTimeStart) / - BigInt(1000000)).toString(); + result.retreivedFromCacheTime = ( + (cacheRetreiveTimeEnd - cacheRetreiveTimeStart) / + BigInt(1000000) + ).toString(); result.retreivedFromCache = true; if (doExecute) { result.execResult = await this.env.enqueue(async () => { @@ -1788,15 +1855,42 @@ export class BaseCompiler { const inputFilename = writeSummary.inputFilename; const [result, optOutput] = await this.doCompilation( - inputFilename, dirPath, key, options, filters, backendOptions, libraries, tools); - - return await this.afterCompilation(result, doExecute, key, executeParameters, tools, backendOptions, - filters, options, optOutput); + inputFilename, + dirPath, + key, + options, + filters, + backendOptions, + libraries, + tools + ); + + return await this.afterCompilation( + result, + doExecute, + key, + executeParameters, + tools, + backendOptions, + filters, + options, + optOutput + ); }); } - async afterCompilation(result, doExecute, key, executeParameters, tools, backendOptions, filters, options, - optOutput, customBuildPath) { + async afterCompilation( + result, + doExecute, + key, + executeParameters, + tools, + backendOptions, + filters, + options, + optOutput, + customBuildPath + ) { // Start the execution as soon as we can, but only await it at the end. const execPromise = doExecute ? this.handleExecution(key, executeParameters) : null; @@ -1804,8 +1898,12 @@ export class BaseCompiler { delete result.optPath; result.optOutput = optOutput; } - result.tools = _.union(result.tools, await Promise.all(this.runToolsOfType(tools, 'postcompilation', - this.getCompilationInfo(key, result, customBuildPath)))); + result.tools = _.union( + result.tools, + await Promise.all( + this.runToolsOfType(tools, 'postcompilation', this.getCompilationInfo(key, result, customBuildPath)) + ) + ); result = this.extractDeviceCode(result, filters); @@ -1828,8 +1926,7 @@ export class BaseCompiler { result = filters.demangle ? await this.postProcessAsm(result, filters) : result; if (this.compiler.supportsCfg && backendOptions.produceCfg) { if (!options.includes('-emit-llvm')) { - result.cfg = cfg.generateStructure(this.compiler.compilerType, - this.compiler.version, result.asm); + result.cfg = cfg.generateStructure(this.compiler.compilerType, this.compiler.version, result.asm); } else { // for now do not generate a cfg for llvm ir result.cfg = {}; @@ -1873,7 +1970,8 @@ export class BaseCompiler { async processOptOutput(optPath) { const output = []; - const optStream = fs.createReadStream(optPath, {encoding: 'utf-8'}) + const optStream = fs + .createReadStream(optPath, {encoding: 'utf-8'}) .pipe(new compilerOptInfo.LLVMOptTransformer()); for await (const opt of optStream) { @@ -1885,8 +1983,7 @@ export class BaseCompiler { if (this.compiler.demangler) { const result = JSON.stringify(output, null, 4); try { - const demangleResult = await this.exec( - this.compiler.demangler, ['-n', '-p'], {input: result}); + const demangleResult = await this.exec(this.compiler.demangler, ['-n', '-p'], {input: result}); return JSON.parse(demangleResult.stdout); } catch (exception) { // swallow exception and return non-demangled output @@ -1910,9 +2007,7 @@ export class BaseCompiler { } isCfgCompiler(compilerVersion) { - return compilerVersion.includes('clang') || - compilerVersion.match(/^([\w-]*-)?g((\+\+)|(cc)|(dc))/g) !== null; - + return compilerVersion.includes('clang') || compilerVersion.match(/^([\w-]*-)?g((\+\+)|(cc)|(dc))/g) !== null; } async processGccDumpOutput(opts, result, removeEmptyPasses, outputFilename) { @@ -1943,21 +2038,24 @@ export class BaseCompiler { // Fake 2 lines as coming from -fdump-passes // This allows the insertion of 'gimple' and 'original' // tree dumps that are not really part of a tree pass. - treeDumpsNotInPasses.push ( - [ { text: 'tree-original: ON'}, - { - filename_suffix: 't.original', - name: 'original (tree)', - command_prefix: '-fdump-tree-original', - }, + treeDumpsNotInPasses.push( + [ + {text: 'tree-original: ON'}, + { + filename_suffix: 't.original', + name: 'original (tree)', + command_prefix: '-fdump-tree-original', + }, ], - [ { text: 'tree-gimple: ON'}, - { - filename_suffix: 't.gimple', - name: 'gimple (tree)', - command_prefix: '-fdump-tree-gimple', - }, - ]); + [ + {text: 'tree-gimple: ON'}, + { + filename_suffix: 't.gimple', + name: 'gimple (tree)', + command_prefix: '-fdump-tree-gimple', + }, + ] + ); } if (opts.ipaDump) selectedPasses.push('ipa'); @@ -1973,24 +2071,21 @@ export class BaseCompiler { const toRemoveFromStderr = /^\s*((ipa|tree|rtl)-)|(\*)([\w-]+).*(ON|OFF)$/; const dumpPassesLines = treeDumpsNotInPasses.concat( - Object.values(result.stderr).map( - x => [x, this.fromInternalGccDumpName(x.text, selectedPasses)])); + Object.values(result.stderr).map(x => [x, this.fromInternalGccDumpName(x.text, selectedPasses)]) + ); for (const [obj, selectizeObject] of dumpPassesLines) { if (selectizeObject) { - if (opts.pass && opts.pass.name === selectizeObject.name) - passFound = true; + if (opts.pass && opts.pass.name === selectizeObject.name) passFound = true; if (removeEmptyPasses) { const f = fs.readdirSync(rootDir).filter(fn => fn.endsWith(selectizeObject.filename_suffix)); // pass is enabled, but the dump hasn't produced anything: // don't add it to the drop down menu - if (f.length === 0) - continue; + if (f.length === 0) continue; - if (opts.pass && opts.pass.name === selectizeObject.name) - dumpFileName = path.join(rootDir, f[0]); + if (opts.pass && opts.pass.name === selectizeObject.name) dumpFileName = path.join(rootDir, f[0]); } output.all.push(selectizeObject); @@ -2002,10 +2097,10 @@ export class BaseCompiler { } result.stderr = filtered_stderr; - if (opts.pass && passFound){ + if (opts.pass && passFound) { output.currentPassOutput = ''; - if (dumpFileName && await fs.pathExists(dumpFileName)) + if (dumpFileName && (await fs.pathExists(dumpFileName))) output.currentPassOutput = await fs.readFile(dumpFileName, 'utf-8'); // else leave the currentPassOutput empty. Can happen when some // UI options are changed and a now disabled pass is still @@ -2030,9 +2125,7 @@ but nothing was dumped. Possible causes are: async execPostProcess(result, postProcesses, outputFilename, maxSize) { const postCommand = `cat "${outputFilename}" | ${postProcesses.join(' | ')}`; - return this.handlePostProcessResult( - result, - await this.exec('bash', ['-c', postCommand], {maxOutput: maxSize})); + return this.handlePostProcessResult(result, await this.exec('bash', ['-c', postCommand], {maxOutput: maxSize})); } preProcess(source, filters) { @@ -2043,29 +2136,30 @@ but nothing was dumped. Possible causes are: } async postProcess(result, outputFilename, filters) { - const postProcess = _.compact(this.compiler.postProcess); const maxSize = this.env.ceProps('max-asm-size', 64 * 1024 * 1024); const optPromise = result.hasOptOutput ? this.processOptOutput(result.optPath) : ''; - const asmPromise = (filters.binary && this.supportsObjdump()) - ? this.objdump(outputFilename, result, maxSize, filters.intel, filters.demangle) - : (async () => { - if (result.asmSize === undefined) { - result.asm = '<No output file>'; - return result; - } - if (result.asmSize >= maxSize) { - result.asm = `<No output: generated assembly was too large (${result.asmSize} > ${maxSize} bytes)>`; - return result; - } - if (postProcess.length > 0) { - return this.execPostProcess(result, postProcess, outputFilename, maxSize); - } else { - const contents = await fs.readFile(outputFilename); - result.asm = contents.toString(); - return result; - } - })(); + const asmPromise = + filters.binary && this.supportsObjdump() + ? this.objdump(outputFilename, result, maxSize, filters.intel, filters.demangle) + : (async () => { + if (result.asmSize === undefined) { + result.asm = '<No output file>'; + return result; + } + if (result.asmSize >= maxSize) { + const msg = 'No output: generated assembly was too large'; + result.asm += `<${msg} (${result.asmSize} > ${maxSize} bytes)>`; + return result; + } + if (postProcess.length > 0) { + return this.execPostProcess(result, postProcess, outputFilename, maxSize); + } else { + const contents = await fs.readFile(outputFilename); + result.asm = contents.toString(); + return result; + } + })(); return Promise.all([asmPromise, optPromise]); } @@ -2102,9 +2196,8 @@ but nothing was dumped. Possible causes are: getArgumentParser() { let exe = this.compiler.exe.toLowerCase(); - if (exe.includes('clang') - || exe.includes('icpx') - || exe.includes('icx')) { // check this first as "clang++" matches "g++" + if (exe.includes('clang') || exe.includes('icpx') || exe.includes('icx')) { + // check this first as "clang++" matches "g++" return ClangParser; } else if (exe.includes('g++') || exe.includes('gcc')) { return GCCParser; @@ -2134,8 +2227,7 @@ but nothing was dumped. Possible causes are: } initialiseLibraries(clientOptions) { - this.supportedLibraries = this.getSupportedLibraries(this.compiler.libsArr, - clientOptions.libs[this.lang.id]); + this.supportedLibraries = this.getSupportedLibraries(this.compiler.libsArr, clientOptions.libs[this.lang.id]); } async initialise(mtime, clientOptions, isPrediscovered = false) { @@ -2172,8 +2264,8 @@ but nothing was dumped. Possible causes are: this.compiler.version = version; this.compiler.fullVersion = fullVersion; this.compiler.supportsCfg = this.isCfgCompiler(version); - // all C/C++ compilers support -E - this.compiler.supportsPpView = (this.compiler.lang === 'c' || this.compiler.lang === 'c++'); + // all C/C++ compilers support -E + this.compiler.supportsPpView = this.compiler.lang === 'c' || this.compiler.lang === 'c++'; this.compiler.supportsAstView = this.couldSupportASTDump(version); } diff --git a/lib/buildenvsetup/ceconan.js b/lib/buildenvsetup/ceconan.js index 960326187..65493a599 100644 --- a/lib/buildenvsetup/ceconan.js +++ b/lib/buildenvsetup/ceconan.js @@ -30,12 +30,14 @@ import request from 'request'; import tar from 'tar-stream'; import _ from 'underscore'; -import { logger } from '../logger'; +import {logger} from '../logger'; -import { BuildEnvSetupBase } from './base'; +import {BuildEnvSetupBase} from './base'; export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase { - static get key() { return 'ceconan'; } + static get key() { + return 'ceconan'; + } constructor(compilerInfo, env, execCompilerCachedFunc) { super(compilerInfo, env, execCompilerCachedFunc); @@ -92,7 +94,7 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase { } async downloadAndExtractPackage(libId, version, downloadPath, packageUrl) { - return new Promise((resolve) => { + return new Promise(resolve => { const startTime = process.hrtime.bigint(); const extract = tar.extract(); const gunzip = zlib.createGunzip(); @@ -144,7 +146,7 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase { } async findMatchingHash(buildProperties, possibleBuilds) { - return _.findKey(possibleBuilds, (elem) => { + return _.findKey(possibleBuilds, elem => { return _.all(buildProperties, (val, key) => { return val === elem.settings[key]; }); @@ -178,9 +180,9 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase { if (hash) { logger.debug(`Found conan hash ${hash} for ${libVer}`); allDownloads.push( - this.getPackageUrl(libVerBuilds.id, lookupversion, hash).then((downloadUrl) => { + this.getPackageUrl(libVerBuilds.id, lookupversion, hash).then(downloadUrl => { return this.downloadAndExtractPackage(libVerBuilds.id, lookupversion, dirPath, downloadUrl); - }), + }) ); } else { logger.info(`No build found for ${libVer} matching ${JSON.stringify(buildProperties)}`); @@ -200,10 +202,10 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase { } hasBinariesToLink(details) { - return (details.libpath.length === 0) && ((details.staticliblink.length > 0) || (details.liblink.length > 0)); + return details.libpath.length === 0 && (details.staticliblink.length > 0 || details.liblink.length > 0); } hasAtLeastOneBinaryToLink(libraryDetails) { - return _.some(libraryDetails, (details) => this.hasBinariesToLink(details)); + return _.some(libraryDetails, details => this.hasBinariesToLink(details)); } } diff --git a/lib/clientstate-normalizer.js b/lib/clientstate-normalizer.js index ba349f36f..3d9387c1e 100644 --- a/lib/clientstate-normalizer.js +++ b/lib/clientstate-normalizer.js @@ -22,12 +22,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -import { - ClientState, - ClientStateCompiler, - ClientStateConformanceView, - ClientStateExecutor, -} from './clientstate'; +import {ClientState, ClientStateCompiler, ClientStateConformanceView, ClientStateExecutor} from './clientstate'; export class ClientStateNormalizer { constructor() { @@ -134,8 +129,7 @@ export class ClientStateNormalizer { const session = this.normalized.findOrCreateSession(component.componentState.id); session.language = component.componentState.lang; session.source = component.componentState.source; - if (component.componentState.filename) - session.filename = component.componentState.filename; + if (component.componentState.filename) session.filename = component.componentState.filename; } else if (component.componentName === 'compiler') { let compiler; if (component.componentState.id) { @@ -179,8 +173,7 @@ export class ClientStateNormalizer { executor.argumentsVisible = component.componentState.argsPanelShown; executor.stdin = component.componentState.execStdin; executor.stdinVisible = component.componentState.stdinPanelShown; - if (component.componentState.wrap) - executor.wrap = true; + if (component.componentState.wrap) executor.wrap = true; if (component.componentState.source) { const session = this.normalized.findOrCreateSession(component.componentState.source); @@ -192,27 +185,34 @@ export class ClientStateNormalizer { tree.executors.push(executor); } } else if (component.componentName === 'ast') { - this.addSpecialOutputToCompiler(component.componentState.id, 'ast', - component.componentState.editorid); + this.addSpecialOutputToCompiler(component.componentState.id, 'ast', component.componentState.editorid); } else if (component.componentName === 'opt') { - this.addSpecialOutputToCompiler(component.componentState.id, 'opt', - component.componentState.editorid); + this.addSpecialOutputToCompiler(component.componentState.id, 'opt', component.componentState.editorid); } else if (component.componentName === 'cfg') { - this.addSpecialOutputToCompiler(component.componentState.id, 'cfg', - component.componentState.editorid); + this.addSpecialOutputToCompiler(component.componentState.id, 'cfg', component.componentState.editorid); } else if (component.componentName === 'gccdump') { - this.addSpecialOutputToCompiler(component.componentState._compilerid, 'gccdump', - component.componentState._editorid); + this.addSpecialOutputToCompiler( + component.componentState._compilerid, + 'gccdump', + component.componentState._editorid + ); } else if (component.componentName === 'output') { - this.addSpecialOutputToCompiler(component.componentState.compiler, 'compilerOutput', - component.componentState.editor); + this.addSpecialOutputToCompiler( + component.componentState.compiler, + 'compilerOutput', + component.componentState.editor + ); } else if (component.componentName === 'conformance') { const session = this.normalized.findOrCreateSession(component.componentState.editorid); session.conformanceview = new ClientStateConformanceView(component.componentState); } else if (component.componentName === 'tool') { - this.addToolToCompiler(component.componentState.compiler, component.componentState.editor, - component.componentState.toolId, component.componentState.args, - component.componentState.stdin); + this.addToolToCompiler( + component.componentState.compiler, + component.componentState.editor, + component.componentState.toolId, + component.componentState.args, + component.componentState.stdin + ); } else if (component.content) { this.fromGoldenLayoutContent(component.content); } @@ -222,7 +222,7 @@ export class ClientStateNormalizer { fixFilesInTrees() { for (const tree of this.normalized.trees) { - tree.files = tree.files.filter((file) => file.isIncluded); + tree.files = tree.files.filter(file => file.isIncluded); for (const file of tree.files) { if (file.editorId) { @@ -297,7 +297,7 @@ class GoldenLayoutComponents { componentName: 'ast', componentState: { id: compilerIndex, - editorid: customSessionId ? customSessionId : (session ? session.id : undefined), + editorid: customSessionId ? customSessionId : session ? session.id : undefined, }, isClosable: true, reorderEnabled: true, @@ -310,7 +310,7 @@ class GoldenLayoutComponents { componentName: 'opt', componentState: { id: compilerIndex, - editorid: customSessionId ? customSessionId : (session ? session.id : undefined), + editorid: customSessionId ? customSessionId : session ? session.id : undefined, }, isClosable: true, reorderEnabled: true, @@ -323,7 +323,7 @@ class GoldenLayoutComponents { componentName: 'opt', componentState: { id: compilerIndex, - editorid: customSessionId ? customSessionId : (session ? session.id : undefined), + editorid: customSessionId ? customSessionId : session ? session.id : undefined, options: { navigation: false, physics: false, @@ -340,7 +340,7 @@ class GoldenLayoutComponents { componentName: 'gccdump', componentState: { _compilerid: compilerIndex, - _editorid: customSessionId ? customSessionId : (session ? session.id : undefined), + _editorid: customSessionId ? customSessionId : session ? session.id : undefined, }, isClosable: true, reorderEnabled: true, @@ -353,7 +353,7 @@ class GoldenLayoutComponents { componentName: 'output', componentState: { compiler: compilerIndex, - editor: customSessionId ? customSessionId : (session ? session.id : undefined), + editor: customSessionId ? customSessionId : session ? session.id : undefined, wrap: false, fontScale: 14, }, @@ -367,7 +367,7 @@ class GoldenLayoutComponents { type: 'component', componentName: 'tool', componentState: { - editor: customSessionId ? customSessionId : (session ? session.id : undefined), + editor: customSessionId ? customSessionId : session ? session.id : undefined, compiler: compilerIndex, toolId: toolId, args: args, @@ -534,7 +534,7 @@ class GoldenLayoutComponents { type: 'component', componentName: 'tool', componentState: { - tree: customTreeId ? customTreeId : (tree ? tree.id : undefined), + tree: customTreeId ? customTreeId : tree ? tree.id : undefined, compiler: compilerIndex, toolId: toolId, args: args, @@ -569,56 +569,44 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { } newTreeFromTree(tree, width) { - return this.newStackWithOneComponent(width, - this.createTreeComponent(tree), - ); + return this.newStackWithOneComponent(width, this.createTreeComponent(tree)); } newSourceStackFromSession(session, width) { - return this.newStackWithOneComponent(width, - this.createSourceComponent(session), - ); + return this.newStackWithOneComponent(width, this.createSourceComponent(session)); } newAstStackFromCompiler(session, compilerIndex, width) { - return this.newStackWithOneComponent(width, - this.createAstComponent(session, compilerIndex), - ); + return this.newStackWithOneComponent(width, this.createAstComponent(session, compilerIndex)); } newOptStackFromCompiler(session, compilerIndex, width) { - return this.newStackWithOneComponent(width, - this.createOptComponent(session, compilerIndex), - ); + return this.newStackWithOneComponent(width, this.createOptComponent(session, compilerIndex)); } newCfgStackFromCompiler(session, compilerIndex, width) { - return this.newStackWithOneComponent(width, - this.createCfgComponent(session, compilerIndex), - ); + return this.newStackWithOneComponent(width, this.createCfgComponent(session, compilerIndex)); } newGccDumpStackFromCompiler(session, compilerIndex, width) { - return this.newStackWithOneComponent(width, - this.createGccDumpComponent(session, compilerIndex), - ); + return this.newStackWithOneComponent(width, this.createGccDumpComponent(session, compilerIndex)); } newCompilerOutStackFromCompiler(session, compilerIndex, width) { - return this.newStackWithOneComponent(width, - this.createCompilerOutComponent(session, compilerIndex), - ); + return this.newStackWithOneComponent(width, this.createCompilerOutComponent(session, compilerIndex)); } newToolStackFromCompiler(session, compilerIndex, toolId, args, stdin, width) { - return this.newStackWithOneComponent(width, - this.createToolComponent(session, compilerIndex, toolId, args, stdin), + return this.newStackWithOneComponent( + width, + this.createToolComponent(session, compilerIndex, toolId, args, stdin) ); } newConformanceViewStack(session, width, conformanceview) { - const stack = this.newStackWithOneComponent(width, - this.createConformanceViewComponent(session, conformanceview), + const stack = this.newStackWithOneComponent( + width, + this.createConformanceViewComponent(session, conformanceview) ); for (const compiler of conformanceview.compilers) { @@ -634,15 +622,14 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { } newCompilerStackFromSession(session, compiler, width) { - return this.newStackWithOneComponent(width, - this.createCompilerComponent(session, compiler, false, compiler._internalId), + return this.newStackWithOneComponent( + width, + this.createCompilerComponent(session, compiler, false, compiler._internalId) ); } newExecutorStackFromSession(session, executor, width) { - return this.newStackWithOneComponent(width, - this.createExecutorComponent(session, executor), - ); + return this.newStackWithOneComponent(width, this.createExecutorComponent(session, executor)); } createSourceContentArray(state, left, right) { @@ -707,7 +694,8 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { type: 'column', width: 100, content: this.createSourceContentArray(state, left, left), - }]; + }, + ]; return gl; } @@ -748,34 +736,28 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { ], }, ], - }]; + }, + ]; let stack = gl.content[0].content[0].content[1].content[0]; for (let idxCompiler = 0; idxCompiler < tree.compilers.length; idxCompiler++) { const compiler = tree.compilers[idxCompiler]; - stack.content.push( - this.createCompilerComponentForTree(tree, compiler, customTreeId, idxCompiler + 1), - ); + stack.content.push(this.createCompilerComponentForTree(tree, compiler, customTreeId, idxCompiler + 1)); for (const viewtype of compiler.specialoutputs) { - stack.content.push( - this.createSpecialOutputComponentForTreeCompiler(viewtype, idxCompiler), - ); + stack.content.push(this.createSpecialOutputComponentForTreeCompiler(viewtype, idxCompiler)); } for (const tool of compiler.tools) { stack.content.push( - this.createToolComponentForTreeCompiler(tree, idxCompiler + 1, tool.id, - tool.args, tool.stdin), + this.createToolComponentForTreeCompiler(tree, idxCompiler + 1, tool.id, tool.args, tool.stdin) ); } } for (let idxExecutor = 0; idxExecutor < tree.executors.length; idxExecutor++) { - stack.content.push( - this.createExecutorComponentForTree(tree, tree.executors[idxExecutor], customTreeId), - ); + stack.content.push(this.createExecutorComponentForTree(tree, tree.executors[idxExecutor], customTreeId)); } return gl; @@ -796,9 +778,7 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { { type: 'stack', width: 100, - content: [ - this.createDiffComponent(left.compiler + 1, right.compiler + 1), - ], + content: [this.createDiffComponent(left.compiler + 1, right.compiler + 1)], }, ], }, @@ -812,34 +792,26 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { type: 'stack', width: customWidth ? customWidth : 50, activeItemIndex: 0, - content: [ - this.createSourceComponent(session, customSessionId), - ], + content: [this.createSourceComponent(session, customSessionId)], }; for (let idxCompiler = 0; idxCompiler < session.compilers.length; idxCompiler++) { const compiler = session.compilers[idxCompiler]; - stack.content.push( - this.createCompilerComponent(session, compiler, customSessionId), - ); + stack.content.push(this.createCompilerComponent(session, compiler, customSessionId)); for (const viewtype of compiler.specialoutputs) { - stack.content.push( - this.createSpecialOutputComponent(viewtype, session, idxCompiler, customSessionId), - ); + stack.content.push(this.createSpecialOutputComponent(viewtype, session, idxCompiler, customSessionId)); } for (const tool of compiler.tools) { stack.content.push( - this.createToolComponent(false, idxCompiler + 1, tool.id, tool.args, tool.stdin, customSessionId), + this.createToolComponent(false, idxCompiler + 1, tool.id, tool.args, tool.stdin, customSessionId) ); } } for (let idxExecutor = 0; idxExecutor < session.executors.length; idxExecutor++) { - stack.content.push( - this.createExecutorComponent(session, session.executors[idxExecutor], customSessionId), - ); + stack.content.push(this.createExecutorComponent(session, session.executors[idxExecutor], customSessionId)); } return stack; @@ -855,7 +827,7 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { }); slides.push(gl); } - + return slides; } @@ -967,8 +939,11 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { let stack = this.newSourceStackFromSession(session, 100); this.golden.content[0].content[idxSession].content[0].content.push(stack); - const compilerWidth = 100 / - (1 + session.compilers.length + session.executors.length + + const compilerWidth = + 100 / + (1 + + session.compilers.length + + session.executors.length + session.countNumberOfSpecialOutputsAndTools()); if (session.conformanceview) { @@ -982,8 +957,10 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { this.golden.content[0].content[idxSession].content[1].content.push(stack); for (const viewtype of compiler.specialoutputs) { - let stack = this.newStackWithOneComponent(compilerWidth, - this.createSpecialOutputComponent(viewtype, session, idxCompiler)); + let stack = this.newStackWithOneComponent( + compilerWidth, + this.createSpecialOutputComponent(viewtype, session, idxCompiler) + ); if (stack) { this.golden.content[0].content[idxSession].content[1].content.push(stack); @@ -991,8 +968,14 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { } for (const tool of compiler.tools) { - let stack = this.newToolStackFromCompiler(session, idxCompiler + 1, - tool.id, tool.args, tool.stdin, compilerWidth); + let stack = this.newToolStackFromCompiler( + session, + idxCompiler + 1, + tool.id, + tool.args, + tool.stdin, + compilerWidth + ); this.golden.content[0].content[idxSession].content[1].content.push(stack); } } @@ -1010,8 +993,12 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { content: [], }; - const width = 100 / (1 + session.compilers.length + session.executors.length + - session.countNumberOfSpecialOutputsAndTools()); + const width = + 100 / + (1 + + session.compilers.length + + session.executors.length + + session.countNumberOfSpecialOutputsAndTools()); this.golden.content[0].content.push(this.newSourceStackFromSession(session, width)); if (session.conformanceview) { @@ -1025,8 +1012,10 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { this.golden.content[0].content.push(stack); for (const viewtype of compiler.specialoutputs) { - let stack = this.newStackWithOneComponent(width, - this.createSpecialOutputComponent(viewtype, session, idxCompiler)); + let stack = this.newStackWithOneComponent( + width, + this.createSpecialOutputComponent(viewtype, session, idxCompiler) + ); if (stack) { this.golden.content[0].content.push(stack); @@ -1034,8 +1023,15 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents { } for (const tool of compiler.tools) { - let stack = this.newToolStackFromCompiler(session, compiler, idxCompiler + 1, - tool.id, tool.args, tool.stdin, width); + let stack = this.newToolStackFromCompiler( + session, + compiler, + idxCompiler + 1, + tool.id, + tool.args, + tool.stdin, + width + ); this.golden.content[0].content.push(stack); } } diff --git a/lib/compiler-arguments.js b/lib/compiler-arguments.js index 6a9d5c430..a87962396 100644 --- a/lib/compiler-arguments.js +++ b/lib/compiler-arguments.js @@ -25,8 +25,8 @@ import AWS from 'aws-sdk'; import _ from 'underscore'; -import { logger } from './logger'; -import { S3Bucket } from './s3-handler'; +import {logger} from './logger'; +import {S3Bucket} from './s3-handler'; export class CompilerArguments { constructor(compilerId) { @@ -83,7 +83,7 @@ export class CompilerArguments { let arr = _.pairs(possibleArguments); arr.sort((a, b) => { - if ((a[1].timesused === 0) && (b[1].timesused === 0)) { + if (a[1].timesused === 0 && b[1].timesused === 0) { // prefer optimization flags or standard if statistics are not available if (a[1].description.includes('optimization')) { return -1; @@ -99,7 +99,7 @@ export class CompilerArguments { return 1; } } else { - return (b[1].timesused - a[1].timesused); + return b[1].timesused - a[1].timesused; } }); arr = _.first(arr, this.maxPopularArguments); @@ -111,9 +111,11 @@ export class CompilerArguments { } match(documentedOption, givenOption) { - if (documentedOption.includes('<number>') - || documentedOption.includes('<n>') - || documentedOption.includes('=val')) { + if ( + documentedOption.includes('<number>') || + documentedOption.includes('<n>') || + documentedOption.includes('=val') + ) { const numre = /\d*$/i; if (documentedOption.indexOf(givenOption.replace(numre, '')) === 0) { return documentedOption; @@ -155,15 +157,13 @@ export class CompilerArguments { addOptionToStatistics(option, timesUsed) { if (!timesUsed) timesUsed = 1; - const possibleKeys = _.compact( - _.keys(this.possibleArguments).map((val) => this.match(val, option)), - ); + const possibleKeys = _.compact(_.keys(this.possibleArguments).map(val => this.match(val, option))); for (const key of possibleKeys) { if (this.possibleArguments[key]) { this.possibleArguments[key].timesused += timesUsed; - if (this.storeSpecificArguments && (key !== option)) { + if (this.storeSpecificArguments && key !== option) { if (!this.possibleArguments[key].specifically) { this.possibleArguments[key].specifically = []; } diff --git a/lib/compiler-finder.js b/lib/compiler-finder.js index 9f5645b4a..73a12e52a 100644 --- a/lib/compiler-finder.js +++ b/lib/compiler-finder.js @@ -25,14 +25,14 @@ import http from 'http'; import https from 'https'; import path from 'path'; -import { promisify } from 'util'; +import {promisify} from 'util'; import fs from 'fs-extra'; import _ from 'underscore'; import urljoin from 'url-join'; -import { InstanceFetcher } from './aws'; -import { logger } from './logger'; +import {InstanceFetcher} from './aws'; +import {logger} from './logger'; const sleep = promisify(setTimeout); @@ -72,59 +72,70 @@ export class CompilerFinder { return this.retryPromise( () => { return new Promise((resolve, reject) => { - const request = requestLib.get({ - hostname: host, - port: port, - path: apiPath, - headers: { - Accept: 'application/json', - }, - }, res => { - let error; - const {statusCode, headers: {'content-type': contentType}} = res; - - if (statusCode !== 200) { - error = new Error('Failed fetching remote compilers from ' + - `${uriSchema}://${host}:${port}${apiPath}\n` + - `Status Code: ${statusCode}`); - } else if (!/^application\/json/.test(contentType)) { - error = new Error('Invalid content-type.\n' + - `Expected application/json but received ${contentType}`); - } - if (error) { - logger.error(error.message); - // consume response data to free up memory - res.resume(); - reject(error); - return; - } - let str = ''; - res.on('data', chunk => { - str += chunk; - }); - res.on('end', () => { - try { - const compilers = JSON.parse(str).map(compiler => { - // Fix up old upstream implementations of Compiler Explorer - // e.g. https://www.godbolt.ms - // (see https://github.com/compiler-explorer/compiler-explorer/issues/1768) - if (!compiler.alias) compiler.alias = []; - if (typeof compiler.alias == 'string') compiler.alias = [compiler.alias]; - // End fixup - compiler.exe = null; - compiler.remote = { - target: `${uriSchema}://${host}:${port}`, - path: urljoin('/', uriBase, 'api/compiler', compiler.id, 'compile'), - }; - return compiler; + const request = requestLib + .get( + { + hostname: host, + port: port, + path: apiPath, + headers: { + Accept: 'application/json', + }, + }, + res => { + let error; + const { + statusCode, + headers: {'content-type': contentType}, + } = res; + + if (statusCode !== 200) { + error = new Error( + 'Failed fetching remote compilers from ' + + `${uriSchema}://${host}:${port}${apiPath}\n` + + `Status Code: ${statusCode}` + ); + } else if (!/^application\/json/.test(contentType)) { + error = new Error( + 'Invalid content-type.\n' + + `Expected application/json but received ${contentType}` + ); + } + if (error) { + logger.error(error.message); + // consume response data to free up memory + res.resume(); + reject(error); + return; + } + let str = ''; + res.on('data', chunk => { + str += chunk; + }); + res.on('end', () => { + try { + const compilers = JSON.parse(str).map(compiler => { + // Fix up old upstream implementations of Compiler Explorer + // e.g. https://www.godbolt.ms + // (see https://github.com/compiler-explorer/compiler-explorer/issues/1768) + if (!compiler.alias) compiler.alias = []; + if (typeof compiler.alias == 'string') compiler.alias = [compiler.alias]; + // End fixup + compiler.exe = null; + compiler.remote = { + target: `${uriSchema}://${host}:${port}`, + path: urljoin('/', uriBase, 'api/compiler', compiler.id, 'compile'), + }; + return compiler; + }); + resolve(compilers); + } catch (e) { + logger.error(`Error parsing response from ${uri} '${str}': ${e.message}`); + reject(e); + } }); - resolve(compilers); - } catch (e) { - logger.error(`Error parsing response from ${uri} '${str}': ${e.message}`); - reject(e); } - }); - }) + ) .on('error', reject) .on('timeout', () => reject('timeout')); request.setTimeout(this.awsProps('proxyTimeout', 1000)); @@ -132,7 +143,7 @@ export class CompilerFinder { }, `${host}:${port}`, props('proxyRetries', 5), - props('proxyRetryMs', 500), + props('proxyRetryMs', 500) ).catch(() => { logger.warn(`Unable to contact ${host}:${port}; skipping`); return []; @@ -142,11 +153,15 @@ export class CompilerFinder { async fetchAws() { logger.info('Fetching instances from AWS'); const instances = await this.awsInstances(); - return Promise.all(instances.map(instance => { - logger.info('Checking instance ' + instance.InstanceId); - const address = this.awsProps('externalTestMode', false) ? instance.PublicDnsName : instance.PrivateDnsName; - return this.fetchRemote(address, this.args.port, '', this.awsProps, null); - })); + return Promise.all( + instances.map(instance => { + logger.info('Checking instance ' + instance.InstanceId); + const address = this.awsProps('externalTestMode', false) + ? instance.PublicDnsName + : instance.PrivateDnsName; + return this.fetchRemote(address, this.args.port, '', this.awsProps, null); + }) + ); } async compilerConfigFor(langId, compilerName, parentProps) { @@ -199,7 +214,7 @@ export class CompilerFinder { id: compilerName, exe: exe, name: isSemVer && baseName ? `${baseName} ${semverVer}` : name, - alias: _.filter(props('alias', '').split(':'), (a) => a !== ''), + alias: _.filter(props('alias', '').split(':'), a => a !== ''), options: actualOptions, versionFlag: props('versionFlag'), versionRe: props('versionRe'), @@ -237,9 +252,9 @@ export class CompilerFinder { isSemVer: isSemVer, semver: semverVer, libsArr: this.getSupportedLibrariesArr(props, langId), - tools: _.omit( - this.optionsHandler.get().tools[langId], - tool => tool.isCompilerExcluded(compilerName, props)), + tools: _.omit(this.optionsHandler.get().tools[langId], tool => + tool.isCompilerExcluded(compilerName, props) + ), unwiseOptions: props('unwiseOptions', '').split('|'), hidden: props('hidden', false), buildenvsetup: { @@ -251,15 +266,17 @@ export class CompilerFinder { }; if (props('demanglerClassFile') !== undefined) { - logger.error(`Error in compiler.${compilerName}: ` + - 'demanglerClassFile is no longer supported, please use demanglerType'); + logger.error( + `Error in compiler.${compilerName}: ` + + 'demanglerClassFile is no longer supported, please use demanglerType' + ); return []; } if (process.platform === 'win32') { - compilerInfo.libPath = compilerInfo.libPath.split(';').filter((p) => p !== ''); + compilerInfo.libPath = compilerInfo.libPath.split(';').filter(p => p !== ''); } else { - compilerInfo.libPath = compilerInfo.libPath.split(':').filter((p) => p !== ''); + compilerInfo.libPath = compilerInfo.libPath.split(':').filter(p => p !== ''); } logger.debug('Found compiler', compilerInfo); @@ -267,7 +284,7 @@ export class CompilerFinder { } getSupportedLibrariesArr(props) { - return _.filter(props('supportsLibraries', '').split(':'), (a) => a !== ''); + return _.filter(props('supportsLibraries', '').split(':'), a => a !== ''); } async recurseGetCompilers(langId, compilerName, parentProps) { @@ -315,8 +332,11 @@ export class CompilerFinder { _.each(ids, (list, id) => { if (list.length !== 1) { foundClash = true; - logger.error(`Compiler ID clash for '${id}' - used by ${ - _.map(list, o => `lang:${o.lang} name:${o.name}`).join(', ')}`); + logger.error( + `Compiler ID clash for '${id}' - used by ${_.map(list, o => `lang:${o.lang} name:${o.name}`).join( + ', ' + )}` + ); } }); return {compilers, foundClash}; @@ -327,7 +347,7 @@ export class CompilerFinder { try { return await promiseFunc(); } catch (e) { - if (fails < (maxFails - 1)) { + if (fails < maxFails - 1) { logger.warn(`Failed ${name} : ${e}, retrying`); await sleep(retryMs); } else { @@ -367,7 +387,9 @@ export class CompilerFinder { async find() { const compilerList = await this.getCompilers(); const compilers = await this.compileHandler.setCompilers( - compilerList.flat(Infinity), this.optionsHandler.get()); + compilerList.flat(Infinity), + this.optionsHandler.get() + ); const result = this.ensureDistinct(_.compact(compilers)); return {foundClash: result.foundClash, compilers: _.sortBy(result.compilers, 'name')}; } diff --git a/lib/compilers/ada.js b/lib/compilers/ada.js index 8b33ae269..936f173d9 100644 --- a/lib/compilers/ada.js +++ b/lib/compilers/ada.js @@ -24,11 +24,13 @@ import path from 'path'; -import { BaseCompiler } from '../base-compiler'; +import {BaseCompiler} from '../base-compiler'; import * as utils from '../utils'; export class AdaCompiler extends BaseCompiler { - static get key() { return 'ada'; } + static get key() { + return 'ada'; + } constructor(info, env) { super(info, env); @@ -51,9 +53,9 @@ export class AdaCompiler extends BaseCompiler { return path.join(dirPath, 'example.o'); } - optionsForBackend(backendOptions, outputFilename){ + optionsForBackend(backendOptions, outputFilename) { // super is needed as it handles the GCC Dump files. - const opts = super.optionsForBackend (backendOptions, outputFilename); + const opts = super.optionsForBackend(backendOptions, outputFilename); if (backendOptions.produceGnatDebug && this.compiler.supportsGnatDebugViews) // This is using stdout @@ -86,7 +88,7 @@ export class AdaCompiler extends BaseCompiler { '-eS', // commands are not errors '-cargs', // Compiler Switches for gcc. '-o', - outputFilename, + outputFilename ); if (this.compiler.intelAsm && filters.intel) { @@ -100,7 +102,7 @@ export class AdaCompiler extends BaseCompiler { 'make', '-eS', '-g', - '-cargs', // Compiler Switches for gcc. + '-cargs' // Compiler Switches for gcc. ); } @@ -126,9 +128,7 @@ export class AdaCompiler extends BaseCompiler { // If the compiler contains a RTS, add the extra --RTS=. // FIXME: should probably check the user did not use one. if (this.compiler.adarts) { - options.splice(i, 0, - `--RTS=${this.compiler.adarts}`, - ); + options.splice(i, 0, `--RTS=${this.compiler.adarts}`); } break; } diff --git a/lib/compilers/clean.js b/lib/compilers/clean.js index 572b91829..2d81b28bd 100644 --- a/lib/compilers/clean.js +++ b/lib/compilers/clean.js @@ -76,44 +76,21 @@ export class CleanCompiler extends BaseCompiler { if (!matches) matches = line.match(typeeerrorRegex); if (matches) { - return ( - '<source>:' + - matches[1] + - ',0: error: (' + - matches[2] + - ') ' + - matches[3] - ); + return '<source>:' + matches[1] + ',0: error: (' + matches[2] + ') ' + matches[3]; } matches = line.match(errorLineRegex); if (matches) { - return ( - '<source>:' + matches[1] + ',0: error: ' + matches[2] - ); + return '<source>:' + matches[1] + ',0: error: ' + matches[2]; } matches = line.match(parseerrorRegex); if (matches) { if (matches[3] === '') { - return ( - '<source>:' + - matches[1] + - ',' + - matches[2] + - ': error: ' + - matches[4] - ); + return '<source>:' + matches[1] + ',' + matches[2] + ': error: ' + matches[4]; } else { return ( - '<source>:' + - matches[1] + - ',' + - matches[2] + - ': error: (' + - matches[3] + - ') ' + - matches[4] + '<source>:' + matches[1] + ',' + matches[2] + ': error: (' + matches[3] + ') ' + matches[4] ); } } @@ -132,9 +109,7 @@ export class CleanCompiler extends BaseCompiler { execOptions.customCwd = tmpDir; if (await utils.dirExists(path.join(compilerPath, '../exe'))) { execOptions.env.CLEANLIB = path.join(compilerPath, '../exe'); - } else if ( - await utils.dirExists(path.join(compilerPath, '../lib/exe')) - ) { + } else if (await utils.dirExists(path.join(compilerPath, '../lib/exe'))) { execOptions.env.CLEANLIB = path.join(compilerPath, '../lib/exe'); } execOptions.env.CLEANPATH = this.compiler.libPath.join(':'); @@ -153,14 +128,8 @@ export class CleanCompiler extends BaseCompiler { const result = await this.exec(compiler, options, execOptions); result.inputFilename = inputFilename; - result.stdout = utils.parseOutput( - this.preprocessOutput(result.stdout), - inputFilename, - ); - result.stderr = utils.parseOutput( - this.preprocessOutput(result.stderr), - inputFilename, - ); + result.stdout = utils.parseOutput(this.preprocessOutput(result.stdout), inputFilename); + result.stderr = utils.parseOutput(this.preprocessOutput(result.stderr), inputFilename); if (!options.includes('-S')) { const aOut = path.join(tmpDir, 'a.out'); diff --git a/lib/compilers/dotnet.ts b/lib/compilers/dotnet.ts index f93a912da..cd9ec8e86 100644 --- a/lib/compilers/dotnet.ts +++ b/lib/compilers/dotnet.ts @@ -27,8 +27,8 @@ import path from 'path'; import fs from 'fs-extra'; /// <reference types="../base-compiler" /> -import { BaseCompiler } from '../base-compiler'; -import { DotNetAsmParser } from '../parsers/asm-parser-dotnet'; +import {BaseCompiler} from '../base-compiler'; +import {DotNetAsmParser} from '../parsers/asm-parser-dotnet'; class DotNetCompiler extends BaseCompiler { private rID: string; @@ -58,13 +58,30 @@ class DotNetCompiler extends BaseCompiler { } get configurableOptions() { - return ['--targetos', '--targetarch', '--instruction-set', '--singlemethodtypename', '--singlemethodname', - '--singlemethodindex', '--singlemethodgenericarg', '--codegenopt', '--codegen-options']; + return [ + '--targetos', + '--targetarch', + '--instruction-set', + '--singlemethodtypename', + '--singlemethodname', + '--singlemethodindex', + '--singlemethodgenericarg', + '--codegenopt', + '--codegen-options', + ]; } get configurableSwitches() { - return ['-O', '--optimize', '--Od', '--optimize-disabled', '--Os', '--optimize-space', '--Ot', - '--optimize-time']; + return [ + '-O', + '--optimize', + '--Od', + '--optimize-disabled', + '--Os', + '--optimize-space', + '--Ot', + '--optimize-time', + ]; } async runCompiler(compiler, options, inputFileName, execOptions) { @@ -84,12 +101,11 @@ class DotNetCompiler extends BaseCompiler { this.buildConfig, this.targetFramework, this.rID, - 'publish', + 'publish' ); const programDllPath = path.join(programPublishPath, 'CompilerExplorer.dll'); - const projectFileContent = - `<Project Sdk="Microsoft.NET.Sdk"> + const projectFileContent = `<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>${this.targetFramework}</TargetFramework> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> @@ -110,7 +126,7 @@ class DotNetCompiler extends BaseCompiler { execOptions.env.DOTNET_CLI_TELEMETRY_OPTOUT = 'true'; execOptions.env.DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 'true'; execOptions.env.NUGET_PACKAGES = this.nugetPackagesPath; - execOptions.env.DOTNET_NOLOGO='true'; + execOptions.env.DOTNET_NOLOGO = 'true'; execOptions.customCwd = programDir; await fs.writeFile(projectFilePath, projectFileContent); @@ -148,7 +164,7 @@ class DotNetCompiler extends BaseCompiler { programPublishPath, programDllPath, crossgen2Options, - this.getOutputFilename(programDir, this.outputFilebase), + this.getOutputFilename(programDir, this.outputFilebase) ); if (crossgen2Result.code !== 0) { @@ -164,9 +180,20 @@ class DotNetCompiler extends BaseCompiler { async runCrossgen2(compiler, execOptions, crossgen2Path, publishPath, dllPath, options, outputPath) { const crossgen2Options = [ - crossgen2Path, '-r', path.join(publishPath, '*'), dllPath, '-o', 'CompilerExplorer.r2r.dll', - '--codegenopt', 'NgenDisasm=*', '--codegenopt', 'JitDiffableDasm=1', '--parallelism', '1', - '--inputbubble', '--compilebubblegenerics', + crossgen2Path, + '-r', + path.join(publishPath, '*'), + dllPath, + '-o', + 'CompilerExplorer.r2r.dll', + '--codegenopt', + 'NgenDisasm=*', + '--codegenopt', + 'JitDiffableDasm=1', + '--parallelism', + '1', + '--inputbubble', + '--compilebubblegenerics', ].concat(options); const result = await this.exec(compiler, crossgen2Options, execOptions); @@ -176,7 +203,7 @@ class DotNetCompiler extends BaseCompiler { await fs.writeFile( outputPath, - result.stdout.map(o => o.text).reduce((a, n) => `${a}\n${n}`), + result.stdout.map(o => o.text).reduce((a, n) => `${a}\n${n}`) ); return result; @@ -184,13 +211,19 @@ class DotNetCompiler extends BaseCompiler { } export class CSharpCompiler extends DotNetCompiler { - static get key() { return 'csharp'; } + static get key() { + return 'csharp'; + } } export class FSharpCompiler extends DotNetCompiler { - static get key() { return 'fsharp'; } + static get key() { + return 'fsharp'; + } } export class VBCompiler extends DotNetCompiler { - static get key() { return 'vb'; } + static get key() { + return 'vb'; + } } diff --git a/lib/compilers/erlang.js b/lib/compilers/erlang.js index 31018086c..ef57b0d01 100644 --- a/lib/compilers/erlang.js +++ b/lib/compilers/erlang.js @@ -24,13 +24,15 @@ import path from 'path'; -import { BaseCompiler } from '../base-compiler'; -import { logger } from '../logger'; +import {BaseCompiler} from '../base-compiler'; +import {logger} from '../logger'; -import { ErlangParser } from './argument-parsers'; +import {ErlangParser} from './argument-parsers'; export class ErlangCompiler extends BaseCompiler { - static get key() { return 'erlang'; } + static get key() { + return 'erlang'; + } /* eslint-disable no-unused-vars */ optionsForFilter(filters, outputFilename) { @@ -38,7 +40,7 @@ export class ErlangCompiler extends BaseCompiler { '-noshell', '-eval', '{ok, Input} = init:get_argument(input),' + - '{ok, _, Output} = compile:file(Input, [\'S\', binary, no_line_info, report]),' + + "{ok, _, Output} = compile:file(Input, ['S', binary, no_line_info, report])," + `{ok,Fd} = file:open("${outputFilename}", [write]),` + 'beam_listing:module(Fd, Output),' + 'file:close(Fd),' + @@ -78,7 +80,7 @@ export class ErlangCompiler extends BaseCompiler { return this.execCompilerCached( versionCmd, ['-noshell', '-eval', 'io:fwrite("~s~n", [erlang:system_info(otp_release)]), halt().'], - execOptions, + execOptions ); } catch (err) { logger.error(`Unable to get version for compiler '${this.compiler.exe}' - ${err}`); diff --git a/lib/compilers/nim.js b/lib/compilers/nim.js index 5d24bb923..215a1d1d7 100644 --- a/lib/compilers/nim.js +++ b/lib/compilers/nim.js @@ -27,20 +27,16 @@ import path from 'path'; import fs from 'fs-extra'; import _ from 'underscore'; -import { BaseCompiler } from '../base-compiler'; +import {BaseCompiler} from '../base-compiler'; -import { NimParser } from './argument-parsers'; +import {NimParser} from './argument-parsers'; -const NimCommands = [ - 'compile', 'compileToC', 'c', - 'compileToCpp', 'cpp', 'cc', - 'compileToOC', 'objc', - 'js', - 'check', -]; +const NimCommands = ['compile', 'compileToC', 'c', 'compileToCpp', 'cpp', 'cc', 'compileToOC', 'objc', 'js', 'check']; export class NimCompiler extends BaseCompiler { - static get key() { return 'nim'; } + static get key() { + return 'nim'; + } constructor(info, env) { super(info, env); @@ -74,24 +70,18 @@ export class NimCompiler extends BaseCompiler { isCpp = ['compileToCpp', 'cpp', 'cc'], isObjC = ['compileToOC', 'objc']; - if (isC.includes(command)) - return '.c.o'; - else if (isCpp.includes(command)) - return '.cpp.o'; - else if (isObjC.includes(command)) - return '.m.o'; - else - return null; + if (isC.includes(command)) return '.c.o'; + else if (isCpp.includes(command)) return '.cpp.o'; + else if (isObjC.includes(command)) return '.m.o'; + else return null; } getCacheFile(options, inputFilename, cacheDir) { const commandsInOptions = _.intersection(options, NimCommands); - if (commandsInOptions.length === 0) - return null; + if (commandsInOptions.length === 0) return null; const command = commandsInOptions[0]; const extension = this.expectedExtensionFromCommand(command); - if (!extension) - return null; + if (!extension) return null; const moduleName = path.basename(inputFilename); const resultName = '@m' + moduleName + extension; return path.join(cacheDir, resultName); @@ -101,8 +91,7 @@ export class NimCompiler extends BaseCompiler { const options = result.compilationOptions; const cacheDir = this.cacheDir(outputFilename); try { - if (_.intersection(options, ['js', 'check']).length > 0) - filters.binary = false; + if (_.intersection(options, ['js', 'check']).length > 0) filters.binary = false; else { filters.binary = true; const objFile = this.getCacheFile(options, result.inputFilename, cacheDir); @@ -134,7 +123,7 @@ export class NimCompiler extends BaseCompiler { libLinks, userOptions, [this.filename(inputFilename)], - staticLibLinks, + staticLibLinks ); } } diff --git a/lib/demangler/base.js b/lib/demangler/base.js index 42342b4e2..4c658e6ce 100644 --- a/lib/demangler/base.js +++ b/lib/demangler/base.js @@ -22,12 +22,12 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -import { logger } from '../logger'; -import { AsmRegex } from '../parsers/asmregex'; -import { SymbolStore } from '../symbol-store'; +import {logger} from '../logger'; +import {AsmRegex} from '../parsers/asmregex'; +import {SymbolStore} from '../symbol-store'; import * as utils from '../utils'; -import { PrefixTree } from './prefix-tree'; +import {PrefixTree} from './prefix-tree'; export class BaseDemangler extends AsmRegex { constructor(demanglerExe, compiler) { @@ -90,17 +90,21 @@ export class BaseDemangler extends AsmRegex { collectLabels() { const symbolMatchers = [ this.jumpDef, - this.callPtrDef4, this.callPtrDef3, this.callPtrDef2, this.callPtrDef1, + this.callPtrDef4, + this.callPtrDef3, + this.callPtrDef2, + this.callPtrDef1, this.callDef, - this.movUnderscoreDef, this.leaUnderscoreDef, this.quadUnderscoreDef, + this.movUnderscoreDef, + this.leaUnderscoreDef, + this.quadUnderscoreDef, ]; for (let j = 0; j < this.result.asm.length; ++j) { const line = this.result.asm[j].text; if (!line) continue; const labelMatch = line.match(this.labelDef); - if (labelMatch) - this.symbolstore.add(labelMatch[labelMatch.length - 1]); + if (labelMatch) this.symbolstore.add(labelMatch[labelMatch.length - 1]); for (const reToMatch of symbolMatchers) { const matches = line.match(reToMatch); @@ -128,7 +132,9 @@ export class BaseDemangler extends AsmRegex { addTranslation(symbol, translation) { if (this.includeMetadata) { - translation += this.getMetadata(symbol).map((meta) => ' [' + meta.description + ']').join(','); + translation += this.getMetadata(symbol) + .map(meta => ' [' + meta.description + ']') + .join(','); } if (this.symbolstore.contains(symbol)) { @@ -141,15 +147,14 @@ export class BaseDemangler extends AsmRegex { processOutput(output) { const lines = utils.splitLines(output.stdout); if (lines.length > this.input.length) { - logger.error(`Demangler output issue ${lines.length} > ${this.input.length}`, - this.input, output); + logger.error(`Demangler output issue ${lines.length} > ${this.input.length}`, this.input, output); throw new Error('Internal issue in demangler'); } - for (let i = 0; i < lines.length; ++i) - this.addTranslation(this.input[i], lines[i]); + for (let i = 0; i < lines.length; ++i) this.addTranslation(this.input[i], lines[i]); - const translations = [...this.symbolstore.listTranslations(), ...this.othersymbols.listTranslations()] - .filter(elem => elem[0] !== elem[1]); + const translations = [...this.symbolstore.listTranslations(), ...this.othersymbols.listTranslations()].filter( + elem => elem[0] !== elem[1] + ); if (translations.length > 0) { const tree = new PrefixTree(translations); @@ -166,11 +171,7 @@ export class BaseDemangler extends AsmRegex { execDemangler(options) { options.maxOutput = -1; - return this.compiler.exec( - this.demanglerExe, - this.demanglerArguments, - options, - ); + return this.compiler.exec(this.demanglerExe, this.demanglerArguments, options); } async process(result, execOptions) { diff --git a/lib/exec.js b/lib/exec.js index cb7730299..b0a072103 100644 --- a/lib/exec.js +++ b/lib/exec.js @@ -30,8 +30,8 @@ import Graceful from 'node-graceful'; import treeKill from 'tree-kill'; import _ from 'underscore'; -import { logger } from './logger'; -import { propsFor } from './properties'; +import {logger} from './logger'; +import {propsFor} from './properties'; const execProps = propsFor('execution'); @@ -64,9 +64,11 @@ export function executeDirect(command, args, options, filenameTransform) { } let okToCache = true; - const cwd = options.customCwd ? options.customCwd : ( - (command.startsWith('/mnt') && process.env.wsl) ? process.env.winTmp : process.env.tmpDir - ); + const cwd = options.customCwd + ? options.customCwd + : command.startsWith('/mnt') && process.env.wsl + ? process.env.winTmp + : process.env.tmpDir; logger.debug('Execution', {type: 'executing', command: command, args: args, env: env, cwd: cwd}); const startTime = process.hrtime.bigint(); @@ -79,9 +81,11 @@ export function executeDirect(command, args, options, filenameTransform) { }); let running = true; - const kill = options.killChild || (() => { - if (running) treeKill(child.pid); - }); + const kill = + options.killChild || + (() => { + if (running) treeKill(child.pid); + }); const streams = { stderr: '', @@ -89,19 +93,20 @@ export function executeDirect(command, args, options, filenameTransform) { truncated: false, }; let timeout; - if (timeoutMs) timeout = setTimeout(() => { - logger.warn(`Timeout for ${command} ${args} after ${timeoutMs}ms`); - okToCache = false; - kill(); - streams.stderr += '\nKilled - processing time exceeded'; - }, timeoutMs); + if (timeoutMs) + timeout = setTimeout(() => { + logger.warn(`Timeout for ${command} ${args} after ${timeoutMs}ms`); + okToCache = false; + kill(); + streams.stderr += '\nKilled - processing time exceeded'; + }, timeoutMs); function setupStream(stream, name) { if (stream === undefined) return; stream.on('data', data => { if (streams.truncated) return; - const newLength = (streams[name].length + data.length); - if ((maxOutput > 0) && (newLength > maxOutput)) { + const newLength = streams[name].length + data.length; + if (maxOutput > 0 && newLength > maxOutput) { streams[name] = streams[name] + data.slice(0, maxOutput - streams[name].length); streams[name] += '\n[Truncated]'; streams.truncated = true; @@ -175,9 +180,7 @@ export function getNsJailOptions(configName, command, args, options) { if (options.timeoutMs) { const ExtraWallClockLeewayMs = 1000; - jailingOptions.push( - `--time_limit=${Math.round((options.timeoutMs + ExtraWallClockLeewayMs) / 1000)}`, - ); + jailingOptions.push(`--time_limit=${Math.round((options.timeoutMs + ExtraWallClockLeewayMs) / 1000)}`); } const homeDir = '/app'; @@ -185,15 +188,9 @@ export function getNsJailOptions(configName, command, args, options) { if (options.customCwd) { if (options.appHome) { const relativeCwd = path.join(homeDir, path.relative(options.appHome, options.customCwd)); - jailingOptions.push( - '--cwd', relativeCwd, - '--bindmount', `${options.appHome}:${homeDir}`, - ); + jailingOptions.push('--cwd', relativeCwd, '--bindmount', `${options.appHome}:${homeDir}`); } else { - jailingOptions.push( - '--cwd', homeDir, - '--bindmount', `${options.customCwd}:${homeDir}`, - ); + jailingOptions.push('--cwd', homeDir, '--bindmount', `${options.customCwd}:${homeDir}`); } const replacement = options.customCwd; @@ -210,8 +207,7 @@ export function getNsJailOptions(configName, command, args, options) { } for (const [key, value] of Object.entries(env)) { - if (value !== undefined) - jailingOptions.push(`--env=${key}=${value}`); + if (value !== undefined) jailingOptions.push(`--env=${key}=${value}`); } delete options.env; @@ -243,29 +239,19 @@ export function getSandboxNsjailOptions(command, args, options) { function sandboxNsjail(command, args, options) { logger.info('Sandbox execution via nsjail', {command, args}); const nsOpts = getSandboxNsjailOptions(command, args, options); - return executeDirect( - execProps('nsjail'), - nsOpts.args, - nsOpts.options, - nsOpts.filenameTransform); + return executeDirect(execProps('nsjail'), nsOpts.args, nsOpts.options, nsOpts.filenameTransform); } function executeNsjail(command, args, options) { const nsOpts = getNsJailOptions('execute', command, args, options); - return executeDirect( - execProps('nsjail'), - nsOpts.args, - nsOpts.options, - nsOpts.filenameTransform); + return executeDirect(execProps('nsjail'), nsOpts.args, nsOpts.options, nsOpts.filenameTransform); } function withFirejailTimeout(args, options) { if (options && options.timeoutMs) { // const ExtraWallClockLeewayMs = 1000; const ExtraCpuLeewayMs = 1500; - return args.concat([ - `--rlimit-cpu=${Math.round((options.timeoutMs + ExtraCpuLeewayMs) / 1000)}`, - ]); + return args.concat([`--rlimit-cpu=${Math.round((options.timeoutMs + ExtraCpuLeewayMs) / 1000)}`]); } return args; } @@ -280,7 +266,8 @@ function sandboxFirejail(command, args, options) { '--terminate-orphans', '--profile=' + getFirejailProfileFilePath('sandbox'), `--private=${execPath}`, - '--private-cwd']); + '--private-cwd', + ]); if (options.ldPath) { jailingOptions.push(`--env=LD_LIBRARY_PATH=${options.ldPath}`); @@ -292,12 +279,7 @@ function sandboxFirejail(command, args, options) { } delete options.env; - return executeDirect( - execProps('firejail'), - jailingOptions - .concat([`./${execName}`]) - .concat(args), - options); + return executeDirect(execProps('firejail'), jailingOptions.concat([`./${execName}`]).concat(args), options); } const sandboxDispatchTable = { @@ -312,8 +294,7 @@ const sandboxDispatchTable = { export async function sandbox(command, args, options) { const type = execProps('sandboxType', 'firejail'); const dispatchEntry = sandboxDispatchTable[type]; - if (!dispatchEntry) - throw new Error(`Bad sandbox type ${type}`); + if (!dispatchEntry) throw new Error(`Bad sandbox type ${type}`); return dispatchEntry(command, args, options); } @@ -329,7 +310,7 @@ export function initialiseWine() { const server = execProps('wineServer'); const executionType = execProps('executionType', 'none'); // We need to fire up a firejail wine server even in nsjail world (for now). - const firejail = (executionType === 'firejail' || executionType === 'nsjail') ? execProps('firejail') : null; + const firejail = executionType === 'firejail' || executionType === 'nsjail' ? execProps('firejail') : null; const env = applyWineEnv({PATH: process.env.PATH}); const prefix = env.WINEPREFIX; @@ -366,14 +347,12 @@ export function initialiseWine() { wine, 'cmd', ], - {env: env, detached: true}); + {env: env, detached: true} + ); logger.info(`firejailed pid=${wineServer.pid}`); } else { logger.info(`Starting a new, long-lived wineserver complex ${server}`); - wineServer = child_process.spawn( - wine, - ['cmd'], - {env: env, detached: true}); + wineServer = child_process.spawn(wine, ['cmd'], {env: env, detached: true}); logger.info(`wineserver pid=${wineServer.pid}`); } @@ -385,7 +364,7 @@ export function initialiseWine() { const waitingPromises = []; function waitForExit(process, name) { - return new Promise((resolve) => { + return new Promise(resolve => { process.on('close', () => { logger.info(`Process '${name}' closed`); resolve(); @@ -419,8 +398,9 @@ export function initialiseWine() { resolve(); } }); - wineServer.stderr.on('data', - data => logger.info(`stderr output from wine server complex: ${data.toString().trim()}`)); + wineServer.stderr.on('data', data => + logger.info(`stderr output from wine server complex: ${data.toString().trim()}`) + ); wineServer.on('error', e => { logger.error(`WINE server complex exited with error ${e}`); reject(e); @@ -503,15 +483,13 @@ function executeNone(command, args, options) { const executeDispatchTable = { none: executeNone, firejail: executeFirejail, - nsjail: (command, args, options) => needsWine(command) - ? executeFirejail(command, args, options) - : executeNsjail(command, args, options), + nsjail: (command, args, options) => + needsWine(command) ? executeFirejail(command, args, options) : executeNsjail(command, args, options), }; export async function execute(command, args, options) { const type = execProps('executionType', 'none'); const dispatchEntry = executeDispatchTable[type]; - if (!dispatchEntry) - throw new Error(`Bad sandbox type ${type}`); + if (!dispatchEntry) throw new Error(`Bad sandbox type ${type}`); return dispatchEntry(command, args, options); } diff --git a/lib/handlers/api.js b/lib/handlers/api.js index dd8110aef..993c675bb 100644 --- a/lib/handlers/api.js +++ b/lib/handlers/api.js @@ -26,13 +26,13 @@ import bodyParser from 'body-parser'; import express from 'express'; import _ from 'underscore'; -import { ClientStateNormalizer } from '../clientstate-normalizer'; -import { logger } from '../logger'; -import { getShortenerTypeByKey } from '../shortener'; +import {ClientStateNormalizer} from '../clientstate-normalizer'; +import {logger} from '../logger'; +import {getShortenerTypeByKey} from '../shortener'; import * as utils from '../utils'; -import { withAssemblyDocumentationProviders } from './assembly-documentation'; -import { FormattingHandler } from './formatting'; +import {withAssemblyDocumentationProviders} from './assembly-documentation'; +import {FormattingHandler} from './formatting'; export class ApiHandler { constructor(compileHandler, ceProps, storageHandler, urlShortenService) { @@ -45,13 +45,11 @@ export class ApiHandler { this.handle = express.Router(); const cacheHeader = `public, max-age=${ceProps('apiMaxAgeSecs', 24 * 60 * 60)}`; this.handle.use((req, res, next) => { - res.header( - { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept', - 'Cache-Control': cacheHeader, - }, - ); + res.header({ + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept', + 'Cache-Control': cacheHeader, + }); next(); }); this.handle.get('/compilers', this.handleCompilers.bind(this)); @@ -63,9 +61,7 @@ export class ApiHandler { // Binding for assembly documentation withAssemblyDocumentationProviders(this.handle); // Legacy binding for old clients. - this.handle.get('/asm/:opcode', - (req, res) => res.redirect(`amd64/${req.params.opcode}`), - ); + this.handle.get('/asm/:opcode', (req, res) => res.redirect(`amd64/${req.params.opcode}`)); const maxUploadSize = ceProps('maxUploadSize', '1mb'); const textParser = bodyParser.text({limit: ceProps('bodyParserLimit', maxUploadSize), type: () => true}); @@ -73,12 +69,16 @@ export class ApiHandler { this.handle.post('/compiler/:compiler/compile', textParser, compileHandler.handle.bind(compileHandler)); this.handle.post('/compiler/:compiler/cmake', compileHandler.handleCmake.bind(compileHandler)); this.handle.post('/popularArguments/:compiler', compileHandler.handlePopularArguments.bind(compileHandler)); - this.handle.post('/optimizationArguments/:compiler', - compileHandler.handleOptimizationArguments.bind(compileHandler)); + this.handle.post( + '/optimizationArguments/:compiler', + compileHandler.handleOptimizationArguments.bind(compileHandler) + ); this.handle.get('/popularArguments/:compiler', compileHandler.handlePopularArguments.bind(compileHandler)); - this.handle.get('/optimizationArguments/:compiler', - compileHandler.handleOptimizationArguments.bind(compileHandler)); + this.handle.get( + '/optimizationArguments/:compiler', + compileHandler.handleOptimizationArguments.bind(compileHandler) + ); const formatHandler = new FormattingHandler(ceProps); this.handle.post('/format/:tool', (req, res) => formatHandler.handle(req, res)); @@ -103,7 +103,8 @@ export class ApiHandler { shortlinkInfoHandler(req, res, next) { const id = req.params.id; - this.storageHandler.expandId(id) + this.storageHandler + .expandId(id) .then(result => { const config = JSON.parse(result.config); @@ -139,7 +140,7 @@ export class ApiHandler { } filterCompilerProperties(list, selectedFields) { - return _.map(list, (compiler) => { + return _.map(list, compiler => { return _.pick(compiler, selectedFields); }); } @@ -149,8 +150,16 @@ export class ApiHandler { if (req.query.fields === 'all') { res.send(list); } else { - const defaultfields = ['id', 'name', 'lang', 'compilerType', 'semver', 'extensions', 'monaco', - 'instructionSet']; + const defaultfields = [ + 'id', + 'name', + 'lang', + 'compilerType', + 'semver', + 'extensions', + 'monaco', + 'instructionSet', + ]; if (req.query.fields) { const filteredList = this.filterCompilerProperties(list, req.query.fields.split(',')); res.send(filteredList); @@ -164,17 +173,20 @@ export class ApiHandler { const maxLength = _.max(_.pluck(_.pluck(list, 'id').concat([title]), 'length')); res.set('Content-Type', 'text/plain'); - res.send(utils.padRight(title, maxLength) + ' | Name\n' - + list.map(lang => utils.padRight(lang.id, maxLength) + ' | ' + lang.name).join('\n')); + res.send( + utils.padRight(title, maxLength) + + ' | Name\n' + + list.map(lang => utils.padRight(lang.id, maxLength) + ' | ' + lang.name).join('\n') + ); } getLibrariesAsArray(languageId) { const libsForLanguageObj = this.options.options.libs[languageId]; if (!libsForLanguageObj) return []; - return Object.keys(libsForLanguageObj).map((key) => { + return Object.keys(libsForLanguageObj).map(key => { const language = libsForLanguageObj[key]; - const versionArr = Object.keys(language.versions).map((key) => { + const versionArr = Object.keys(language.versions).map(key => { let versionObj = Object.assign({}, language.versions[key]); versionObj.id = key; return versionObj; @@ -222,7 +234,7 @@ export class ApiHandler { handleCompilers(req, res) { let filteredCompilers = this.compilers; if (req.params.language) { - filteredCompilers = this.compilers.filter((val) => val.lang === req.params.language); + filteredCompilers = this.compilers.filter(val => val.lang === req.params.language); } this.outputList(filteredCompilers, 'Compiler Name', req, res); diff --git a/lib/handlers/assembly-documentation.ts b/lib/handlers/assembly-documentation.ts index 0c1570870..e21b85425 100644 --- a/lib/handlers/assembly-documentation.ts +++ b/lib/handlers/assembly-documentation.ts @@ -24,46 +24,53 @@ import express from 'express'; -import { BaseAssemblyDocumentationProvider, getDocumentationProviderTypeByKey } from '../asm-docs'; -import { propsFor } from '../properties'; +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, + 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}'` }); + 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; + 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(); - } -}); +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(); + } + }); diff --git a/lib/logger.js b/lib/logger.js index 9fa497df8..9e3644063 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -24,18 +24,15 @@ import os from 'os'; -import { LEVEL, MESSAGE } from 'triple-beam'; +import {LEVEL, MESSAGE} from 'triple-beam'; import winston from 'winston'; import LokiTransport from 'winston-loki'; -import { Papertrail } from 'winston-papertrail'; +import {Papertrail} from 'winston-papertrail'; import TransportStream from 'winston-transport'; const consoleTransportInstance = new winston.transports.Console(); export const logger = winston.createLogger({ - format: winston.format.combine( - winston.format.colorize(), - winston.format.splat(), - winston.format.simple()), + format: winston.format.combine(winston.format.colorize(), winston.format.splat(), winston.format.simple()), transports: [consoleTransportInstance], }); @@ -66,13 +63,11 @@ class MyPapertrailTransport extends TransportStream { this.hostname = os.hostname(); this.program = opts.identifier; - this.transport = new Papertrail( - { - host: opts.host, - port: opts.port, - logFormat: (level, message) => message, - }, - ); + this.transport = new Papertrail({ + host: opts.host, + port: opts.port, + logFormat: (level, message) => message, + }); } log(info, callback) { @@ -81,7 +76,7 @@ class MyPapertrailTransport extends TransportStream { }); // We can't use callback here as winston-papertrail is a bit lax in calling it back - this.transport.sendMessage(this.hostname, this.program, info[LEVEL], info[MESSAGE], (x) => x); + this.transport.sendMessage(this.hostname, this.program, info[LEVEL], info[MESSAGE], x => x); callback(); } } @@ -89,7 +84,7 @@ class MyPapertrailTransport extends TransportStream { export function logToLoki(url) { const transport = new LokiTransport({ host: url, - labels: { job: 'ce' }, + labels: {job: 'ce'}, batching: true, interval: 3, // remove color from log level label - loki really doesn't like it @@ -105,13 +100,15 @@ export function logToLoki(url) { export function logToPapertrail(host, port, identifier) { const transport = new MyPapertrailTransport({ - host: host, port: port, identifier: identifier, + host: host, + port: port, + identifier: identifier, }); - transport.transport.on('error', (err) => { + transport.transport.on('error', err => { logger.error(err); }); - transport.transport.on('connect', (message) => { + transport.transport.on('connect', message => { logger.info(message); }); logger.add(transport); diff --git a/lib/tooling/clang-tidy-tool.js b/lib/tooling/clang-tidy-tool.js index 10e1ad5fe..6866db6b5 100644 --- a/lib/tooling/clang-tidy-tool.js +++ b/lib/tooling/clang-tidy-tool.js @@ -28,10 +28,12 @@ import fs from 'fs-extra'; import * as utils from '../utils'; -import { BaseTool } from './base-tool'; +import {BaseTool} from './base-tool'; export class ClangTidyTool extends BaseTool { - static get key() { return 'clang-tidy-tool'; } + static get key() { + return 'clang-tidy-tool'; + } constructor(toolInfo, env) { super(toolInfo, env); @@ -66,15 +68,12 @@ export class ClangTidyTool extends BaseTool { compileFlags = compileFlags.concat(includeflags); compileFlags = compileFlags.concat(libOptions); - const manualCompileFlags = options.filter(option => (option !== sourcefile)); + const manualCompileFlags = options.filter(option => option !== sourcefile); compileFlags = compileFlags.concat(manualCompileFlags); compileFlags = compileFlags.concat(this.tool.options); // TODO: do we want compile_flags.txt rather than prefixing everything with -extra-arg= - await fs.writeFile( - path.join(dir, 'compile_flags.txt'), - compileFlags.join('\n'), - ); + await fs.writeFile(path.join(dir, 'compile_flags.txt'), compileFlags.join('\n')); const result = await super.runTool(compilationInfo, sourcefile, args); result.sourcechanged = false; diff --git a/lib/tooling/pvs-studio-tool.js b/lib/tooling/pvs-studio-tool.js index d357509b4..5dd9fb447 100644 --- a/lib/tooling/pvs-studio-tool.js +++ b/lib/tooling/pvs-studio-tool.js @@ -60,7 +60,7 @@ export class PvsStudioTool extends BaseTool { const libOptions = super.getLibraryOptions(compilationInfo.libraries, compilationInfo.compiler); compileFlags = compileFlags.concat(libOptions); - const manualCompileFlags = compilationInfo.options.filter(option => (option !== inputFilepath)); + const manualCompileFlags = compilationInfo.options.filter(option => option !== inputFilepath); compileFlags = compileFlags.concat(manualCompileFlags); compileFlags = compileFlags.filter(function (flag) { @@ -74,19 +74,21 @@ export class PvsStudioTool extends BaseTool { args.push('analyze', '--source-file', inputFilepath); const outputFilePath = path.join(sourceDir, 'pvs-studio-log.log'); args.push( - '--output-file', outputFilePath, + '--output-file', + outputFilePath, // Exclude directories from analysis - '-e', '/opt', - '-e', '/usr', - '--pvs-studio-path', path.dirname(this.tool.exe) + '/pvs-studio', + '-e', + '/opt', + '-e', + '/usr', + '--pvs-studio-path', + path.dirname(this.tool.exe) + '/pvs-studio', // TODO: expand this to switch() for all supported compilers: // visualcpp, clang, gcc, bcc, bcc_clang64, iar, keil5, keil5_gnu - '--preprocessor', + '--preprocessor' ); - if (compilationInfo.compiler.group.includes('clang')) - args.push('clang'); - else - args.push('gcc'); + if (compilationInfo.compiler.group.includes('clang')) args.push('clang'); + else args.push('gcc'); // Now let's push the path to the compiler if (this.tool.compilerLanguage === 'c') { @@ -108,15 +110,20 @@ export class PvsStudioTool extends BaseTool { const plogConverterOutputFilePath = path.join(sourceDir, 'pvs-studio-log.err'); const plogConverterArgs = []; - plogConverterArgs.push('-t', 'errorfile', '-a', 'FAIL:1,2,3;GA:1,2,3', '-o', + plogConverterArgs.push( + '-t', + 'errorfile', + '-a', + 'FAIL:1,2,3;GA:1,2,3', + '-o', plogConverterOutputFilePath, - 'pvs-studio-log.log'); + 'pvs-studio-log.log' + ); const plogExecOptions = this.getDefaultExecOptions(); plogExecOptions.customCwd = sourceDir; - const plogConverterResult = await exec.execute( - this.plogConverterPath, plogConverterArgs, plogExecOptions); + const plogConverterResult = await exec.execute(this.plogConverterPath, plogConverterArgs, plogExecOptions); if (plogConverterResult.code !== 0) { logger.warn('plog-converter failed', plogConverterResult); return this.convertResult(plogConverterResult, inputFilepath); @@ -127,8 +134,9 @@ export class PvsStudioTool extends BaseTool { // (*.PVS-Studio.i) // This name can't be parsed by utils.parseOutput // so let's just replace it with a source file name. - const plogConverterOutput = plogRawOutput.toString().replace( - sourceDir + '/example.PVS-Studio.i', inputFilepath); + const plogConverterOutput = plogRawOutput + .toString() + .replace(sourceDir + '/example.PVS-Studio.i', inputFilepath); result.stdout = utils.parseOutput(plogConverterOutput, plogConverterResult.filenameTransform(inputFilepath)); diff --git a/package.json b/package.json index 3b4d70c0c..4369d9c88 100644 --- a/package.json +++ b/package.json @@ -152,6 +152,7 @@ }, "scripts": { "ci-lint": "eslint --format github .", + "ci-lint-files": "eslint --format github", "ci-test": "nyc npm run test", "lint": "eslint .", "lint-fix": "eslint --fix .", @@ -167,14 +168,15 @@ "prepare": "husky install", "format": "prettier --ignore-unknown ./static/**/*.ts", "format-fix": "prettier --write --ignore-unknown ./static/**/*.ts", + "format-fix-files": "prettier --write --ignore-unknown", "format-check": "prettier --ignore-unknown --check ./static/**/*.ts", "ts-compile": "tsc", "webpack": "webpack --node-env=production" }, "lint-staged": { "*.[jt]s": [ - "npm run ci-lint --", - "npm run format-fix --" + "npm run ci-lint-files --", + "npm run format-fix-files --" ] }, "license": "BSD-2-Clause" diff --git a/test/demangler-tests.js b/test/demangler-tests.js index efe795a24..133c4a936 100644 --- a/test/demangler-tests.js +++ b/test/demangler-tests.js @@ -22,13 +22,13 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -import { CppDemangler, Win32Demangler } from '../lib/demangler'; -import { PrefixTree } from '../lib/demangler/prefix-tree'; +import {CppDemangler, Win32Demangler} from '../lib/demangler'; +import {PrefixTree} from '../lib/demangler/prefix-tree'; import * as exec from '../lib/exec'; -import { SymbolStore } from '../lib/symbol-store'; +import {SymbolStore} from '../lib/symbol-store'; import * as utils from '../lib/utils'; -import { chai, fs, path, resolvePathFromTestRoot } from './utils'; +import {chai, fs, path, resolvePathFromTestRoot} from './utils'; const cppfiltpath = 'c++filt'; @@ -54,25 +54,22 @@ describe('Basic demangling', function () { demangler.demanglerArguments = ['-n']; return Promise.all([ - demangler.process(result).then((output) => { + demangler.process(result).then(output => { output.asm[0].text.should.equal('Hello, World!'); }), ]); }); it('One label and some asm', function () { - const result = {}; - result.asm = [ - {text: '_Z6squarei:'}, - {text: ' ret'}, - ]; + const result = {asm: [{text: '_Z6squarei:'}, {text: ' ret'}]}; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; return Promise.all([ - demangler.process(result) - .then((output) => { + demangler + .process(result) + .then(output => { output.asm[0].text.should.equal('square(int):'); output.asm[1].text.should.equal(' ret'); }) @@ -81,43 +78,43 @@ describe('Basic demangling', function () { }); it('One label and use of a label', function () { - const result = {}; - result.asm = [ - {text: '_Z6squarei:'}, - {text: ' mov eax, $_Z6squarei'}, - ]; + const result = {asm: [{text: '_Z6squarei:'}, {text: ' mov eax, $_Z6squarei'}]}; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; return Promise.all([ - demangler.process(result).then((output) => { - output.asm[0].text.should.equal('square(int):'); - output.asm[1].text.should.equal(' mov eax, $square(int)'); - }) + demangler + .process(result) + .then(output => { + output.asm[0].text.should.equal('square(int):'); + output.asm[1].text.should.equal(' mov eax, $square(int)'); + }) .catch(catchCppfiltNonexistence), ]); }); it('Two destructors', function () { - const result = {}; - result.asm = [ - {text: '_ZN6NormalD0Ev:'}, - {text: ' callq _ZdlPv'}, - {text: '_Z7caller1v:'}, - {text: ' rep ret'}, - {text: '_Z7caller2P6Normal:'}, - {text: ' cmp rax, OFFSET FLAT:_ZN6NormalD0Ev'}, - {text: ' jmp _ZdlPvm'}, - {text: '_ZN6NormalD2Ev:'}, - {text: ' rep ret'}, - ]; + const result = { + asm: [ + {text: '_ZN6NormalD0Ev:'}, + {text: ' callq _ZdlPv'}, + {text: '_Z7caller1v:'}, + {text: ' rep ret'}, + {text: '_Z7caller2P6Normal:'}, + {text: ' cmp rax, OFFSET FLAT:_ZN6NormalD0Ev'}, + {text: ' jmp _ZdlPvm'}, + {text: '_ZN6NormalD2Ev:'}, + {text: ' rep ret'}, + ], + }; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; - return demangler.process(result) - .then((output) => { + return demangler + .process(result) + .then(output => { output.asm[0].text.should.equal('Normal::~Normal() [deleting destructor]:'); output.asm[1].text.should.equal(' callq operator delete(void*)'); output.asm[6].text.should.equal(' jmp operator delete(void*, unsigned long)'); @@ -126,10 +123,7 @@ describe('Basic demangling', function () { }); it('Should ignore comments (CL)', function () { - const result = {}; - result.asm = [ - {text: ' call ??3@YAXPEAX_K@Z ; operator delete'}, - ]; + const result = {asm: [{text: ' call ??3@YAXPEAX_K@Z ; operator delete'}]}; const demangler = new Win32Demangler(cppfiltpath, new DummyCompiler()); demangler.result = result; @@ -137,18 +131,11 @@ describe('Basic demangling', function () { demangler.collectLabels(); const output = demangler.win32RawSymbols; - output.should.deep.equal( - [ - '??3@YAXPEAX_K@Z', - ], - ); + output.should.deep.equal(['??3@YAXPEAX_K@Z']); }); it('Should ignore comments (CPP)', function () { - const result = {}; - result.asm = [ - {text: ' call hello ; operator delete'}, - ]; + const result = {asm: [{text: ' call hello ; operator delete'}]}; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; @@ -157,18 +144,11 @@ describe('Basic demangling', function () { demangler.collectLabels(); const output = demangler.othersymbols.listSymbols(); - output.should.deep.equal( - [ - 'hello', - ], - ); + output.should.deep.equal(['hello']); }); it('Should also support ARM branch instructions', () => { - const result = {}; - result.asm = [ - {text: ' bl _ZN3FooC1Ev'}, - ]; + const result = {asm: [{text: ' bl _ZN3FooC1Ev'}]}; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; @@ -177,18 +157,11 @@ describe('Basic demangling', function () { demangler.collectLabels(); const output = demangler.othersymbols.listSymbols(); - output.should.deep.equal( - [ - '_ZN3FooC1Ev', - ], - ); + output.should.deep.equal(['_ZN3FooC1Ev']); }); it('Should NOT handle undecorated labels', () => { - const result = {}; - result.asm = [ - {text: '$LN3@caller2:'}, - ]; + const result = {asm: [{text: '$LN3@caller2:'}]}; const demangler = new Win32Demangler(cppfiltpath, new DummyCompiler()); demangler.result = result; @@ -196,16 +169,11 @@ describe('Basic demangling', function () { demangler.collectLabels(); const output = demangler.win32RawSymbols; - output.should.deep.equal( - [], - ); + output.should.deep.equal([]); }); it('Should ignore comments after jmps', function () { - const result = {}; - result.asm = [ - {text: ' jmp _Z1fP6mytype # TAILCALL'}, - ]; + const result = {asm: [{text: ' jmp _Z1fP6mytype # TAILCALL'}]}; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; @@ -214,18 +182,11 @@ describe('Basic demangling', function () { demangler.collectLabels(); const output = demangler.othersymbols.listSymbols(); - output.should.deep.equal( - [ - '_Z1fP6mytype', - ], - ); + output.should.deep.equal(['_Z1fP6mytype']); }); it('Should still work with normal jmps', function () { - const result = {}; - result.asm = [ - {text: ' jmp _Z1fP6mytype'}, - ]; + const result = {asm: [{text: ' jmp _Z1fP6mytype'}]}; const demangler = new CppDemangler(cppfiltpath, new DummyCompiler()); demangler.demanglerArguments = ['-n']; @@ -234,11 +195,7 @@ describe('Basic demangling', function () { demangler.collectLabels(); const output = demangler.othersymbols.listSymbols(); - output.should.deep.equal( - [ - '_Z1fP6mytype', - ], - ); + output.should.deep.equal(['_Z1fP6mytype']); }); }); @@ -262,7 +219,7 @@ async function DoDemangleTest(filename) { describe('File demangling', () => { if (process.platform !== 'linux') { - it('Should be skipped', (done) => { + it('Should be skipped', done => { done(); }); @@ -313,12 +270,12 @@ describe('Demangler prefix tree', () => { new PrefixTree().replaceAll('Testing 123').should.eq('Testing 123'); }); it('should leave unmatching text alone', () => { - replacements.replaceAll('Some text with none of the first letter of the ordered letter list') + replacements + .replaceAll('Some text with none of the first letter of the ordered letter list') .should.eq('Some text with none of the first letter of the ordered letter list'); }); it('should handle a mixture', () => { - replacements.replaceAll('Everyone loves an aardvark') - .should.eq('Everyone loves short_an long_ardvshort_ark'); + replacements.replaceAll('Everyone loves an aardvark').should.eq('Everyone loves short_an long_ardvshort_ark'); }); it('should find exact matches', () => { replacements.findExact('a').should.eq('short_a'); diff --git a/test/exec-tests.js b/test/exec-tests.js index 1f65d9b85..1bcccd82d 100644 --- a/test/exec-tests.js +++ b/test/exec-tests.js @@ -27,7 +27,7 @@ import path from 'path'; import * as exec from '../lib/exec'; import * as props from '../lib/properties'; -import { chai } from './utils'; +import {chai} from './utils'; const expect = chai.expect; @@ -40,118 +40,114 @@ function testExecOutput(x) { } describe('Execution tests', () => { - if (process.platform !== 'win32') { // POSIX + if (process.platform !== 'win32') { + // POSIX describe('Executes external commands', () => { it('supports output', () => { - return exec.execute('echo', ['hello', 'world'], {}) - .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 0, - okToCache: true, - stderr: '', - stdout: 'hello world\n', - }); + return exec.execute('echo', ['hello', 'world'], {}).then(testExecOutput).should.eventually.deep.equals({ + code: 0, + okToCache: true, + stderr: '', + stdout: 'hello world\n', + }); }); it('limits output', () => { - return exec.execute('echo', ['A very very very very very long string'], {maxOutput: 10}) + return exec + .execute('echo', ['A very very very very very long string'], {maxOutput: 10}) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 0, - okToCache: true, - stderr: '', - stdout: 'A very ver\n[Truncated]', - }); + .should.eventually.deep.equals({ + code: 0, + okToCache: true, + stderr: '', + stdout: 'A very ver\n[Truncated]', + }); }); it('handles failing commands', () => { - return exec.execute('false', [], {}) - .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 1, - okToCache: true, - stderr: '', - stdout: '', - }); + return exec.execute('false', [], {}).then(testExecOutput).should.eventually.deep.equals({ + code: 1, + okToCache: true, + stderr: '', + stdout: '', + }); }); it('handles timouts', () => { - return exec.execute('sleep', ['5'], {timeoutMs: 10}) + return exec + .execute('sleep', ['5'], {timeoutMs: 10}) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: -1, - okToCache: false, - stderr: '\nKilled - processing time exceeded', - stdout: '', - }); + .should.eventually.deep.equals({ + code: -1, + okToCache: false, + stderr: '\nKilled - processing time exceeded', + stdout: '', + }); }); it('handles missing executables', () => { - return exec.execute('__not_a_command__', [], {}) - .should.be.rejectedWith('ENOENT'); + return exec.execute('__not_a_command__', [], {}).should.be.rejectedWith('ENOENT'); }); it('handles input', () => { - return exec.execute('cat', [], {input: 'this is stdin'}) + return exec + .execute('cat', [], {input: 'this is stdin'}) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 0, - okToCache: true, - stderr: '', - stdout: 'this is stdin', - }); + .should.eventually.deep.equals({ + code: 0, + okToCache: true, + stderr: '', + stdout: 'this is stdin', + }); }); }); - } else { // win32 + } else { + // win32 describe('Executes external commands', () => { // note: we use powershell, since echo is a builtin, and false doesn't exist it('supports output', () => { - return exec.execute('powershell', ['-Command', 'echo "hello world"'], {}) + return exec + .execute('powershell', ['-Command', 'echo "hello world"'], {}) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 0, - okToCache: true, - stderr: '', - stdout: 'hello world\r\n', - }); + .should.eventually.deep.equals({ + code: 0, + okToCache: true, + stderr: '', + stdout: 'hello world\r\n', + }); }); it('limits output', () => { - return exec.execute('powershell', ['-Command', 'echo "A very very very very very long string"'], {maxOutput: 10}) + return exec + .execute('powershell', ['-Command', 'echo "A very very very very very long string"'], { + maxOutput: 10, + }) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 0, - okToCache: true, - stderr: '', - stdout: 'A very ver\n[Truncated]', - }); + .should.eventually.deep.equals({ + code: 0, + okToCache: true, + stderr: '', + stdout: 'A very ver\n[Truncated]', + }); }); it('handles failing commands', () => { - return exec.execute('powershell', ['-Command', 'function Fail { exit 1 }; Fail'], {}) + return exec + .execute('powershell', ['-Command', 'function Fail { exit 1 }; Fail'], {}) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 1, - okToCache: true, - stderr: '', - stdout: '', - }); + .should.eventually.deep.equals({ + code: 1, + okToCache: true, + stderr: '', + stdout: '', + }); }); it('handles timouts', () => { - return exec.execute('powershell', ['-Command', '"sleep 5"'], {timeoutMs: 10}) + return exec + .execute('powershell', ['-Command', '"sleep 5"'], {timeoutMs: 10}) .then(testExecOutput) - .should.eventually.deep.equals( - { - code: 1, - okToCache: false, - stderr: '\nKilled - processing time exceeded', - stdout: '', - }); + .should.eventually.deep.equals({ + code: 1, + okToCache: false, + stderr: '\nKilled - processing time exceeded', + stdout: '', + }); }); it('handles missing executables', () => { - return exec.execute('__not_a_command__', [], {}) - .should.be.rejectedWith('ENOENT'); + return exec.execute('__not_a_command__', [], {}).should.be.rejectedWith('ENOENT'); }); }); } @@ -164,11 +160,11 @@ describe('Execution tests', () => { props.reset(); }); it('should handle simple cases', () => { - const {args, options, filenameTransform} = exec.getNsJailOptions( - 'sandbox', - '/path/to/compiler', - ['1', '2', '3'], - ); + const {args, options, filenameTransform} = exec.getNsJailOptions('sandbox', '/path/to/compiler', [ + '1', + '2', + '3', + ]); args.should.deep.equals([ '--config', exec.getNsJailCfgFilePath('sandbox'), @@ -177,32 +173,24 @@ describe('Execution tests', () => { '/path/to/compiler', '1', '2', - '3']); + '3', + ]); options.should.deep.equals({}); expect(filenameTransform).to.be.undefined; }); it('should pass through options', () => { - const options = exec.getNsJailOptions( - 'sandbox', - '/path/to/compiler', - [], - {some: 1, thing: 2}, - ).options; + const options = exec.getNsJailOptions('sandbox', '/path/to/compiler', [], {some: 1, thing: 2}).options; options.should.deep.equals({some: 1, thing: 2}); }); it('should not pass through unknown configs', () => { - expect(() => exec.getNsJailOptions( - 'custom-config', - '/path/to/compiler', - ['1', '2', '3'], - )).to.throw(); + expect(() => exec.getNsJailOptions('custom-config', '/path/to/compiler', ['1', '2', '3'])).to.throw(); }); it('should remap paths when using customCwd', () => { const {args, options, filenameTransform} = exec.getNsJailOptions( 'sandbox', './exec', ['/some/custom/cwd/file', '/not/custom/file'], - {customCwd: '/some/custom/cwd'}, + {customCwd: '/some/custom/cwd'} ); args.should.deep.equals([ '--config', @@ -215,38 +203,26 @@ describe('Execution tests', () => { '--', './exec', '/app/file', - '/not/custom/file']); + '/not/custom/file', + ]); options.should.deep.equals({}); expect(filenameTransform).to.not.be.undefined; filenameTransform('moo').should.equal('moo'); filenameTransform('/some/custom/cwd/file').should.equal('/app/file'); }); it('should handle timeouts', () => { - const args = exec.getNsJailOptions( - 'sandbox', - '/path/to/compiler', - [], - {timeoutMs: 1234}, - ).args; + const args = exec.getNsJailOptions('sandbox', '/path/to/compiler', [], {timeoutMs: 1234}).args; args.should.include('--time_limit=2'); }); it('should handle linker paths', () => { - const {args, options} = exec.getNsJailOptions( - 'sandbox', - '/path/to/compiler', - [], - {ldPath: '/a/lib/path'}, - ); + const {args, options} = exec.getNsJailOptions('sandbox', '/path/to/compiler', [], {ldPath: '/a/lib/path'}); options.should.deep.equals({}); args.should.include('--env=LD_LIBRARY_PATH=/a/lib/path'); }); it('should handle envs', () => { - const {args, options} = exec.getNsJailOptions( - 'sandbox', - '/path/to/compiler', - [], - {env: {ENV1: '1', ENV2: '2'}}, - ); + const {args, options} = exec.getNsJailOptions('sandbox', '/path/to/compiler', [], { + env: {ENV1: '1', ENV2: '2'}, + }); options.should.deep.equals({}); args.should.include('--env=ENV1=1'); args.should.include('--env=ENV2=2'); @@ -262,11 +238,7 @@ describe('Execution tests', () => { }); it('Normal situation without customCwd', () => { - const {args, options} = exec.getSandboxNsjailOptions( - '/tmp/hellow/output.s', - [], - {}, - ); + const {args, options} = exec.getSandboxNsjailOptions('/tmp/hellow/output.s', [], {}); options.should.deep.equals({}); args.should.deep.equals([ @@ -283,13 +255,9 @@ describe('Execution tests', () => { }); it('Normal situation', () => { - const {args, options} = exec.getSandboxNsjailOptions( - '/tmp/hellow/output.s', - [], - { - customCwd: '/tmp/hellow', - }, - ); + const {args, options} = exec.getSandboxNsjailOptions('/tmp/hellow/output.s', [], { + customCwd: '/tmp/hellow', + }); options.should.deep.equals({}); args.should.deep.equals([ @@ -306,13 +274,9 @@ describe('Execution tests', () => { }); it('Subdirectory', () => { - const {args, options} = exec.getSandboxNsjailOptions( - '/tmp/hellow/subdir/output.s', - [], - { - customCwd: '/tmp/hellow', - }, - ); + const {args, options} = exec.getSandboxNsjailOptions('/tmp/hellow/subdir/output.s', [], { + customCwd: '/tmp/hellow', + }); options.should.deep.equals({}); if (process.platform !== 'win32') { @@ -331,15 +295,10 @@ describe('Execution tests', () => { }); it('CMake outside tree building', () => { - const {args, options} = exec.getNsJailOptions( - 'execute', - '/opt/compiler-explorer/cmake/bin/cmake', - ['..'], - { - customCwd: '/tmp/hellow/build', - appHome: '/tmp/hellow', - }, - ); + const {args, options} = exec.getNsJailOptions('execute', '/opt/compiler-explorer/cmake/bin/cmake', ['..'], { + customCwd: '/tmp/hellow/build', + appHome: '/tmp/hellow', + }); options.should.deep.equals({ appHome: '/tmp/hellow', diff --git a/test/java-tests.js b/test/java-tests.js index 0dc562621..d1ed2cb1e 100644 --- a/test/java-tests.js +++ b/test/java-tests.js @@ -22,10 +22,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -import { JavaCompiler } from '../lib/compilers'; +import {JavaCompiler} from '../lib/compilers'; import * as utils from '../lib/utils'; -import { fs, makeCompilationEnvironment } from './utils'; +import {fs, makeCompilationEnvironment} from './utils'; const languages = { java: {id: 'java'}, @@ -62,54 +62,42 @@ describe('Basic compiler setup', function () { describe('Forbidden compiler arguments', function () { it('JavaCompiler should not allow -d parameter', () => { const compiler = new JavaCompiler(info, env); - compiler.filterUserOptions(['hello', '-d', '--something', '--something-else']).should.deep.equal( - ['hello', '--something-else'], - ); - compiler.filterUserOptions(['hello', '-d']).should.deep.equal( - ['hello'], - ); - compiler.filterUserOptions(['-d', 'something', 'something-else']).should.deep.equal( - ['something-else'], - ); + compiler + .filterUserOptions(['hello', '-d', '--something', '--something-else']) + .should.deep.equal(['hello', '--something-else']); + compiler.filterUserOptions(['hello', '-d']).should.deep.equal(['hello']); + compiler.filterUserOptions(['-d', 'something', 'something-else']).should.deep.equal(['something-else']); }); it('JavaCompiler should not allow -s parameter', () => { const compiler = new JavaCompiler(info, env); - compiler.filterUserOptions(['hello', '-s', '--something', '--something-else']).should.deep.equal( - ['hello', '--something-else'], - ); - compiler.filterUserOptions(['hello', '-s']).should.deep.equal( - ['hello'], - ); - compiler.filterUserOptions(['-s', 'something', 'something-else']).should.deep.equal( - ['something-else'], - ); + compiler + .filterUserOptions(['hello', '-s', '--something', '--something-else']) + .should.deep.equal(['hello', '--something-else']); + compiler.filterUserOptions(['hello', '-s']).should.deep.equal(['hello']); + compiler.filterUserOptions(['-s', 'something', 'something-else']).should.deep.equal(['something-else']); }); it('JavaCompiler should not allow --source-path parameter', () => { const compiler = new JavaCompiler(info, env); - compiler.filterUserOptions(['hello', '--source-path', '--something', '--something-else']).should.deep.equal( - ['hello', '--something-else'], - ); - compiler.filterUserOptions(['hello', '--source-path']).should.deep.equal( - ['hello'], - ); - compiler.filterUserOptions(['--source-path', 'something', 'something-else']).should.deep.equal( - ['something-else'], - ); + compiler + .filterUserOptions(['hello', '--source-path', '--something', '--something-else']) + .should.deep.equal(['hello', '--something-else']); + compiler.filterUserOptions(['hello', '--source-path']).should.deep.equal(['hello']); + compiler + .filterUserOptions(['--source-path', 'something', 'something-else']) + .should.deep.equal(['something-else']); }); it('JavaCompiler should not allow -sourcepath parameter', () => { const compiler = new JavaCompiler(info, env); - compiler.filterUserOptions(['hello', '-sourcepath', '--something', '--something-else']).should.deep.equal( - ['hello', '--something-else'], - ); - compiler.filterUserOptions(['hello', '-sourcepath']).should.deep.equal( - ['hello'], - ); - compiler.filterUserOptions(['-sourcepath', 'something', 'something-else']).should.deep.equal( - ['something-else'], - ); + compiler + .filterUserOptions(['hello', '-sourcepath', '--something', '--something-else']) + .should.deep.equal(['hello', '--something-else']); + compiler.filterUserOptions(['hello', '-sourcepath']).should.deep.equal(['hello']); + compiler + .filterUserOptions(['-sourcepath', 'something', 'something-else']) + .should.deep.equal(['something-else']); }); }); }); @@ -158,15 +146,11 @@ describe('javap parsing', () => { asm: '<Compilation failed>', }; - compiler.processAsm(result).should.deep.equal([ - {text: '<Compilation failed>', source: null}, - ]); + compiler.processAsm(result).should.deep.equal([{text: '<Compilation failed>', source: null}]); }); it('Parses simple class with one method', () => { - return Promise.all([ - testJava('test/java/square', 'javap-square'), - ]); + return Promise.all([testJava('test/java/square', 'javap-square')]); }); it('Preserves ordering of multiple classes', () => { diff --git a/test/storage/storage-s3-tests.js b/test/storage/storage-s3-tests.js index 7df00654b..46a287066 100644 --- a/test/storage/storage-s3-tests.js +++ b/test/storage/storage-s3-tests.js @@ -25,8 +25,8 @@ import AWS from 'aws-sdk-mock'; import * as properties from '../../lib/properties'; -import { StorageS3 } from '../../lib/storage'; -import { should } from '../utils'; +import {StorageS3} from '../../lib/storage'; +import {should} from '../utils'; // NB!!! Anything using mocked AWS calls needs to be initialised in the `it(...)` block! If you initialise it in the // `describe()` top level code then it won't be mocked in time. We only mock and de-mock before/after else we end up @@ -63,17 +63,15 @@ describe('Find unique subhash tests', () => { }); it('works when empty', () => { const storage = new StorageS3(httpRootDir, compilerProps, awsProps); - dynamoDbQueryHandlers.push((q) => { + dynamoDbQueryHandlers.push(q => { q.TableName.should.equal('table'); return {}; }); - return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal( - { - alreadyPresent: false, - prefix: 'ABCDEF', - uniqueSubHash: 'ABCDEFGHI', - }, - ); + return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal({ + alreadyPresent: false, + prefix: 'ABCDEF', + uniqueSubHash: 'ABCDEFGHI', + }); }); it('works when not empty', () => { const storage = new StorageS3(httpRootDir, compilerProps, awsProps); @@ -87,15 +85,13 @@ describe('Find unique subhash tests', () => { ], }; }); - return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal( - { - alreadyPresent: false, - prefix: 'ABCDEF', - uniqueSubHash: 'ABCDEFGHI', - }, - ); + return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal({ + alreadyPresent: false, + prefix: 'ABCDEF', + uniqueSubHash: 'ABCDEFGHI', + }); }); - it('works when there\' a collision', () => { + it("works when there' a collision", () => { const storage = new StorageS3(httpRootDir, compilerProps, awsProps); dynamoDbQueryHandlers.push(() => { return { @@ -107,13 +103,11 @@ describe('Find unique subhash tests', () => { ], }; }); - return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal( - { - alreadyPresent: false, - prefix: 'ABCDEF', - uniqueSubHash: 'ABCDEFGHIJ', - }, - ); + return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal({ + alreadyPresent: false, + prefix: 'ABCDEF', + uniqueSubHash: 'ABCDEFGHIJ', + }); }); it('finds an existing match', () => { const storage = new StorageS3(httpRootDir, compilerProps, awsProps); @@ -127,13 +121,11 @@ describe('Find unique subhash tests', () => { ], }; }); - return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal( - { - alreadyPresent: true, - prefix: 'ABCDEF', - uniqueSubHash: 'ABCDEFGHI', - }, - ); + return storage.findUniqueSubhash('ABCDEFGHIJKLMNOPQRSTUV').should.eventually.deep.equal({ + alreadyPresent: true, + prefix: 'ABCDEF', + uniqueSubHash: 'ABCDEFGHI', + }); }); }); @@ -158,14 +150,14 @@ describe('Stores to s3', () => { }; const ran = {s3: false, dynamo: false}; - s3PutObjectHandlers.push((q) => { + s3PutObjectHandlers.push(q => { q.Bucket.should.equal('bucket'); q.Key.should.equal('prefix/ABCDEFGHIJKLMNOP'); q.Body.should.equal('yo'); ran.s3 = true; return {}; }); - dynamoDbPutItemHandlers.push((q) => { + dynamoDbPutItemHandlers.push(q => { q.TableName.should.equals('table'); q.Item.should.deep.equals({ prefix: {S: 'ABCDEF'}, @@ -223,8 +215,7 @@ describe('Retrieves from s3', () => { }); it('should handle failures', async () => { const storage = new StorageS3(httpRootDir, compilerProps, awsProps); - for (let i = 0; i < 10; ++i) - dynamoDbGetItemHandlers.push(() => ({})); + for (let i = 0; i < 10; ++i) dynamoDbGetItemHandlers.push(() => ({})); return storage.expandId('ABCDEF').should.be.rejectedWith(Error, 'ID ABCDEF not present in links table'); }); }); @@ -243,18 +234,16 @@ describe('Updates counts in s3', async () => { const storage = new StorageS3(httpRootDir, compilerProps, awsProps); let called = false; dynamoDbUpdateItemHandlers.push(q => { - q.should.deep.equals( - { - ExpressionAttributeValues: {':inc': {N: '1'}}, - Key: { - prefix: {S: 'ABCDEF'}, - unique_subhash: {S: 'ABCDEF'}, - }, - ReturnValues: 'NONE', - TableName: 'table', - UpdateExpression: 'SET stats.clicks = stats.clicks + :inc', + q.should.deep.equals({ + ExpressionAttributeValues: {':inc': {N: '1'}}, + Key: { + prefix: {S: 'ABCDEF'}, + unique_subhash: {S: 'ABCDEF'}, }, - ); + ReturnValues: 'NONE', + TableName: 'table', + UpdateExpression: 'SET stats.clicks = stats.clicks + :inc', + }); called = true; }); await storage.incrementViewCount('ABCDEF'); diff --git a/test/tool-tests.js b/test/tool-tests.js index 2430772e4..9c780d77a 100644 --- a/test/tool-tests.js +++ b/test/tool-tests.js @@ -22,9 +22,9 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -import { CompilerDropinTool } from '../lib/tooling/compiler-dropin-tool'; +import {CompilerDropinTool} from '../lib/tooling/compiler-dropin-tool'; -import { path } from './utils'; +import {path} from './utils'; describe('CompilerDropInTool', () => { it('Should support llvm based compilers', () => { @@ -42,12 +42,10 @@ describe('CompilerDropInTool', () => { const sourcefile = 'example.cpp'; const orderedArgs = tool.getOrderedArguments(compilationInfo, includeflags, [], args, sourcefile); - orderedArgs.should.deep.equal( - [ - '--gcc-toolchain=/opt/compiler-explorer/gcc-7.2.0', - '--gcc-toolchain=/opt/compiler-explorer/gcc-7.2.0', - ], - ); + orderedArgs.should.deep.equal([ + '--gcc-toolchain=/opt/compiler-explorer/gcc-7.2.0', + '--gcc-toolchain=/opt/compiler-explorer/gcc-7.2.0', + ]); }); it('Should support gcc based compilers', () => { @@ -65,12 +63,10 @@ describe('CompilerDropInTool', () => { const sourcefile = 'example.cpp'; const orderedArgs = tool.getOrderedArguments(compilationInfo, includeflags, [], args, sourcefile); - orderedArgs.should.deep.equal( - [ - '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.0'), - '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.0'), - ], - ); + orderedArgs.should.deep.equal([ + '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.0'), + '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.0'), + ]); }); it('Should not support riscv gcc compilers', () => { @@ -106,12 +102,10 @@ describe('CompilerDropInTool', () => { const sourcefile = 'example.cpp'; const orderedArgs = tool.getOrderedArguments(compilationInfo, includeflags, [], args, sourcefile); - orderedArgs.should.deep.equal( - [ - '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.2.0'), - '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.2.0'), - ], - ); + orderedArgs.should.deep.equal([ + '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.2.0'), + '--gcc-toolchain=' + path.resolve('/opt/compiler-explorer/gcc-8.2.0'), + ]); }); it('Should not support WINE MSVC compilers', () => { @@ -120,12 +114,10 @@ describe('CompilerDropInTool', () => { const compilationInfo = { compiler: { exe: '/opt/compiler-explorer/windows/19.14.26423/bin/cl.exe', - options: + options: '/I/opt/compiler-explorer/windows/10.0.10240.0/ucrt/ ' + '/I/opt/compiler-explorer/windows/19.14.26423/include/', - internalIncludePaths: [ - '/opt/compiler-explorer/windows/19.14.26423/include', - ], + internalIncludePaths: ['/opt/compiler-explorer/windows/19.14.26423/include'], }, options: [], }; @@ -144,9 +136,7 @@ describe('CompilerDropInTool', () => { compiler: { exe: '/opt/compiler-explorer/clang-concepts-trunk/bin/clang++', options: '-stdlib=libc++', - internalIncludePaths: [ - '/opt/compiler-explorer/clang-concepts-trunk/something/etc/include', - ], + internalIncludePaths: ['/opt/compiler-explorer/clang-concepts-trunk/something/etc/include'], }, options: [], }; @@ -165,9 +155,7 @@ describe('CompilerDropInTool', () => { compiler: { exe: '/opt/compiler-explorer/clang-concepts-trunk/bin/clang++', options: '--gcc-toolchain=/opt/compiler-explorer/gcc-8.2.0', - internalIncludePaths: [ - '/opt/compiler-explorer/clang-concepts-trunk/something/etc/include', - ], + internalIncludePaths: ['/opt/compiler-explorer/clang-concepts-trunk/something/etc/include'], }, options: [], }; @@ -177,13 +165,11 @@ describe('CompilerDropInTool', () => { const libOptions = ['-DMYLIBDEF', '-pthread']; const orderedArgs = tool.getOrderedArguments(compilationInfo, includeflags, libOptions, args, sourcefile); - orderedArgs.should.deep.equal( - [ - '--gcc-toolchain=/opt/compiler-explorer/gcc-8.2.0', - '--gcc-toolchain=/opt/compiler-explorer/gcc-8.2.0', - '-DMYLIBDEF', - '-pthread', - ], - ); + orderedArgs.should.deep.equal([ + '--gcc-toolchain=/opt/compiler-explorer/gcc-8.2.0', + '--gcc-toolchain=/opt/compiler-explorer/gcc-8.2.0', + '-DMYLIBDEF', + '-pthread', + ]); }); }); |