solium.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. 'use strict';
  2. import * as Solium from 'solium';
  3. import { DiagnosticSeverity, IConnection,
  4. } from 'vscode-languageserver';
  5. import Linter from './linter';
  6. import * as fs from 'fs';
  7. export const defaultSoliumRules = {
  8. };
  9. export default class SoliumService implements Linter {
  10. public static readonly EMPTY_CONFIG = {rules: {}};
  11. private fileConfig: any;
  12. private soliumRules;
  13. private vsConnection: IConnection;
  14. constructor(rootPath: string, soliumRules: any, vsConnection: IConnection) {
  15. this.vsConnection = vsConnection;
  16. this.loadFileConfig(rootPath);
  17. this.setIdeRules(soliumRules);
  18. }
  19. public setIdeRules(soliumRules: any) {
  20. if (typeof soliumRules === 'undefined' || soliumRules === null) {
  21. this.soliumRules = defaultSoliumRules;
  22. } else {
  23. this.soliumRules = soliumRules;
  24. }
  25. if (typeof this.soliumRules['indentation'] === 'undefined' || this.soliumRules['indentation'] === null) {
  26. this.soliumRules['indentation'] = 'false';
  27. }
  28. if (process.platform === 'win32') {
  29. if (typeof this.soliumRules['linebreak-style'] === 'undefined' || this.soliumRules['linebreak-style'] === null) {
  30. this.soliumRules['linebreak-style'] = 'off';
  31. }
  32. }
  33. }
  34. public lintAndFix(documentText) {
  35. return Solium.lintAndFix(documentText, this.getAllSettings());
  36. }
  37. public getAllSettings() {
  38. if (this.fileConfig !== SoliumService.EMPTY_CONFIG && this.fileConfig !== false) {
  39. return this.fileConfig;
  40. }
  41. return {
  42. 'extends': 'solium:recommended',
  43. 'options': { 'returnInternalIssues': true },
  44. 'plugins': ['security'],
  45. 'rules': this.soliumRules,
  46. };
  47. }
  48. public validate(filePath, documentText) {
  49. let items = [];
  50. try {
  51. items = Solium.lint(documentText, this.getAllSettings());
  52. } catch (err) {
  53. const match = /An error .*?\nSyntaxError: (.*?) Line: (\d+), Column: (\d+)/.exec(err.message);
  54. if (match) {
  55. const line = parseInt(match[2], 10) - 1;
  56. const character = parseInt(match[3], 10) - 1;
  57. return [
  58. {
  59. message: `Syntax error: ${match[1]}`,
  60. range: {
  61. end: {
  62. character: character,
  63. line: line,
  64. },
  65. start: {
  66. character: character,
  67. line: line,
  68. },
  69. },
  70. severity: DiagnosticSeverity.Error,
  71. },
  72. ];
  73. } else {
  74. // this.vsConnection.window.showErrorMessage('solium error: ' + err);
  75. this.vsConnection.console.error('solium error: ' + err);
  76. }
  77. }
  78. return items.map(this.soliumLintResultToDiagnostic);
  79. }
  80. public soliumLintResultToDiagnostic(lintResult) {
  81. const severity = lintResult.type === 'warning' ?
  82. DiagnosticSeverity.Warning :
  83. DiagnosticSeverity.Error;
  84. const line = lintResult.line - 1;
  85. return {
  86. message: `${lintResult.ruleName}: ${lintResult.message}`,
  87. range: {
  88. end: {
  89. character: lintResult.node.end,
  90. line: line,
  91. },
  92. start: {
  93. character: lintResult.column,
  94. line: line,
  95. },
  96. },
  97. severity: severity,
  98. };
  99. }
  100. private loadFileConfig(rootPath: string) {
  101. const filePath = `${rootPath}/.soliumrc.json`;
  102. const readConfig = this.readFileConfig.bind(this, filePath);
  103. readConfig();
  104. fs.watchFile(filePath, {persistent: false}, readConfig);
  105. }
  106. private readFileConfig(filePath: string) {
  107. this.fileConfig = SoliumService.EMPTY_CONFIG;
  108. fs.readFile(filePath, 'utf-8', this.onConfigLoaded.bind(this));
  109. }
  110. private onConfigLoaded(err: any, data: string) {
  111. this.fileConfig = (!err) && JSON.parse(data);
  112. }
  113. }