Skip to content

Commit

Permalink
Remove use of editorconfig module to avoid dependency on one-ini
Browse files Browse the repository at this point in the history
…wasm file. (#12579)
  • Loading branch information
Colengms authored Aug 20, 2024
1 parent a0f863c commit 7dcd5a4
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 288 deletions.
2 changes: 0 additions & 2 deletions Extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6505,7 +6505,6 @@
"@vscode/test-electron": "^2.3.10",
"async-child-process": "^1.1.1",
"await-notify": "^1.0.1",
"copy-webpack-plugin": "^12.0.2",
"eslint": "^8.45.0",
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-import": "^2.29.1",
Expand Down Expand Up @@ -6534,7 +6533,6 @@
"@vscode/extension-telemetry": "^0.9.6",
"chokidar": "^3.6.0",
"comment-json": "^4.2.3",
"editorconfig": "^2.0.0",
"escape-string-regexp": "^2.0.0",
"glob": "^7.2.3",
"minimatch": "^3.0.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import * as vscode from 'vscode';
import { ResponseError } from 'vscode-languageclient';
import { DefaultClient, FormatDocumentRequest, FormatParams, FormatResult } from '../client';
import { getEditorConfigSettings } from '../editorConfig';
import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { CppSettings, OtherSettings, getEditorConfigSettings } from '../settings';
import { CppSettings, OtherSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';

export class DocumentFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import * as vscode from 'vscode';
import { ResponseError } from 'vscode-languageclient';
import { DefaultClient, FormatParams, FormatRangeRequest, FormatResult } from '../client';
import { getEditorConfigSettings } from '../editorConfig';
import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { CppSettings, getEditorConfigSettings } from '../settings';
import { CppSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';

export class DocumentRangeFormattingEditProvider implements vscode.DocumentRangeFormattingEditProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import * as vscode from 'vscode';
import { ResponseError } from 'vscode-languageclient';
import { DefaultClient, FormatOnTypeRequest, FormatParams, FormatResult } from '../client';
import { getEditorConfigSettings } from '../editorConfig';
import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { CppSettings, getEditorConfigSettings } from '../settings';
import { CppSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';

export class OnTypeFormattingEditProvider implements vscode.OnTypeFormattingEditProvider {
Expand Down
4 changes: 2 additions & 2 deletions Extension/src/LanguageServer/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,13 @@ import {
import { Location, TextEdit, WorkspaceEdit } from './commonTypes';
import * as configs from './configurations';
import { DataBinding } from './dataBinding';
import { cachedEditorConfigSettings, getEditorConfigSettings } from './editorConfig';
import { CppSourceStr, clients, configPrefix, updateLanguageConfigurations, usesCrashHandler, watchForCrashes } from './extension';
import { LocalizeStringParams, getLocaleId, getLocalizedString } from './localization';
import { PersistentFolderState, PersistentWorkspaceState } from './persistentState';
import { createProtocolFilter } from './protocolFilter';
import * as refs from './references';
import { CppSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams, getEditorConfigSettings } from './settings';
import { CppSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams } from './settings';
import { SettingsTracker } from './settingsTracker';
import { ConfigurationType, LanguageStatusUI, getUI } from './ui';
import { handleChangedFromCppToC, makeLspRange, makeVscodeLocation, makeVscodeRange } from './utils';
Expand Down Expand Up @@ -102,7 +103,6 @@ let workspaceHash: string = "";
let workspaceDisposables: vscode.Disposable[] = [];
export let workspaceReferences: refs.ReferencesManager;
export const openFileVersions: Map<string, number> = new Map<string, number>();
export const cachedEditorConfigSettings: Map<string, any> = new Map<string, any>();
export const cachedEditorConfigLookups: Map<string, boolean> = new Map<string, boolean>();
export let semanticTokensLegend: vscode.SemanticTokensLegend | undefined;

Expand Down
168 changes: 168 additions & 0 deletions Extension/src/LanguageServer/editorConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';

import * as fs from 'fs';
import * as path from 'path';

export const cachedEditorConfigSettings: Map<string, any> = new Map<string, any>();

export function mapIndentationReferenceToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "statementBegin") {
return "statement_begin";
}
if (value === "outermostParenthesis") {
return "outermost_parenthesis";
}
}
return "innermost_parenthesis";
}

export function mapIndentToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "leftmostColumn") {
return "leftmost_column";
}
if (value === "oneLeft") {
return "one_left";
}
}
return "none";
}

export function mapNewOrSameLineToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "newLine") {
return "new_line";
}
if (value === "sameLine") {
return "same_line";
}
}
return "ignore";
}

export function mapWrapToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "allOneLineScopes") {
return "all_one_line_scopes";
}
if (value === "oneLiners") {
return "one_liners";
}
}
return "never";
}

function matchesSection(filePath: string, section: string): boolean {
const fileName: string = path.basename(filePath);
// Escape all regex special characters except '*' and '?'.
// Convert wildcards '*' to '.*' and '?' to '.'.
const sectionPattern = section.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.');
const regex: RegExp = new RegExp(`^${sectionPattern}$`);
return regex.test(fileName);
}

