From 583e45825cce61df7f4e2372e6167b2df33cd44c Mon Sep 17 00:00:00 2001 From: Yaohai Zheng Date: Thu, 9 Mar 2017 16:01:09 +0800 Subject: [PATCH 1/2] Update activation events. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2c88075..7c169dec 100644 --- a/package.json +++ b/package.json @@ -207,4 +207,4 @@ "winreg": "^1.2.3", "winston": "^2.3.1" } -} +} \ No newline at end of file From 8001ddb1fa800a8a29d1b29762bad111e5752830 Mon Sep 17 00:00:00 2001 From: Yaohai Zheng Date: Mon, 20 Mar 2017 09:38:53 +0800 Subject: [PATCH 2/2] Switch to C++ extension for language service. --- package.json | 32 ++++------- src/arduino/arduino.ts | 14 +++-- src/arduino/boardManager.ts | 1 + src/common/constants.ts | 2 + src/extension.ts | 14 +---- src/langService/completionProvider.ts | 81 +++++++++++++++++++++++++-- 6 files changed, 101 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 7c169dec..8d42b53c 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,11 @@ "contributes": { "snippets": [ { - "language": "arduino", + "language": "cpp", "path": "./snippets/arduino.json" }, { - "language": "cpp", + "language": "c", "path": "./snippets/arduino.json" } ], @@ -138,19 +138,15 @@ } } }, - "languages": [ - { - "id": "arduino", - "extensions": [ - ".ino" - ], - "aliases": [ - "Arduino", - "arduino", - "ino" - ], - "configuration": "./syntaxes/arduino.configuration.json" + "configurationDefaults": { + "[cpp]": { + "editor.quickSuggestions": true }, + "[c]": { + "editor.quickSuggestions": true + } + }, + "languages": [ { "id": "arduino-output", "mimetypes": [ @@ -160,7 +156,7 @@ ], "grammars": [ { - "language": "arduino", + "language": "cpp", "path": "./syntaxes/arduino.tmLanguage", "scopeName": "source.cpp.arduino" }, @@ -169,11 +165,7 @@ "scopeName": "arduino.output", "path": "./syntaxes/arduino.output.tmLanguage" } - ], - "explorer": { - "treeLabel": "Arduino Examples", - "treeExplorerNodeProviderId": "arduinoExampleTree" - } + ] }, "scripts": { "vscode:prepublish": "gulp build", diff --git a/src/arduino/arduino.ts b/src/arduino/arduino.ts index b291d553..47d7be45 100644 --- a/src/arduino/arduino.ts +++ b/src/arduino/arduino.ts @@ -126,9 +126,10 @@ export class ArduinoApp { libPaths = this.getDefaultPackageLibPaths(); } - const configFilePath = path.join(vscode.workspace.rootPath, constants.ARDUINO_CONFIG_FILE); + const configFilePath = path.join(vscode.workspace.rootPath, constants.CPP_CONFIG_FILE); let deviceContext = null; if (!util.fileExistsSync(configFilePath)) { + util.mkdirRecursivelySync(configFilePath); deviceContext = {}; } else { deviceContext = util.tryParseJSON(fs.readFileSync(configFilePath, "utf8")); @@ -142,6 +143,8 @@ export class ArduinoApp { deviceContext.configurations.forEach((section) => { if (section.name === util.getCppConfigPlatform()) { configSection = section; + configSection.browse = configSection.browse || {}; + configSection.browse.limitSymbolsToIncludedHeaders = false; } }); @@ -149,6 +152,7 @@ export class ArduinoApp { configSection = { name: util.getCppConfigPlatform(), includePath: [], + browse: { limitSymbolsToIncludedHeaders: false }, }; deviceContext.configurations.push(configSection); } @@ -179,13 +183,13 @@ export class ArduinoApp { await util.spawn(this._settings.commandPath, showOutput ? arduinoChannel.channel : null, ["--install-boards", `${packageName}:${arch}${version && ":" + version}`]); - arduinoChannel.end(`Installed board package - ${packageName}`); + arduinoChannel.end(`Installed board package - ${packageName}${os.EOL}`); } public uninstallBoard(boardName: string, packagePath: string) { arduinoChannel.start(`Uninstall board package - ${boardName}...`); util.rmdirRecursivelySync(packagePath); - arduinoChannel.end(`Installed board package - ${boardName}`); + arduinoChannel.end(`Uninstalled board package - ${boardName}${os.EOL}`); } public async installLibrary(libName: string, version: string = "", showOutput: boolean = true) { @@ -195,13 +199,13 @@ export class ArduinoApp { showOutput ? arduinoChannel.channel : null, ["--install-library", `${libName}${version && ":" + version}`]); - arduinoChannel.end(`Installed libarray - ${libName}`); + arduinoChannel.end(`Installed libarray - ${libName}${os.EOL}`); } public uninstallLibrary(libName: string, libPath: string) { arduinoChannel.start(`Remove library - ${libName}`); util.rmdirRecursivelySync(libPath); - arduinoChannel.end(`Removed library - ${libName}`); + arduinoChannel.end(`Removed library - ${libName}${os.EOL}`); } public getDefaultPackageLibPaths(): string[] { diff --git a/src/arduino/boardManager.ts b/src/arduino/boardManager.ts index d860e893..e1db2cb7 100644 --- a/src/arduino/boardManager.ts +++ b/src/arduino/boardManager.ts @@ -244,6 +244,7 @@ export class BoardManager { dc.board = this.getBoardKey((chosen).entry); this._currentBoard = (chosen).entry; this._boardStatusBar.text = chosen.label; + this._arduinoApp.addLibPath(null); } } diff --git a/src/common/constants.ts b/src/common/constants.ts index ed2fc9ac..f8b35444 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -8,6 +8,8 @@ import * as vscode from "vscode"; export const ARDUINO_CONFIG_FILE = path.join(".vscode", "arduino.json"); +export const CPP_CONFIG_FILE = path.join(".vscode", "c_cpp_properties.json"); + export const ARDUINO_MODE: vscode.DocumentSelector = [ { language: "cpp", scheme: "file" }, { language: "arduino", scheme: "file" }, diff --git a/src/extension.ts b/src/extension.ts index 7357b3c2..51a5de56 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -13,10 +13,7 @@ import { ArduinoSettings } from "./arduino/settings"; import { ARDUINO_MANAGER_PROTOCOL, ARDUINO_MODE, BOARD_MANAGER_URI, LIBRARY_MANAGER_URI } from "./common/constants"; import { DeviceContext } from "./deviceContext"; import { ClangProvider } from "./langService/clang"; -import { ClangFormatter } from "./langService/clangFormatter"; import { CompletionProvider } from "./langService/completionProvider"; -import { DefinitionProvider } from "./langService/definitionProvider"; -import { FormatterProvider } from "./langService/formatterProvider"; import * as Logger from "./logger/logger"; import { SerialMonitor } from "./serialmonitor/serialMonitor"; @@ -102,17 +99,8 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(registerCommand("arduino.sendMessageToSerialPort", () => monitor.sendMessageToSerialPort())); context.subscriptions.push(registerCommand("arduino.closeSerialMonitor", (port) => monitor.closeSerialMonitor(port))); - // Add arduino specific language suport. - const clangProvider = new ClangProvider(arduinoApp); - clangProvider.initialize(); - const completionProvider = new CompletionProvider(clangProvider); - context.subscriptions.push(clangProvider); + const completionProvider = new CompletionProvider(arduinoApp); context.subscriptions.push(vscode.languages.registerCompletionItemProvider(ARDUINO_MODE, completionProvider, "<", '"', ".")); - const definitionProvider = new DefinitionProvider(clangProvider); - context.subscriptions.push(vscode.languages.registerDefinitionProvider(ARDUINO_MODE, definitionProvider)); - const clangFormatter = new ClangFormatter(arduinoSettings); - const formatterProvider = new FormatterProvider(clangFormatter); - context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(ARDUINO_MODE, formatterProvider)); // Example explorer, only work under VSCode insider version. if (typeof vscode.window.registerTreeExplorerNodeProvider === "function" diff --git a/src/langService/completionProvider.ts b/src/langService/completionProvider.ts index 5b4865cb..56c71188 100644 --- a/src/langService/completionProvider.ts +++ b/src/langService/completionProvider.ts @@ -3,11 +3,32 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *-------------------------------------------------------------------------------------------*/ +import * as childProcess from "child_process"; +import * as fs from "fs"; +import * as path from "path"; import * as vscode from "vscode"; -import { ClangProvider } from "./clang"; +import * as constants from "../common/constants"; +import * as platform from "../common/platform"; +import * as util from "../common/util"; + +import { ArduinoApp } from "../arduino/arduino"; export class CompletionProvider implements vscode.CompletionItemProvider { - public constructor(private _clangProvider: ClangProvider) { + + private _headerFiles = new Set(); + + private _libPaths = new Set(); + + private _watcher: vscode.FileSystemWatcher; + + private _cppConfigFile: string = path.join(vscode.workspace.rootPath, constants.CPP_CONFIG_FILE); + + constructor(private _arduinoApp: ArduinoApp) { + this.updateLibList(); + this._watcher = vscode.workspace.createFileSystemWatcher(this._cppConfigFile); + this._watcher.onDidCreate(() => this.updateLibList()); + this._watcher.onDidChange(() => this.updateLibList()); + this._watcher.onDidDelete(() => this.updateLibList()); } public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): @@ -18,13 +39,63 @@ export class CompletionProvider implements vscode.CompletionItemProvider { if (match) { let result = []; - this._clangProvider.headerFiles.forEach((headerFile) => { + this._headerFiles.forEach((headerFile) => { result.push(new vscode.CompletionItem(headerFile, vscode.CompletionItemKind.File)); }); return result; - } else { - return this._clangProvider.provideCompletionItems(document, position, token); } } + private updateLibList(): void { + this._libPaths.clear(); + this._headerFiles.clear(); + this._arduinoApp.getDefaultPackageLibPaths().forEach((defaultPath) => { + this._libPaths.add(defaultPath); + }); + + if (fs.existsSync(this._cppConfigFile)) { + + const deviceConfig = util.tryParseJSON(fs.readFileSync(this._cppConfigFile, "utf8")); + if (deviceConfig) { + if (deviceConfig.sketch) { + const appFolder = path.dirname(deviceConfig.sketch); + if (util.directoryExistsSync(appFolder)) { + this._libPaths.add(path.normalize(appFolder)); + } + } + if (deviceConfig.configurations) { + const plat = util.getCppConfigPlatform(); + deviceConfig.configurations.forEach((configSection) => { + if (configSection.name === plat && Array.isArray(configSection.includePath)) { + configSection.includePath.forEach((includePath) => { + this._libPaths.add(path.normalize(includePath)); + }); + } + }); + } + } + } + + this._libPaths.forEach((includePath) => { + this.addLibFiles(includePath); + }); + } + + private addLibFiles(libPath: string): void { + if (!util.directoryExistsSync(libPath)) { + return; + } + const subItems = fs.readdirSync(libPath); + subItems.forEach((item) => { + try { + let state = fs.statSync(path.join(libPath, item)); + if (state.isFile() && item.endsWith(".h")) { + this._headerFiles.add(item); + } else if (state.isDirectory()) { + this.addLibFiles(path.join(libPath, item)); + } + } catch (ex) { + } + }); + } }