diff --git a/README.md b/README.md index 6db0057..a8a48f0 100644 --- a/README.md +++ b/README.md @@ -276,22 +276,14 @@ There are two linters included with the extension, solhint and solium / ethlint. ### Solhint -To lint Solidity code you can use the Solhint linter https://github.com/protofire/solhint, the linter can be configured it using the following user settings: +To lint Solidity code you can use the Solhint linter https://github.com/protofire/solhint, the linter is configured using `.solhint.json` files. -```json -"solidity.linter": "solhint", -"solidity.solhintRules": { - "avoid-sha3": "warn" -} -``` - -This extension supports `.solhint.json` configuration file. It must be placed to project root -directory. After any changes in `.solhint.json` it will be synchronized with current IDE -configuration. +This extension supports `.solhint.json` configuration files placed **anywhere in the project** (not only the root). +Solhint automatically merges configurations following the [official configuration scheme](https://github.com/protofire/solhint?tab=readme-ov-file#configuration), with support for [multiple config files](https://github.com/protofire/solhint?tab=readme-ov-file#multiple-configs). This is the default linter now. -NOTE: Solhint plugins are not supported yet. +NOTE: Solhint plugins are not supported yet. NOTE: The `solidity.solhintRules` setting is no longer supported. ### Solium / Ethlint diff --git a/package.json b/package.json index f3be757..d084fdd 100644 --- a/package.json +++ b/package.json @@ -151,13 +151,6 @@ "default": "solhint", "description": "Enables linting using either solium (ethlint) or solhint. Possible options 'solhint' and 'solium', the default is solhint" }, - "solidity.solhintRules": { - "type": [ - "object" - ], - "default": null, - "description": "Solhint linting validation rules" - }, "solidity.solhintPackageDirectory": { "type": "string", "default": "", diff --git a/src/server.ts b/src/server.ts index 0b286dc..c0c0a70 100644 --- a/src/server.ts +++ b/src/server.ts @@ -48,7 +48,6 @@ interface SoliditySettings { nodemodulespackage: string; defaultCompiler: keyof compilerType; soliumRules: any; - solhintRules: any; solhintPackageDirectory: string; validationDelay: number; packageDefaultDependenciesDirectory: string|string[]; @@ -116,7 +115,6 @@ let compileUsingRemoteVersion = ''; let compileUsingLocalVersion = ''; let nodeModulePackage = ''; let defaultCompiler = compilerType.embedded; -let solhintDefaultRules = {}; let soliumDefaultRules = {}; let solhintPackageDirectory = ''; let validationDelay = 1500; @@ -302,7 +300,6 @@ function updateSoliditySettings(soliditySettings: SoliditySettings) { enabledAsYouTypeErrorCheck = soliditySettings.enabledAsYouTypeCompilationErrorCheck; compileUsingLocalVersion = soliditySettings.compileUsingLocalVersion; compileUsingRemoteVersion = soliditySettings.compileUsingRemoteVersion; - solhintDefaultRules = soliditySettings.solhintRules; soliumDefaultRules = soliditySettings.soliumRules; solhintPackageDirectory = soliditySettings.solhintPackageDirectory; validationDelay = soliditySettings.validationDelay; @@ -336,7 +333,7 @@ function updateSoliditySettings(soliditySettings: SoliditySettings) { switch (linterName(soliditySettings)) { case 'solhint': { - linter = new SolhintService(rootPath, solhintDefaultRules, solhintPackageDirectory); + linter = new SolhintService(rootPath, solhintPackageDirectory); break; } case 'solium': { @@ -602,7 +599,7 @@ function linterRules(settings: SoliditySettings) { if (_linterName === 'solium') { return settings.soliumRules; } else { - return settings.solhintRules; + return null; } } diff --git a/src/server/linter/solhint.ts b/src/server/linter/solhint.ts index ff6d3d8..9272fd0 100644 --- a/src/server/linter/solhint.ts +++ b/src/server/linter/solhint.ts @@ -7,27 +7,27 @@ import { Diagnostic, Range, DiagnosticSeverity as Severity } from 'vscode-langua import Linter from './linter'; export default class SolhintService implements Linter { - private config: ValidationConfig; + private rootPath: string; private linter: any; - constructor(rootPath: string, rules: any, packageDirectory: string) { - this.config = new ValidationConfig(rootPath, rules); + constructor(rootPath: string, packageDirectory: string) { + this.rootPath = rootPath; this.linter = packageDirectory ? require(path.join(rootPath, packageDirectory)) : linter_; } public loadFileConfig(rootPath: string) { - this.config.loadFileConfig(rootPath); + // No-op: configuration is handled by solhint processFile } public setIdeRules(rules: any) { - this.config.setIdeRules(rules); + // No-op: IDE rules are not supported anymore } public validate(filePath: string, documentText: string): Diagnostic[] { - return this.linter - .processStr(documentText, this.config.build(), filePath) - .messages - .map(e => this.toDiagnostic(e)); + const result = this.rootPath + ? this.linter.processFile(filePath, undefined, this.rootPath) + : this.linter.processFile(filePath); + return (result.messages || []).map((e) => this.toDiagnostic(e)); } private toDiagnostic(error) { @@ -53,71 +53,3 @@ export default class SolhintService implements Linter { }; } } - - -class ValidationConfig { - public static readonly DEFAULT_RULES = {'func-visibility': false}; - public static readonly EMPTY_CONFIG = {rules: {}}; - - private ideRules: any; - private fileConfig: any; - private currentWatchFile: string; - - constructor(rootPath: string, ideRules: any) { - this.setIdeRules(ideRules); - this.loadFileConfig(rootPath); - } - - public setIdeRules(rules: any) { - this.ideRules = rules || {}; - } - - public build() { - let extendsConfig = ['solhint:recommended']; - if (this.fileConfig.extends !== 'undefined' && this.fileConfig.extends !== null) { - extendsConfig = this.fileConfig.extends; - } - - let pluginsConfig = []; - if (this.fileConfig.plugins !== 'undefined' && this.fileConfig.plugins !== null) { - console.log(`pluginsConfig: ${this.fileConfig.plugins}`); - pluginsConfig = this.fileConfig.plugins; - } - - return { - extends: extendsConfig, - plugins: pluginsConfig, - rules: Object.assign( - ValidationConfig.DEFAULT_RULES, - this.ideRules, - this.fileConfig.rules, - ), - }; - } - - public isRootPathSet(rootPath: string): boolean { - return typeof rootPath !== 'undefined' && rootPath !== null; - } - - public loadFileConfig(rootPath: string) { - - if (this.isRootPathSet(rootPath)) { - const filePath = `${rootPath}/.solhint.json`; - const readConfig = this.readFileConfig.bind(this, filePath); - - readConfig(); - this.currentWatchFile = filePath; - // fs.watchFile(filePath, {persistent: false}, readConfig); - } else { - this.fileConfig = ValidationConfig.EMPTY_CONFIG; - } - } - - private readFileConfig(filePath: string) { - this.fileConfig = ValidationConfig.EMPTY_CONFIG; - if (fs.existsSync(filePath)) { - this.fileConfig = JSON.parse(fs.readFileSync(filePath, 'utf-8')); - } - } - -}