Skip to content
This repository was archived by the owner on Dec 22, 2024. It is now read-only.

Commit 8d712d4

Browse files
elektronikworkshophlovdal
authored andcommitted
* Added a global configuration switch which allows the IntelliSense auto-configuration to be turned off
* Prepared the compiler parser code to be injected into "upload" and "upload using programmer" without overhead * Updated intellisense.ts to use only "let" instead of "var" which is much safer * Updated branch documentation
1 parent 0b6845a commit 8d712d4

File tree

5 files changed

+103
-52
lines changed

5 files changed

+103
-52
lines changed

BRANCHNOTES.md

+19-16
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,17 @@ src/arduino/arduino.ts
4040
| | :heavy_check_mark: Basic file output |
4141
| | :white_check_mark: Merging of parsing result and existing file content |
4242
| | :white_check_mark: Handling inexistent files and folders |
43-
| **Configuration flags** | :white_check_mark: |
43+
| **Configuration flags** | :heavy_check_mark: Disable flag for IntelliSense auto-config |
44+
| | :white_check_mark: Perhaps a general IntelliSense flag `{off/manual, auto, oldstyle}` whereas the old can be removed at some point |
45+
| | :white_check_mark: Fine grained IntelliSense control: Global en-/disable and project override. This is probably more useful since the most boards will hopefully work and for the very special cases the user can disable the feature for this single project but still can enjoy it within his regular projects. |
4446
| **Unit tests** | :white_check_mark: Basic parser (known boards, match/no match)|
4547
| | :white_check_mark: Querying of compiler built-in includes |
4648
| | :white_check_mark: Throwing arbitrary data at parser engines |
4749
| | :white_check_mark: JSON input |
4850
| | :white_check_mark: JSON output |
4951
| | :white_check_mark: Configuration merging |
5052
| **General** | :white_check_mark: Review and remove previous attempts messing with `c_cpp_properties.json` |
51-
| | :white_check_mark: Auto-run verify after setting a board to generate a valid `c_cpp_properties.json`, identify other occasions where this applies |
53+
| | :white_check_mark: Auto-run verify after setting a board to generate a valid `c_cpp_properties.json`, identify other occasions where this applies (usually when adding new libraries), hint the user to run *verify*? |
5254

5355
`*` not committed to branch yet
5456

