Fix lint warnings, another round of formatting, one bug fix (parser.ts, parse switch helpers, : is needed for a switch path value and = is needed for a switch define value). Few more link warnings and code review feedback and suggestions left.

This commit is contained in:
Andreea Isac 2019-08-27 15:21:05 -07:00
Родитель 7e2a568b47
Коммит b256a6624b
16 изменённых файлов: 1300 добавлений и 1398 удалений

27
.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "mycompile",
},
{
"name": "Node Attach",
"type": "node",
"request": "attach",
"port": 5858
}
]
}

11
.vscode/settings.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
"typescript.tsdk": "./node_modules/typescript/lib",
"editor.detectIndentation": false // we want to use the TS server from our node_modules folder to control its version
}

14
.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "mycompile",
"type": "npm",
"script": "mycompile",
"problemMatcher": [
"$tsc-watch"
],
"isBackground": true
}
]
}

2169
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -25,27 +25,27 @@
"commands": [
{
"command": "Make.buildTarget",
"title": "MAKE: Run the MAKEFILE target of the current build configuration"
"title": "Make: Run the MAKEFILE target of the current build configuration"
},
{
"command": "Make.launchDebug",
"title": "MAKE: Debug the selected binary target"
"title": "Make: Debug the selected binary target"
},
{
"command": "Make.launchRun",
"title": "MAKE: Run the selected binary target in the terminal"
"title": "Make: Run the selected binary target in the terminal"
},
{
"command": "Make.setBuildConfiguration",
"title": "MAKE: Set the current build configuration"
"title": "Make: Set the current build configuration"
},
{
"command": "Make.setBuildTarget",
"title": "MAKE: Set the target to be built by make"
"title": "Make: Set the target to be built by make"
},
{
"command": "Make.setLaunchConfiguration",
"title": "MAKE: Set the make launch configuration"
"title": "Make: Set the make launch configuration"
}
],
"configuration": {
@ -122,13 +122,16 @@
},
"devDependencies": {
"@types/mocha": "^2.2.42",
"@types/node": "^10.12.21",
"@types/node": "^10.14.16",
"tslint": "^5.18.0",
"typescript": "^3.3.1",
"vscode": "^1.1.28"
"tslint-microsoft-contrib": "^6.2.0",
"tslint-no-unused-expression-chai": "^0.1.4",
"vrsource-tslint-rules": "^6.0.0",
"typescript": "^3.5.3",
"vscode": "^1.1.36"
},
"dependencies": {
"module-alias": "^2.0.6",
"vscode-cpptools": "^2.1.2"
}
}
}

Просмотреть файл

