Skip to content

Eslint (draft) #148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
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
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/out
**/node_modules
!.eslintrc.js
67 changes: 67 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'jest', 'prettier'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
sourceType: 'module',
project: './server/tsconfig.json',
},
rules: {
'prettier/prettier': [
'error',
{
trailingComma: 'all',
singleQuote: true,
printWidth: 90,
semi: false,
},
],
'@typescript-eslint/no-unused-vars': [
'error',
{
vars: 'all',
args: 'none',
argsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'no-console': [
'error',
{
allow: ['warn', 'error'],
},
],
'prefer-destructuring': [
'error',
{
array: false,
object: true,
},
],
'prefer-const': 'error',
'prefer-template': 'error',

'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/prefer-interface': 'off',
'@typescript-eslint/no-var-requires': 'off',
'no-unused-vars': 'off', // replaced by @typescript-eslint/no-unused-vars
},
env: {
browser: false,
node: true,
es6: true,
'jest/globals': true,
},
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ server/out
.DS_Store
*.log
coverage
.eslintcache
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: node_js
node_js:
- '6'
- '10'
- '12'
cache: yarn
script:
- yarn run check:bail
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"search.exclude": {
"out": true
},
"tslint.autoFixOnSave": true,
"eslint.autoFixOnSave": true,
"typescript.tsdk": "./node_modules/typescript/lib",
"typescript.tsc.autoDetect": "off"
}
7 changes: 3 additions & 4 deletions docs/development-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ There are two moving parts.
- **Server**: A node server written in Typescript that implements the
[Language Server Protocol (LSP)][LSP].

- **Client**: A super tiny Visual Studio Code (vscode) extension which basically
just tells vscode how to launch the LSP server.
**Client**: A Visual Studio Code (vscode) extension which wraps the LSP server.

The project has a root `package.json` file which is really just there for
convenience - it proxies to the `package.json` files in the `vscode-client` and
Expand Down Expand Up @@ -44,7 +43,7 @@ below.

## Development Tools

To support a good develop workflow we set up [TSLint][tslint], [Prettier][prettier] and integration tests using [Jest][jest]:
To support a good develop workflow we set up [eslint][eslint], [Prettier][prettier] and integration tests using [Jest][jest]:

yarn run check # (runs lint, prettier and tests)
yarn run lint
Expand Down Expand Up @@ -82,6 +81,6 @@ I'm open to suggestions on how to improve this workflow.
[ide-bash]: https://github.com/mads-hartmann/ide-bash
[jest]: https://facebook.github.io/jest/
[prettier]: https://prettier.io/
[tslint]: https://palantir.github.io/tslint/
[eslint]: https://eslint.org/
[yarn]: https://yarnpkg.com/lang/en/docs/install/
[node]: https://nodejs.org/en/download/
45 changes: 24 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,33 @@
"private": true,
"scripts": {
"clean": "rm -rf *.log */*.log */out node_modules vscode-client/node_modules server/node_modules",
"postinstall": "cd server && yarn install && cd ../vscode-client && yarn install && cd ..",
"postinstall": "cd server && yarn install && yarn link && cd ../vscode-client && yarn install && yarn link bash-language-server && cd ..",
"compile": "yarn run compile:server && yarn run compile:client",
"compile:client": "cd vscode-client && yarn run compile",
"compile:server": "cd server && yarn run compile",
"lint": "tslint --project vscode-client --fix && tslint --project server --fix",
"lint:bail": "tslint --project vscode-client && tslint --project server",
"test": "jest --runInBand --forceExit",
"test:coverage": "yarn run test -- --coverage",
"test:watch": "yarn run test -- --watch",
"lint": "yarn lint:bail --fix",
"lint:bail": "eslint . --ext js,ts,tsx --cache",
"test": "jest --runInBand",
"test:coverage": "yarn run test --coverage",
"test:watch": "yarn run test --watch",
"check": "yarn run lint && yarn run compile && yarn run test",
"check:bail": "yarn run lint:bail && yarn run compile && yarn run test",
"reinstall-server": "npm uninstall -g bash-language-server && yarn compile:server && npm i -g ./server"
},
"devDependencies": {
"@types/jest": "^22.2.2",
"@types/node": "^9.6.2",
"electron-rebuild": "^1.7.3",
"jest": "^22.4.3",
"prettier": "^1.11.1",
"ts-jest": "^22.4.2",
"tslint-config-prettier": "^1.10.0",
"tslint-plugin-prettier": "^1.3.0",
"tslint": "^5.9.1",
"typescript": "^2.8.1",
"vscode-languageserver": "^4.1.1"
"@types/jest": "^24.0.18",
"@types/node": "^12.7.5",
"@typescript-eslint/eslint-plugin": "^1.10.2",
"@typescript-eslint/parser": "^1.10.2",
"eslint": "^5.16.0",
"eslint-config-prettier": "^5.0.0",
"eslint-plugin-jest": "^22.17.0",
"eslint-plugin-prettier": "^3.1.0",
"jest": "^24.9.0",
"prettier": "^1.18.2",
"ts-jest": "^24.1.0",
"typescript": "3.5.2",
"vscode-languageserver": "^5.2.1"
},
"resolutions": {
"sane": "^3.0.2"
Expand All @@ -42,21 +44,22 @@
"ts"
],
"modulePathIgnorePatterns": [
"<rootDir>/server/out"
"<rootDir>/server/out",
"<rootDir>/vscode-client/out"
],
"transform": {
"\\.ts$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
"\\.ts$": "ts-jest"
},
"globals": {
"ts-jest": {
"tsConfigFile": "server/tsconfig.json"
"tsConfig": "./server/tsconfig.json"
}
},
"testMatch": [
"<rootDir>/**/__tests__/*.ts"
],
"setupFiles": [
"./server/setupJest.ts"
"./setupJest.ts"
],
"collectCoverageFrom": [
"**/*.ts",
Expand Down
1 change: 1 addition & 0 deletions server/bin/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env node
/* eslint-disable no-console */

const server = require('../out/index')
const package = require('../package')
Expand Down
8 changes: 4 additions & 4 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"license": "MIT",
"version": "1.5.6",
"publisher": "mads-hartmann",
"main": "out/server.js",
"main": "./out/server.js",
"typings": "./out/server.d.ts",
"bin": {
"bash-language-server": "./bin/main.js"
},
Expand All @@ -20,11 +21,10 @@
"glob": "^7.1.2",
"request": "^2.83.0",
"request-promise-native": "^1.0.5",
"tree-sitter": "^0.13.22",
"tree-sitter-bash": "^0.13.7",
"turndown": "^4.0.2",
"urijs": "^1.19.1",
"vscode-languageserver": "^4.1.1"
"vscode-languageserver": "^5.2.1",
"web-tree-sitter": "^0.15.9"
},
"scripts": {
"compile": "rm -rf out && ../node_modules/.bin/tsc -p ./",
Expand Down
4 changes: 2 additions & 2 deletions server/src/__tests__/__snapshots__/analyzer.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Array [
"message": "Failed to parse expression",
"range": Object {
"end": Object {
"character": 0,
"line": 10,
"character": 1,
"line": 9,
},
"start": Object {
"character": 0,
Expand Down
9 changes: 6 additions & 3 deletions server/src/__tests__/analyzer.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import FIXTURES from '../../../testing/fixtures'
import Analyzer from '../analyser'
import { initializeParser } from '../parser'

const analyzer = new Analyzer()
let analyzer: Analyzer

const CURRENT_URI = 'dummy-uri.sh'
beforeEach(() => {
analyzer.analyze(CURRENT_URI, FIXTURES.INSTALL)

beforeAll(async () => {
const parser = await initializeParser()
analyzer = new Analyzer(parser)
})

describe('analyze', () => {
Expand Down
38 changes: 24 additions & 14 deletions server/src/analyser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// tslint:disable:no-submodule-imports
import * as fs from 'fs'
import * as glob from 'glob'
import * as Path from 'path'

import * as request from 'request-promise-native'
import * as Parser from 'tree-sitter'
import * as bash from 'tree-sitter-bash'
import * as URI from 'urijs'
import * as Parser from 'web-tree-sitter'

import * as LSP from 'vscode-languageserver'

import { uniqueBasedOnHash } from './util/array'
Expand All @@ -33,28 +32,33 @@ export default class Analyzer {
* If the rootPath is provided it will initialize all *.sh files it can find
* anywhere on that path.
*/
public static fromRoot(
connection: LSP.Connection,
rootPath: string | null,
): Promise<Analyzer> {
public static fromRoot({
connection,
rootPath,
parser,
}: {
connection: LSP.Connection
rootPath: string | null
parser: Parser
}): Promise<Analyzer> {
// This happens if the users opens a single bash script without having the
// 'window' associated with a specific project.
if (!rootPath) {
return Promise.resolve(new Analyzer())
return Promise.resolve(new Analyzer(parser))
}

return new Promise((resolve, reject) => {
glob('**/*.sh', { cwd: rootPath }, (err, paths) => {
if (err != null) {
reject(err)
} else {
const analyzer = new Analyzer()
const analyzer = new Analyzer(parser)
paths.forEach(p => {
const absolute = Path.join(rootPath, p)
// only analyze files, glob pattern may match directories
if (fs.existsSync(absolute) && fs.lstatSync(absolute).isFile()) {
const uri = 'file://' + absolute
connection.console.log('Analyzing ' + uri)
const uri = `file://${absolute}`
connection.console.log(`Analyzing ${uri}`)
analyzer.analyze(
uri,
LSP.TextDocument.create(
Expand All @@ -72,6 +76,8 @@ export default class Analyzer {
})
}

private parser: Parser

private uriToTextDocument: { [uri: string]: LSP.TextDocument } = {}

private uriToTreeSitterTrees: Trees = {}
Expand All @@ -83,9 +89,15 @@ export default class Analyzer {

private treeSitterTypeToLSPKind: Kinds = {
// These keys are using underscores as that's the naming convention in tree-sitter.
/* eslint-disable @typescript-eslint/camelcase */
environment_variable_assignment: LSP.SymbolKind.Variable,
function_definition: LSP.SymbolKind.Function,
variable_assignment: LSP.SymbolKind.Variable,
/* eslint-enable @typescript-eslint/camelcase */
}

public constructor(parser: Parser) {
this.parser = parser
}

/**
Expand Down Expand Up @@ -239,9 +251,7 @@ export default class Analyzer {
public analyze(uri: string, document: LSP.TextDocument): LSP.Diagnostic[] {
const contents = document.getText()

const parser = new Parser()
parser.setLanguage(bash)
const tree = parser.parse(contents)
const tree = this.parser.parse(contents)

this.uriToTextDocument[uri] = document
this.uriToTreeSitterTrees[uri] = tree
Expand Down
2 changes: 1 addition & 1 deletion server/src/executables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class Executables {
/**
* Find all programs in your PATH
*/
public list(): Array<string> {
public list(): string[] {
return Array.from(this.executables.values())
}

Expand Down
Loading