@@ -139,30 +141,31 @@ As one can see with the ESP32-gcc not all include directories are named `include
139141

140142

141143
### Settings
142-
Global user settings, on linux under `~/.config/Code/User/settings.json`, for instance:
144+
#### Global Settings
145+
Under linux at `~/.config/Code/User/settings.json`, for instance:
143146
```json
144147
{
145148
"arduino.additionalUrls": "",
146149
"arduino.logLevel": "verbose",
147-
"C_Cpp.default.cppStandard": "c++11",
148-
"C_Cpp.default.cStandard": "c11",
149150
"arduino.disableTestingOpen": true,
150151
"workbench.editor.enablePreview": false
151152
}
152153
```
153-
Project settings in `.vscode/arduino.json`
154+
Code: [src/arduino/arduinoSettings.ts](src/arduino/arduinoSettings.ts)
155+
Code: [src/arduino/vscodeSettings.ts](src/arduino/vscodeSettings.ts)
156+
Validator: [package.json](package.json)
157+
158+
#### Project Settings
159+
Path in project `.vscode/arduino.json`
154160
```json
155161
{
156-
"board": "arduino:avr:nano",
157-
"configuration": "cpu=atmega328old",
158-
"sketch": "examples/lcdpong-butenc/lcdpong-butenc.ino",
159-
"port": "/dev/ttyUSB0"
160-
}
161-
```
162-
The global settings are [here](src/arduino/vscodeSettings.ts)
163-
```ts
164-
if (VscodeSettings.getInstance().logLevel === "verbose") {
165-
args.push("--verbose");
162+
"board": "arduino:avr:nano",
163+
"configuration": "cpu=atmega328old",
164+
"sketch": "examples/lcdpong-butenc/lcdpong-butenc.ino",
165+
"port": "/dev/ttyUSB0"
166166
}
167167
```
168+
Code: [src/deviceContext.ts](src/deviceContext.ts)
169+
Validator: [misc/arduinoValidator.json](misc/arduinoValidator.json)
170+
168171
### Global Tasks in vscode-arduino

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,11 @@
491491
"arduino.defaultBaudRate": {
492492
"type": "number",
493493
"default": 115200
494+
},
495+
"arduino.disableIntelliSenseAutoGen": {
496+
"type": "boolean",
497+
"default": false,
498+
"description": "When disabled vscode-arduino will not auto-generate an IntelliSense configuration (i.e. c_cpp_properties.json) by analyzing the compiler output."
494499
}
495500
}
496501
},

src/arduino/arduino.ts

+43-16
Original file line numberDiff line numberDiff line change
@@ -313,28 +313,17 @@ export class ArduinoApp {
313313
}
314314

315315
arduinoChannel.show();
316-
// we need to return the result of verify
316+
317317
try {
318-
var gccParserEngine = new CompilerCmdParserEngineGcc(dc.sketch);
319-
let compilerParser = new CompilerCmdParser([gccParserEngine]);
318+
let compilerParserContext = this.makeCompilerParserContext(dc);
320319

321320
await util.spawn(this._settings.commandPath,
322321
arduinoChannel.channel,
323322
args,
324323
{},
325-
compilerParser.callback);
326-
327-
// Write compiler command parser result to IntelliSense
328-
// configuration file in case parsing was successful.
329-
if (compilerParser.result) {
330-
var cppPropsPath = path.join(ArduinoWorkspace.rootPath, constants.CPP_CONFIG_FILE);
331-
var cppProps = new CCppProperties(cppPropsPath);
332-
cppProps.merge(compilerParser.result);
333-
cppProps.write();
334-
arduinoChannel.info("IntelliSense configuration generated successfully.");
335-
} else {
336-
arduinoChannel.warning("Failed to generate IntelliSense configuration.");
337-
}
324+
compilerParserContext.callback);
325+
326+
compilerParserContext.conclude();
338327

339328
arduinoChannel.end(`Finished verify sketch - ${dc.sketch}${os.EOL}`);
340329
return true;
@@ -349,6 +338,44 @@ export class ArduinoApp {
349338
}
350339
}
351340

341+
/** Creates a context which is used for compiler command parsing
342+
* during building (verify, upload, ...).
343+
*
344+
* This context makes sure that it can be used in those sections
345+
* without having to check whether this feature is en- or disabled
346+
* and keeps the calling context more readable.
347+
*
348+
* @param dc The device context of the caller.
349+
*/
350+
private makeCompilerParserContext(dc: DeviceContext)
351+
: { callback: (s:string)=>void; conclude: ()=>void; }
352+
{
353+
if (!VscodeSettings.getInstance().disableIntelliSenseAutoGen) {
354+
355+
// setup the parser with its engines
356+
let gccParserEngine = new CompilerCmdParserEngineGcc(dc.sketch);
357+
let compilerParser = new CompilerCmdParser([gccParserEngine]);
358+
359+
// set up the function to be called after parsing
360+
let _conclude = () => {
361+
let cppPropsPath = path.join(ArduinoWorkspace.rootPath, constants.CPP_CONFIG_FILE);
362+
if (compilerParser.processResult(cppPropsPath)) {
363+
arduinoChannel.info("IntelliSense configuration generated successfully.");
364+
} else {
365+
arduinoChannel.warning("Failed to generate IntelliSense configuration.");
366+
}
367+
};
368+
return {
369+
callback: compilerParser.callback,
370+
conclude: _conclude,
371+
};
372+
}
373+
return {
374+
callback: undefined,
375+
conclude: ()=>void{},
376+
};
377+
};
378+
352379
public tryToUpdateIncludePaths() {
353380
const configFilePath = path.join(ArduinoWorkspace.rootPath, constants.CPP_CONFIG_FILE);
354381
if (!fs.existsSync(configFilePath)) {

src/arduino/intellisense.ts

+30-20
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class CompilerCmdParserResult {
2424
defines: Array<string> = [];
2525
options: Array<string> = [];
2626
compiler: string = "";
27-
/** Dropped arguments like -c -Ox */
27+
/** Dropped arguments like -c -Ox -o, the input and output file. */
2828
trash: Array<string> = [];
2929
};
3030

@@ -71,13 +71,13 @@ export abstract class CompilerCmdParserEngine
7171
public match(line: string): CompilerCmdParserResult
7272
{
7373
// check for regexes that must match
74-
for (var re of this._match) {
74+
for (let re of this._match) {
7575
if (line.search(re) == -1) {
7676
return undefined;
7777
}
7878
}
7979
// check for regexes that mustn't match
80-
for (var re of this._nomatch) {
80+
for (let re of this._nomatch) {
8181
if (line.search(re) != -1) {
8282
return undefined;
8383
}
@@ -116,10 +116,10 @@ export class CompilerCmdParserEngineGcc
116116
}
117117
protected parse(line: string): CompilerCmdParserResult
118118
{
119-
var result = new CompilerCmdParserResult();
120-
var args = line.split(/\s+/);
119+
let result = new CompilerCmdParserResult();
120+
let args = line.split(/\s+/);
121121

122-
for (var arg of args) {
122+
for (let arg of args) {
123123

124124
// drop empty arguments
125125
if (!arg.length) {
@@ -131,41 +131,41 @@ export class CompilerCmdParserEngineGcc
131131
// "-DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\""
132132
// "-DARDUINO_BOARD=\"ESP32_DEV\""
133133
// "-DARDUINO_VARIANT=\"doitESP32devkitV1\""
134-
var packed = arg.match(/^"(.+)"$/);
134+
let packed = arg.match(/^"(.+)"$/);
135135
if (packed) {
136136
arg = packed[1];
137137
}
138138

139139
// extract defines
140-
var define = arg.match(/^-D(.+)/);
140+
let define = arg.match(/^-D(.+)/);
141141
if (define) {
142142
result.defines.push(define[1]);
143143
continue;
144144
}
145145

146146
// extract includes
147-
var include = arg.match(/^-I(.+)/);
147+
let include = arg.match(/^-I(.+)/);
148148
if (include) {
149149
result.includes.push(include[1]);
150150
continue;
151151
}
152152

153153
// extract the compiler executable
154-
var c = arg.match(/g\+\+$/);
154+
let c = arg.match(/g\+\+$/);
155155
if (c) {
156156
result.compiler = arg;
157157
continue;
158158
}
159159

160160
// filter out option trash
161-
var t = arg.match(/^-o|^-O|^-g|^-c|cpp(?:\.o){0,1}$/);
161+
let t = arg.match(/^-o|^-O|^-g|^-c|cpp(?:\.o){0,1}$/);
162162
if (t) {
163163
result.trash.push(arg);
164164
continue;
165165
}
166166

167167
// collect options
168-
var o = arg.match(/^-/);
168+
let o = arg.match(/^-/);
169169
if (o) {
170170
result.options.push(arg);
171171
continue;
@@ -182,8 +182,8 @@ export class CompilerCmdParserEngineGcc
182182

183183
// Spawn synchronous child process and run bash command
184184
// Source: https://stackoverflow.com/a/6666338
185-
var compilerinfocmd = `${result.compiler} -xc++ -E -v - < /dev/null 2>&1`;
186-
var child = spawnSync("bash", ["-c", compilerinfocmd], { encoding : 'utf8' });
185+
let compilerinfocmd = `${result.compiler} -xc++ -E -v - < /dev/null 2>&1`;
186+
let child = spawnSync("bash", ["-c", compilerinfocmd], { encoding : 'utf8' });
187187

188188
if (child.error || child.status != 0) {
189189
// TODO: report the execution failure
@@ -201,11 +201,11 @@ export class CompilerCmdParserEngineGcc
201201
// #include "..." search starts here:
202202
//
203203
// but I havn't seen it so far.
204-
var includeregex = /^#include\s+<\.\.\.>\ssearch\sstarts\shere\:$(.+)^End\sof\ssearch\slist\.$/ms;
205-
var match = child.stdout.match(includeregex);
204+
let includeregex = /^#include\s+<\.\.\.>\ssearch\sstarts\shere\:$(.+)^End\sof\ssearch\slist\.$/ms;
205+
let match = child.stdout.match(includeregex);
206206
if (match) {
207207
// Split list by newlines. Should be platform independent
208-
var lines = match[1].split(/\s*(?:\r|\r\n|\n)\s*/);
208+
let lines = match[1].split(/\s*(?:\r|\r\n|\n)\s*/);
209209
// Filter out empty elements (in most cases only the last element)
210210
lines = lines.filter(function (val:string){return val != ""});
211211
// Add built-in includes to command line includes
@@ -256,7 +256,7 @@ export class CompilerCmdParser
256256
*/
257257
public parse(line: string): boolean
258258
{
259-
for (var engine of this._engines) {
259+
for (let engine of this._engines) {
260260
this._result = engine.match(line);
261261
if (this._result) {
262262
return true;
@@ -275,6 +275,16 @@ export class CompilerCmdParser
275275
}
276276
}
277277
}
278+
public processResult(configPath: string): boolean
279+
{
280+
if (this._result) {
281+
let cppProps = new CCppProperties(configPath);
282+
cppProps.merge(this._result);
283+
cppProps.write();
284+
return true;
285+
}
286+
return false;
287+
}
278288
}
279289

280290
/** Class representing the contents of the IntelliSense
@@ -335,7 +345,7 @@ export class CCppProperties
335345
}
336346
public merge(result: CompilerCmdParserResult)
337347
{
338-
var pc = new CCppPropertiesContent(result);
348+
let pc = new CCppPropertiesContent(result);
339349

340350
// TODO:
341351
// * merge with existing configuration if desired
@@ -353,7 +363,7 @@ export class CCppProperties
353363
// * write file only if modified
354364

355365
if (this.propFileContent) {
356-
var content = JSON.stringify(this.propFileContent, null, 4);
366+
let content = JSON.stringify(this.propFileContent, null, 4);
357367
fs.writeFileSync(this.proppath, content);
358368
}
359369
}

src/arduino/vscodeSettings.ts

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const configKeys = {
1515
IGNORE_BOARDS: "arduino.ignoreBoards",
1616
SKIP_HEADER_PROVIDER: "arduino.skipHeaderProvider",
1717
DEFAULT_BAUD_RATE: "arduino.defaultBaudRate",
18+
DISABLE_INTELLISENSE_AUTO_GEN: "arduino.disableIntelliSenseAutoGen",
1819
};
1920

2021
export interface IVscodeSettings {
@@ -28,6 +29,7 @@ export interface IVscodeSettings {
2829
ignoreBoards: string[];
2930
skipHeaderProvider: boolean;
3031
defaultBaudRate: number;
32+
disableIntelliSenseAutoGen: boolean;
3133
updateAdditionalUrls(urls: string | string[]): void;
3234
}
3335

@@ -87,6 +89,10 @@ export class VscodeSettings implements IVscodeSettings {
8789
return this.getConfigValue<boolean>(configKeys.SKIP_HEADER_PROVIDER);
8890
}
8991

92+
public get disableIntelliSenseAutoGen(): boolean {
93+
return this.getConfigValue<boolean>(configKeys.DISABLE_INTELLISENSE_AUTO_GEN);
94+
}
95+
9096
public async updateAdditionalUrls(value) {
9197
await this.setConfigValue(configKeys.ADDITIONAL_URLS, value, true);
9298
}

0 commit comments

Comments
 (0)