diff --git a/README.md b/README.md index c1ba914..0493e87 100644 --- a/README.md +++ b/README.md @@ -206,11 +206,6 @@ Currently, LSP provide following features: * Auto-Completion for headerfile paths when importing in C/C++ files (Displays a list of available `*.h` files in `$PWD/.unikraft`). * Validates if null or repeated imports are there in `C/C++` files. -### Note: - - * To enable `C/C++` auto-completion or validation feature provided by LSP enable `unikraft.enableCCompletion` attribute in `$PWD/.vscode/settings.json` file. By default this attribute is set by extension itself based on the installation of [`C/C++ Extension` provided by microsoft](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) on the host machine. - * LSP server read `C_Cpp.default.includePath` attribute from `$PWD/.vscode/settings.json` file set by client to show a list of headerfiles to user present in `$PWD/.unikraft` dir to include when user imports headerfile in any `C/C++` file. - ### Auto-Completion LSP provide auto-completion feature for all the attributes of `Kraftfile` and only for importing in `C/C++` files. @@ -243,10 +238,6 @@ LSP provide Hover feature only for all the attributes of `Kraftfile`. LSP provide validation feature against null value of any attribute in `Kraftfile`. -#### `C/C++` file imports Validation - -![C/C++ validation](https://github.com/unikraft/ide-vscode/blob/main/media/c-validation.gif) - ## Known Issues * The `External libraries` view is not automatically updated when the following are changed manually: diff --git a/client/src/UnikraftExtension.ts b/client/src/UnikraftExtension.ts index 838ffed..f1f0da1 100644 --- a/client/src/UnikraftExtension.ts +++ b/client/src/UnikraftExtension.ts @@ -18,7 +18,6 @@ import { env } from 'process'; import { basename } from 'path'; import { existsSync, readFileSync, rmSync } from 'fs'; import { sync as commandExistsSync } from 'command-exists'; -import { enableCCompletion } from './config' export class UnikraftExtension { constructor(private context: vscode.ExtensionContext) { } @@ -122,9 +121,6 @@ export class UnikraftExtension { await reloadIncludes(projectPath); await reloadConfig(projectPath); - - // Checking if `C/C++` Extension is installed on the system. - await enableCCompletion(); } private initExtension() { diff --git a/client/src/config.ts b/client/src/config.ts index ab3eaf6..ae0dd1e 100644 --- a/client/src/config.ts +++ b/client/src/config.ts @@ -1,27 +1,4 @@ import { ConfigurationTarget, workspace } from 'vscode'; -import { execSync } from "child_process"; - -// enableCCompletion set `enableCCompletion` to true if `C/C++ Extension` is not installed on the system. -export async function enableCCompletion() { - let installedExts: string = ""; - - // Try to fetch all the installed extension names on the system. - installedExts = execSync('code --list-extensions').toString(); - - // Checks, If `C/C++ Extension` (ID: ms-vscode.cpptools) provided by microsoft already exist. - // If so, then update the workspace configuration with `enableCCompletion: false` - // Otherwise, set it to `enableCCompletion: true` to enable server's custom headerfiles completion. - let confUnikraft = workspace.getConfiguration().get("unikraft"); - if (confUnikraft === null || confUnikraft === undefined) { - await workspace.getConfiguration().update("unikraft", { - "enableCCompletion": !installedExts.includes("ms-vscode.cpptools") - }, ConfigurationTarget.Workspace); - confUnikraft = workspace.getConfiguration().get("unikraft"); - } else { - confUnikraft["enableCCompletion"] = !installedExts.includes("ms-vscode.cpptools"); - await workspace.getConfiguration().update("unikraft", confUnikraft, ConfigurationTarget.Workspace); - } -} // provideDefaultConfigC checks & provide default configuations for c/c++. export async function provideDefaultConfigC() { diff --git a/client/src/extension.ts b/client/src/extension.ts index eed9a98..6544dee 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -44,8 +44,6 @@ export async function activate(context: ExtensionContext) { // { scheme: 'file', language: 'plaintext' }, { pattern: '*.y(a)ml' }, { scheme: 'file', language: 'yaml' }, - { scheme: 'file', language: 'cpp' }, - { scheme: 'file', language: 'c' } ], synchronize: { // Notify the server about file changes to '.clientrc' files contained in the workspace. diff --git a/package.json b/package.json index 70579e0..63d3c2c 100644 --- a/package.json +++ b/package.json @@ -54,11 +54,6 @@ } }, "unikraft": { - "enableCCompletion": { - "type": "boolean", - "default": false, - "description": "Enables Server to show auto-completion elements for headerfiles in `.c/.h` extension files, By default it checks host machine if `C/C++ Extension` provided by microsoft is installed and sets itself." - }, "client": { "sources": { "type": "string", diff --git a/server/src/c/complete.ts b/server/src/c/complete.ts deleted file mode 100644 index c6f0808..0000000 --- a/server/src/c/complete.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ - -import { - CompletionItem, - TextDocumentPositionParams -} from 'vscode-languageserver/node' - -import { getCurrentWord } from '../utils'; -import { importCompletionItems } from './complete/import'; - -export function cCompletionItems( - currentUriText: string, - params: TextDocumentPositionParams, - workspaceDir: string, - includePath: string[] -): CompletionItem[] { - let items: CompletionItem[] = []; - const lineStr = currentUriText.split('\n')[params.position.line].trim(); - const word = getCurrentWord(params.position.character, lineStr); - if (!word) { - return []; - } - - items = items.concat(importCompletionItems(word, lineStr, params.textDocument.uri, workspaceDir, includePath)); - - return items; -} diff --git a/server/src/c/complete/import.ts b/server/src/c/complete/import.ts deleted file mode 100644 index 268c85b..0000000 --- a/server/src/c/complete/import.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ - -import { - CompletionItemKind, - CompletionItem, -} from 'vscode-languageserver/node' -import { readDirRecursively } from '../utils'; -import { unikraft } from '../../utils'; - -// importCompletionItems returns completionItems for importing files. -export function importCompletionItems( - word: string, - lineStr: string, - uri: string, - workspaceDir: string, - includePath: string[] -): CompletionItem[] { - let items: CompletionItem[] = []; - - if ( - includePath.length > 0 && - lineStr.startsWith("#include") && - word.startsWith(`"`) && - word.endsWith(`"`) - ) { - // fileDepthCounter counts the depth of the file user making changes to, - // So that acurate relative path of the including headerfile can be provided. - const docLocationInWorkdir = uri.slice(uri.lastIndexOf("//") + 1).replace(workspaceDir, ""); - const depthCount = docLocationInWorkdir.split('/').length - 2; - let depth: string = ''; - for (let i = 0; i < depthCount; i++) { - depth += '../'; - } - - includePath.forEach(path => { - const files: string[] = readDirRecursively(path); - files.forEach(file => { - const fileName = file.slice(file.lastIndexOf("/") + 1); - const filePath = file.replace(workspaceDir + "/", ""); - items = items.concat({ - label: fileName, - labelDetails: { - description: unikraft - }, - insertText: depth + filePath, - kind: CompletionItemKind.File, - data: path, - detail: depth + filePath, - }); - }); - }); - } else if (word.startsWith("#")) { - items.push( - { - label: "include", - labelDetails: { - description: unikraft - }, - insertText: `include `, - kind: CompletionItemKind.Snippet, - data: "#include", - detail: "It is used to import header files in C.", - documentation: `\`\`\` \n` + - `#include "sample.h" \n` + - `\`\`\`` - } - ); - } - - return items -} diff --git a/server/src/c/utils.ts b/server/src/c/utils.ts deleted file mode 100644 index 00fe035..0000000 --- a/server/src/c/utils.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ - -import { lstatSync, readdirSync } from 'fs'; -import { join } from 'path'; - - -export function readDirRecursively(path: string): string[] { - let files: string[] = []; - const dirContents = readdirSync(path); - for (let i = 0; i < dirContents.length; i++) { - const contentPath = join(path, dirContents[i]); - if (lstatSync(contentPath).isDirectory()) { - const tempItems = readDirRecursively(contentPath); - files = files.concat(tempItems); - } else { - files.push(contentPath); - } - } - return files; -} diff --git a/server/src/c/validate.ts b/server/src/c/validate.ts deleted file mode 100644 index 3031ce5..0000000 --- a/server/src/c/validate.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ - -import { - Diagnostic, -} from 'vscode-languageserver/node'; - -import { - TextDocument -} from 'vscode-languageserver-textdocument'; -import { validateImports } from './validate/import'; - -export function validateC(document: TextDocument): Diagnostic[] { - let diagnostics: Diagnostic[] = []; - - diagnostics = diagnostics.concat(validateImports(document)) - - return diagnostics -} diff --git a/server/src/c/validate/import.ts b/server/src/c/validate/import.ts deleted file mode 100644 index 1721b21..0000000 --- a/server/src/c/validate/import.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ - -import { - Diagnostic, - DiagnosticSeverity, -} from 'vscode-languageserver/node'; - -import { - TextDocument -} from 'vscode-languageserver-textdocument'; -import { unikraftLanguageServer } from '../../utils'; - -export function validateImports(document: TextDocument): Diagnostic[] { - const diagnostics: Diagnostic[] = []; - const docText = document.getText(); - const docTextLines = docText.split('\n'); - const importedStrs: { - lineStr: string, - lineNum: number - }[] = []; - - docTextLines.forEach((lineStr, lineNum) => { - lineStr = lineStr.trim(); - if (lineStr.startsWith("#include") && lineStr.includes(`"`)) { - const firstInd = lineStr.indexOf(`"`); - const lastInd = lineStr.lastIndexOf(`"`); - if (lineStr.slice(firstInd + 1, lastInd) === "") { - diagnostics.push({ - severity: DiagnosticSeverity.Error, - range: { - start: { - line: lineNum, - character: 0 - }, - end: { - line: lineNum, - character: docTextLines[lineNum].length - } - }, - message: `Error: Empty inclusion`, - source: unikraftLanguageServer - }); - } else { - importedStrs.push({ - lineStr: lineStr.slice(firstInd + 1, lastInd + 2), - lineNum: lineNum - }); - } - } - }) - - for (let i = 0; i < importedStrs.length; i++) { - for (let j = i + 1; j < importedStrs.length; j++) { - if (importedStrs[i].lineStr === importedStrs[j].lineStr) { - diagnostics.push({ - severity: DiagnosticSeverity.Error, - range: { - start: { - line: importedStrs[j].lineNum, - character: 0 - }, - end: { - line: importedStrs[j].lineNum, - character: docTextLines[importedStrs[j].lineNum].length - } - }, - message: `Error: Repeated inclusion`, - source: unikraftLanguageServer - }); - } - } - } - return diagnostics; -} diff --git a/server/src/kraftfile/attributes/unikraft.ts b/server/src/kraftfile/attributes/unikraft.ts index 60117c7..ac6787e 100644 --- a/server/src/kraftfile/attributes/unikraft.ts +++ b/server/src/kraftfile/attributes/unikraft.ts @@ -6,7 +6,7 @@ import { } from 'vscode-languageserver/node' import { HoverItem } from '../types'; -import { codeBlockStr, minimalKraftfile, reTriggerCompletionCMD } from '../utils'; +import { codeBlockStr, minimalKraftfile } from '../utils'; import { unikraft } from "../../utils"; const label: string = "unikraft"; diff --git a/server/src/kraftfile/complete.ts b/server/src/kraftfile/complete.ts index 57660ae..6da4b46 100644 --- a/server/src/kraftfile/complete.ts +++ b/server/src/kraftfile/complete.ts @@ -26,12 +26,10 @@ import { platformValueCompletionItem } from './values/targets'; import { getCurrentWordFromYamlFile } from '../utils'; import { targetsValueCompletionItem } from './values/targets'; -const yaml = require("yaml"); - export function kraftfileCompletionItems(currentUriText: string, workspaceDir: string, params: TextDocumentPositionParams): CompletionItem[] { let items: CompletionItem[] = []; const lines = currentUriText.split('\n'); - let lineStr = lines[params.position.line]; + const lineStr = lines[params.position.line]; let isValue: boolean = false; let isNested: boolean = false; let paretnAttribute: string = ""; diff --git a/server/src/kraftfile/validate/cmd.ts b/server/src/kraftfile/validate/cmd.ts index 2fdf572..c2d668b 100644 --- a/server/src/kraftfile/validate/cmd.ts +++ b/server/src/kraftfile/validate/cmd.ts @@ -16,7 +16,7 @@ export function validateCmd(document: TextDocument, kraftfile: KraftYamlType): D return [] } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); const alertPos = docText.indexOf("cmd"); const emptyWarning = { diff --git a/server/src/kraftfile/validate/libraries.ts b/server/src/kraftfile/validate/libraries.ts index 51ccd7f..6b5046e 100644 --- a/server/src/kraftfile/validate/libraries.ts +++ b/server/src/kraftfile/validate/libraries.ts @@ -16,7 +16,7 @@ export function validateLibraries(document: TextDocument, kraftfile: KraftYamlTy return []; } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); const emptyWarning: string = `Warning: Empty value.`; diff --git a/server/src/kraftfile/validate/name.ts b/server/src/kraftfile/validate/name.ts index b5ff67a..1aec024 100644 --- a/server/src/kraftfile/validate/name.ts +++ b/server/src/kraftfile/validate/name.ts @@ -16,7 +16,7 @@ export function validateName(document: TextDocument, kraftfile: KraftYamlType): return []; } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); const alertPos = docText.indexOf("name"); const emptyWarning = { diff --git a/server/src/kraftfile/validate/rootfs.ts b/server/src/kraftfile/validate/rootfs.ts index 90c198d..1a86934 100644 --- a/server/src/kraftfile/validate/rootfs.ts +++ b/server/src/kraftfile/validate/rootfs.ts @@ -16,7 +16,7 @@ export function validateRootfs(document: TextDocument, kraftfile: KraftYamlType) return []; } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); const alertPos = docText.indexOf("rootfs"); const emptyWarning = { diff --git a/server/src/kraftfile/validate/runtime.ts b/server/src/kraftfile/validate/runtime.ts index eaa4180..e04f594 100644 --- a/server/src/kraftfile/validate/runtime.ts +++ b/server/src/kraftfile/validate/runtime.ts @@ -16,7 +16,7 @@ export function validateRuntime(document: TextDocument, kraftfile: KraftYamlType return []; } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); const alertPos = docText.indexOf("runtime"); const emptyWarning = { diff --git a/server/src/kraftfile/validate/template.ts b/server/src/kraftfile/validate/template.ts index 35637f9..543c75b 100644 --- a/server/src/kraftfile/validate/template.ts +++ b/server/src/kraftfile/validate/template.ts @@ -16,9 +16,9 @@ export function validateTemplate(document: TextDocument, kraftfile: KraftYamlTyp return []; } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); - let tempAlertPos = docText.indexOf("template"); + const tempAlertPos = docText.indexOf("template"); const warnMsg = `Warning: Empty value.` const emptyWarning = { severity: DiagnosticSeverity.Warning, diff --git a/server/src/kraftfile/validate/volumes.ts b/server/src/kraftfile/validate/volumes.ts index 7c81dbc..be50e5e 100644 --- a/server/src/kraftfile/validate/volumes.ts +++ b/server/src/kraftfile/validate/volumes.ts @@ -16,7 +16,7 @@ export function validateVolumes(document: TextDocument, kraftfile: KraftYamlType return []; } - let diagnostics: Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const docText = document.getText(); const volumesAlertPos = docText.indexOf("volumes"); const warnMsg = `Warning: Empty value.`; diff --git a/server/src/kraftfile/values/name.ts b/server/src/kraftfile/values/name.ts index c4eeace..e291b8a 100644 --- a/server/src/kraftfile/values/name.ts +++ b/server/src/kraftfile/values/name.ts @@ -8,7 +8,7 @@ import { unikraft } from '../../utils' import { codeBlockStr, getInLineAttribute } from '../utils'; export function nameValueCompletionItem(lineStr: string, workspaceDir: string): CompletionItem[] { - let attr: string | undefined = getInLineAttribute(lineStr); + const attr: string | undefined = getInLineAttribute(lineStr); if (!attr || attr != "name") { return []; } diff --git a/server/src/kraftfile/values/targets.ts b/server/src/kraftfile/values/targets.ts index aa6c129..a7d9fb1 100644 --- a/server/src/kraftfile/values/targets.ts +++ b/server/src/kraftfile/values/targets.ts @@ -132,7 +132,7 @@ export function targetsValueCompletionItem(paretnAttribute: string): CompletionI } export function architectureValueCompletionItem(lineStr: string): CompletionItem[] { - let attr: string | undefined = getInLineAttribute(lineStr); + const attr: string | undefined = getInLineAttribute(lineStr); if (!attr || attr != "arch" && attr != "architecture") { return []; } @@ -181,7 +181,7 @@ export function architectureValueCompletionItem(lineStr: string): CompletionItem } export function platformValueCompletionItem(lineStr: string): CompletionItem[] { - let attr: string | undefined = getInLineAttribute(lineStr); + const attr: string | undefined = getInLineAttribute(lineStr); if (!attr || attr != "plat" && attr != "platform") { return []; } diff --git a/server/src/server.ts b/server/src/server.ts index 4af2ee9..9944cac 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -25,7 +25,6 @@ import { import { kraftfileCompletionItems } from './kraftfile/complete'; import { readdirSync } from 'fs'; -import { cCompletionItems } from './c/complete'; import { getKraftfileHoverItem } from './kraftfile/hover'; import { UnikraftServerConfigType, UnikraftConfigType } from './types'; @@ -45,8 +44,6 @@ let hasUnikraftDir: boolean = false; let workspaceDir: string = ''; let currentUriText: string = ''; let workspaceUnikraftConfig: UnikraftConfigType = {} as UnikraftConfigType; -let enabledCCompletion: boolean = false; -const includePath: string[] = []; connection.onInitialize((params: InitializeParams) => { const capabilities = params.capabilities; @@ -162,13 +159,6 @@ connection.onCompletion( switch (true) { case isKraftfile(params.textDocument.uri): return kraftfileCompletionItems(currentUriText, workspaceDir, params); - - case enabledCCompletion && isCFile(params.textDocument.uri): - if (!hasUnikraftDir) { - return []; - } - - return cCompletionItems(currentUriText, params, workspaceDir, includePath); } return []; } @@ -265,24 +255,4 @@ async function initGlobalVars() { if (workspaceSettings && workspaceSettings["unikraft"]) { workspaceUnikraftConfig = workspaceSettings["unikraft"] } - - // Checking the value of `enableCCompletion` in workspace configuration. - if (workspaceUnikraftConfig && workspaceUnikraftConfig["enableCCompletion"]) { - enabledCCompletion = true; - if ( - workspaceSettings["C_Cpp"] && - workspaceSettings["C_Cpp"]["default"] && - workspaceSettings["C_Cpp"]["default"]["includePath"] - ) { - const tmpPaths: string[] = workspaceSettings["C_Cpp"]["default"]["includePath"]; - tmpPaths.forEach((path, index) => { - if (path.endsWith("**")) { - path = path.slice(0, path.lastIndexOf("**")); - } - includePath[index] = path; - }) - } - } else { - enabledCCompletion = false; - } } diff --git a/server/src/utils.ts b/server/src/utils.ts index db15897..cb44e8c 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -3,7 +3,6 @@ import { Diagnostic } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { validateKraftfile } from './kraftfile/validate' -import { validateC } from './c/validate'; export const unikraft = "Unikraft"; export const unikraftLanguageServer = "Unikraft Language Server"; @@ -25,8 +24,6 @@ export function validateFile(document: TextDocument): Diagnostic[] | undefined { switch (true) { case getDefaultKraftfileNames().includes(docUri.slice(docUri.lastIndexOf("/") + 1)): return validateKraftfile(document); - case isCFile(docUri): - return validateC(document); default: break; }