From 2ae38a0c3fea47c9ec850a37836427460f4abb98 Mon Sep 17 00:00:00 2001 From: Matt Godbolt Date: Mon, 11 Aug 2025 12:14:13 -0500 Subject: [PATCH] Make argument parsers instances instead of static classes (#8017) - Made parsers stateful instances instead of shared static state (for mllvm options). Fixes #8011 as this is caused by multiple clang-based compilers being run concurrently and stomping over each others' state. - passes `Compiler` to the constructor, which removes some param passing - Added some missing awaits - Tried to get things less dependent on `examples`, only `go` needs it - Spotted that `zig` c++ might have issues in discovery - Fly-by fixed a broken go path in ppc64le_gl122 - removed a redundant override in coccinelle - made the mojo parser actually use the parser it defined - canonified tablegen's special method - I changed the zig parser too but as best I can tell it was broken before (the `1` return value from the command it runs:) ``` ubuntu@ip-172-30-0-164:/infra/.deploy$ /opt/compiler-explorer/zig-0.14.1/zig c++ -mllvm --help-list-hidden /infra/.deploy/examples/c++/default.cpp -S -o /tmp/output.s ... --x86-use-vzeroupper - Minimize AVX to SSE transition penalty --xcore-max-threads= - Maximum number of threads (for emulation thread-local storage) /infra/.deploy/examples/c++/default.cpp:1:1: error: FileNotFound ``` return code 1 (means it's not cached) --------- Co-authored-by: Partouf --- compiler-args-app.ts | 25 +- etc/config/go.amazon.properties | 2 +- lib/base-compiler.ts | 10 +- lib/compilers/argument-parsers.ts | 695 +++++++++++------------ lib/compilers/coccinelle.ts | 4 - lib/compilers/mojo.ts | 5 + lib/compilers/rust.ts | 2 +- lib/compilers/tablegen.ts | 2 +- test/analysis-tests.ts | 1 + test/android-tests.ts | 4 +- test/base-compiler-tests.ts | 5 + test/compilers/argument-parsers-tests.ts | 98 ++-- test/demangler-tests.ts | 2 +- test/pascal-tests.ts | 4 +- 14 files changed, 450 insertions(+), 409 deletions(-) diff --git a/compiler-args-app.ts b/compiler-args-app.ts index 4475fcbba..83e11bb0f 100644 --- a/compiler-args-app.ts +++ b/compiler-args-app.ts @@ -29,6 +29,7 @@ import {CompilerArguments} from './lib/compiler-arguments.js'; import * as Parsers from './lib/compilers/argument-parsers.js'; import {executeDirect} from './lib/exec.js'; import {logger} from './lib/logger.js'; +import {BaseParser} from './lib/compilers/argument-parsers.js'; const program = new Command(); program @@ -90,6 +91,13 @@ class CompilerArgsApp { execCompilerCached: async (command: string, args: string[]) => { return executeDirect(command, args, {}, fn => fn); }, + getDefaultExecOptions: () => { + return { + env: process.env, + cwd: process.cwd(), + timeout: 10000, + }; + } }; if (this.parserName === 'juliawrapper') { @@ -99,22 +107,22 @@ class CompilerArgsApp { async getPossibleStdvers() { const parser = this.getParser(); - return await parser.getPossibleStdvers(this.compiler); + return await parser.getPossibleStdvers(); } async getPossibleTargets() { const parser = this.getParser(); - return await parser.getPossibleTargets(this.compiler); + return await parser.getPossibleTargets(); } async getPossibleEditions() { const parser = this.getParser(); - return await parser.getPossibleEditions(this.compiler); + return await parser.getPossibleEditions(); } - getParser() { + getParser(): BaseParser { if (compilerParsers[this.parserName as keyof typeof compilerParsers]) { - return compilerParsers[this.parserName as keyof typeof compilerParsers]; + return new (compilerParsers[this.parserName as keyof typeof compilerParsers])(this.compiler); } console.error('Unknown parser type'); process.exit(1); @@ -122,7 +130,7 @@ class CompilerArgsApp { async doTheParsing() { const parser = this.getParser(); - await parser.parse(this.compiler); + await parser.parse(); const options = this.compiler.possibleArguments.possibleArguments; if (parser.hasSupportStartsWith(options, '--target=')) { console.log('supportsTargetIs'); @@ -150,6 +158,11 @@ class CompilerArgsApp { console.log(await this.getPossibleTargets()); console.log('Editions:'); console.log(await this.getPossibleEditions()); + + console.log('supportsOptOutput:', !!this.compiler.compiler.supportsOptOutput); + console.log('supportsStackUsageOutput', !!this.compiler.compiler.supportsStackUsageOutput); + console.log('optPipeline:', this.compiler.compiler.optPipeline); + console.log('supportsGccDump', !!this.compiler.compiler.supportsGccDump); } } diff --git a/etc/config/go.amazon.properties b/etc/config/go.amazon.properties index 24a3a83f1..789ca7037 100644 --- a/etc/config/go.amazon.properties +++ b/etc/config/go.amazon.properties @@ -448,7 +448,7 @@ compiler.ppc64le_gl120.exe=/opt/compiler-explorer/golang-1.20/go/bin/go compiler.ppc64le_gl120.semver=1.20 compiler.ppc64le_gl121.exe=/opt/compiler-explorer/golang-1.21.13/go/bin/go compiler.ppc64le_gl121.semver=1.21.13 -compiler.ppc64le_gl122.exe=/opt/compiler-explorer/golang-1.22.1)/go/bin/go +compiler.ppc64le_gl122.exe=/opt/compiler-explorer/golang-1.22.1/go/bin/go compiler.ppc64le_gl122.semver=1.22.12 compiler.ppc64le_gl123.exe=/opt/compiler-explorer/golang-1.23.8/go/bin/go compiler.ppc64le_gl123.semver=1.23.8 diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts index c0f78d5b1..df51c8682 100644 --- a/lib/base-compiler.ts +++ b/lib/base-compiler.ts @@ -217,6 +217,7 @@ export class BaseCompiler { labelNames: [], }); protected executionEnvironmentClass: any; + protected readonly argParser: BaseParser; constructor(compilerInfo: PreliminaryCompilerInfo & {disabledFilters?: string[]}, env: CompilationEnvironment) { // Information about our compiler @@ -306,6 +307,7 @@ export class BaseCompiler { } this.packager = new Packager(); + this.argParser = new (this.getArgumentParserClass())(this); } copyAndFilterLibraries(allLibraries: Record, filter: string[]) { @@ -3598,8 +3600,7 @@ but nothing was dumped. Possible causes are: async getTargetsAsOverrideValues(): Promise { if (!this.buildenvsetup || !this.buildenvsetup.getCompilerArch()) { - const parserCls = this.getArgumentParserClass(); - const targets = await parserCls.getPossibleTargets(this); + const targets = await this.argParser.getPossibleTargets(); return targets.map(target => { return { @@ -3612,8 +3613,7 @@ but nothing was dumped. Possible causes are: } async getPossibleStdversAsOverrideValues(): Promise { - const parser = this.getArgumentParserClass(); - return await parser.getPossibleStdvers(this); + return await this.argParser.getPossibleStdvers(); } async populatePossibleRuntimeTools() { @@ -3794,7 +3794,7 @@ but nothing was dumped. Possible causes are: } return this; } - const initResult = await this.getArgumentParserClass().parse(this); + const initResult = await this.argParser.parse(); this.possibleArguments.possibleArguments = {}; await this.populatePossibleOverrides(); diff --git a/lib/compilers/argument-parsers.ts b/lib/compilers/argument-parsers.ts index d337978d5..7e43089b3 100644 --- a/lib/compilers/argument-parsers.ts +++ b/lib/compilers/argument-parsers.ts @@ -24,7 +24,6 @@ import fs from 'node:fs/promises'; import path from 'node:path'; -import process from 'node:process'; import * as Sentry from '@sentry/node'; import _ from 'underscore'; @@ -39,32 +38,22 @@ import * as utils from '../utils.js'; import {JuliaCompiler} from './julia.js'; export class BaseParser { - static setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) {} + protected readonly compiler: BaseCompiler; - static hasSupport(options: Record, forOption: string) { + constructor(compiler: BaseCompiler) { + this.compiler = compiler; + } + async setCompilerSettingsFromOptions(options: Record) {} + + hasSupport(options: Record, forOption: string) { return _.keys(options).find(option => option.includes(forOption)); } - static hasSupportStartsWith(options: Record, forOption: string) { + hasSupportStartsWith(options: Record, forOption: string) { return _.keys(options).find(option => option.startsWith(forOption)); } - static getExamplesRoot(): string { - return props.get('builtin', 'sourcePath', './examples/'); - } - - static getDefaultExampleFilename() { - return 'c++/default.cpp'; - } - - static getExampleFilepath(): string { - let filename = path.join(this.getExamplesRoot(), this.getDefaultExampleFilename()); - if (!path.isAbsolute(filename)) filename = path.join(process.cwd(), filename); - - return filename; - } - - static parseLines(stdout: string, optionWithDescRegex: RegExp, optionWithoutDescRegex?: RegExp) { + parseLines(stdout: string, optionWithDescRegex: RegExp, optionWithoutDescRegex?: RegExp) { let previousOption: false | string = false; const options: Record = {}; @@ -116,105 +105,113 @@ export class BaseParser { return options; } - static spaceCompress(text: string): string { + spaceCompress(text: string): string { return text.replaceAll(' ', ' '); } - static async getPossibleTargets(compiler: BaseCompiler): Promise { + async getPossibleTargets(): Promise { return []; } - static async getPossibleStdvers(compiler: BaseCompiler): Promise { + async getPossibleStdvers(): Promise { return []; } // Currently used only for Rust - static async getPossibleEditions(compiler: BaseCompiler): Promise { + async getPossibleEditions(): Promise { return []; } - static async getOptions(compiler: BaseCompiler, helpArg: string) { + // Currently used only for TableGen + async getPossibleActions(): Promise { + return []; + } + + async getOptions(helpArg: string) { const optionFinder1 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*) {2,}(.*)/i; const optionFinder2 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [helpArg]); const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder1, optionFinder2) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } // async for compatibility with children, who call getOptions - static async parse(compiler: BaseCompiler) { - return compiler; + async parse() { + return this.compiler; } } export class GCCParser extends BaseParser { - static async checkAndSetMasmIntelIfSupported(compiler: BaseCompiler) { + async checkAndSetMasmIntelIfSupported() { // -masm= may be available but unsupported by the compiler. - const res = await compiler.execCompilerCached(compiler.compiler.exe, [ + const res = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [ '-fsyntax-only', '--target-help', '-masm=intel', ]); if (res.code === 0) { - compiler.compiler.intelAsm = '-masm=intel'; - compiler.compiler.supportsIntel = true; + this.compiler.compiler.intelAsm = '-masm=intel'; + this.compiler.compiler.supportsIntel = true; } } - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { + override async setCompilerSettingsFromOptions(options: Record) { const keys = _.keys(options); logger.debug(`gcc-like compiler options: ${keys.join(' ')}`); if (this.hasSupport(options, '-masm=')) { - await this.checkAndSetMasmIntelIfSupported(compiler); + await this.checkAndSetMasmIntelIfSupported(); } if (this.hasSupport(options, '-fstack-usage')) { - compiler.compiler.stackUsageArg = '-fstack-usage'; - compiler.compiler.supportsStackUsageOutput = true; + this.compiler.compiler.stackUsageArg = '-fstack-usage'; + this.compiler.compiler.supportsStackUsageOutput = true; } if (this.hasSupport(options, '-fdiagnostics-color')) { - if (compiler.compiler.options) compiler.compiler.options += ' '; - compiler.compiler.options += '-fdiagnostics-color=always'; + if (this.compiler.compiler.options) this.compiler.compiler.options += ' '; + this.compiler.compiler.options += '-fdiagnostics-color=always'; } if (this.hasSupport(options, '-fverbose-asm')) { - compiler.compiler.supportsVerboseAsm = true; + this.compiler.compiler.supportsVerboseAsm = true; } if (this.hasSupport(options, '-fopt-info')) { - compiler.compiler.optArg = '-fopt-info-all=all.opt'; - compiler.compiler.supportsOptOutput = true; + this.compiler.compiler.optArg = '-fopt-info-all=all.opt'; + this.compiler.compiler.supportsOptOutput = true; } // This check is not infallible, but takes care of Rust and Swift being picked up :) if (_.find(keys, key => key.startsWith('-fdump-'))) { - compiler.compiler.supportsGccDump = true; + this.compiler.compiler.supportsGccDump = true; // By default, consider the compiler to be a regular GCC (eg. gcc, // g++) and do the extra work of filtering out enabled pass that did // not produce anything. - compiler.compiler.removeEmptyGccDump = true; + this.compiler.compiler.removeEmptyGccDump = true; } - if (this.hasSupportStartsWith(options, '-march=')) compiler.compiler.supportsMarch = true; - if (this.hasSupportStartsWith(options, '--target=')) compiler.compiler.supportsTargetIs = true; - if (this.hasSupportStartsWith(options, '--target ')) compiler.compiler.supportsTarget = true; + if (this.hasSupportStartsWith(options, '-march=')) this.compiler.compiler.supportsMarch = true; + if (this.hasSupportStartsWith(options, '--target=')) this.compiler.compiler.supportsTargetIs = true; + if (this.hasSupportStartsWith(options, '--target ')) this.compiler.compiler.supportsTarget = true; } - static override async parse(compiler: BaseCompiler) { + override async parse() { const results = await Promise.all([ - this.getOptions(compiler, '-fsyntax-only --help'), - this.getOptions(compiler, '-fsyntax-only --target-help'), - this.getOptions(compiler, '-fsyntax-only --help=common'), - this.getOptions(compiler, '-fsyntax-only --help=warnings'), - this.getOptions(compiler, '-fsyntax-only --help=optimizers'), - this.getOptions(compiler, '-fsyntax-only --help=target'), + this.getOptions('-fsyntax-only --help'), + this.getOptions('-fsyntax-only --target-help'), + this.getOptions('-fsyntax-only --help=common'), + this.getOptions('-fsyntax-only --help=warnings'), + this.getOptions('-fsyntax-only --help=optimizers'), + this.getOptions('-fsyntax-only --help=target'), ]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getPossibleTargets(compiler: BaseCompiler): Promise { + override async getPossibleTargets(): Promise { const re = /Known valid arguments for -march= option:\s+(.*)/; - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['-fsyntax-only', '--target-help']); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [ + '-fsyntax-only', + '--target-help', + ]); const match = result.stdout.match(re); if (match) { return match[1].split(' '); @@ -222,13 +219,13 @@ export class GCCParser extends BaseParser { return []; } - static getLanguageSpecificHelpFlags(): string[] { + getLanguageSpecificHelpFlags(): string[] { return ['-fsyntax-only', '--help=c++']; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { const possible: CompilerOverrideOptions = []; - const options = await this.getOptionsStrict(compiler, this.getLanguageSpecificHelpFlags()); + const options = await this.getOptionsStrict(this.getLanguageSpecificHelpFlags()); for (const opt in options) { if (opt.startsWith('-std=') && !options[opt].description?.startsWith('Deprecated')) { const stdver = opt.substring(5); @@ -241,57 +238,57 @@ export class GCCParser extends BaseParser { return possible; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder1 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*) {2,}(.*)/i; const optionFinder2 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' ')); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg)); const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder1, optionFinder2) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } - static async getOptionsStrict(compiler: BaseCompiler, helpArgs: string[]) { + async getOptionsStrict(helpArgs: string[]) { const optionFinder = /^ {2}(--?[\d+,<=>[\]a-z|-]*) *(.*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArgs); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, helpArgs); return result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {}; } } export class ClangParser extends BaseParser { - static mllvmOptions = new Set(); + mllvmOptions = new Set(); - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { + override async setCompilerSettingsFromOptions(options: Record) { const keys = _.keys(options); logger.debug(`clang-like compiler options: ${keys.join(' ')}`); if (keys.length === 0) { - logger.error(`compiler options appear empty for ${compiler.compiler.id}`); + logger.error(`compiler options appear empty for ${this.compiler.compiler.id}`); } if (this.hasSupport(options, '-fsave-optimization-record')) { - compiler.compiler.optArg = '-fsave-optimization-record'; - compiler.compiler.supportsOptOutput = true; + this.compiler.compiler.optArg = '-fsave-optimization-record'; + this.compiler.compiler.supportsOptOutput = true; } if (this.hasSupport(options, '-fstack-usage')) { - compiler.compiler.stackUsageArg = '-fstack-usage'; - compiler.compiler.supportsStackUsageOutput = true; + this.compiler.compiler.stackUsageArg = '-fstack-usage'; + this.compiler.compiler.supportsStackUsageOutput = true; } if (this.hasSupport(options, '-fverbose-asm')) { - compiler.compiler.supportsVerboseAsm = true; + this.compiler.compiler.supportsVerboseAsm = true; } if (this.hasSupport(options, '-emit-llvm')) { - compiler.compiler.supportsIrView = true; - compiler.compiler.irArg = ['-Xclang', '-emit-llvm', '-fsyntax-only']; - compiler.compiler.minIrArgs = ['-emit-llvm']; + this.compiler.compiler.supportsIrView = true; + this.compiler.compiler.irArg = ['-Xclang', '-emit-llvm', '-fsyntax-only']; + this.compiler.compiler.minIrArgs = ['-emit-llvm']; } // if (this.hasSupport(options, '-emit-cir')) { // #7265: clang-trunk supposedly has '-emit-cir', but it's not doing much. Checking explicitly // for clangir in the compiler name instead. - if (compiler.compiler.name?.includes('clangir')) { - compiler.compiler.supportsClangirView = true; + if (this.compiler.compiler.name?.includes('clangir')) { + this.compiler.compiler.supportsClangirView = true; } if ( @@ -299,61 +296,60 @@ export class ClangParser extends BaseParser { this.mllvmOptions.has('--print-before-all') && this.mllvmOptions.has('--print-after-all') ) { - compiler.compiler.optPipeline = { + this.compiler.compiler.optPipeline = { arg: ['-mllvm', '--print-before-all', '-mllvm', '--print-after-all'], moduleScopeArg: [], noDiscardValueNamesArg: [], }; if (this.mllvmOptions.has('--print-module-scope')) { - compiler.compiler.optPipeline.moduleScopeArg = ['-mllvm', '-print-module-scope']; + this.compiler.compiler.optPipeline.moduleScopeArg = ['-mllvm', '-print-module-scope']; } if (this.hasSupport(options, '-fno-discard-value-names')) { - compiler.compiler.optPipeline.noDiscardValueNamesArg = ['-fno-discard-value-names']; + this.compiler.compiler.optPipeline.noDiscardValueNamesArg = ['-fno-discard-value-names']; } } - if (this.hasSupport(options, '-fcolor-diagnostics')) compiler.compiler.options += ' -fcolor-diagnostics'; - if (this.hasSupport(options, '-fno-crash-diagnostics')) compiler.compiler.options += ' -fno-crash-diagnostics'; + if (this.hasSupport(options, '-fcolor-diagnostics')) this.compiler.compiler.options += ' -fcolor-diagnostics'; + if (this.hasSupport(options, '-fno-crash-diagnostics')) + this.compiler.compiler.options += ' -fno-crash-diagnostics'; - if (this.hasSupportStartsWith(options, '--target=')) compiler.compiler.supportsTargetIs = true; - if (this.hasSupportStartsWith(options, '--target ')) compiler.compiler.supportsTarget = true; + if (this.hasSupportStartsWith(options, '--target=')) this.compiler.compiler.supportsTargetIs = true; + if (this.hasSupportStartsWith(options, '--target ')) this.compiler.compiler.supportsTarget = true; } - static getMainHelpOptions(): string[] { + getMainHelpOptions(): string[] { return ['--help']; } - static getHiddenHelpOptions(exampleFile: string): string[] { - return ['-mllvm', '--help-list-hidden', exampleFile, '-c']; + getHiddenHelpOptions(): string[] { + return ['-mllvm', '--help-list-hidden', '-x', 'c++', '/dev/null', '-c']; } - static getStdVersHelpOptions(exampleFile: string): string[] { - return ['-std=c++9999999', exampleFile, '-c']; + getStdVersHelpOptions(): string[] { + return ['-std=c++9999999', '-x', 'c++', '/dev/null', '-c']; } - static getTargetsHelpOptions(): string[] { + getTargetsHelpOptions(): string[] { return ['--print-targets']; } - static override async parse(compiler: BaseCompiler) { + override async parse() { try { - const options = await this.getOptions(compiler, this.getMainHelpOptions().join(' ')); - - const filename = this.getExampleFilepath(); + const options = await this.getOptions(this.getMainHelpOptions().join(' ')); this.mllvmOptions = new Set( - _.keys(await this.getOptions(compiler, this.getHiddenHelpOptions(filename).join(' '), false, true)), + _.keys(await this.getOptions(this.getHiddenHelpOptions().join(' '), false, true)), ); - this.setCompilerSettingsFromOptions(compiler, options); + await this.setCompilerSettingsFromOptions(options); } catch (error) { - const err = `Error while trying to generate llvm backend arguments for ${compiler.compiler.id}: ${error}`; + const err = `Error while trying to generate llvm backend arguments for ${this.compiler.compiler.id}: ${error}`; logger.error(err); Sentry.captureMessage(err); } - return compiler; + return this.compiler; } - static getRegexMatchesAsStdver(match: RegExpMatchArray | null, maxToMatch: number): CompilerOverrideOptions { + getRegexMatchesAsStdver(match: RegExpMatchArray | null, maxToMatch: number): CompilerOverrideOptions { if (!match) return []; if (!match[maxToMatch]) return []; @@ -371,7 +367,7 @@ export class ClangParser extends BaseParser { return arr; } - static extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { + extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { const possible: CompilerOverrideOptions = []; const re1 = /note: use '([\w+:]*)' for '(.*)' standard/; const re2 = /note: use '([\w+:]*)' or '([\w+:]*)' for '(.*)' standard/; @@ -400,16 +396,17 @@ export class ClangParser extends BaseParser { return possible; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { let possible: CompilerOverrideOptions = []; - // clang doesn't have a --help option to get the std versions, we'll have to compile with a fictional stdversion to coax a response - const filename = this.getExampleFilepath(); - - const result = await compiler.execCompilerCached(compiler.compiler.exe, this.getStdVersHelpOptions(filename), { - ...compiler.getDefaultExecOptions(), - createAndUseTempDir: true, - }); + const result = await this.compiler.execCompilerCached( + this.compiler.compiler.exe, + this.getStdVersHelpOptions(), + { + ...this.compiler.getDefaultExecOptions(), + createAndUseTempDir: true, + }, + ); if (result.stderr) { const lines = utils.splitLines(result.stderr); @@ -422,7 +419,7 @@ export class ClangParser extends BaseParser { return possible; } - static extractPossibleTargets(lines: string[]): string[] { + extractPossibleTargets(lines: string[]): string[] { const re = /\s+([\w-]*)\s*-\s.*/; return lines .map(line => { @@ -435,31 +432,35 @@ export class ClangParser extends BaseParser { .filter(Boolean) as string[]; } - static override async getPossibleTargets(compiler: BaseCompiler): Promise { - const result = await compiler.execCompilerCached(compiler.compiler.exe, this.getTargetsHelpOptions()); + override async getPossibleTargets(): Promise { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, this.getTargetsHelpOptions()); return this.extractPossibleTargets(utils.splitLines(result.stdout)); } - static override async getOptions(compiler: BaseCompiler, helpArg: string, populate = true, isolate = false) { + override async getOptions(helpArg: string, populate = true, isolate = false) { const optionFinderWithDesc = /^ {2}?(--?[\d#+,<=>A-Z[\]a-z|-]*\s?[\d+,<=>A-Z[\]a-z|-]*)\s+([A-Z].*)/; const optionFinderWithoutDesc = /^ {2}?(--?[\d#+,<=>[\]a-z|-]*\s?[\d+,<=>[\]a-z|-]*)/i; - const execOptions = {...compiler.getDefaultExecOptions()}; + const execOptions = {...this.compiler.getDefaultExecOptions()}; if (isolate) execOptions.createAndUseTempDir = true; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '), execOptions); + const result = await this.compiler.execCompilerCached( + this.compiler.compiler.exe, + splitArguments(helpArg), + execOptions, + ); const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinderWithDesc, optionFinderWithoutDesc) : {}; - if (populate) compiler.possibleArguments.populateOptions(options); + if (populate) this.compiler.possibleArguments.populateOptions(options); return options; } } export class ClangirParser extends ClangParser { - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { - ClangParser.setCompilerSettingsFromOptions(compiler, options); + override async setCompilerSettingsFromOptions(options: Record) { + await super.setCompilerSettingsFromOptions(options); - compiler.compiler.optPipeline = { + this.compiler.compiler.optPipeline = { arg: [], moduleScopeArg: ['-mmlir', '--mlir-print-ir-before-all', '-mmlir', '--mlir-print-ir-after-all'], noDiscardValueNamesArg: [], @@ -476,39 +477,31 @@ export class ClangirParser extends ClangParser { } export class GCCCParser extends GCCParser { - static override getLanguageSpecificHelpFlags(): string[] { + override getLanguageSpecificHelpFlags(): string[] { return ['-fsyntax-only', '--help=c']; } - - static override getDefaultExampleFilename() { - return 'c/default.c'; - } } export class ClangCParser extends ClangParser { - static override getDefaultExampleFilename() { - return 'c/default.c'; - } - - static override getStdVersHelpOptions(exampleFile: string): string[] { - return ['-std=c9999999', exampleFile, '-c']; + override getStdVersHelpOptions(): string[] { + return ['-std=c9999999', '-x', 'c', '/dev/null', '-c']; } } export class CircleParser extends ClangParser { - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder1 = /^ +(--?[\w#,.<=>[\]|-]*) {2,}- (.*)/i; const optionFinder2 = /^ +(--?[\w#,.<=>[\]|-]*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' ')); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg)); const options = result.code === 0 ? this.parseLines(result.stdout, optionFinder1, optionFinder2) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { const possible: CompilerOverrideOptions = []; const optionFinder = /^ {4}=([\w+]*) +- +(.*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, ['--help']); let isInStdVerSection = false; for (const line of utils.splitLines(result.stdout)) { if (!isInStdVerSection && line.startsWith(' --std=')) { @@ -536,101 +529,101 @@ export class CircleParser extends ClangParser { } export class LDCParser extends BaseParser { - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { + override async setCompilerSettingsFromOptions(options: Record) { if (this.hasSupport(options, '--fsave-optimization-record')) { - compiler.compiler.optArg = '--fsave-optimization-record'; - compiler.compiler.supportsOptOutput = true; + this.compiler.compiler.optArg = '--fsave-optimization-record'; + this.compiler.compiler.supportsOptOutput = true; } if (this.hasSupport(options, '-fverbose-asm')) { - compiler.compiler.supportsVerboseAsm = true; + this.compiler.compiler.supportsVerboseAsm = true; } if (this.hasSupport(options, '--print-before-all') && this.hasSupport(options, '--print-after-all')) { - compiler.compiler.optPipeline = { + this.compiler.compiler.optPipeline = { arg: ['--print-before-all', '--print-after-all'], moduleScopeArg: [], noDiscardValueNamesArg: [], }; if (this.hasSupport(options, '--print-module-scope')) { - compiler.compiler.optPipeline.moduleScopeArg = ['--print-module-scope']; + this.compiler.compiler.optPipeline.moduleScopeArg = ['--print-module-scope']; } if (this.hasSupport(options, '--fno-discard-value-names')) { - compiler.compiler.optPipeline.noDiscardValueNamesArg = ['--fno-discard-value-names']; + this.compiler.compiler.optPipeline.noDiscardValueNamesArg = ['--fno-discard-value-names']; } } if (this.hasSupport(options, '--enable-color')) { - compiler.compiler.options += ' --enable-color'; + this.compiler.compiler.options += ' --enable-color'; } } - static override async parse(compiler: BaseCompiler) { - const options = await this.getOptions(compiler, '--help-hidden'); - this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + override async parse() { + const options = await this.getOptions('--help-hidden'); + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string, populate = true) { + override async getOptions(helpArg: string, populate = true) { const optionFinder = /^\s*(--?[\d+,<=>[\]a-z|-]*)\s*(.*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' ')); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg)); const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {}; if (populate) { - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); } return options; } } export class ElixirParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } } export class ErlangParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class PascalParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class MojoParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class ICCParser extends GCCParser { - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { + override async setCompilerSettingsFromOptions(options: Record) { const keys = _.keys(options); if (this.hasSupport(options, '-masm=')) { - compiler.compiler.intelAsm = '-masm=intel'; - compiler.compiler.supportsIntel = true; + this.compiler.compiler.intelAsm = '-masm=intel'; + this.compiler.compiler.supportsIntel = true; } if (this.hasSupport(options, '-fdiagnostics-color')) { - if (compiler.compiler.options) compiler.compiler.options += ' '; - compiler.compiler.options += '-fdiagnostics-color=always'; + if (this.compiler.compiler.options) this.compiler.compiler.options += ' '; + this.compiler.compiler.options += '-fdiagnostics-color=always'; } if (_.find(keys, key => key.startsWith('-fdump-'))) { - compiler.compiler.supportsGccDump = true; - compiler.compiler.removeEmptyGccDump = true; + this.compiler.compiler.supportsGccDump = true; + this.compiler.compiler.removeEmptyGccDump = true; } - if (this.hasSupportStartsWith(options, '-march=')) compiler.compiler.supportsMarch = true; - if (this.hasSupportStartsWith(options, '--target=')) compiler.compiler.supportsTargetIs = true; - if (this.hasSupportStartsWith(options, '--target ')) compiler.compiler.supportsTarget = true; + if (this.hasSupportStartsWith(options, '-march=')) this.compiler.compiler.supportsMarch = true; + if (this.hasSupportStartsWith(options, '--target=')) this.compiler.compiler.supportsTargetIs = true; + if (this.hasSupportStartsWith(options, '--target ')) this.compiler.compiler.supportsTarget = true; } - static extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { + extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { const stdverRe = /-std=/; const descRe = /^\s{12}([\w+]*)\s+(.*)/; const possible: CompilerOverrideOptions = []; @@ -663,72 +656,72 @@ export class ICCParser extends GCCParser { return possible; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']); + override async getPossibleStdvers(): Promise { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, ['--help']); const lines = utils.splitLines(result.stdout); return this.extractPossibleStdvers(lines); } - static override async parse(compiler: BaseCompiler) { - const results = await Promise.all([this.getOptions(compiler, '-fsyntax-only --help')]); + override async parse() { + const results = await Promise.all([this.getOptions('-fsyntax-only --help')]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } } export class ISPCParser extends BaseParser { - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { + override async setCompilerSettingsFromOptions(options: Record) { if (this.hasSupport(options, '--x86-asm-syntax')) { - compiler.compiler.intelAsm = '--x86-asm-syntax=intel'; - compiler.compiler.supportsIntel = true; + this.compiler.compiler.intelAsm = '--x86-asm-syntax=intel'; + this.compiler.compiler.supportsIntel = true; } } - static override async parse(compiler: BaseCompiler) { - const options = await this.getOptions(compiler, '--help'); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + override async parse() { + const options = await this.getOptions('--help'); + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { - const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]); + override async getOptions(helpArg: string) { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [helpArg]); const optionFinder = /^\s*\[(--?[\d\s()+,/<=>a-z{|}-]*)]\s*(.*)/i; const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } } export class JavaParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class KotlinParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class ScalaParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class VCParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '/help'); - return compiler; + override async parse() { + await this.getOptions('/help'); + return this.compiler; } - static override parseLines(stdout: string, optionRegex: RegExp) { + override parseLines(stdout: string, optionRegex: RegExp) { let previousOption: string | false = false; const options: Record = {}; @@ -782,7 +775,7 @@ export class VCParser extends BaseParser { return options; } - static extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { + extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { const stdverRe = /\/std:<(.*)>\s.*/; const descRe = /(c\+\+.*) - (.*)/; const possible: CompilerOverrideOptions = []; @@ -812,45 +805,45 @@ export class VCParser extends BaseParser { return possible; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['/help']); + override async getPossibleStdvers(): Promise { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, ['/help']); const lines = utils.splitLines(result.stdout); return this.extractPossibleStdvers(lines); } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { - const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]); + override async getOptions(helpArg: string) { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [helpArg]); const optionFinder = /^\s*(\/[\w#+,.:<=>[\]{|}-]*)\s*(.*)/i; const options = result.code === 0 ? this.parseLines(result.stdout, optionFinder) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } } export class RustParser extends BaseParser { - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { + override async setCompilerSettingsFromOptions(options: Record) { if (this.hasSupport(options, '--color')) { - if (compiler.compiler.options) compiler.compiler.options += ' '; - compiler.compiler.options += '--color=always'; + if (this.compiler.compiler.options) this.compiler.compiler.options += ' '; + this.compiler.compiler.options += '--color=always'; } - if (this.hasSupportStartsWith(options, '--target=')) compiler.compiler.supportsTargetIs = true; - if (this.hasSupportStartsWith(options, '--target ')) compiler.compiler.supportsTarget = true; + if (this.hasSupportStartsWith(options, '--target=')) this.compiler.compiler.supportsTargetIs = true; + if (this.hasSupportStartsWith(options, '--target ')) this.compiler.compiler.supportsTarget = true; } - static override async parse(compiler: BaseCompiler) { + override async parse() { const results = await Promise.all([ - this.getOptions(compiler, '--help'), - this.getOptions(compiler, '-C help'), - this.getOptions(compiler, '--help -v'), + this.getOptions('--help'), + this.getOptions('-C help'), + this.getOptions('--help -v'), ]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getPossibleEditions(compiler: BaseCompiler): Promise { - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help', '-v']); + override async getPossibleEditions(): Promise { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, ['--help', '-v']); const re = /--edition ?/; const match = result.stdout.match(re); @@ -861,12 +854,12 @@ export class RustParser extends BaseParser { return []; } - static override async getPossibleTargets(compiler: BaseCompiler): Promise { - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--print', 'target-list']); + override async getPossibleTargets(): Promise { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, ['--print', 'target-list']); return utils.splitLines(result.stdout).filter(Boolean); } - static parseRustHelpLines(stdout: string) { + parseRustHelpLines(stdout: string) { let previousOption: false | string = false; const options: Record = {}; @@ -916,8 +909,8 @@ export class RustParser extends BaseParser { return options; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' ')); + override async getOptions(helpArg: string) { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg)); let options = {}; if (result.code === 0) { if (helpArg === '-C help') { @@ -928,62 +921,62 @@ export class RustParser extends BaseParser { options = this.parseRustHelpLines(result.stdout + result.stderr); } } - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } } export class ZksolcParser extends RustParser { - static override async parse(compiler: BaseCompiler) { - const options = await this.getOptions(compiler, '--help'); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + override async parse() { + const options = await this.getOptions('--help'); + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } } export class SolxParser extends RustParser { - static override async parse(compiler: BaseCompiler) { - const options = await this.getOptions(compiler, '--help'); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + override async parse() { + const options = await this.getOptions('--help'); + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } } export class MrustcParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } } export class C2RustParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await C2RustParser.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } } export class NimParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class CrystalParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, 'build'); - return compiler; + override async parse() { + await this.getOptions('build'); + return this.compiler; } } export class TableGenParser extends BaseParser { - static async getPossibleActions(compiler: BaseCompiler): Promise { - const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']); + override async getPossibleActions(): Promise { + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, ['--help']); return this.extractPossibleActions(utils.splitLines(result.stdout)); } - static extractPossibleActions(lines: string[]): CompilerOverrideOptions { + extractPossibleActions(lines: string[]): CompilerOverrideOptions { const actions: CompilerOverrideOptions = []; let found_actions = false; @@ -1013,48 +1006,49 @@ export class TableGenParser extends BaseParser { } export class TypeScriptNativeParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } } export class TurboCParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, ''); - return compiler; + override async parse() { + await this.getOptions(''); + return this.compiler; } } export class ToitParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '-help'); - return compiler; + override async parse() { + await this.getOptions('-help'); + return this.compiler; } } export class JuliaParser extends BaseParser { // Get help line from wrapper not Julia runtime - static override async getOptions(compiler: JuliaCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder = /^\s*(--?[\d+,<=>[\]a-z|-]*)\s*(.*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, [ - compiler.compilerWrapperPath, + const juliaCompiler = this.compiler as JuliaCompiler; + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [ + juliaCompiler.compilerWrapperPath, helpArg, ]); const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } - static override async parse(compiler: JuliaCompiler) { - await this.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } } export class Z88dkParser extends BaseParser { - static override async getPossibleTargets(compiler: BaseCompiler): Promise { - const configPath = path.join(path.dirname(compiler.compiler.exe), '../share/z88dk/lib/config'); + override async getPossibleTargets(): Promise { + const configPath = path.join(path.dirname(this.compiler.compiler.exe), '../share/z88dk/lib/config'); const targets: string[] = []; const dir = await fs.readdir(configPath); for (const filename of dir) { @@ -1067,79 +1061,71 @@ export class Z88dkParser extends BaseParser { } export class WasmtimeParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } } export class ZigParser extends GCCParser { - static override async parse(compiler: BaseCompiler) { - const results = await Promise.all([ZigParser.getOptions(compiler, 'build-obj --help')]); + override async parse() { + const results = await Promise.all([this.getOptions('build-obj --help')]); const options = Object.assign({}, ...results); - await GCCParser.setCompilerSettingsFromOptions(compiler, options); - if (GCCParser.hasSupportStartsWith(options, '-target ')) compiler.compiler.supportsHyphenTarget = true; - return compiler; + await this.setCompilerSettingsFromOptions(options); + if (this.hasSupportStartsWith(options, '-target ')) this.compiler.compiler.supportsHyphenTarget = true; + return this.compiler; } } export class ZigCxxParser extends ClangParser { - static override getMainHelpOptions(): string[] { + override getMainHelpOptions(): string[] { return ['c++', '--help']; } - static override getHiddenHelpOptions(exampleFile: string): string[] { - return ['c++', '-mllvm', '--help-list-hidden', exampleFile, '-S', '-o', '/tmp/output.s']; + override getHiddenHelpOptions(): string[] { + return ['c++', '-mllvm', '--help-list-hidden', '-x', 'c++', '/dev/null', '-S', '-o', '/tmp/output.s']; } - static override getStdVersHelpOptions(exampleFile: string): string[] { - return ['c++', '-std=c++9999999', exampleFile, '-S', '-o', '/tmp/output.s']; + override getStdVersHelpOptions(): string[] { + return ['c++', '-std=c++9999999', '-x', 'c++', '/dev/null', '-S', '-o', '/tmp/output.s']; } - static override getTargetsHelpOptions(): string[] { + override getTargetsHelpOptions(): string[] { return ['c++', '--print-targets']; } } export class GccFortranParser extends GCCParser { - static override getDefaultExampleFilename() { - return 'fortran/default.f90'; - } - - static override getLanguageSpecificHelpFlags(): string[] { + override getLanguageSpecificHelpFlags(): string[] { return ['-fsyntax-only', '--help=fortran']; } } export class FlangParser extends ClangParser { - static override getDefaultExampleFilename() { - return 'fortran/default.f90'; - } - - static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record) { - super.setCompilerSettingsFromOptions(compiler, options); + override async setCompilerSettingsFromOptions(options: Record) { + await super.setCompilerSettingsFromOptions(options); // flang does not allow -emit-llvm to be used as it is with clang // as -Xflang -emit-llvm. Instead you just give -emit-llvm to flang // directly. if (this.hasSupport(options, '-emit-llvm')) { - compiler.compiler.supportsIrView = true; - compiler.compiler.irArg = ['-emit-llvm']; - compiler.compiler.minIrArgs = ['-emit-llvm']; + this.compiler.compiler.supportsIrView = true; + this.compiler.compiler.irArg = ['-emit-llvm']; + this.compiler.compiler.minIrArgs = ['-emit-llvm']; } - compiler.compiler.supportsIntel = true; - compiler.compiler.intelAsm = '-masm=intel'; + this.compiler.compiler.supportsIntel = true; + this.compiler.compiler.intelAsm = '-masm=intel'; } - static override hasSupport(options: Record, param: string) { + override hasSupport(options: Record, param: string) { // param is available but we get a warning, so lets not use it if (param === '-fcolor-diagnostics') return; - return BaseParser.hasSupport(options, param); + return super.hasSupport(options, param); } - static override extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { + override extractPossibleStdvers(lines: string[]): CompilerOverrideOptions { const possible: CompilerOverrideOptions = []; const re1 = /error: Only -std=([\w+]*) is allowed currently./; for (const line of lines) { @@ -1156,101 +1142,102 @@ export class FlangParser extends ClangParser { } export class GHCParser extends GCCParser { - static override async parse(compiler: BaseCompiler) { - const results = await Promise.all([this.getOptions(compiler, '--help')]); + override async parse() { + const results = await Promise.all([this.getOptions('--help')]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder1 = /^ {4}(-[\w[\]]+)\s+(.*)/i; const optionFinder2 = /^ {4}(-[\w[\]]+)/; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' ')); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg)); const options = result.code === 0 ? this.parseLines(result.stdout, optionFinder1, optionFinder2) : {}; - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } } export class SwiftParser extends ClangParser { - static override async parse(compiler: BaseCompiler) { - const results = await Promise.all([this.getOptions(compiler, '--help')]); + override async parse() { + const results = await Promise.all([this.getOptions('--help')]); const options = Object.assign({}, ...results); - this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { return []; } - static override async getPossibleTargets(compiler: BaseCompiler): Promise { + override async getPossibleTargets(): Promise { return []; } } export class TendraParser extends GCCParser { - static override async parse(compiler: BaseCompiler) { - const results = await Promise.all([this.getOptions(compiler, '--help')]); + override async parse() { + const results = await Promise.all([this.getOptions('--help')]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder = /^ *(-[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*) : +(.*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' ')); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg)); const options = this.parseLines(result.stdout + result.stderr, optionFinder); - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { return []; } - static override async getPossibleTargets(compiler: BaseCompiler): Promise { + override async getPossibleTargets(): Promise { return []; } } export class GolangParser extends GCCParser { - static override getDefaultExampleFilename() { - return 'go/default.go'; - } - - static override async parse(compiler: BaseCompiler) { + override async parse() { + // NB this file _must_ be visible to the jail, if you're using one. This may bite on a local install when your + // example path may not match paths available in the jail (e.g. `/infra/.deploy/examples`) + // TODO: find a way to invoke GoLang without needing a real example Go file. + const examplesRoot = props.get('builtin', 'sourcePath', './examples/'); + const exampleFilepath = path.resolve(path.join(examplesRoot, 'go/default.go')); const results = await Promise.all([ - this.getOptions(compiler, 'build -o ./output.s "-gcflags=-S --help" ' + this.getExampleFilepath()), + this.getOptions('build -o /tmp/output.s "-gcflags=-S --help" ' + exampleFilepath), ]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder1 = /^\s*(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)\s+(.*)/i; const optionFinder2 = /^\s*(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, splitArguments(helpArg), { - ...compiler.getDefaultExecOptions(), + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, splitArguments(helpArg), { + ...this.compiler.getDefaultExecOptions(), createAndUseTempDir: true, }); const options = this.parseLines(result.stdout + result.stderr, optionFinder1, optionFinder2); - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } } export class GnuCobolParser extends GCCParser { - static override getLanguageSpecificHelpFlags(): string[] { + override getLanguageSpecificHelpFlags(): string[] { return ['--help']; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { const possible: CompilerOverrideOptions = []; - const options = await this.getOptionsStrict(compiler, this.getLanguageSpecificHelpFlags()); + const options = await this.getOptionsStrict(this.getLanguageSpecificHelpFlags()); for (const opt in options) { if (opt.startsWith('-std=')) { const vers = options[opt].description @@ -1272,43 +1259,43 @@ export class GnuCobolParser extends GCCParser { } export class MadpascalParser extends GCCParser { - static override async parse(compiler: BaseCompiler) { - const results = await Promise.all([this.getOptions(compiler, '')]); + override async parse() { + const results = await Promise.all([this.getOptions('')]); const options = Object.assign({}, ...results); - await this.setCompilerSettingsFromOptions(compiler, options); - return compiler; + await this.setCompilerSettingsFromOptions(options); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder = /^(-[\w:<>]*) *(.*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, []); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, []); const options = this.parseLines(result.stdout + result.stderr, optionFinder); - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } - static override async getPossibleStdvers(compiler: BaseCompiler): Promise { + override async getPossibleStdvers(): Promise { return []; } - static override async getPossibleTargets(compiler: BaseCompiler): Promise { + override async getPossibleTargets(): Promise { return ['a8', 'c64', 'c4p', 'raw', 'neo']; } } export class GlslangParser extends BaseParser { - static override async parse(compiler: BaseCompiler) { - await this.getOptions(compiler, '--help'); - return compiler; + override async parse() { + await this.getOptions('--help'); + return this.compiler; } - static override async getOptions(compiler: BaseCompiler, helpArg: string) { + override async getOptions(helpArg: string) { const optionFinder1 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*) {2,}(.*)/i; const optionFinder2 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i; - const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]); + const result = await this.compiler.execCompilerCached(this.compiler.compiler.exe, [helpArg]); // glslang will return a return code of 1 when calling --help (since it means nothing was compiled) const options = this.parseLines(result.stdout + result.stderr, optionFinder1, optionFinder2); - compiler.possibleArguments.populateOptions(options); + this.compiler.possibleArguments.populateOptions(options); return options; } } diff --git a/lib/compilers/coccinelle.ts b/lib/compilers/coccinelle.ts index 7e14f9593..e932cff3b 100644 --- a/lib/compilers/coccinelle.ts +++ b/lib/compilers/coccinelle.ts @@ -133,10 +133,6 @@ export class CoccinelleCCompiler extends BaseCompiler { return super.getIrOutputFilename(inputFilename, filters); } - override getArgumentParserClass() { - return super.getArgumentParserClass(); - } - override isCfgCompiler() { return false; } diff --git a/lib/compilers/mojo.ts b/lib/compilers/mojo.ts index 5f1a8bef5..7c4409652 100644 --- a/lib/compilers/mojo.ts +++ b/lib/compilers/mojo.ts @@ -27,6 +27,7 @@ import path from 'node:path'; import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js'; import {BaseCompiler} from '../base-compiler.js'; import {changeExtension} from '../utils.js'; +import {MojoParser} from './argument-parsers.js'; export class MojoCompiler extends BaseCompiler { static get key() { @@ -95,4 +96,8 @@ export class MojoCompiler extends BaseCompiler { const irText = await fs.readFile(llPath, 'utf8'); return {asm: irText.split('\n').map(text => ({text}))}; } + + override getArgumentParserClass() { + return MojoParser; + } } diff --git a/lib/compilers/rust.ts b/lib/compilers/rust.ts index 4b02ba4c4..39c48af5e 100644 --- a/lib/compilers/rust.ts +++ b/lib/compilers/rust.ts @@ -117,7 +117,7 @@ export class RustCompiler extends BaseCompiler { } override async populatePossibleOverrides() { - const possibleEditions = await RustParser.getPossibleEditions(this); + const possibleEditions = await this.argParser.getPossibleEditions(); if (possibleEditions.length > 0) { let defaultEdition: undefined | string; if (!this.compiler.semver || this.isNightly()) { diff --git a/lib/compilers/tablegen.ts b/lib/compilers/tablegen.ts index 0780af002..4ea02fde0 100644 --- a/lib/compilers/tablegen.ts +++ b/lib/compilers/tablegen.ts @@ -26,7 +26,7 @@ export class TableGenCompiler extends BaseCompiler { } override async populatePossibleOverrides() { - const possibleActions = await TableGenParser.getPossibleActions(this); + const possibleActions = await this.argParser.getPossibleActions(); if (possibleActions.length > 0) { this.compiler.possibleOverrides?.push({ name: CompilerOverrideType.action, diff --git a/test/analysis-tests.ts b/test/analysis-tests.ts index 42f56cdae..bfbe78996 100644 --- a/test/analysis-tests.ts +++ b/test/analysis-tests.ts @@ -100,6 +100,7 @@ describe('LLVM-mca tool definition', () => { }, lang: 'analysis', disabledFilters: 'labels,directives,debugCalls' as any, + exe: 'clang', }); expect(new AnalysisTool(info, ce).getInfo().disabledFilters).toEqual(['labels', 'directives', 'debugCalls']); }); diff --git a/test/android-tests.ts b/test/android-tests.ts index 90484cb68..11824cec2 100644 --- a/test/android-tests.ts +++ b/test/android-tests.ts @@ -40,13 +40,13 @@ const languages = { }; const androidJavaInfo = { - exe: null, + exe: 'java', remote: true, lang: languages.androidJava.id, } as unknown as CompilerInfo; const androidKotlinInfo = { - exe: null, + exe: 'kotlin', remote: true, lang: languages.androidKotlin.id, } as unknown as CompilerInfo; diff --git a/test/base-compiler-tests.ts b/test/base-compiler-tests.ts index ec7eb6900..4bc149b8d 100644 --- a/test/base-compiler-tests.ts +++ b/test/base-compiler-tests.ts @@ -129,6 +129,7 @@ describe('Compiler execution', () => { supportsExecute: true, supportsBinary: true, options: '--hello-abc -I"/opt/some thing 1.0/include" -march="magic 8bit"', + exe: 'compiler-exe', }); const win32CompilerInfo = makeFakeCompilerInfo({ remote: { @@ -142,6 +143,7 @@ describe('Compiler execution', () => { supportsExecute: true, supportsBinary: true, options: '/std=c++17 /I"C:/program files (x86)/Company name/Compiler 1.2.3/include" /D "MAGIC=magic 8bit"', + exe: 'compiler.exe', }); const noExecuteSupportCompilerInfo = makeFakeCompilerInfo({ remote: { @@ -153,6 +155,7 @@ describe('Compiler execution', () => { lang: 'c++', ldPath: [], libPath: [], + exe: 'g++', }); const someOptionsCompilerInfo = makeFakeCompilerInfo({ remote: { @@ -167,6 +170,7 @@ describe('Compiler execution', () => { supportsExecute: true, supportsBinary: true, options: '--hello-abc -I"/opt/some thing 1.0/include"', + exe: 'clang++', }); beforeAll(() => { @@ -681,6 +685,7 @@ describe('getDefaultExecOptions', () => { ldPath: [], libPath: [], extraPath: ['/tmp/p1', '/tmp/p2'], + exe: 'g++', }); beforeAll(() => { diff --git a/test/compilers/argument-parsers-tests.ts b/test/compilers/argument-parsers-tests.ts index 0b6d01057..a431fecf5 100644 --- a/test/compilers/argument-parsers-tests.ts +++ b/test/compilers/argument-parsers-tests.ts @@ -49,13 +49,18 @@ function makeCompiler(stdout?: string, stderr?: string, code?: number) { describe('option parser', () => { it('should do nothing for the base parser', async () => { const compiler = makeCompiler(); - await expect(BaseParser.parse(compiler)).resolves.toEqual(compiler); + const parser = new BaseParser(compiler); + await expect(parser.parse()).resolves.toEqual(compiler); }); it('should handle empty options', async () => { - await expect(BaseParser.getOptions(makeCompiler(), '')).resolves.toEqual({}); + const compiler = makeCompiler(); + const parser = new BaseParser(compiler); + await expect(parser.getOptions('')).resolves.toEqual({}); }); it('should parse single-dash options', async () => { - await expect(BaseParser.getOptions(makeCompiler('-foo\n'), '')).resolves.toEqual({ + const compiler = makeCompiler('-foo\n'); + const parser = new BaseParser(compiler); + await expect(parser.getOptions('')).resolves.toEqual({ '-foo': { description: '', timesused: 0, @@ -63,7 +68,9 @@ describe('option parser', () => { }); }); it('should parse double-dash options', async () => { - await expect(BaseParser.getOptions(makeCompiler('--foo\n'), '')).resolves.toEqual({ + const compiler = makeCompiler('--foo\n'); + const parser = new BaseParser(compiler); + await expect(parser.getOptions('')).resolves.toEqual({ '--foo': { description: '', timesused: 0, @@ -71,7 +78,9 @@ describe('option parser', () => { }); }); it('should parse stderr options', async () => { - await expect(BaseParser.getOptions(makeCompiler('', '--bar=monkey\n'), '')).resolves.toEqual({ + const compiler = makeCompiler('', '--bar=monkey\n'); + const parser = new BaseParser(compiler); + await expect(parser.getOptions('')).resolves.toEqual({ '--bar=monkey': { description: '', timesused: 0, @@ -79,46 +88,56 @@ describe('option parser', () => { }); }); it('handles non-option text', async () => { - await expect(BaseParser.getOptions(makeCompiler('-foo=123\nthis is a fish\n-badger=123'), '')).resolves.toEqual( - { - '-foo=123': {description: 'this is a fish', timesused: 0}, - '-badger=123': {description: '', timesused: 0}, - }, - ); + const compiler = makeCompiler('-foo=123\nthis is a fish\n-badger=123'); + const parser = new BaseParser(compiler); + await expect(parser.getOptions('')).resolves.toEqual({ + '-foo=123': {description: 'this is a fish', timesused: 0}, + '-badger=123': {description: '', timesused: 0}, + }); }); it('should ignore if errors occur', async () => { - await expect(BaseParser.getOptions(makeCompiler('--foo\n', '--bar\n', 1), '')).resolves.toEqual({}); + const compiler = makeCompiler('--foo\n', '--bar\n', 1); + const parser = new BaseParser(compiler); + await expect(parser.getOptions('')).resolves.toEqual({}); }); }); describe('gcc parser', () => { it('should handle empty options', async () => { - const result = await GCCParser.parse(makeCompiler()); + const compiler = makeCompiler(); + const parser = new GCCParser(compiler); + const result = await parser.parse(); expect(result.compiler).not.toHaveProperty('supportsGccDump'); expect(result.compiler.options).toEqual(''); }); it('should handle options', async () => { - const result = await GCCParser.parse(makeCompiler('-masm=intel\n-fdiagnostics-color=[blah]\n-fdump-tree-all')); + const compiler = makeCompiler('-masm=intel\n-fdiagnostics-color=[blah]\n-fdump-tree-all'); + const parser = new GCCParser(compiler); + const result = await parser.parse(); expect(result.compiler.supportsGccDump).toBe(true); expect(result.compiler.supportsIntel).toBe(true); expect(result.compiler.intelAsm).toEqual('-masm=intel'); expect(result.compiler.options).toEqual('-fdiagnostics-color=always'); }); it('should handle undefined options', async () => { - const result = await GCCParser.parse(makeCompiler('-fdiagnostics-color=[blah]')); + const compiler = makeCompiler('-fdiagnostics-color=[blah]'); + const parser = new GCCParser(compiler); + const result = await parser.parse(); expect(result.compiler.options).toEqual('-fdiagnostics-color=always'); }); }); describe('clang parser', () => { it('should handle empty options', async () => { - const result = await ClangParser.parse(makeCompiler()); + const compiler = makeCompiler(); + const parser = new ClangParser(compiler); + const result = await parser.parse(); expect(result.compiler.options).toEqual(''); }); it('should handle options', async () => { - const result = await ClangParser.parse( - makeCompiler(' -fno-crash-diagnostics\n -fsave-optimization-record\n -fcolor-diagnostics'), - ); + const compiler = makeCompiler(' -fno-crash-diagnostics\n -fsave-optimization-record\n -fcolor-diagnostics'); + const parser = new ClangParser(compiler); + const result = await parser.parse(); expect(result.compiler.supportsOptOutput).toBe(true); expect(result.compiler.optArg).toEqual('-fsave-optimization-record'); expect(result.compiler.options).toContain('-fcolor-diagnostics'); @@ -129,7 +148,9 @@ describe('clang parser', () => { describe('pascal parser', () => { it('should handle empty options', async () => { - const result = await PascalParser.parse(makeCompiler()); + const compiler = makeCompiler(); + const parser = new PascalParser(compiler); + const result = await parser.parse(); expect(result.compiler.options).toEqual(''); }); }); @@ -144,7 +165,8 @@ describe('popular compiler arguments', () => { }); it('should return 5 arguments', async () => { - const result = await ClangParser.parse(compiler); + const parser = new ClangParser(compiler); + const result = await parser.parse(); expect(result.possibleArguments.getPopularArguments()).toEqual({ '-O': {description: 'Optimization level', timesused: 0}, '-fcolor-diagnostics': {description: '', timesused: 0}, @@ -155,7 +177,8 @@ describe('popular compiler arguments', () => { }); it('should return arguments except the ones excluded', async () => { - const result = await ClangParser.parse(compiler); + const parser = new ClangParser(compiler); + const result = await parser.parse(); expect(result.possibleArguments.getPopularArguments(['-O3', '--hello'])).toEqual({ '-fcolor-diagnostics': {description: '', timesused: 0}, '-fsave-optimization-record': {description: '', timesused: 0}, @@ -166,7 +189,8 @@ describe('popular compiler arguments', () => { }); it('should be able to exclude special params with assignments', async () => { - const result = await ClangParser.parse(compiler); + const parser = new ClangParser(compiler); + const result = await parser.parse(); expect(result.possibleArguments.getPopularArguments(['-std=c++14', '-g', '--hello'])).toEqual({ '-O': {description: 'Optimization level', timesused: 0}, '-fcolor-diagnostics': {description: '', timesused: 0}, @@ -188,7 +212,9 @@ describe('VC argument parser', () => { ' /something: Something Else', ' /etc Etcetera', ]; - const stdvers = VCParser.extractPossibleStdvers(lines); + const compiler = makeCompiler(); + const parser = new VCParser(compiler); + const stdvers = parser.extractPossibleStdvers(lines); expect(stdvers).toEqual([ { name: 'c++14: ISO/IEC 14882:2014 (default)', @@ -221,7 +247,9 @@ describe('ICC argument parser', () => { ' gnu++98 conforms to 1998 ISO C++ standard plus GNU extensions', '-etc', ]; - const stdvers = ICCParser.extractPossibleStdvers(lines); + const compiler = makeCompiler(); + const parser = new ICCParser(compiler); + const stdvers = parser.extractPossibleStdvers(lines); expect(stdvers).toEqual([ { name: 'c99: conforms to ISO/IEC 9899:1999 standard for C programs', @@ -255,7 +283,9 @@ describe('TableGen argument parser', () => { ' --gen-x86-mnemonic-tables - Generate X86...', ' --no-warn-on-unused-template-args - Disable...', ]; - const actions = TableGenParser.extractPossibleActions(lines); + const compiler = makeCompiler(); + const parser = new TableGenParser(compiler); + const actions = parser.extractPossibleActions(lines); expect(actions).toEqual([ {name: 'gen-attrs: Generate attributes', value: '--gen-attrs'}, {name: 'print-detailed-records: Print full details...', value: '--print-detailed-records'}, @@ -278,7 +308,8 @@ describe('Rust editions parser', () => { ' stable edition is 2024.', ]; const compiler = makeCompiler(lines.join('\n')); - const editions = await RustParser.getPossibleEditions(compiler); + const parser = new RustParser(compiler); + const editions = await parser.getPossibleEditions(); expect(editions).toEqual(['2015', '2018', '2021', '2024', 'future']); }); @@ -294,7 +325,8 @@ describe('Rust editions parser', () => { ' compiling code.', ]; const compiler = makeCompiler(lines.join('\n')); - const editions = await RustParser.getPossibleEditions(compiler); + const parser = new RustParser(compiler); + const editions = await parser.getPossibleEditions(); expect(editions).toEqual(['2015', '2018']); }); }); @@ -312,9 +344,10 @@ describe('Rust help message parser', () => { ' -W, --warn OPT Set lint warnings', ]; const compiler = makeCompiler(lines.join('\n')); - await RustParser.parse(compiler); + const parser = new RustParser(compiler); + await parser.parse(); expect(compiler.compiler.supportsTarget).toBe(true); - await expect(RustParser.getOptions(compiler, '--help')).resolves.toEqual({ + await expect(parser.getOptions('--help')).resolves.toEqual({ '-l [KIND[:MODIFIERS]=]NAME[:RENAME]': { description: 'Link the generated crate(s) to the specified native library NAME. The optional KIND can be one of', @@ -344,9 +377,10 @@ describe('Rust help message parser', () => { ' -W, --warn Set lint warnings', ]; const compiler = makeCompiler(lines.join('\n')); - await RustParser.parse(compiler); + const parser = new RustParser(compiler); + await parser.parse(); expect(compiler.compiler.supportsTarget).toBe(true); - await expect(RustParser.getOptions(compiler, '--help')).resolves.toEqual({ + await expect(parser.getOptions('--help')).resolves.toEqual({ '-l [[:]=][:]': { description: 'Link the generated crate(s) to the specified native library NAME. The optional KIND can be one of', diff --git a/test/demangler-tests.ts b/test/demangler-tests.ts index 45fc3e311..634e1b886 100644 --- a/test/demangler-tests.ts +++ b/test/demangler-tests.ts @@ -52,7 +52,7 @@ class DummyCompiler extends BaseCompiler { } as unknown as CompilationEnvironment; // using c++ as the compiler needs at least one language - const compiler = makeFakeCompilerInfo({lang: 'c++'}); + const compiler = makeFakeCompilerInfo({lang: 'c++', exe: 'gcc'}); super(compiler, env); } diff --git a/test/pascal-tests.ts b/test/pascal-tests.ts index ddf75ae09..d71e58f7c 100644 --- a/test/pascal-tests.ts +++ b/test/pascal-tests.ts @@ -44,7 +44,7 @@ describe('Pascal', () => { beforeAll(() => { const ce = makeCompilationEnvironment({languages}); const info = { - exe: null, + exe: 'pascal-compiler', remote: true, lang: languages.pascal.id, }; @@ -498,7 +498,7 @@ describe('Pascal', () => { beforeAll(() => { const ce = makeCompilationEnvironment({languages}); const info = { - exe: null, + exe: 'pascal.exe', remote: true, lang: languages.pascal.id, };