@ -1,3 +1,5 @@
// Configuration support
import * as child_process from 'child_process';
import * as fs from 'fs';
import * as logger from './logger';
@ -18,8 +20,7 @@ export interface MakeConfiguration {
// A name associated with a particular build command process and args/options
name: string;
// make, nmake, specmake...
// make, nmake, specmake...
// This is sent to spawnChildProcess as process name
// It can have full path, relative path or only tool name
// Don't include args in commandName
@ -40,14 +41,14 @@ export interface MakeConfiguration {
// If no particular current configuration is defined in settings, set to 'Default'.
let currentMakeConfiguration: string | undefined;
export function getCurrentMakeConfiguration(): string | undefined { return currentMakeConfiguration; }
export function setCurrentMakeConfiguration(configuration: string) {
export function setCurrentMakeConfiguration(configuration: string): void {
currentMakeConfiguration = configuration;
statusBar.setConfiguration(currentMakeConfiguration);
getCommandForConfiguration(currentMakeConfiguration);
}
// Read the current configuration from settings storage, update status bar item
function readCurrentMakeConfiguration() {
function readCurrentMakeConfiguration(): void {
let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
currentMakeConfiguration = workspaceConfiguration.get<string>("Make.buildConfiguration");
if (!currentMakeConfiguration) {
@ -77,8 +78,8 @@ export function launchConfigurationToString(configuration: LaunchConfiguration):
}
export function stringToLaunchConfiguration(str: string): LaunchConfiguration | undefined {
let regexp = /(.*)\>(.*)\((.*)\)/mg;
let match = regexp.exec(str);
let regexp: RegExp = /(.*)\>(.*)\((.*)\)/mg;
let match: RegExpExecArray | null = regexp.exec(str);
if (match) {
let fullPath: string = util.makeFullPath(match[2], match[1]);
@ -88,7 +89,7 @@ export function stringToLaunchConfiguration(str: string): LaunchConfiguration |
cwd: match[1],
binary: fullPath,
args: splitArgs
}
};
} else {
return undefined;
}
@ -96,13 +97,13 @@ export function stringToLaunchConfiguration(str: string): LaunchConfiguration |
let currentLaunchConfiguration: LaunchConfiguration | undefined;
export function getCurrentLaunchConfiguration(): LaunchConfiguration | undefined { return currentLaunchConfiguration; }
export function setCurrentLaunchConfiguration(configuration: LaunchConfiguration) {
export function setCurrentLaunchConfiguration(configuration: LaunchConfiguration): void {
currentLaunchConfiguration = configuration;
statusBar.setLaunchConfiguration(launchConfigurationToString(currentLaunchConfiguration));
}
// Read the current launch configuration from settings storage, update status bar item
function readCurrentLaunchConfiguration() {
function readCurrentLaunchConfiguration(): void {
let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
currentLaunchConfiguration = workspaceConfiguration.get<LaunchConfiguration>("Make.launchConfiguration");
if (currentLaunchConfiguration) {
@ -117,22 +118,22 @@ function readCurrentLaunchConfiguration() {
// for IntelliSense.
let configurationCommandName: string;
export function getConfigurationCommandName(): string { return configurationCommandName; }
export function setConfigurationCommandName(name: string) { configurationCommandName = name; }
export function setConfigurationCommandName(name: string): void { configurationCommandName = name; }
let configurationCommandArgs: string[] = [];
export function getConfigurationCommandArgs(): string[] { return configurationCommandArgs; }
export function setConfigurationCommandArgs(args: string[]) { configurationCommandArgs = args; }
export function setConfigurationCommandArgs(args: string[]): void { configurationCommandArgs = args; }
// Read from settings storage, update status bar item
// Current make configuration command = process name + arguments
function readCurrentMakeConfigurationCommand() {
function readCurrentMakeConfigurationCommand(): void {
// Read from disk instead of from the MakeConfiguration array, to get up to date content
readMakeConfigurations();
getCommandForConfiguration(currentMakeConfiguration);
}
// Helper to find in the array of MakeConfiguration which command/args correspond to a configuration name
export function getCommandForConfiguration(configuration: string | undefined) {
export function getCommandForConfiguration(configuration: string | undefined): void {
let makeConfiguration: MakeConfiguration | undefined = makeConfigurations.find(k => {
if (k.name === currentMakeConfiguration) {
return { ...k, keep: true };
@ -154,9 +155,9 @@ export function getCommandForConfiguration(configuration: string | undefined) {
// The file is allowed to be missing, in which case the MakeConfiguration array remains empty.
let makeConfigurations: MakeConfiguration[] = [];
export function getMakeConfigurations(): MakeConfiguration[] { return makeConfigurations; }
export function setMakeConfigurations(configurations: MakeConfiguration[]) { makeConfigurations = configurations; }
export function setMakeConfigurations(configurations: MakeConfiguration[]): void { makeConfigurations = configurations; }
function readMakeConfigurations() {
function readMakeConfigurations(): void {
let configurationsJsonPath: string = vscode.workspace.rootPath + "\/.vscode\/make_configurations.json";
if (util.checkFileExistsSync(configurationsJsonPath)) {
logger.message("Reading configurations from file \/.vscode\/make_configurations.json");
@ -173,10 +174,10 @@ function readMakeConfigurations() {
// Saved into the settings storage. Also reflected in the configuration status bar button
let currentTarget: string | undefined;
export function getCurrentTarget(): string | undefined { return currentTarget; }
export function setCurrentTarget(target: string | undefined) { currentTarget = target; }
export function setCurrentTarget(target: string | undefined): void { currentTarget = target; }
// Read current target from settings storage, update status bar item
function readCurrentTarget() {
function readCurrentTarget(): void {
// If no particular target is defined in settings, use 'Default' for the button
// but keep the variable empty, to not apend it to the make command.
let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
@ -191,7 +192,7 @@ function readCurrentTarget() {
}
// Initialization from settings (or backup default rules), done at activation time
export function initFromSettings() {
export function initFromSettings(): void {
readCurrentMakeConfiguration();
readCurrentMakeConfigurationCommand();
readCurrentTarget();
@ -200,7 +201,7 @@ export function initFromSettings() {
// Fill a drop-down with all the configuration names defined by the user in .vscode\make_configurations.json
// Triggers a cpptools configuration provider update after selection.
export async function setNewConfiguration() {
export async function setNewConfiguration(): Promise<void> {
// read from the configurations file instead of currentMakefileConfiguration
// just in case the content changed on disk.
await readMakeConfigurations();
@ -208,7 +209,7 @@ export async function setNewConfiguration() {
return k.name;
}));
const chosen = await vscode.window.showQuickPick(items);
const chosen: string | undefined = await vscode.window.showQuickPick(items);
if (chosen) {
currentMakeConfiguration = chosen;
let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
@ -227,7 +228,7 @@ export async function setNewConfiguration() {
// TODO: deduce also symbol paths.
// TODO: implement UI to collect this information.
// TODO: refactor the dry-run part into make.ts
export async function setNewLaunchConfiguration() {
export async function setNewLaunchConfiguration(): Promise<void> {
let commandArgs: string[] = [];
// Append --dry-run (to not perform any real build operation),
// --always-make (to not skip over targets when timestamps indicate nothing needs to be done)
@ -247,22 +248,22 @@ export async function setNewLaunchConfiguration() {
let process: child_process.ChildProcess;
try {
var stdout = (result: string): void => {
let stdout = (result: string): void => {
stdoutStr += result;
};
var stderr = (result: string): void => {
let stderr = (result: string): void => {
stderrStr += result;
};
var closing = (retCode: number, signal: string): void => {
let closing = (retCode: number, signal: string): void => {
if (retCode !== 0) {
logger.message("The verbose make dry-run command for parsing binaries launch configuration failed.");
logger.message(stderrStr);
}
logger.message("The dry-run output for parsing the binaries launch configuration");
logger.message(stdoutStr);
//logger.message("The dry-run output for parsing the binaries launch configuration");
//logger.message(stdoutStr);
let binariesLaunchConfigurations: LaunchConfiguration[] = parser.parseForLaunchConfiguration(stdoutStr);
selectLaunchConfiguration(binariesLaunchConfigurations);
};
@ -275,7 +276,7 @@ export async function setNewLaunchConfiguration() {
}
// TODO: refactor the dry-run part into make.ts
export async function setNewTarget() {
export async function setNewTarget(): Promise<void> {
let commandArgs: string[] = [];
// all: must be first argument, to make sure all targets are evaluated and not a subset
// --dry-run: to ensure no real build is performed for the targets analysis
@ -288,15 +289,15 @@ export async function setNewTarget() {
let process: child_process.ChildProcess;
try {
var stdout = (result: string): void => {
let stdout = (result: string): void => {
stdoutStr += result;
};
var stderr = (result: string): void => {
let stderr = (result: string): void => {
stderrStr += result;
};
var closing = (retCode: number, signal: string): void => {
let closing = (retCode: number, signal: string): void => {
if (retCode !== 0) {
logger.message("The verbose make dry-run command for parsing targets failed.");
logger.message(stderrStr);
@ -318,8 +319,8 @@ export async function setNewTarget() {
// Fill a drop-down with all the target names run by building the makefile for the current configuration
// Triggers a cpptools configuration provider update after selection.
// TODO: change the UI list to multiple selections mode and store an array of current active targets
export async function selectTarget(makefileTargets: string[]) {
const chosen = await vscode.window.showQuickPick(makefileTargets);
export async function selectTarget(makefileTargets: string[]): Promise<void> {
const chosen: string | undefined = await vscode.window.showQuickPick(makefileTargets);
if (chosen) {
currentTarget = chosen;
statusBar.setTarget(currentTarget);
@ -334,7 +335,7 @@ export async function selectTarget(makefileTargets: string[]) {
// Fill a drop-down with all the launch configurations found for binaries built by the makefile
// under the scope of the current build configuration and target
// Selection updates current launch configuration that will be ready for the next debug/run operation
export async function selectLaunchConfiguration(launchConfigurations: LaunchConfiguration[]) {
export async function selectLaunchConfiguration(launchConfigurations: LaunchConfiguration[]): Promise<void> {
let items: string[] = [];
launchConfigurations.forEach(config => {
items.push(launchConfigurationToString(config));
@ -345,7 +346,7 @@ export async function selectLaunchConfiguration(launchConfigurations: LaunchConf
// TODO: create a quick pick with description and details for items
// to better view the long targets commands
const chosen = await vscode.window.showQuickPick(items);
const chosen: string | undefined = await vscode.window.showQuickPick(items);
if (chosen) {
statusBar.setLaunchConfiguration(chosen);
currentLaunchConfiguration = stringToLaunchConfiguration(chosen);
@ -353,4 +354,3 @@ export async function selectLaunchConfiguration(launchConfigurations: LaunchConf
workspaceConfiguration.update("Make.launchConfiguration", currentLaunchConfiguration);
}
}

Просмотреть файл

@ -1,3 +1,5 @@
// Support for integration with CppTools Custom Configuration Provider
import * as logger from './logger';
import * as path from 'path';
import * as util from './util';
@ -5,7 +7,7 @@ import * as vscode from 'vscode';
import * as cpp from 'vscode-cpptools';
let cummulativeBrowsePath: string[] = [];
export function clearCummulativeBrowsePath() {
export function clearCummulativeBrowsePath(): void {
cummulativeBrowsePath = [];
}
@ -17,26 +19,25 @@ export class CppConfigurationProvider implements cpp.CustomConfigurationProvider
private workspaceBrowseConfiguration: cpp.WorkspaceBrowseConfiguration = { browsePath: [] };
private getConfiguration(uri: vscode.Uri): cpp.SourceFileConfigurationItem | undefined {
const norm_path = path.normalize(uri.fsPath);
const norm_path: string = path.normalize(uri.fsPath);
return this.fileIndex.get(norm_path);
}
public async canProvideConfiguration(uri: vscode.Uri) {
public async canProvideConfiguration(uri: vscode.Uri): Promise<boolean> {
return !!this.getConfiguration(uri);
}
public async provideConfigurations(uris: vscode.Uri[]) {
public async provideConfigurations(uris: vscode.Uri[]): Promise<cpp.SourceFileConfigurationItem[]> {
return util.dropNulls(uris.map(u => this.getConfiguration(u)));
}
public async canProvideBrowseConfiguration() {
public async canProvideBrowseConfiguration(): Promise<boolean> {
return true;
}
public async provideBrowseConfiguration() { return this.workspaceBrowseConfiguration; }
public async provideBrowseConfiguration(): Promise<cpp.WorkspaceBrowseConfiguration> { return this.workspaceBrowseConfiguration; }
public dispose() { }
public dispose(): void { }
private readonly fileIndex = new Map<string, cpp.SourceFileConfigurationItem>();
@ -44,7 +45,7 @@ export class CppConfigurationProvider implements cpp.CustomConfigurationProvider
// - incorporate relevant settings from the environment
// INCLUDE= for include paths
// _CL_= parse for defines, undefines, standard and response files
// Attention for defines syntax: _CL_=/DMyDefine#1 versus /DMyDefine1
// Attention for defines syntax: _CL_=/DMyDefine#1 versus /DMyDefine=1
// - take into account the effect of undefines /U
// In case of conflicting switches, the command prompt overwrites the makefile
public buildCustomConfigurationProvider(
@ -55,7 +56,7 @@ export class CppConfigurationProvider implements cpp.CustomConfigurationProvider
intelliSenseMode: util.IntelliSenseMode,
compilerPath: string,
windowsSdkVersion: string,
filesPaths: string[]) {
filesPaths: string[]): void {
const configuration: cpp.SourceFileConfiguration = {
defines,
standard,
@ -100,7 +101,7 @@ export class CppConfigurationProvider implements cpp.CustomConfigurationProvider
};
}
public logConfigurationProvider() {
public logConfigurationProvider(): void {
logger.message("Sending Workspace Browse Configuration: -----------------------------------");
logger.message(" Browse Path: " + this.workspaceBrowseConfiguration.browsePath.join(";"));
logger.message(" Standard: " + this.workspaceBrowseConfiguration.standard);
@ -127,4 +128,3 @@ export class CppConfigurationProvider implements cpp.CustomConfigurationProvider
});
}
}

Просмотреть файл

@ -1,6 +1,6 @@
'use strict';
// Makefile Tools extension
require('module-alias/register');
'use strict';
import * as configuration from './configuration';
import * as cpptools from './cpptools';
@ -29,18 +29,18 @@ export class MakefileToolsExtension {
}
// Parse the dry-run output and populate data for cpptools
public constructIntellisense(dryRunOutputStr: string) {
public constructIntellisense(dryRunOutputStr: string): void {
parser.parseForCppToolsCustomConfigProvider(dryRunOutputStr);
}
public dispose() {
public dispose(): void {
if (this.cppToolsAPI) {
this.cppToolsAPI.dispose();
}
}
// Register this extension as a new provider or request an update
public async registerCppToolsProvider() {
public async registerCppToolsProvider(): Promise<void> {
await this.ensureCppToolsProviderRegistered();
if (this.cppToolsAPI) {
@ -53,7 +53,7 @@ export class MakefileToolsExtension {
}
}
public ensureCppToolsProviderRegistered() {
public ensureCppToolsProviderRegistered(): Promise<void> {
// make sure this extension is registered as provider only once
if (!this.cppConfigurationProviderRegister) {
this.cppConfigurationProviderRegister = this.registerCppTools();
@ -62,7 +62,7 @@ export class MakefileToolsExtension {
return this.cppConfigurationProviderRegister;
}
public async registerCppTools() {
public async registerCppTools(): Promise<void> {
if (!this.cppToolsAPI) {
this.cppToolsAPI = await cpp.getCppToolsApi(cpp.Version.v2);
}
@ -81,14 +81,14 @@ export class MakefileToolsExtension {
compilerPath: string,
windowsSdkVersion: string,
filesPaths: string[]
) {
): void {
this.cppConfigurationProvider.buildCustomConfigurationProvider(defines, includePath, forcedInclude, standard, intelliSenseMode, compilerPath, windowsSdkVersion, filesPaths);
}
}
// A change of target or configuration triggered a new dry-run,
// which produced a new output string to be parsed
export async function updateProvider(dryRunOutputStr: string) {
export async function updateProvider(dryRunOutputStr: string): Promise<void> {
logger.message("Updating the CppTools IntelliSense Configuration Provider.");
if (extension) {
extension.constructIntellisense(dryRunOutputStr);
@ -96,7 +96,7 @@ export async function updateProvider(dryRunOutputStr: string) {
}
}
export async function activate(context: vscode.ExtensionContext) {
export async function activate(context: vscode.ExtensionContext): Promise<void> {
vscode.window.showInformationMessage('The extension "vscode-makefile-tools" is now active');
statusBar = ui.getUI();
@ -150,7 +150,7 @@ export async function activate(context: vscode.ExtensionContext) {
make.dryRun();
}
export async function deactivate() {
export async function deactivate(): Promise<void> {
vscode.window.showInformationMessage('The extension "vscode-makefile-tools" is de-activated');
const items = [

Просмотреть файл

@ -1,3 +1,5 @@
// Launch support: debug and run in terminal
import * as configuration from './configuration';
import * as util from './util';
import * as vscode from 'vscode';
@ -92,13 +94,13 @@ export class Launcher implements vscode.Disposable {
// Invoke a VS Code running terminal passing it all the information
// from the current launch configuration
public async runCurrentTarget() {
public async runCurrentTarget(): Promise<vscode.Terminal> {
const terminalOptions: vscode.TerminalOptions = {
name: 'Make/Launch',
};
// Use cmd.exe on Windows
if (process.platform == 'win32') {
if (process.platform === 'win32') {
terminalOptions.shellPath = 'C:\\Windows\\System32\\cmd.exe';
terminalOptions.cwd = this.launchCurrentDir();
}
@ -108,14 +110,14 @@ export class Launcher implements vscode.Disposable {
}
// Add a pair of quotes just in case there is a space in the binary path
let terminalCommand: string = '"' + this.launchTargetPath() + '" '
let terminalCommand: string = '"' + this.launchTargetPath() + '" ';
terminalCommand += this.launchTargetArgs().join(" ");
this.launchTerminal.sendText(terminalCommand);
this.launchTerminal.show();
return this.launchTerminal;
}
public dispose() {
public dispose(): void {
if (this.launchTerminal) {
this.launchTerminal.dispose();
}

Просмотреть файл

@ -1,10 +1,12 @@
// Logging support
import * as vscode from 'vscode';
// todo: implement more verbosity levels (currently loggingLevel is read but never used)
let loggingLevel: string | undefined;
let makeOutputChannel: vscode.OutputChannel | undefined;
function getCurrentLoggingLevel() {
function getCurrentLoggingLevel(): string | undefined {
if (!loggingLevel) {
let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
loggingLevel = workspaceConfiguration.get<string>("Make.loggingLevel");
@ -13,7 +15,7 @@ function getCurrentLoggingLevel() {
return loggingLevel;
}
function getOutputChannel() {
function getOutputChannel(): vscode.OutputChannel {
if (!makeOutputChannel) {
makeOutputChannel = vscode.window.createOutputChannel("Makefile tools");
}
@ -21,14 +23,14 @@ function getOutputChannel() {
return makeOutputChannel;
}
export function message(message: string) {
let channel = getOutputChannel();
export function message(message: string): void {
let channel: vscode.OutputChannel = getOutputChannel();
channel.appendLine(message);
}
// This is used for a few scenarios where the message already has end of line incorporated.
// Example: stdout/stderr of a child process read before the stream is closed.
export function messageNoCR(message: string) {
let channel = getOutputChannel();
export function messageNoCR(message: string): void {
let channel: vscode.OutputChannel = getOutputChannel();
channel.append(message);
}

Просмотреть файл

@ -1,3 +1,5 @@
// Support for make operations
import * as child_process from 'child_process';
import * as configuration from './configuration';
import * as ext from './extension';
@ -5,12 +7,12 @@ import * as logger from './logger';
import * as util from './util';
import * as vscode from 'vscode';
export async function buildCurrentTarget() {
export async function buildCurrentTarget(): Promise<void> {
let process: child_process.ChildProcess;
let commandArgs: string[] = [];
// Prepend the target to the arguments given in the configurations json.
let currentTarget = configuration.getCurrentTarget();
let currentTarget: string | undefined = configuration.getCurrentTarget();
if (currentTarget) {
commandArgs.push(currentTarget);
}
@ -21,15 +23,15 @@ export async function buildCurrentTarget() {
try {
// Append without end of line since there is one already included in the stdout/stderr fragments
var stdout = (result: string): void => {
let stdout = (result: string): void => {
logger.messageNoCR(result);
};
var stderr = (result: string): void => {
let stderr = (result: string): void => {
logger.messageNoCR(result);
};
var closing = (retCode: number, signal: string): void => {
let closing = (retCode: number, signal: string): void => {
if (retCode !== 0) {
logger.message("The current target failed to build.");
} else {
@ -44,13 +46,13 @@ export async function buildCurrentTarget() {
}
}
export async function dryRun() {
export async function dryRun(): Promise<void> {
let process: child_process.ChildProcess;
let commandArgs: string[] = [];
// Prepend the target to the arguments given in the configurations json.
let currentTarget = configuration.getCurrentTarget();
let currentTarget: string | undefined = configuration.getCurrentTarget();
if (currentTarget) {
commandArgs.push(currentTarget);
}
@ -70,19 +72,21 @@ export async function dryRun() {
let stdoutStr: string = "";
let stderrStr: string = "";
var stdout = (result: string): void => {
let stdout = (result: string): void => {
stdoutStr += result;
};
var stderr = (result: string): void => {
let stderr = (result: string): void => {
stderrStr += result;
};
var closing = (retCode: number, signal: string): void => {
let closing = (retCode: number, signal: string): void => {
if (retCode !== 0) {
logger.message("The make dry-run command failed.");
logger.message(stderrStr);
}
console.log("Make dry-run output to parse is:\n" + stdoutStr);
//console.log("Make dry-run output to parse is:\n" + stdoutStr);
ext.updateProvider(stdoutStr);
};
@ -92,4 +96,3 @@ export async function dryRun() {
return;
}
}

Просмотреть файл

@ -10,7 +10,6 @@ import * as logger from './logger';
import * as path from 'path';
import * as util from './util';
import * as vscode from 'vscode';
import { LaunchConfiguration } from './configuration';
const compilers: string[] = ["clang", "cl", "gcc", "cc", "icc", "icl", "g\\+\\+", "c\\+\\+"];
const linkers: string[] = ["link", "ilink", "ld", "gcc", "clang", "cc", "g\\+\\+", "c\\+\\+"]; // any aliases/symlinks ?
@ -19,20 +18,22 @@ const sourceFileExtensions: string[] = ["cpp", "cc", "cxx", "c"];
export function parseTargets(verboseLog: string): string[] {
// Extract the text between "# Files" and "# Finished Make data base" lines
// There can be more than one matching section.
let regexpExtract = /(# Files\n*)([\s\S]*?)(# Finished Make data base)/mg;
let result: string[] | null;
let extractedLog : string = "";
let regexpExtract: RegExp = /(# Files\n*)([\s\S]*?)(# Finished Make data base)/mg;
let result: RegExpExecArray | null;
let extractedLog: string = "";
var matches: string[] = [];
var match: string[] | null;
let matches: string[] = [];
let match: string[] | null;
while (result = regexpExtract.exec(verboseLog)) {
result = regexpExtract.exec(verboseLog);
while (result) {
extractedLog = result[2];
// skip lines starting with {#,.} or preceeded by "# Not a target" and extract the target
let regexpTarget = /^(?!\n?[#\.])(?<!^\n?# Not a target:\s*)\s*(\S+):\s+/mg;
let regexpTarget: RegExp = /^(?!\n?[#\.])(?<!^\n?# Not a target:\s*)\s*(\S+):\s+/mg;
while (match = regexpTarget.exec(extractedLog)) {
match = regexpTarget.exec(extractedLog);
while (match) {
// Make sure we don't insert duplicates.
// They can be caused by the makefile syntax of defining variables for a target.
// That creates multiple lines with the same target name followed by :,
@ -40,7 +41,11 @@ export function parseTargets(verboseLog: string): string[] {
if (!matches.includes(match[1])) {
matches.push(match[1]);
}
match = regexpTarget.exec(extractedLog);
}
result = regexpExtract.exec(verboseLog);
}
if (matches) {
@ -61,7 +66,7 @@ function preprocessDryRunOutput(dryRunOutputStr: string): string {
preprocessedDryRunOutputStr = preprocessedDryRunOutputStr.replace(/ && /g, "\n"); // \r
preprocessedDryRunOutputStr = preprocessedDryRunOutputStr.replace(/;/g, "\n"); // \r
// Extract the link command
// Extract the link command
// Keep the /link switch to the cl command because otherwise we will see compiling without /c
// and we will deduce some other output binary based on its /Fe or /Fo or first source given,
// instead of the output binary defined via the link operation (which will be parsed on the next line).
@ -100,7 +105,7 @@ interface ToolInvocation {
// Helper that parses the given line as a tool invocation.
// The full path that is returned is calculated with the following logic:
// - make a full path out of the one given in the makefile
// - make a full path out of the one given in the makefile
// and the current path that is calculated as of now
// - if the tool is not found at the full path above and if requested,
// it will be searched in all the paths of the PATH environment variable
@ -124,7 +129,7 @@ function parseLineAsTool(
// make sure to append extension if the array of tools has only one element,
// in which case .join is not doing anything
if (toolNames.length == 1) {
if (toolNames.length === 1) {
regexpStr += ('\\.exe');
}
@ -134,7 +139,7 @@ function parseLineAsTool(
regexpStr += toolNames.join('|') + ')[\\s\\"]+(.*)$';
let regexp: RegExp = RegExp(regexpStr, "mg");
let match = regexp.exec(line);
let match: RegExpExecArray | null = regexp.exec(line);
if (!match) {
return undefined;
@ -187,25 +192,17 @@ function parseMultipleSwitchFromToolArguments(args: string, sw: string): string[
// - can be wrapped by a pair of ', before the switch prefix and after the switch value
// - the value can be wrapped by a pair of "
// - one or none or more spaces/tabs between the switch and the value
let regexpStr = '(^|\\s+)\\\'?(\\/' + sw + '(:|=|\\s*)|-' + sw + '(:|=|\\s*))(\\".*?\\"|[^\\\'\\s]+)\\\'?';
let regexp = RegExp(regexpStr, "mg");
var match: string[] | null;
var results: string[] = [];
let regexpStr: string = '(^|\\s+)\\\'?(\\/' + sw + '(:|=|\\s*)|-' + sw + '(:|=|\\s*))(\\".*?\\"|[^\\\'\\s]+)\\\'?';
let regexp: RegExp = RegExp(regexpStr, "mg");
let match: RegExpExecArray | null;
let results: string[] = [];
while (match = regexp.exec(args)) {
match = regexp.exec(args);
while (match) {
let result: string = match[5].trim();
// Reject a case when the given switch is a substring of another switch:
// Hypotethical example switches "sw" and "switch" (todo: find real example):
// -switch:value should be parsed as switch="switch" and value="value",
// but with the regexp above and without the check below
// it is parsed as switch="sw" and value="itch:value"
if (match[5].includes(":") || match[5].includes("=")) {
continue;
}
result = result.replace(/"/g, "");
results.push(result);
match = regexp.exec(args);
}
return results;
@ -226,25 +223,17 @@ function parseSingleSwitchFromToolArguments(args: string, sw: string[]): string
// - can be wrapped by a pair of ', before the switch prefix and after the switch value
// - the value can be wrapped by a pair of "
// - ':' or '=' or one/none/more spaces/tabs between the switch and the value
let regexpStr = '(^|\\s+)\\\'?(\\/|-)(' + sw.join("|") + ')(:|=|\\s*)(\\".*?\\"|[^\\\'\\s]+)\\\'?';
let regexp = RegExp(regexpStr, "mg");
var match: string[] | null;
var results: string[] = [];
let regexpStr: string = '(^|\\s+)\\\'?(\\/|-)(' + sw.join("|") + ')(:|=|\\s*)(\\".*?\\"|[^\\\'\\s]+)\\\'?';
let regexp: RegExp = RegExp(regexpStr, "mg");
let match: RegExpExecArray | null;
let results: string[] = [];
while (match = regexp.exec(args)) {
match = regexp.exec(args);
while (match) {
let result: string = match[5].trim();
// Reject a case when the given switch is a substring of another switch:
// Hypotethical example switches "sw" and "switch" (todo: find real example):
// -switch:value should be parsed as switch="switch" and value="value",
// but with the regexp above and without the check below
// it is parsed as switch="sw" and value="itch:value"
if (match[5].includes(":") || match[5].includes("=")) {
continue;
}
result = result.replace(/"/g, "");
results.push(result);
match = regexp.exec(args);
}
return results.pop();
@ -252,7 +241,7 @@ function parseSingleSwitchFromToolArguments(args: string, sw: string[]): string
// Helper that answers whether a particular switch is passed to the tool.
// When calling this helper, we are not interested in obtaining the
// (or there is no) value passed in via the switch.
// (or there is no) value passed in via the switch.
// There must be at least one space/tab before the switch,
// so that we don't match a path by mistake.
// Same after the switch, in case the given name is a substring
@ -263,11 +252,10 @@ function parseSingleSwitchFromToolArguments(args: string, sw: string[]): string
function isSwitchPassedInArguments(args: string, sw: string[]): boolean {
// - or / as switch prefix
// - one or more spaces/tabs after
let regexpStr = '(\\s*)(\\/|-)(' + sw.join("|") + ')(\\s+|$)';
let regexp = RegExp(regexpStr, "mg");
var match: string[] | null;
let regexpStr: string = '(\\s*)(\\/|-)(' + sw.join("|") + ')(\\s+|$)';
let regexp: RegExp = RegExp(regexpStr, "mg");
if (match = regexp.exec(args)) {
if (regexp.exec(args)) {
return true;
}
@ -282,7 +270,7 @@ function parseFilesFromToolArguments(args: string, exts: string[]): string[] {
// one or more spaces/tabs before and after
// with or without quotes surrounding the argument
// (todo: handle the scenario when quotes enclose just the directory path, without the file name)
let regexpStr = '(';
let regexpStr: string = '(';
exts.forEach(ext => {
regexpStr += '\\".*?\\.' + ext + '\\"|';
regexpStr += '\\S+\\.' + ext;
@ -293,14 +281,16 @@ function parseFilesFromToolArguments(args: string, exts: string[]): string[] {
});
regexpStr += ')';
let regexp = RegExp(regexpStr, "mg");
var match: string[] | null;
var files: string[] = [];
let regexp: RegExp = RegExp(regexpStr, "mg");
let match: string[] | null;
let files: string[] = [];
while (match = regexp.exec(args)) {
match = regexp.exec(args);
while (match) {
let result: string = match[1].trim();
result = result.replace(/"/g, "");
files.push(result);
match = regexp.exec(args);
}
return files;
@ -313,7 +303,7 @@ function currentPathAfterCommand(line: string, currentPathHistory: string[]): st
line = line.trimLeft();
let lastCurrentPath: string = (currentPathHistory.length > 0) ? currentPathHistory[currentPathHistory.length - 1] : "";
let newCurrentPath : string = "";
let newCurrentPath: string = "";
if (line.startsWith('cd -')) {
// Swap the last two current paths in the history.
@ -321,17 +311,17 @@ function currentPathAfterCommand(line: string, currentPathHistory: string[]): st
currentPathHistory.pop();
}
let lastCurrentPath2 : string = (currentPathHistory.length > 0) ? currentPathHistory.pop() || "" : lastCurrentPath;
let lastCurrentPath2: string = (currentPathHistory.length > 0) ? currentPathHistory.pop() || "" : lastCurrentPath;
logger.message("Analyzing line: " +line);
logger.message("Analyzing line: " + line);
logger.message("CD- command: leaving directory " + lastCurrentPath + " and entering directory " + lastCurrentPath2);
currentPathHistory.push(lastCurrentPath);
currentPathHistory.push(lastCurrentPath2);
} else if (line.startsWith('popd') || line.includes('Leaving directory')) {
let lastCurrentPath : string = (currentPathHistory.length > 0) ? currentPathHistory[currentPathHistory.length - 1] : "";
let lastCurrentPath: string = (currentPathHistory.length > 0) ? currentPathHistory[currentPathHistory.length - 1] : "";
currentPathHistory.pop();
let lastCurrentPath2 : string = (currentPathHistory.length > 0) ? currentPathHistory[currentPathHistory.length - 1] : "";
logger.message("Analyzing line: " +line);
let lastCurrentPath2: string = (currentPathHistory.length > 0) ? currentPathHistory[currentPathHistory.length - 1] : "";
logger.message("Analyzing line: " + line);
logger.message("POPD command or end of MAKE -C: leaving directory " + lastCurrentPath + " and entering directory " + lastCurrentPath2);
} else if (line.startsWith('cd')) {
newCurrentPath = util.makeFullPath(line.slice(3), lastCurrentPath);
@ -346,23 +336,23 @@ function currentPathAfterCommand(line: string, currentPathHistory: string[]): st
}
currentPathHistory.push(newCurrentPath);
logger.message("Analyzing line: " +line);
logger.message("Analyzing line: " + line);
logger.message("CD command: entering directory " + newCurrentPath);
} else if (line.startsWith('pushd')) {
newCurrentPath = util.makeFullPath(line.slice(6), lastCurrentPath);
currentPathHistory.push(newCurrentPath);
logger.message("Analyzing line: " +line);
logger.message("Analyzing line: " + line);
logger.message("PUSHD command: entering directory " + newCurrentPath);
} else if (line.includes('Entering directory')) {
// equivalent to pushd
let match = line.match("(.*)(Entering directory ')(.*)'");
let match: RegExpMatchArray | null = line.match("(.*)(Entering directory ')(.*)'");
if (match) {
newCurrentPath = util.makeFullPath(match[3], lastCurrentPath) || "";
} else {
newCurrentPath = "Could not parse directory";
}
logger.message("Analyzing line: " +line);
logger.message("Analyzing line: " + line);
logger.message("MAKE -C: entering directory " + newCurrentPath);
currentPathHistory.push(newCurrentPath);
}
@ -371,9 +361,9 @@ function currentPathAfterCommand(line: string, currentPathHistory: string[]): st
}
// Parse the output of the make dry-run command in order to provide CppTools
// with information about includes, defines, compiler path....etc...
// with information about includes, defines, compiler path....etc...
// as needed by CustomConfigurationProvider
export function parseForCppToolsCustomConfigProvider(dryRunOutputStr: string) {
export function parseForCppToolsCustomConfigProvider(dryRunOutputStr: string): void {
logger.message('Parsing dry-run output for CppTools Custom Configuration Provider...');
// Do some preprocessing on the dry-run output to make the RegExp parsing easier
@ -404,9 +394,9 @@ export function parseForCppToolsCustomConfigProvider(dryRunOutputStr: string) {
logger.message("Found compiler command: " + line);
// Compiler path is either what the makefile provides or found in the PATH environment variable or empty
let compilerFullPath = compilerTool.fullPath || "";
let compilerFullPath: string = compilerTool.fullPath || "";
if (!compilerTool.found) {
let toolBaseName : string = path.basename(compilerFullPath);
let toolBaseName: string = path.basename(compilerFullPath);
compilerFullPath = util.toolPathInEnv(toolBaseName) || "";
}
logger.message(" Compiler path: " + compilerFullPath);
@ -430,7 +420,7 @@ export function parseForCppToolsCustomConfigProvider(dryRunOutputStr: string) {
// Parse the IntelliSense mode
// how to deal with aliases and symlinks (CC, C++), which can point to any toolsets
var intelliSenseMode: util.IntelliSenseMode = "msvc-x64";
let intelliSenseMode: util.IntelliSenseMode = "msvc-x64";
if (path.basename(compilerTool.fullPath).startsWith("clang")) {
intelliSenseMode = "clang-x64";
} else if (path.basename(compilerTool.fullPath).startsWith("gcc") ||
@ -441,7 +431,7 @@ export function parseForCppToolsCustomConfigProvider(dryRunOutputStr: string) {
// For windows, parse the sdk version
// todo: scan on disk for most recent sdk installation
var windowsSDKVersion: string | undefined = "";
let windowsSDKVersion: string | undefined = "";
if (process.platform === "win32") {
windowsSDKVersion = process.env["WindowsSDKVersion"];
if (!windowsSDKVersion) {
@ -465,7 +455,7 @@ export function parseForCppToolsCustomConfigProvider(dryRunOutputStr: string) {
// Parse the output of the make dry-run command in order to provide VS Code debugger
// with information about binaries, their execution paths and arguments
export function parseForLaunchConfiguration(dryRunOutputStr: string): LaunchConfiguration[] {
export function parseForLaunchConfiguration(dryRunOutputStr: string): configuration.LaunchConfiguration[] {
logger.message('Parsing dry-run output for Launch (debug/run) configuration...');
// Do some preprocessing on the dry-run output to make the RegExp parsing easier
@ -479,7 +469,7 @@ export function parseForLaunchConfiguration(dryRunOutputStr: string): LaunchConf
// array of full path executables built by this makefile
let targetBinaries: string[] = [];
// array of launch configurations, for each of the binaries above
let launchConfigurations: LaunchConfiguration[] = [];
let launchConfigurations: configuration.LaunchConfiguration[] = [];
// The first pass of reading the dry-run output, line by line
// searching for compilers, linkers and directory changing commands
@ -596,7 +586,7 @@ export function parseForLaunchConfiguration(dryRunOutputStr: string): LaunchConf
// Include limited launch configuration, when only the binary is known,
// in which case the execution path is defaulting to workspace root folder
// and there are no args.
let launchConfiguration : LaunchConfiguration = {
let launchConfiguration: configuration.LaunchConfiguration = {
binary: targetBinary,
cwd: vscode.workspace.rootPath || "",
args: []
@ -656,7 +646,7 @@ export function parseForLaunchConfiguration(dryRunOutputStr: string): LaunchConf
// Include complete launch configuration: binary, execution path and args
// are known from parsing the dry-run
let splitArgs: string[] = targetBinaryTool.arguments.split(" ");
let launchConfiguration: LaunchConfiguration = {
let launchConfiguration: configuration.LaunchConfiguration = {
binary: targetBinaryTool.fullPath,
cwd: currentPath,
// TODO: consider optionally quoted arguments

Просмотреть файл

@ -1,3 +1,5 @@
// UI support for this extension: buttons and quickpicks.
import * as configuration from './configuration';
import * as path from 'path';
import * as vscode from 'vscode';
@ -12,15 +14,15 @@ export class UI {
private debugButton: vscode.StatusBarItem;
private runButton: vscode.StatusBarItem;
public setConfiguration(configuration: string) {
public setConfiguration(configuration: string): void {
this.configurationButton.text = "Build configuration: " + configuration;
}
public setTarget(target: string) {
public setTarget(target: string): void {
this.targetButton.text = "Target to build: " + target;
}
public setLaunchConfiguration(launchConfigurationStr: string | undefined) {
public setLaunchConfiguration(launchConfigurationStr: string | undefined): void {
if (launchConfigurationStr) {
this.launchConfigurationButton.text = "Launch configuration: ";
this.launchConfigurationButton.text += "[";

Просмотреть файл

@ -1,3 +1,5 @@
// Helper APIs used by this extension
import * as fs from 'fs';
import * as child_process from 'child_process';
import * as path from 'path';
@ -168,4 +170,4 @@ export function removeQuotes(str: string): string {
}
return str;
}
}

Просмотреть файл

@ -7,7 +7,7 @@
"es6"
],
"sourceMap": true,
"rootDir": "src",
"rootDir": ".",
"strict": true /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
@ -17,5 +17,8 @@
"exclude": [
"node_modules",
".vscode-test"
],
"include": [
"**/*.ts"
]
}

Просмотреть файл

@ -1,15 +1,121 @@
{
"rules": {
"no-string-throw": true,
"no-unused-expression": true,
"no-duplicate-variable": true,
"curly": true,
"class-name": true,
"semicolon": [
true,
"always"
],
"triple-equals": true
},
"defaultSeverity": "warning"
}
"rules": {
"adjacent-overload-signatures": true,
"align": true,
"array-type": [true, "array"],
"arrow-return-shorthand": true,
"ban-comma-operator": true,
"binary-expression-operand-order": true,
"callable-types": true,
"class-name": true,
"comment-format": true,
"curly": true,
"encoding": true,
"eofline": true,
"ext-variable-name": [
true,
[
"class",
"pascal"
],
[
"function",
"camel"
]
],
"file-header": [
true,
".*"
],
"import-spacing": true,
"indent": [
true,
"spaces",
4
],
"label-position": true,
"match-default-export-name": true,
"member-ordering": true,
"new-parens": true,
"no-arg": true,
"no-bitwise": true,
"no-boolean-literal-compare": true,
"no-conditional-assignment": true,
"no-consecutive-blank-lines": true,
"no-construct": true,
"no-debugger": true,
"no-default-export": true,
"no-duplicate-imports": true,
"no-duplicate-super": true,
"no-duplicate-switch-case": true,
"no-duplicate-variable": true,
"no-unused-expression-chai": true,
"no-eval": true,
"no-import-side-effect": true,
"no-internal-module": true,
"no-invalid-this": true,
"no-irregular-whitespace": true,
"no-mergeable-namespace": true,
"no-misused-new": true,
"no-namespace": true,
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-reference": true,
"no-reference-import": true,
"no-return-await": true,
"no-sparse-arrays": true,
"no-switch-case-fall-through": true,
"no-this-assignment": true,
"no-trailing-whitespace": true,
"no-unnecessary-callback-wrapper": true,
"no-unnecessary-initializer": true,
"no-unnecessary-qualifier": true,
"no-unsafe-finally": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-var-keyword": true,
"no-var-requires": true,
"number-literal-format": true,
"one-line": [
true,
"check-catch",
"check-finally",
"check-else",
"check-open-brace",
"check-whitespace"
],
"one-variable-per-declaration": true,
"prefer-method-signature": true,
"prefer-object-spread": true,
"prefer-while": true,
"promise-must-complete": true,
"semicolon": true,
"space-within-parens": true,
"trailing-comma": true,
"triple-equals": true,
"type-literal-delimiter": true,
"typedef": [
true,
"variable-declaration",
"call-signature"
],
"typedef-whitespace": true,
"typeof-compare": true,
"unified-signatures": true,
"use-default-type-parameter": true,
"use-isnan": true,
"whitespace": [
true,
"check-branch",
"check-operator",
"check-separator",
"check-preblock",
"check-type"
]
},
"rulesDirectory": [
"node_modules/tslint-microsoft-contrib",
"node_modules/tslint-no-unused-expression-chai/rules",
"node_modules/vrsource-tslint-rules/rules"
]
}