function parseEditorConfigContent(content: string): Record<string, any> {
const lines = content.split(/\r?\n/);
const config: Record<string, any> = {};
let currentSection: string | null = '*'; // Use '*' for sectionless (global) settings.

lines.forEach(line => {
line = line.trim();

if (!line || line.startsWith('#') || line.startsWith(';')) {
// Skip empty lines and comments.
return;
}

if (line.startsWith('[') && line.endsWith(']')) {
// New section (e.g., [*.js])
currentSection = line.slice(1, -1).trim();
config[currentSection] = config[currentSection] || {};
} else {
// Key-value pair (e.g., indent_style = space).
const [key, ...values] = line.split('=');
if (key && values.length > 0) {
const trimmedKey = key.trim();
const value = values.join('=').trim();
if (currentSection) {
// Ensure the current section is initialized.
if (!config[currentSection]) {
config[currentSection] = {};
}
config[currentSection][trimmedKey] = value;
}
}
}
});

return config;
}

function getEditorConfig(filePath: string): any {
let combinedConfig: any = {};
let globalConfig: any = {};
let currentDir: string = path.dirname(filePath);
const rootDir: string = path.parse(currentDir).root;

// Traverse from the file's directory to the root directory.
for (;;) {
const editorConfigPath: string = path.join(currentDir, '.editorconfig');
if (fs.existsSync(editorConfigPath)) {
const configFileContent: string = fs.readFileSync(editorConfigPath, 'utf-8');
const configData = parseEditorConfigContent(configFileContent);

// Extract global (sectionless) entries.
if (configData['*']) {
globalConfig = {
...globalConfig,
...configData['*']
};
}

// Match sections and combine configurations.
Object.keys(configData).forEach((section: string) => {
if (section !== '*' && matchesSection(filePath, section)) {
combinedConfig = {
...combinedConfig,
...configData[section]
};
}
});

// Check if the current .editorconfig is the root.
if (configData['*']?.root?.toLowerCase() === 'true') {
break; // Stop searching after processing the root = true file.
}
}
if (currentDir === rootDir) {
break; // Stop the loop after checking the root directory.
}
currentDir = path.dirname(currentDir);
}

// Merge global config with section-based config.
return {
...globalConfig,
...combinedConfig
};
}

// Look up the appropriate .editorconfig settings for the specified file.
// This is intentionally not async to avoid races due to multiple entrancy.
export function getEditorConfigSettings(fsPath: string): Promise<any> {
let editorConfigSettings: any = cachedEditorConfigSettings.get(fsPath);
if (!editorConfigSettings) {
editorConfigSettings = getEditorConfig(fsPath);
cachedEditorConfigSettings.set(fsPath, editorConfigSettings);
}
return editorConfigSettings;
}
67 changes: 2 additions & 65 deletions Extension/src/LanguageServer/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
'use strict';

import { execSync } from 'child_process';
import * as editorConfig from 'editorconfig';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
Expand All @@ -17,7 +16,8 @@ import * as which from 'which';
import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isObject, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common';
import { isWindows } from '../constants';
import * as telemetry from '../telemetry';
import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client';
import { cachedEditorConfigLookups, DefaultClient, hasTrustedCompilerPaths } from './client';
import { getEditorConfigSettings, mapIndentationReferenceToEditorConfig, mapIndentToEditorConfig, mapNewOrSameLineToEditorConfig, mapWrapToEditorConfig } from './editorConfig';
import { clients } from './extension';
import { CommentPattern } from './languageConfig';
import { PersistentState } from './persistentState';
Expand Down Expand Up @@ -1076,66 +1076,3 @@ export class OtherSettings {
public get searchExclude(): Excludes { return this.getAsExcludes("search", "exclude", this.defaultSearchExcludes, this.resource); }
public get workbenchSettingsEditor(): string { return this.getAsString("workbench.settings", "editor", this.resource, "ui"); }
}

function mapIndentationReferenceToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "statementBegin") {
return "statement_begin";
}
if (value === "outermostParenthesis") {
return "outermost_parenthesis";
}
}
return "innermost_parenthesis";
}

function mapIndentToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "leftmostColumn") {
return "leftmost_column";
}
if (value === "oneLeft") {
return "one_left";
}
}
return "none";
}

function mapNewOrSameLineToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "newLine") {
return "new_line";
}
if (value === "sameLine") {
return "same_line";
}
}
return "ignore";
}

function mapWrapToEditorConfig(value: string | undefined): string {
if (value !== undefined) {
// Will never actually be undefined, as these settings have default values.
if (value === "allOneLineScopes") {
return "all_one_line_scopes";
}
if (value === "oneLiners") {
return "one_liners";
}
}
return "never";
}

// Look up the appropriate .editorconfig settings for the specified file.
// This is intentionally not async to avoid races due to multiple entrancy.
export function getEditorConfigSettings(fsPath: string): Promise<any> {
let editorConfigSettings: any = cachedEditorConfigSettings.get(fsPath);
if (!editorConfigSettings) {
editorConfigSettings = editorConfig.parseSync(fsPath);
cachedEditorConfigSettings.set(fsPath, editorConfigSettings);
}
return editorConfigSettings;
}
11 changes: 0 additions & 11 deletions Extension/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
'use strict';

const path = require('path');
const copyPlugin = require('copy-webpack-plugin');

/**@type {import('webpack').Configuration}*/
const config = {
Expand All @@ -32,16 +31,6 @@ const config = {
extensions: ['.js', '.ts',],
mainFields: ['main', 'module'],
},
plugins: [
new copyPlugin({
patterns: [
{
from: path.resolve(__dirname, 'node_modules', "@one-ini", "wasm", "one_ini_bg.wasm"),
to: path.resolve(__dirname, 'dist', 'src')
}
]
})
],
module: {
rules: [{
test: /\.ts$/,
Expand Down
Loading

0 comments on commit 7dcd5a4

Please sign in to comment.