Skip to content

Commit 99361e8

Browse files
committed
Merge branch 'release/v3.2.0'
2 parents ba9b10c + dded631 commit 99361e8

File tree

12 files changed

+219
-71
lines changed

12 files changed

+219
-71
lines changed

.babelrc

Lines changed: 0 additions & 15 deletions
This file was deleted.

.eslintrc.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
module.exports = {
22
'env': {
3-
'browser': false,
43
'es6': true,
5-
'node': true,
6-
'jasmine': true,
4+
'node': true
75
},
86
'plugins': [
97
'import'
@@ -13,10 +11,9 @@ module.exports = {
1311
'plugin:import/errors',
1412
'plugin:import/warnings'
1513
],
16-
'parser': '@babel/eslint-parser',
1714
'parserOptions': {
18-
'ecmaVersion': 6,
19-
'sourceType': 'module'
15+
'sourceType': 'module',
16+
'ecmaVersion': 13
2017
},
2118
'settings': {
2219
'import/core-modules': [
315 KB
Loading

.vscodeignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
.github/**
12
.vscode/**
23
.vscode-test/**
34
src/**
45
test/**
5-
.babelrc
66
.eslintignore
77
.eslintrc.js
88
.gitignore
9+
**/*.ts
10+
*.vsix
11+
node_modules/**/*.md
12+
node_modules/**/*.map
13+
node_modules/**/test.js
14+
node_modules/**/tests.js
15+
node_modules/**/test/**
16+
node_modules/**/tests/**

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Release Notes
22

3+
## 3.2.0 (2023-06-09)
4+
5+
* Introducing a powerful linting feature that highlights syntactical and stylistic issues in the ["platformio.ini"](https://docs.platformio.org/en/latest/projectconf/index.html) configuration file (issue [#3723](https://github.com/platformio/platformio-vscode-ide/issues/3723))
6+
* Improved project cleanup process by utilizing the ``fullclean`` target instead of ``cleanall``. This ensures a thorough clean-up, including the removal of dependent libraries
7+
* Updated PlatformIO Core Installer Script to [v1.1.3](https://github.com/platformio/platformio-core-installer/releases/tag/v1.1.3)
8+
* Resolved an issue where certain buttons were missing from the status bar in VSCode 1.79 after the recent update (issue [#3736](https://github.com/platformio/platformio-vscode-ide/issues/3736))
9+
10+
![Linting "platformio.ini" configuration file (demo)](https://raw.githubusercontent.com/platformio/platformio-vscode-ide/develop/.github/media/platformio-ini-lint-demo.png)
11+
312
## 3.1.1 (2023-03-16)
413

514
* Added a new ``platformio-ide.uploadAndMonitor`` command which can be used with the custom [PlatformIO Toolbar](https://docs.platformio.org/en/latest/integration/ide/vscode.html#platformio-toolbar)

package.json

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "platformio-ide",
3-
"version": "3.1.1",
3+
"version": "3.2.0",
44
"publisher": "platformio",
55
"engines": {
66
"vscode": "^1.65.0"
@@ -26,7 +26,7 @@
2626
"icon": "assets/images/platformio-logo.png",
2727
"homepage": "https://platformio.org",
2828
"author": {
29-
"name": "PlatformIO.Org"
29+
"name": "PlatformIO Labs"
3030
},
3131
"bugs": {
3232
"url": "https://github.com/platformio/platformio-vscode-ide/issues"
@@ -887,24 +887,19 @@
887887
},
888888
"dependencies": {
889889
"fs-plus": "~3.1.1",
890-
"platformio-node-helpers": "~10.0.0",
890+
"platformio-node-helpers": "~11.0.1",
891891
"platformio-vscode-debug": "~1.4.1"
892892
},
893893
"devDependencies": {
894-
"@babel/core": "~7.21.3",
895-
"@babel/eslint-parser": "~7.21.3",
896-
"@babel/plugin-proposal-class-properties": "~7.18.6",
897-
"@babel/preset-env": "~7.20.2",
898894
"@types/node": "~14",
899895
"@types/vscode": "~1.65.0",
900-
"@vscode/vsce": "~2.18.0",
901-
"babel-loader": "~9.1.2",
902-
"eslint": "~8.36.0",
896+
"@vscode/vsce": "~2.19.0",
897+
"eslint": "~8.42.0",
903898
"eslint-import-resolver-webpack": "~0.13.2",
904899
"eslint-plugin-import": "~2.27.5",
905-
"prettier": "~2.8.4",
906-
"webpack": "~5.76.2",
907-
"webpack-cli": "~5.0.1"
900+
"prettier": "~2.8.8",
901+
"webpack": "~5.85.1",
902+
"webpack-cli": "~5.1.4"
908903
},
909904
"extensionDependencies": [
910905
"ms-vscode.cpptools"

src/home.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,11 @@ export default class PIOHome {
183183
}
184184

185185
onOpenProjectCommand(params) {
186-
if (extension.ProjectManager) {
186+
if (extension.projectManager) {
187187
updateProjectItemState(vscode.Uri.file(params).fsPath, 'selectedEnv', undefined);
188-
extension.ProjectManager.switchToProject(vscode.Uri.file(params).fsPath);
188+
extension.projectManager.switchToProject(vscode.Uri.file(params).fsPath, {
189+
force: true,
190+
});
189191
}
190192
this.disposePanel();
191193
if (vscode.workspace.workspaceFolders) {

src/main.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class PlatformIOVSCodeExtension {
2727
this.context = undefined;
2828
this.pioTerm = undefined;
2929
this.pioHome = undefined;
30-
this.ProjectManager = undefined;
30+
this.projectManager = undefined;
3131
this.subscriptions = [];
3232

3333
this._enterpriseSettings = undefined;
@@ -93,8 +93,8 @@ class PlatformIOVSCodeExtension {
9393
);
9494

9595
this.initDebug();
96-
this.ProjectManager = new ProjectManager();
97-
this.subscriptions.push(this.ProjectManager);
96+
this.projectManager = new ProjectManager();
97+
this.subscriptions.push(this.projectManager);
9898

9999
this.startPIOHome();
100100

src/project/config.js

Lines changed: 145 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@
99
import * as pioNodeHelpers from 'platformio-node-helpers';
1010

1111
import { disposeSubscriptions, listCoreSerialPorts } from '../utils';
12+
import path from 'path';
1213
import vscode from 'vscode';
1314

1415
export class ProjectConfigLanguageProvider {
1516
static DOCUMENT_SELECTOR = { language: 'ini' };
1617
SCOPE_PLATFORMIO = 'platformio';
1718
SCOPE_ENV = 'env';
1819

19-
constructor(projectDir) {
20-
this.projectDir = projectDir;
20+
constructor() {
21+
this.diagnosticCollection =
22+
vscode.languages.createDiagnosticCollection('PlatformIO');
2123
this.subscriptions = [
24+
this.diagnosticCollection,
2225
vscode.languages.registerHoverProvider(
2326
ProjectConfigLanguageProvider.DOCUMENT_SELECTOR,
2427
{
@@ -33,6 +36,12 @@ export class ProjectConfigLanguageProvider {
3336
await this.provideCompletionItems(document, position, token, context),
3437
}
3538
),
39+
vscode.workspace.onDidOpenTextDocument((document) =>
40+
this.lintConfig(document.uri)
41+
),
42+
vscode.workspace.onDidSaveTextDocument((document) =>
43+
this.lintConfig(document.uri)
44+
),
3645
];
3746
// if (vscode.languages.registerInlineCompletionItemProvider) {
3847
// this.subscriptions.push(
@@ -45,17 +54,27 @@ export class ProjectConfigLanguageProvider {
4554
// )
4655
// );
4756
// }
48-
this._options = undefined;
57+
this._optionsCache = new Map();
4958
this._ports = undefined;
59+
60+
// vscode.window.visibleTextEditors.forEach((editor) =>
61+
// this.lintConfig(editor.document)
62+
// );
5063
}
5164

5265
dispose() {
5366
disposeSubscriptions(this.subscriptions);
67+
this._optionsCache.clear();
68+
this.diagnosticCollection.clear();
5469
}
5570

56-
async getOptions() {
57-
if (this._options) {
58-
return this._options;
71+
/**
72+
* Completion
73+
*/
74+
async getOptions(document) {
75+
const configPath = document.uri.fsPath;
76+
if (this._optionsCache.has(configPath)) {
77+
return this._optionsCache.get(configPath);
5978
}
6079
const script = `
6180
import json
@@ -65,10 +84,10 @@ print(json.dumps(get_config_options_schema()))
6584
`;
6685
const output = await pioNodeHelpers.core.getCorePythonCommandOutput(
6786
['-c', script],
68-
{ projectDir: this.projectDir }
87+
{ projectDir: path.dirname(configPath) }
6988
);
70-
this._options = JSON.parse(output.trim());
71-
return this._options;
89+
this._optionsCache.set(configPath, JSON.parse(output));
90+
return this._optionsCache.get(configPath);
7291
}
7392

7493
renderOptionDocs(option) {
@@ -133,7 +152,9 @@ ${option.description}
133152
continue;
134153
}
135154
const optionName = line.split('=')[0].trim();
136-
return (await this.getOptions()).find((option) => option.name === optionName);
155+
return (await this.getOptions(document)).find(
156+
(option) => option.name === optionName
157+
);
137158
}
138159
}
139160

@@ -149,7 +170,9 @@ ${option.description}
149170

150171
async provideHover(document, position) {
151172
const word = document.getText(document.getWordRangeAtPosition(position));
152-
const option = (await this.getOptions()).find((option) => option.name === word);
173+
const option = (await this.getOptions(document)).find(
174+
(option) => option.name === word
175+
);
153176
if (option) {
154177
return new vscode.Hover(this.renderOptionDocs(option));
155178
}
@@ -212,7 +235,7 @@ ${option.description}
212235
if (!scope) {
213236
return;
214237
}
215-
const options = await this.getOptions();
238+
const options = await this.getOptions(document);
216239
return options
217240
.filter((option) => option.scope === scope)
218241
.map((option) => {
@@ -316,4 +339,114 @@ ${option.description}
316339
items.push(this.createCustomCompletionValueItem());
317340
return items;
318341
}
342+
343+
/**
344+
* Linting
345+
*/
346+
async lintConfig(uri) {
347+
// ignore non-platformio.ini docs
348+
if (path.basename(uri.fsPath) !== 'platformio.ini') {
349+
return;
350+
}
351+
const script = `
352+
import configparser
353+
import glob
354+
import json
355+
356+
from platformio import fs
357+
from platformio.project import exception
358+
from platformio.public import ProjectConfig
359+
360+
361+
# remove this code for PIO Core 6.1.8+
362+
class TmpProjectConfig(ProjectConfig):
363+
def read(self, path, parse_extra=True):
364+
if path in self._parsed:
365+
return
366+
self._parsed.append(path)
367+
try:
368+
self._parser.read(path, "utf-8")
369+
except configparser.Error as exc:
370+
raise exception.InvalidProjectConfError(path, str(exc)) from exc
371+
if not parse_extra:
372+
return
373+
# load extra configs
374+
for pattern in self.get("platformio", "extra_configs", []):
375+
if pattern.startswith("~"):
376+
pattern = fs.expanduser(pattern)
377+
for item in glob.glob(pattern, recursive=True):
378+
self.read(item)
379+
380+
381+
errors = []
382+
warnings = []
383+
384+
try:
385+
config = TmpProjectConfig()
386+
config.validate(silent=True)
387+
warnings = config.warnings
388+
config.as_tuple()
389+
except Exception as exc:
390+
if exc.__cause__:
391+
exc = exc.__cause__
392+
item = {"type": exc.__class__.__name__, "message": str(exc)}
393+
for attr in ("lineno", "source"):
394+
if hasattr(exc, attr):
395+
item[attr] = getattr(exc, attr)
396+
errors.append(item)
397+
if item["type"] == "ParsingError" and hasattr(exc, "errors"):
398+
for lineno, line in getattr(exc, "errors"):
399+
errors.append(
400+
{
401+
"type": item["type"],
402+
"message": f"Parsing error: {line}",
403+
"lineno": lineno,
404+
"source": item["source"]
405+
}
406+
)
407+
408+
print(json.dumps(dict(errors=errors, warnings=warnings)))
409+
`;
410+
this.diagnosticCollection.clear();
411+
const projectDir = path.dirname(uri.fsPath);
412+
const output = await pioNodeHelpers.core.getCorePythonCommandOutput(
413+
['-c', script],
414+
{ projectDir }
415+
);
416+
const { errors, warnings } = JSON.parse(output);
417+
this.diagnosticCollection.set(
418+
uri,
419+
warnings.map(
420+
(msg) =>
421+
new vscode.Diagnostic(
422+
new vscode.Range(0, 0, 0, 0),
423+
msg,
424+
vscode.DiagnosticSeverity.Warning
425+
)
426+
)
427+
);
428+
const uriDiagnostics = new Map();
429+
errors.forEach((data) => {
430+
const sourceUri = data.source
431+
? vscode.Uri.file(
432+
path.isAbsolute(data.source)
433+
? data.source
434+
: path.join(projectDir, data.source)
435+
)
436+
: uri;
437+
const diagnostics = uriDiagnostics.get(sourceUri.fsPath) || [];
438+
diagnostics.push(
439+
new vscode.Diagnostic(
440+
new vscode.Range(data?.lineno - 1 || 0, 0, data?.lineno || 0, 0),
441+
data.message,
442+
vscode.DiagnosticSeverity.Error
443+
)
444+
);
445+
uriDiagnostics.set(sourceUri.fsPath, diagnostics);
446+
});
447+
uriDiagnostics.forEach((diagnostics, fsPath) =>
448+
this.diagnosticCollection.set(vscode.Uri.file(fsPath), diagnostics)
449+
);
450+
return !errors.length;
451+
}
319452
}

0 commit comments

Comments
 (0)