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

Switch to C++ extension for language service. #167

Merged
merged 3 commits into from
Mar 21, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 13 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
"contributes": {
Copy link
Contributor

Choose a reason for hiding this comment

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

Add TODO tag: Should remove clang-related config settings and source code.

"snippets": [
{
"language": "arduino",
"language": "cpp",
"path": "./snippets/arduino.json"
},
{
"language": "cpp",
"language": "c",
"path": "./snippets/arduino.json"
}
],
Expand Down Expand Up @@ -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": [
Expand All @@ -160,7 +156,7 @@
],
"grammars": [
{
"language": "arduino",
"language": "cpp",
"path": "./syntaxes/arduino.tmLanguage",
"scopeName": "source.cpp.arduino"
},
Expand All @@ -169,11 +165,7 @@
"scopeName": "arduino.output",
"path": "./syntaxes/arduino.output.tmLanguage"
}
],
"explorer": {
"treeLabel": "Arduino Examples",
"treeExplorerNodeProviderId": "arduinoExampleTree"
}
]
},
"scripts": {
"vscode:prepublish": "gulp build",
Expand Down Expand Up @@ -207,4 +199,4 @@
"winreg": "^1.2.3",
"winston": "^2.3.1"
}
}
}
14 changes: 9 additions & 5 deletions src/arduino/arduino.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand All @@ -142,13 +143,16 @@ export class ArduinoApp {
deviceContext.configurations.forEach((section) => {
if (section.name === util.getCppConfigPlatform()) {
configSection = section;
configSection.browse = configSection.browse || {};
configSection.browse.limitSymbolsToIncludedHeaders = false;
}
});

if (!configSection) {
configSection = {
name: util.getCppConfigPlatform(),
includePath: [],
browse: { limitSymbolsToIncludedHeaders: false },
};
deviceContext.configurations.push(configSection);
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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[] {
Expand Down
1 change: 1 addition & 0 deletions src/arduino/boardManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ export class BoardManager {
dc.board = this.getBoardKey((<any>chosen).entry);
this._currentBoard = (<any>chosen).entry;
this._boardStatusBar.text = chosen.label;
this._arduinoApp.addLibPath(null);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down
14 changes: 1 addition & 13 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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"
Expand Down
81 changes: 76 additions & 5 deletions src/langService/completionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>();

private _libPaths = new Set<string>();

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):
Expand All @@ -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) {
}
});
}
}