Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement addNodeAddonIncludePaths #6731

Merged
merged 11 commits into from
Jan 14, 2021
8 changes: 7 additions & 1 deletion Extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,12 @@
"markdownDescription": "%c_cpp.configuration.vcpkg.enabled.markdownDescription%",
"scope": "resource"
},
"C_Cpp.addNodeAddonIncludePaths": {
"type": "boolean",
"default": false,
"markdownDescription": "%c_cpp.configuration.addNodeAddonIncludePaths.description%",
"scope": "resource"
bmacnaughton marked this conversation as resolved.
Show resolved Hide resolved
},
"C_Cpp.renameRequiresIdentifier": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -2679,4 +2685,4 @@
"integrity": "CF1A01AA75275F76800F6BC1D289F2066DCEBCD983376D344ABF6B03FDB8FEA0"
}
]
}
}
1 change: 1 addition & 0 deletions Extension/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
"c_cpp.configuration.enhancedColorization.description": "If enabled, code is colorized based on IntelliSense. This setting only applies if intelliSenseEngine is set to \"Default\".",
"c_cpp.configuration.codeFolding.description": "If enabled, code folding ranges are provided by the language server.",
"c_cpp.configuration.vcpkg.enabled.markdownDescription": "Enable integration services for the [vcpkg dependency manager](https://aka.ms/vcpkg/).",
"c_cpp.configuration.addNodeAddonIncludePaths.description": "Add include paths from nan and node-addon-api when they're dependencies.",
"c_cpp.configuration.renameRequiresIdentifier.description": "If true, 'Rename Symbol' will require a valid C/C++ identifier.",
"c_cpp.configuration.debugger.useBacktickCommandSubstitution.description": "If true, debugger shell command substitution will use obsolete backtick (`).",
"c_cpp.contributes.views.cppReferencesView.title": "C/C++: Other references results",
Expand Down
58 changes: 57 additions & 1 deletion Extension/src/LanguageServer/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import * as nls from 'vscode-nls';
import { setTimeout } from 'timers';
import * as which from 'which';

const pfs: any = fs.promises;

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();

Expand Down Expand Up @@ -130,6 +132,8 @@ export class CppProperties {
private defaultWindowsSdkVersion: string | null = null;
private vcpkgIncludes: string[] = [];
private vcpkgPathReady: boolean = false;
private nodeAddonIncludes: string[] = [];
private nodeAddonIncludePathsReady: boolean = false;
private defaultIntelliSenseMode?: string;
private defaultCustomConfigurationVariables?: { [key: string]: string };
private readonly configurationGlobPattern: string = "c_cpp_properties.json";
Expand All @@ -155,6 +159,7 @@ export class CppProperties {
this.configFolder = path.join(rootPath, ".vscode");
this.diagnosticCollection = vscode.languages.createDiagnosticCollection(rootPath);
this.buildVcpkgIncludePath();
this.addNodeAddonIncludeLocations(rootPath);
this.disposables.push(vscode.Disposable.from(this.configurationsChanged, this.selectionChanged, this.compileCommandsChanged));
}

Expand Down Expand Up @@ -288,7 +293,8 @@ export class CppProperties {
}

private applyDefaultIncludePathsAndFrameworks(): void {
if (this.configurationIncomplete && this.defaultIncludes && this.defaultFrameworks && this.vcpkgPathReady) {
if (this.configurationIncomplete && this.defaultIncludes && this.defaultFrameworks && this.vcpkgPathReady
&& this.nodeAddonIncludePathsReady) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is no longer needed. It was only needed when the applyDefaultConfigurationValues was being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, obvious when i see it. you have a much better handle on all the moving pieces than i do - thanks for spending time on this.

const configuration: Configuration | undefined = this.CurrentConfiguration;
if (configuration) {
this.applyDefaultConfigurationValues(configuration);
Expand Down Expand Up @@ -317,6 +323,10 @@ export class CppProperties {
} else {
configuration.includePath = [defaultFolder];
}
if (isUnset(settings.addNodeAddonIncludePaths)) {
configuration.includePath = configuration.includePath.concat(this.nodeAddonIncludes);
bmacnaughton marked this conversation as resolved.
Show resolved Hide resolved
}

// browse.path is not set by default anymore. When it is not set, the includePath will be used instead.
if (isUnset(settings.defaultDefines)) {
configuration.defines = (process.platform === 'win32') ? ["_DEBUG", "UNICODE", "_UNICODE"] : [];
Expand Down Expand Up @@ -386,6 +396,52 @@ export class CppProperties {
}
}

private nodeAddonMap: {[dependency: string]: string} = {
"nan": "node --no-warnings -e \"require('nan')\"",
"node-addon-api": "node --no-warnings -p \"require('node-addon-api').include\""
};

private async addNodeAddonIncludeLocations(rootPath: string): Promise<void> {
try {

const settings: CppSettings = new CppSettings(this.rootUri);
if (settings.addNodeAddonIncludePaths) {
const package_json: any = JSON.parse(await pfs.readFile(path.join(rootPath, "package.json"), "utf8"));
bmacnaughton marked this conversation as resolved.
Show resolved Hide resolved
for (const dep in this.nodeAddonMap) {
if (dep in package_json.dependencies) {
const execCmd: string = this.nodeAddonMap[dep];
let stdout: string = await util.execChildProcess(execCmd, rootPath);
bmacnaughton marked this conversation as resolved.
Show resolved Hide resolved
if (!stdout) {
continue;
}

// cleanup newlines
if (stdout[stdout.length - 1] === "\n") {
stdout = stdout.slice(0, -1);
}
// node-addon-api returns a quoted string, e.g., '"/home/user/dir/node_modules/node-addon-api"'.
if (stdout[0] === "\"" && stdout[stdout.length - 1] === "\"") {
stdout = stdout.slice(1, -1);
}
if (stdout) {
// nan returns the path relative to the working directory
stdout = path.resolve(stdout);
if (!await util.checkDirectoryExists(stdout)) {
continue;
}
this.nodeAddonIncludes.push(stdout);
}
}
}
}
} catch (error) {
console.log(error);
} finally {
this.nodeAddonIncludePathsReady = true;
this.handleConfigurationChange();
}
}

private getConfigIndexForPlatform(config: any): number | undefined {
if (!this.configurationJson) {
return undefined;
Expand Down
1 change: 1 addition & 0 deletions Extension/src/LanguageServer/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export class CppSettings extends Settings {
public get preferredPathSeparator(): string | undefined { return super.Section.get<string>("preferredPathSeparator"); }
public get updateChannel(): string | undefined { return super.Section.get<string>("updateChannel"); }
public get vcpkgEnabled(): boolean | undefined { return super.Section.get<boolean>("vcpkg.enabled"); }
public get addNodeAddonIncludePaths(): boolean | undefined { return super.Section.get<boolean>("addNodeAddonIncludePaths"); }
public get renameRequiresIdentifier(): boolean | undefined { return super.Section.get<boolean>("renameRequiresIdentifier"); }
public get defaultIncludePath(): string[] | undefined { return super.Section.get<string[]>("default.includePath"); }
public get defaultDefines(): string[] | undefined { return super.Section.get<string[]>("default.defines"); }
Expand Down