Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
16 changes: 4 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 0 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "",
Expand Down
7 changes: 2 additions & 5 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ interface SoliditySettings {
nodemodulespackage: string;
defaultCompiler: keyof compilerType;
soliumRules: any;
solhintRules: any;
solhintPackageDirectory: string;
validationDelay: number;
packageDefaultDependenciesDirectory: string|string[];
Expand Down Expand Up @@ -116,7 +115,6 @@ let compileUsingRemoteVersion = '';
let compileUsingLocalVersion = '';
let nodeModulePackage = '';
let defaultCompiler = compilerType.embedded;
let solhintDefaultRules = {};
let soliumDefaultRules = {};
let solhintPackageDirectory = '';
let validationDelay = 1500;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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': {
Expand Down Expand Up @@ -602,7 +599,7 @@ function linterRules(settings: SoliditySettings) {
if (_linterName === 'solium') {
return settings.soliumRules;
} else {
return settings.solhintRules;
return null;
}
}

Expand Down
86 changes: 9 additions & 77 deletions src/server/linter/solhint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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'));
}
}

}