This commit is contained in:
Pine Wu 2018-06-25 20:29:01 -07:00
Родитель 1f37ab8d18
Коммит 05ebe0eacd
48 изменённых файлов: 40877 добавлений и 84 удалений

7
.github/CONTRIBUTING.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
## CLA
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

77
.gitignore поставляемый
Просмотреть файл

@ -1,61 +1,24 @@
# Logs
logs
*.log
.DS_Store
node_modules
/dist
/tests/e2e/videos/
/tests/e2e/screenshots/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

5
.postcssrc.js Normal file
Просмотреть файл

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

5
.prettierrc Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{
"printWidth": 100,
"semi": false,
"singleQuote": true
}

10
.travis.yml Normal file
Просмотреть файл

@ -0,0 +1,10 @@
language: node_js
node_js: 8
cache: yarn
install:
- yarn
script:
- yarn test

34
LICENSE
Просмотреть файл

@ -1,21 +1,21 @@
MIT License
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

Просмотреть файл

@ -1,14 +1,29 @@
# Language Server Protocol Inspector
# Contributing
Try it at https://microsoft.github.io/language-server-protocol/inspector/.
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.microsoft.com.
## Motivation
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
When you are using [vscode-languageserver-node](https://github.com/Microsoft/vscode-languageserver-node) to develop a language server, it's possible to specify a setting `"[langId]".trace.server: "verbose"` to make the Language Client log the LSP communication. This log is useful for developing and testing the Language Server, but the log can be lengthy — 5 seconds of usage might generate 5000 lines LSP log. This makes it hard to gain insight from the logs.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
This inspector visualizes the logs to make it easy to understand the communication between the Language Client / Server. It also lets you filter down the logs by search query or language features, so you can quickly identify the logs you are interested in.
![lsp-inspector](https://user-images.githubusercontent.com/4033249/41323525-ba73697a-6e63-11e8-92a3-c655b34126f6.gif)
## Usage
- A log file (log from html Language Server) is loaded by default.
- Click each LSP item to expand its parameters.
- Type a query into the search bar to filter the logs.
- Select a language feature area to filter the logs.
- Collect your own logs and inspect them! For example:
- Set `css.trace.server: "verbose"` in VS Code.
- Open a CSS file.
- Copy everything inside `CSS Language Server` channel into a log file `css.log`.
- Load it from the web app.
- You can try it on real-world logs file at `/tests/unit/logParser/fixture`.
## Running & Developing
- `yarn`
- `yarn serve`

3
cypress.json Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"pluginsFile": "tests/e2e/plugins/index.js"
}

24
jest.config.js Normal file
Просмотреть файл

@ -0,0 +1,24 @@
module.exports = {
moduleFileExtensions: [
'ts',
'tsx',
'js',
'jsx',
'json',
'vue'
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.tsx?$': 'ts-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: [
'jest-serializer-vue'
],
testMatch: [
'<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
]
}

45
package.json Normal file
Просмотреть файл

@ -0,0 +1,45 @@
{
"name": "next",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"format": "prettier --config .prettierrc --write {src,tests}/**/*.{vue,js,ts,json}"
},
"gitHooks": {
"pre-commit": "yarn format"
},
"dependencies": {
"@fortawesome/fontawesome": "^1.1.8",
"@fortawesome/fontawesome-free-solid": "^5.0.13",
"@fortawesome/vue-fontawesome": "^0.0.23",
"vue": "^2.5.16",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@types/fs-extra": "^5.0.3",
"@types/jest": "^22.0.1",
"@vue/cli-plugin-e2e-cypress": "^3.0.0-beta.15",
"@vue/cli-plugin-typescript": "^3.0.0-beta.15",
"@vue/cli-plugin-unit-jest": "^3.0.0-beta.15",
"@vue/cli-service": "^3.0.0-beta.15",
"@vue/test-utils": "^1.0.0-beta.16",
"fs-extra": "^6.0.1",
"node-sass": "^4.9.0",
"prettier": "^1.13.6",
"sass-loader": "^7.0.1",
"ts-jest": "^22.4.6",
"vue-template-compiler": "^2.5.16",
"yorkie": "^1.0.3"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

Двоичные данные
public/favicon.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

18
public/index.html Normal file
Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>LSP Inspector</title>
</head>
<body>
<noscript>
<strong>We're sorry but LSP Inspector doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

34
src/App.vue Normal file
Просмотреть файл

@ -0,0 +1,34 @@
<template>
<div id="app">
<h1>LSP Inspector</h1>
<div id="nav">
<router-link to="/language-server-protocol/inspector/">Usage</router-link> |
<router-link to="/language-server-protocol/inspector/app">App</router-link>
</div>
<router-view/>
</div>
</template>
<style lang="scss" scoped>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
h1 {
margin-top: 120px;
margin-bottom: 40px;
}
</style>

Двоичные данные
src/assets/logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.7 KiB

1
src/assets/search.svg Normal file
Просмотреть файл

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>

После

Ширина:  |  Высота:  |  Размер: 215 B

Просмотреть файл

@ -0,0 +1,28 @@
<template>
<div class="file-picker">
<input type="file" @change="handleFiles">
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
methods: {
handleFiles(e) {
const reader = new FileReader()
const store = this.$store
reader.onload = () => {
store.commit('updateLog', reader.result)
}
reader.readAsText(e.target.files[0])
}
}
})
</script>
<style>
.file-picker {
margin-bottom: 24px;
}
</style>

Просмотреть файл

@ -0,0 +1,41 @@
<template>
<div class="filter-bar">
<span :class="{ active: filter === 'a' }" @click="updateFilter('a')">All</span> |
<span :class="{ active: filter === 'w' }" @click="updateFilter('w')">Workspace</span> |
<span :class="{ active: filter === 't' }" @click="updateFilter('t')">Text</span> |
<span :class="{ active: filter === 'd' }" @click="updateFilter('d')">Diagnostics</span> |
<span :class="{ active: filter === 'l' }" @click="updateFilter('l')">Language</span>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
computed: {
filter() {
return this.$store.state.filter
}
},
methods: {
updateFilter(filter) {
this.$store.commit('updateFilter', filter)
}
}
})
</script>
<style>
.filter-bar {
margin-bottom: 24px;
font-family: 'Input Mono', Menlo, Monaco, 'Courier New', monospace;
}
.filter-bar span {
transition: color 0.1s ease-in;
}
.filter-bar .active {
color: #3eaf7c;
}
.filter-bar span:hover {
color: #3eaf7c88;
}
</style>

69
src/components/Intro.vue Normal file
Просмотреть файл

@ -0,0 +1,69 @@
<template>
<div class="intro">
Welcome to LSP Inspector. Here you can:
<ul>
<li>Visualize lengthy LSP logs so it's easier to understand the communication between Language Server/Client</li>
<li>Expand messages to look deeper into the parameters</li>
<li>Filter the messages by area, type, message name or message parameters</li>
</ul>
<h3>Usage</h3>
Language Servers implemented with <a href="https://github.com/Microsoft/vscode-languageserver-node">vscode-languageserver-node</a>
has an option `[langId].trace.server`. When you set it to `"verbose"`, logs will be printed to the `[langeId]` output channel. Here is
an example of loading CSS language server traces:
<ul>
<li>In VS Code, set `css.trace.server: "verbose"`</li>
<li>Go to Output -> CSS Language Server. Select all output and save them into a log file css.log.</li>
<li>In the inspector, use the file picker to load the log file.</li>
</ul>
<h3>Message Type</h3>
There are 6 types of message communications between the language client/server:
<ul>
<li>
<font-awesome-icon class="fa-icon" icon="comment-alt" style="color: #bb9911de" />
Notification: Client -> Server
</li>
<li>
<font-awesome-icon class="fa-icon" icon="comment-alt" style="color: #bb9911de" transform="flip-h" />
Notification: Server -> Client
</li>
<li>
<font-awesome-icon class="fa-icon" icon="comment" style="color: #1c791cbd" />
Request: Client -> Server
</li>
<li>
<font-awesome-icon class="fa-icon" icon="comment" style="color: #1c791cbd" transform="flip-h" />
Response: Server -> Client
</li>
<li>
<font-awesome-icon class="fa-icon" icon="comment" style="color: #356fa5f7" transform="flip-h" />
Request: Server -> Client
</li>
<li>
<font-awesome-icon class="fa-icon" icon="comment" style="color: #356fa5f7" />
Response: Client -> Server
</li>
</ul>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import FontAwesomeIcon from '@fortawesome/vue-fontawesome'
export default Vue.extend({
components: {
FontAwesomeIcon
}
})
</script>
<style>
.intro {
max-width: 640px;
margin-left: auto;
margin-right: auto;
text-align: left;
}
</style>

135
src/components/Message.vue Normal file
Просмотреть файл

@ -0,0 +1,135 @@
<template>
<span class="msg" :class="[{ current: isCurrent }, item.msgKind]" @mouseover="updateCurrent">
<div>
<span @click="toggleArg">
<font-awesome-icon class="fa-icon" icon="comment" v-if="item.msgKind === 'send-request'" />
<font-awesome-icon class="fa-icon" icon="comment-alt" v-if="item.msgKind === 'send-notification'" />
<font-awesome-icon class="fa-icon" icon="comment" v-if="item.msgKind === 'send-response'" />
</span>
<span class="msg-type" v-if="isLeft" @click="toggleArg">
{{ item.msgType }}
</span>
<span class="msg-timestamp" @click="toggleArg">{{ timestampOrLatency }}</span>
<span class="msg-type" v-if="!isLeft" @click="toggleArg">
{{ item.msgType }}
</span>
<span @click="toggleArg">
<font-awesome-icon class="fa-icon" icon="comment" transform="flip-h" v-if="item.msgKind === 'recv-response'" />
<font-awesome-icon class="fa-icon" icon="comment-alt" tranform="flip-h" v-if="item.msgKind === 'recv-notification'" />
<font-awesome-icon class="fa-icon" icon="comment" transform="flip-h" v-if="item.msgKind === 'recv-request'" />
</span>
</div>
<message-detail :item="item" v-if="this.expanded" @click="noop"></message-detail>
</span>
</template>
<script lang="ts">
import Vue from 'vue'
import FontAwesomeIcon from '@fortawesome/vue-fontawesome'
import MessageDetail from '@/components/MessageDetail.vue'
export default Vue.extend({
name: 'message',
components: {
FontAwesomeIcon,
MessageDetail
},
props: ['item'],
data() {
return {
expanded: false
}
},
computed: {
isLeft() {
return (
this.item.msgKind === 'send-request' ||
this.item.msgKind === 'send-notification' ||
this.item.msgKind === 'send-response'
)
},
timestampOrLatency() {
return this.item.msgKind === 'recv-response' || this.item.msgKind === 'send-response'
? this.item.msgLatency
: this.item.time
},
isCurrent() {
return this.item.msgId === this.$store.state.current
}
},
methods: {
toggleArg() {
this.expanded = !this.expanded
},
updateCurrent() {
if (this.item.msgId) {
this.$store.commit('updateCurrent', this.item.msgId)
} else {
this.$store.commit('updateCurrent', -1)
}
},
noop() {}
}
})
</script>
<style scoped>
.msg {
font-family: 'Input Mono', Menlo, Monaco, 'Courier New', monospace;
font-size: 13px;
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: 20px;
padding: 10px 20px;
}
.msg-timestamp {
color: #e8a1a1;
font-size: 10px;
}
.send-request,
.send-notification,
.send-response {
align-self: flex-start;
text-align: left;
}
.recv-response,
.recv-notification,
.recv-request {
align-self: flex-end;
text-align: right;
}
.send-request,
.recv-response {
color: #1c791cbd;
}
.send-notification,
.recv-notification {
color: #bb9911de;
}
.recv-request,
.send-response {
color: #356fa5f7;
}
/**
* Hover / Expand
*/
.msg {
transition: background-color 0.1s ease-in;
}
.msg:hover {
background-color: rgba(221, 221, 221, 0.3);
}
.msg.current {
background-color: rgba(221, 221, 221, 0.3);
}
</style>

Просмотреть файл

@ -0,0 +1,60 @@
<template>
<div class="msg-detail">
<b>
<a :href="msgLink" target="_blank">
{{ this.item.msgType }}
</a>
</b>
<pre>
<code>{{ JSON.stringify(item.arg, null, 2) }}</code>
</pre>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: ['item'],
computed: {
msgLink() {
return `https://microsoft.github.io/language-server-protocol/specification#${
this.item.msgType
}`
}
}
})
</script>
<style lang="scss">
.msg-detail {
border: 1px solid #eee;
padding: 20px;
font-size: 12px;
text-align: left;
b a {
color: inherit;
}
}
pre {
text-align: left;
max-width: 64rem;
margin-left: auto;
margin-right: auto;
white-space: normal;
text-align: left;
overflow: auto;
overflow-wrap: break-word;
border-radius: 6px;
}
code {
white-space: pre-wrap;
font-family: 'Input Mono', Menlo, Monaco, 'Courier New', monospace !important;
font-size: 12px;
border-radius: 2px;
padding: 0.2rem 0.3rem;
}
</style>

Просмотреть файл

@ -0,0 +1,47 @@
<template>
<div>
<div class="msg-header">
<span>Client</span>
<span>Server</span>
</div>
<div class="msg-list">
<message v-for="(item, i) in this.log" :key="i" :item="item"></message>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Message from '@/components/Message.vue'
export default Vue.extend({
components: {
Message
},
computed: {
log() {
return this.$store.state.items
}
}
})
</script>
<style lang="scss">
.msg-header,
.msg-list {
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.msg-header {
display: flex;
flex-flow: row;
justify-content: space-between;
margin-bottom: 40px;
font-size: 2rem;
}
.msg-list {
display: flex;
flex-flow: column;
}
</style>

Просмотреть файл

@ -0,0 +1,51 @@
<template>
<div class="search-box">
<input v-model="query" autocomplete="off" spellcheck="false">
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
computed: {
query: {
get() {
return this.$store.state.query
},
set(value) {
this.$store.commit('search', value)
}
}
}
})
</script>
<style>
.search-box {
margin-bottom: 40px;
display: inline-block;
position: relative;
margin-right: 0.5rem;
}
.search-box input {
cursor: text;
width: 10rem;
color: #4e6e8e;
display: inline-block;
border: 1px solid #cfd4db;
border-radius: 2rem;
font-size: 0.9rem;
line-height: 2rem;
padding: 0 0.5rem 0 2rem;
outline: none;
transition: all 0.2s ease;
background: #fff url(https://vuepress.vuejs.org/assets/img/search.83621669.svg) 0.6rem 0.5rem
no-repeat;
background-size: 1rem;
}
.search-box input:focus {
cursor: auto;
border-color: #3eaf7c;
}
</style>

Просмотреть файл

@ -0,0 +1,119 @@
export type MsgKind =
| 'send-notification'
| 'recv-notification'
| 'send-request'
| 'recv-request'
| 'send-response'
| 'recv-response'
export interface LspItem {
time: string
msg: string
msgKind: MsgKind
msgType: string
msgId: string
msgLatency: string
arg: any
}
export function parseLSPLog(input: string): LspItem[] {
const lineEnding = isCRLF(input) ? '\r\n' : '\n'
const logs = input.split(lineEnding + lineEnding + lineEnding)
const arr: LspItem[] = []
logs
.map(l => {
const start = l.lastIndexOf('[Trace')
return l.slice(start)
})
.filter(l => {
return l.startsWith('[Trace')
})
.forEach(l => {
const parsed = parseRawLog(l)
if (parsed) {
arr.push(parsed)
}
})
return arr
}
function parseRawLog(log: string) {
const rawLogs = log.split('\n')
const [trace, firstLineJson] = rawLogs
const reTrace = /\[Trace - (.*)\] (.*)/
const reJsonFirstLine = /(Params|Result): (.*)/
if (trace.match(reTrace) && firstLineJson.match(reJsonFirstLine)) {
const [time, msg] = reTrace.exec(trace).slice(1)
const [jsonIdentifier, restOfFirstLineJson] = reJsonFirstLine.exec(firstLineJson).slice(1)
const parsedArg = JSON.parse([restOfFirstLineJson, ...rawLogs.slice(2)].join('\n'))
return {
time,
msg,
...extractMsg(msg),
arg: parsedArg
}
}
}
function extractMsg(msg: string) {
let msgKind
if (msg.startsWith('Sending notification')) {
msgKind = 'send-notification'
} else if (msg.startsWith('Received notification')) {
msgKind = 'recv-notification'
} else if (msg.startsWith('Sending request')) {
msgKind = 'send-request'
} else if (msg.startsWith('Received request')) {
msgKind = 'recv-request'
} else if (msg.startsWith('Sending response')) {
msgKind = 'send-response'
} else if (msg.startsWith('Received response')) {
msgKind = 'recv-response'
} else {
return null
}
const reSendNotification = /Sending notification '(.*)'/
const reRecvNotification = /Received notification '(.*)'/
const reSendRequest = /Sending request '(.*) - \((\d+)\)'/
const reRecvRequest = /Received request '(.*) - \((\d+)\)'/
const reSendResponse = /Sending response '(.*) - \((\d+)\)'.*took (\d+ms)/
const reRecvResponse = /Received response '(.*) - \((\d+)\)' in (\d+ms)/
let msgType, msgId, msgLatency
if (msgKind === 'send-notification') {
;[msgType] = reSendNotification.exec(msg).slice(1)
} else if (msgKind === 'recv-notification') {
;[msgType] = reRecvNotification.exec(msg).slice(1)
} else if (msgKind === 'send-request') {
;[msgType, msgId] = reSendRequest.exec(msg).slice(1)
} else if (msgKind === 'recv-request') {
;[msgType, msgId] = reRecvRequest.exec(msg).slice(1)
} else if (msgKind === 'send-response') {
;[msgType, msgId, msgLatency] = reSendResponse.exec(msg).slice(1)
} else if (msgKind === 'recv-response') {
;[msgType, msgId, msgLatency] = reRecvResponse.exec(msg).slice(1)
} else {
return null
}
return {
msgKind,
msgType,
msgId,
msgLatency
}
}
function isCRLF(input: string) {
const matches = input.match(/\r\n/)
return matches && matches.length > 0
}

28226
src/lsp.json Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

18
src/main.ts Normal file
Просмотреть файл

@ -0,0 +1,18 @@
import Vue from 'vue'
import App from './App.vue'
import router from '@/router'
import store from '@/store'
Vue.config.productionTip = false
import fontawesome from '@fortawesome/fontawesome'
import faComment from '@fortawesome/fontawesome-free-solid/faComment'
import faCommentAlt from '@fortawesome/fontawesome-free-solid/faCommentAlt'
fontawesome.library.add(faComment, faCommentAlt)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

22
src/router.ts Normal file
Просмотреть файл

@ -0,0 +1,22 @@
import Vue from 'vue'
import Router from 'vue-router'
import Inspector from './views/Inspector.vue'
import Usage from './views/Usage.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/language-server-protocol/inspector/',
name: 'Home',
component: Usage
},
{
path: '/language-server-protocol/inspector/app',
name: 'Home',
component: Inspector
}
],
mode: 'history'
})

13
src/shims-tsx.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any
}
}
}

4
src/shims-vue.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}

88
src/store.ts Normal file
Просмотреть файл

@ -0,0 +1,88 @@
import Vue from 'vue'
import Vuex from 'vuex'
import { parseLSPLog, LspItem } from '@/logParser/rawLogParser'
Vue.use(Vuex)
export type Filter =
| 'a' // All
| 'w' // Workspace
| 't' // Text
| 'd' // Diagnostics
| 'l' // Language
export interface State {
items: LspItem[]
query: string
filter: Filter
current: number
}
let items: LspItem[] = require('./lsp.json')
const defaultState: State = {
items,
query: '',
filter: 'a',
current: -1
}
export default new Vuex.Store({
state: defaultState,
mutations: {
updateLog(state, rawLog: string) {
const parsedLog = parseLSPLog(rawLog)
items = parsedLog
state.items = parseLSPLog(rawLog)
},
search(state, query: string) {
state.query = query
state.items = items.filter(item => {
return itemShouldShow(item, state)
})
},
updateFilter(state, filter) {
state.filter = filter
state.items = items.filter(item => {
return itemShouldShow(item, state)
})
},
updateCurrent(state, current) {
state.current = current
}
},
actions: {}
})
function itemShouldShow(item: LspItem, state: State) {
return itemMatchesQuery(item, state.query) && itemMatchesFilter(item, state.filter)
}
function itemMatchesQuery(item: LspItem, query: string) {
return item.msgType.toLowerCase().includes(query.toLowerCase())
}
function itemMatchesFilter(item: LspItem, filter: Filter) {
const textSyncMsgTypes = [
'textDocument/didOpen',
'textDocument/didChange',
'textDocument/willSave',
'textDocument/willSaveWaitUntil',
'textDocument/didSave',
'textDocument/didClose'
]
switch (filter) {
case 'a':
return true
case 'w':
return item.msgType.startsWith('workspace')
case 't':
return textSyncMsgTypes.indexOf(item.msgType) !== -1
case 'd':
return item.msgType === 'textDocument/publishDiagnostics'
case 'l':
return (
item.msgType.startsWith('textDocument') && textSyncMsgTypes.indexOf(item.msgType) === -1
)
}
}

34
src/views/Inspector.vue Normal file
Просмотреть файл

@ -0,0 +1,34 @@
<template>
<div class="inspector">
<file-picker></file-picker>
<filter-bar></filter-bar>
<search-bar></search-bar>
<message-list></message-list>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Intro from '@/components/Intro.vue'
import FilePicker from '@/components/FilePicker.vue'
import FilterBar from '@/components/FilterBar.vue'
import SearchBar from '@/components/SearchBar.vue'
import MessageList from '@/components/MessageList.vue'
export default Vue.extend({
name: 'inspector',
components: {
Intro,
FilePicker,
MessageList,
FilterBar,
SearchBar
}
})
</script>
<style>
.inspector {
margin-bottom: 60px;
}
</style>

16
src/views/Usage.vue Normal file
Просмотреть файл

@ -0,0 +1,16 @@
<template>
<div class="usage">
<intro />
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Intro from '@/components/Intro.vue'
export default Vue.extend({
components: {
Intro
}
})
</script>

Просмотреть файл

@ -0,0 +1,11 @@
// https://docs.cypress.io/guides/guides/plugins-guide.html
module.exports = (on, config) => {
return Object.assign({}, config, {
fixturesFolder: 'tests/e2e/fixtures',
integrationFolder: 'tests/e2e/specs',
screenshotsFolder: 'tests/e2e/screenshots',
videosFolder: 'tests/e2e/videos',
supportFile: 'tests/e2e/support/index.js'
})
}

8
tests/e2e/specs/test.js Normal file
Просмотреть файл

@ -0,0 +1,8 @@
// https://docs.cypress.io/api/introduction/api.html
describe('My First Test', () => {
it('Visits the app root url', () => {
cy.visit('/')
cy.contains('h1', 'LSP Inspector')
})
})

Просмотреть файл

@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

Просмотреть файл

@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

Просмотреть файл

@ -0,0 +1,372 @@
[
{
"time": "4:21:27 PM",
"msg": "Sending request 'initialize - (0)'.",
"msgKind": "send-request",
"msgType": "initialize",
"msgId": "0",
"arg": {
"processId": 19892,
"rootPath": "c:\\Users\\egamma\\projects\\vscode-tslint\\tslint-tests",
"rootUri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests",
"capabilities": {
"workspace": {
"applyEdit": true,
"workspaceEdit": {
"documentChanges": true
},
"didChangeConfiguration": {
"dynamicRegistration": true
},
"didChangeWatchedFiles": {
"dynamicRegistration": true
},
"symbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"executeCommand": {
"dynamicRegistration": true
},
"configuration": true,
"workspaceFolders": true
},
"textDocument": {
"publishDiagnostics": {
"relatedInformation": true
},
"synchronization": {
"dynamicRegistration": true,
"willSave": true,
"willSaveWaitUntil": true,
"didSave": true
},
"completion": {
"dynamicRegistration": true,
"contextSupport": true,
"completionItem": {
"snippetSupport": true,
"commitCharactersSupport": true,
"documentationFormat": ["markdown", "plaintext"],
"deprecatedSupport": true
},
"completionItemKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25
]
}
},
"hover": {
"dynamicRegistration": true,
"contentFormat": ["markdown", "plaintext"]
},
"signatureHelp": {
"dynamicRegistration": true,
"signatureInformation": {
"documentationFormat": ["markdown", "plaintext"]
}
},
"definition": {
"dynamicRegistration": true
},
"references": {
"dynamicRegistration": true
},
"documentHighlight": {
"dynamicRegistration": true
},
"documentSymbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"codeAction": {
"dynamicRegistration": true
},
"codeLens": {
"dynamicRegistration": true
},
"formatting": {
"dynamicRegistration": true
},
"rangeFormatting": {
"dynamicRegistration": true
},
"onTypeFormatting": {
"dynamicRegistration": true
},
"rename": {
"dynamicRegistration": true
},
"documentLink": {
"dynamicRegistration": true
},
"typeDefinition": {
"dynamicRegistration": true
},
"implementation": {
"dynamicRegistration": true
},
"colorProvider": {
"dynamicRegistration": true
}
}
},
"trace": "verbose",
"workspaceFolders": [
{
"uri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests",
"name": "tslint-tests"
}
]
}
},
{
"time": "4:21:28 PM",
"msg": "Received response 'initialize - (0)' in 673ms.",
"msgKind": "recv-response",
"msgType": "initialize",
"msgId": "0",
"msgLatency": "673ms",
"arg": {
"capabilities": {
"textDocumentSync": 1,
"codeActionProvider": true
}
}
},
{
"time": "4:21:28 PM",
"msg": "Sending notification 'initialized'.",
"msgKind": "send-notification",
"msgType": "initialized",
"arg": {}
},
{
"time": "4:21:28 PM",
"msg": "Sending notification 'workspace/didChangeConfiguration'.",
"msgKind": "send-notification",
"msgType": "workspace/didChangeConfiguration",
"arg": {
"settings": {
"tslint": {
"enable": true,
"jsEnable": false,
"rulesDirectory": "",
"validateWithDefaultConfig": false,
"configFile": "",
"ignoreDefinitionFiles": true,
"exclude": "",
"run": "onType",
"nodePath": "",
"autoFixOnSave": false,
"alwaysShowRuleFailuresAsWarnings": false,
"alwaysShowStatus": false,
"trace": {
"server": "verbose"
},
"packageManager": "npm"
}
}
}
},
{
"time": "4:21:28 PM",
"msg": "Sending notification 'textDocument/didOpen'.",
"msgKind": "send-notification",
"msgType": "textDocument/didOpen",
"arg": {
"textDocument": {
"uri":
"file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts",
"languageId": "typescript",
"version": 1,
"text":
"// VS Code provided fix\n// import { hello } from \"./array-type\";\n\n//start with space\n"
}
}
},
{
"time": "4:21:28 PM",
"msg": "Received request 'workspace/configuration - (0)'.",
"msgKind": "recv-request",
"msgType": "workspace/configuration",
"msgId": "0",
"arg": {
"items": [
{
"scopeUri":
"file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts",
"section": "tslint"
}
]
}
},
{
"time": "4:21:28 PM",
"msg": "Sending response 'workspace/configuration - (0)'. Processing request took 6ms",
"msgKind": "send-response",
"msgType": "workspace/configuration",
"msgId": "0",
"msgLatency": "6ms",
"arg": [
{
"enable": true,
"jsEnable": false,
"rulesDirectory": "",
"validateWithDefaultConfig": false,
"configFile": "",
"ignoreDefinitionFiles": true,
"exclude": "",
"run": "onType",
"nodePath": "",
"autoFixOnSave": false,
"alwaysShowRuleFailuresAsWarnings": false,
"alwaysShowStatus": false,
"trace": {
"server": "verbose"
},
"packageManager": "npm",
"workspaceFolderPath": "c:\\Users\\egamma\\projects\\vscode-tslint\\tslint-tests"
}
]
},
{
"time": "4:21:31 PM",
"msg": "Received notification 'window/logMessage'.",
"msgKind": "recv-notification",
"msgType": "window/logMessage",
"arg": {
"type": 3,
"message":
"TSLint library loaded from: c:\\Users\\egamma\\projects\\vscode-tslint\\tslint-tests\\node_modules\\tslint\\lib\\index.js"
}
},
{
"time": "4:21:31 PM",
"msg": "Received notification 'tslint/status'.",
"msgKind": "recv-notification",
"msgType": "tslint/status",
"arg": {
"state": 1
}
},
{
"time": "4:21:31 PM",
"msg": "Received notification 'tslint/status'.",
"msgKind": "recv-notification",
"msgType": "tslint/status",
"arg": {
"state": 2
}
},
{
"time": "4:21:31 PM",
"msg": "Received notification 'textDocument/publishDiagnostics'.",
"msgKind": "recv-notification",
"msgType": "textDocument/publishDiagnostics",
"arg": {
"uri":
"file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts",
"diagnostics": [
{
"severity": 2,
"message": "comment must start with a space (comment-format)",
"range": {
"start": {
"line": 3,
"character": 2
},
"end": {
"line": 3,
"character": 18
}
},
"code": "comment-format",
"source": "tslint"
}
]
}
}
]

Просмотреть файл

@ -0,0 +1,417 @@
[Trace - 4:21:27 PM] Sending request 'initialize - (0)'.
Params: {
"processId": 19892,
"rootPath": "c:\\Users\\egamma\\projects\\vscode-tslint\\tslint-tests",
"rootUri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests",
"capabilities": {
"workspace": {
"applyEdit": true,
"workspaceEdit": {
"documentChanges": true
},
"didChangeConfiguration": {
"dynamicRegistration": true
},
"didChangeWatchedFiles": {
"dynamicRegistration": true
},
"symbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"executeCommand": {
"dynamicRegistration": true
},
"configuration": true,
"workspaceFolders": true
},
"textDocument": {
"publishDiagnostics": {
"relatedInformation": true
},
"synchronization": {
"dynamicRegistration": true,
"willSave": true,
"willSaveWaitUntil": true,
"didSave": true
},
"completion": {
"dynamicRegistration": true,
"contextSupport": true,
"completionItem": {
"snippetSupport": true,
"commitCharactersSupport": true,
"documentationFormat": [
"markdown",
"plaintext"
],
"deprecatedSupport": true
},
"completionItemKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25
]
}
},
"hover": {
"dynamicRegistration": true,
"contentFormat": [
"markdown",
"plaintext"
]
},
"signatureHelp": {
"dynamicRegistration": true,
"signatureInformation": {
"documentationFormat": [
"markdown",
"plaintext"
]
}
},
"definition": {
"dynamicRegistration": true
},
"references": {
"dynamicRegistration": true
},
"documentHighlight": {
"dynamicRegistration": true
},
"documentSymbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"codeAction": {
"dynamicRegistration": true
},
"codeLens": {
"dynamicRegistration": true
},
"formatting": {
"dynamicRegistration": true
},
"rangeFormatting": {
"dynamicRegistration": true
},
"onTypeFormatting": {
"dynamicRegistration": true
},
"rename": {
"dynamicRegistration": true
},
"documentLink": {
"dynamicRegistration": true
},
"typeDefinition": {
"dynamicRegistration": true
},
"implementation": {
"dynamicRegistration": true
},
"colorProvider": {
"dynamicRegistration": true
}
}
},
"trace": "verbose",
"workspaceFolders": [
{
"uri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests",
"name": "tslint-tests"
}
]
}
Debugger listening on ws://127.0.0.1:6010/0956172b-cae0-49f0-9e99-af55cc1f5043
For help see https://nodejs.org/en/docs/inspector
[Trace - 4:21:28 PM] Received response 'initialize - (0)' in 673ms.
Result: {
"capabilities": {
"textDocumentSync": 1,
"codeActionProvider": true
}
}
[Info - 4:21:28 PM] Linter is running.
[Trace - 4:21:28 PM] Sending notification 'initialized'.
Params: {}
[Trace - 4:21:28 PM] Sending notification 'workspace/didChangeConfiguration'.
Params: {
"settings": {
"tslint": {
"enable": true,
"jsEnable": false,
"rulesDirectory": "",
"validateWithDefaultConfig": false,
"configFile": "",
"ignoreDefinitionFiles": true,
"exclude": "",
"run": "onType",
"nodePath": "",
"autoFixOnSave": false,
"alwaysShowRuleFailuresAsWarnings": false,
"alwaysShowStatus": false,
"trace": {
"server": "verbose"
},
"packageManager": "npm"
}
}
}
[Trace - 4:21:28 PM] Sending notification 'textDocument/didOpen'.
Params: {
"textDocument": {
"uri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts",
"languageId": "typescript",
"version": 1,
"text": "// VS Code provided fix\n// import { hello } from \"./array-type\";\n\n//start with space\n"
}
}
[Trace - 4:21:28 PM] onDidChangeConfiguraton
[Trace - 4:21:28 PM] validateAllTextDocuments
[Trace - 4:21:28 PM] onDidOpen
[Trace - 4:21:28 PM] triggerValidation on file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:28 PM] onDidChangeContent
[Trace - 4:21:28 PM] SettingsCache: cache updating cache forfile:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:28 PM] Received request 'workspace/configuration - (0)'.
Params: {
"items": [
{
"scopeUri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts",
"section": "tslint"
}
]
}
[Trace - 4:21:28 PM] Sending response 'workspace/configuration - (0)'. Processing request took 6ms
Result: [
{
"enable": true,
"jsEnable": false,
"rulesDirectory": "",
"validateWithDefaultConfig": false,
"configFile": "",
"ignoreDefinitionFiles": true,
"exclude": "",
"run": "onType",
"nodePath": "",
"autoFixOnSave": false,
"alwaysShowRuleFailuresAsWarnings": false,
"alwaysShowStatus": false,
"trace": {
"server": "verbose"
},
"packageManager": "npm",
"workspaceFolderPath": "c:\\Users\\egamma\\projects\\vscode-tslint\\tslint-tests"
}
]
[Trace - 4:21:28 PM] onDidChangeContent: settings[object Object]
[Trace - 4:21:28 PM] onDidChangeContent: triggerValidateDocument
[Trace - 4:21:28 PM] triggerValidation on file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:28 PM] trigger validateTextDocument
[Trace - 4:21:28 PM] start validateTextDocument
[Trace - 4:21:28 PM] SettingsCache: cache hit for file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:28 PM] validateTextDocument: settings fetched
[Trace - 4:21:28 PM] validateTextDocument: about to load tslint library
[Trace - 4:21:28 PM] loadLibrary for file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:28 PM] SettingsCache: cache hit for file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:28 PM] validateTextDocument: loaded tslint library
Warning: The 'no-unused-variable' rule requires type information.
[Trace - 4:21:31 PM] Received notification 'window/logMessage'.
Params: {
"type": 3,
"message": "TSLint library loaded from: c:\\Users\\egamma\\projects\\vscode-tslint\\tslint-tests\\node_modules\\tslint\\lib\\index.js"
}
[Info - 4:21:31 PM] TSLint library loaded from: c:\Users\egamma\projects\vscode-tslint\tslint-tests\node_modules\tslint\lib\index.js
[Trace - 4:21:31 PM] validateTextDocument: about to validate file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:31 PM] Received notification 'tslint/status'.
Params: {
"state": 1
}
[Trace - 4:21:31 PM] start doValidate file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:31 PM] SettingsCache: cache hit for file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:31 PM] Changed directory to c:\Users\egamma\projects\vscode-tslint\tslint-tests
[Trace - 4:21:31 PM] validateTextDocument: about to getConfiguration
[Trace - 4:21:31 PM] getConfiguration forfile:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts
[Trace - 4:21:31 PM] validateTextDocument: configuration fetched
[Trace - 4:21:31 PM] tslint configuration:
{ extends: [],
jsRules:
Map {
'triple-equals' => { ruleArguments: [ 'allow-null-check' ],
ruleSeverity: 'warning' } },
linterOptions: {},
rules:
Map {
'no-consecutive-blank-lines' => { ruleArguments: [], ruleSeverity: 'warning' },
'array-type' => { ruleArguments: [ 'array-simple' ], ruleSeverity: 'warning' },
'arrow-parens' => { ruleArguments: [], ruleSeverity: 'warning' },
'no-var-keyword' => { ruleArguments: [], ruleSeverity: 'warning' },
'no-unused-variable' => { ruleArguments: [ { 'ignore-pattern': '^_' } ],
ruleSeverity: 'warning' },
'ordered-imports' => { ruleArguments:
[ { 'import-sources-order': 'lowercase-last',
'named-imports-order': 'lowercase-first' } ],
ruleSeverity: 'warning' },
'trailing-comma' => { ruleArguments: [ { multiline: 'always', singleline: 'never' } ],
ruleSeverity: 'warning' },
'class-name' => { ruleArguments: [], ruleSeverity: 'warning' },
'comment-format' => { ruleArguments: [ 'check-space' ], ruleSeverity: 'warning' },
'indent' => { ruleArguments: [ 'spaces' ], ruleSeverity: 'warning' },
'no-eval' => { ruleArguments: [], ruleSeverity: 'warning' },
'no-internal-module' => { ruleArguments: [], ruleSeverity: 'warning' },
'no-trailing-whitespace' => { ruleArguments: [], ruleSeverity: 'warning' },
'no-unsafe-finally' => { ruleArguments: [], ruleSeverity: 'warning' },
'one-line' => { ruleArguments: [ 'check-open-brace', 'check-whitespace' ],
ruleSeverity: 'warning' },
'quotemark' => { ruleArguments: [ 'double' ], ruleSeverity: 'warning' },
'semicolon' => { ruleArguments: [ 'always' ], ruleSeverity: 'warning' },
'triple-equals' => { ruleArguments: [ 'allow-null-check' ],
ruleSeverity: 'warning' },
'typedef-whitespace' => { ruleArguments:
[ { 'call-signature': 'nospace',
'index-signature': 'nospace',
parameter: 'nospace',
'property-declaration': 'nospace',
'variable-declaration': 'nospace' } ],
ruleSeverity: 'warning' },
'variable-name' => { ruleArguments: [ 'ban-keywords' ], ruleSeverity: 'warning' },
'whitespace' => { ruleArguments:
[ 'check-branch',
'check-decl',
'check-operator',
'check-separator',
'check-type' ],
ruleSeverity: 'warning' } },
rulesDirectory: [] }
[Trace - 4:21:31 PM] Linting: start linting with tslint > version 4
[Trace - 4:21:31 PM] Received notification 'tslint/status'.
Params: {
"state": 2
}
[Trace - 4:21:31 PM] Linting: ended linting
[Trace - 4:21:31 PM] doValidate: sending diagnostics: 1
[Trace - 4:21:31 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///c%3A/Users/egamma/projects/vscode-tslint/tslint-tests/tests/comment-format.ts",
"diagnostics": [
{
"severity": 2,
"message": "comment must start with a space (comment-format)",
"range": {
"start": {
"line": 3,
"character": 2
},
"end": {
"line": 3,
"character": 18
}
},
"code": "comment-format",
"source": "tslint"
}
]
}

Просмотреть файл

@ -0,0 +1,22 @@
[
{
"time": "15:31:35",
"msg": "Received notification 'loadingBar'.",
"msgKind": "recv-notification",
"msgType": "loadingBar",
"arg": {
"value": "Loading project...",
"enable": true
}
},
{
"time": "15:31:35",
"msg": "Received notification 'loadingBar'.",
"msgKind": "recv-notification",
"msgType": "loadingBar",
"arg": {
"value": "",
"enable": false
}
}
]

Просмотреть файл

@ -0,0 +1,14 @@
[Trace - 15:31:35] Received notification 'loadingBar'.
Params: {
"value": "Loading project...",
"enable": true
}
[Trace - 15:31:35] Received notification 'loadingBar'.
Params: {
"value": "",
"enable": false
}

Просмотреть файл

@ -0,0 +1,254 @@
[
{
"time": "18:47:28",
"msg": "Sending request 'initialize - (0)'.",
"msgKind": "send-request",
"msgType": "initialize",
"msgId": "0",
"arg": {
"processId": 35928,
"rootPath": "/Users/pine/Code/work/lsp-inspector/inspector",
"rootUri": "file:///Users/pine/Code/work/lsp-inspector/inspector",
"capabilities": {
"workspace": {
"applyEdit": true,
"workspaceEdit": {
"documentChanges": true
},
"didChangeConfiguration": {
"dynamicRegistration": true
},
"didChangeWatchedFiles": {
"dynamicRegistration": true
},
"symbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"executeCommand": {
"dynamicRegistration": true
},
"configuration": true,
"workspaceFolders": true
},
"textDocument": {
"publishDiagnostics": {
"relatedInformation": true
},
"synchronization": {
"dynamicRegistration": true,
"willSave": true,
"willSaveWaitUntil": true,
"didSave": true
},
"completion": {
"dynamicRegistration": true,
"contextSupport": true,
"completionItem": {
"snippetSupport": true,
"commitCharactersSupport": true,
"documentationFormat": ["markdown", "plaintext"],
"deprecatedSupport": true
},
"completionItemKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25
]
}
},
"hover": {
"dynamicRegistration": true,
"contentFormat": ["markdown", "plaintext"]
},
"signatureHelp": {
"dynamicRegistration": true,
"signatureInformation": {
"documentationFormat": ["markdown", "plaintext"]
}
},
"definition": {
"dynamicRegistration": true
},
"references": {
"dynamicRegistration": true
},
"documentHighlight": {
"dynamicRegistration": true
},
"documentSymbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"codeAction": {
"dynamicRegistration": true
},
"codeLens": {
"dynamicRegistration": true
},
"formatting": {
"dynamicRegistration": true
},
"rangeFormatting": {
"dynamicRegistration": true
},
"onTypeFormatting": {
"dynamicRegistration": true
},
"rename": {
"dynamicRegistration": true
},
"documentLink": {
"dynamicRegistration": true
},
"typeDefinition": {
"dynamicRegistration": true
},
"implementation": {
"dynamicRegistration": true
},
"colorProvider": {
"dynamicRegistration": true
},
"foldingRange": {
"dynamicRegistration": false,
"rangeLimit": 5000,
"lineFoldingOnly": true
}
}
},
"initializationOptions": {
"embeddedLanguages": {
"css": true,
"javascript": true
}
},
"trace": "verbose",
"workspaceFolders": [
{
"uri": "file:///Users/pine/Code/work/lsp-inspector/inspector",
"name": "inspector"
}
]
}
},
{
"time": "18:47:29",
"msg": "Received response 'initialize - (0)' in 510ms.",
"msgKind": "recv-response",
"msgType": "initialize",
"msgId": "0",
"msgLatency": "510ms",
"arg": {
"capabilities": {
"textDocumentSync": 1,
"completionProvider": {
"resolveProvider": true,
"triggerCharacters": [".", ":", "<", "\"", "=", "/"]
},
"hoverProvider": true,
"documentHighlightProvider": true,
"documentRangeFormattingProvider": false,
"documentLinkProvider": {
"resolveProvider": false
},
"documentSymbolProvider": true,
"definitionProvider": true,
"signatureHelpProvider": {
"triggerCharacters": ["("]
},
"referencesProvider": true,
"colorProvider": {},
"foldingRangeProvider": true
}
}
},
{
"time": "18:47:29",
"msg": "Sending notification 'initialized'.",
"msgKind": "send-notification",
"msgType": "initialized",
"arg": {}
}
]

Просмотреть файл

@ -0,0 +1,256 @@
[Trace - 18:47:28] Sending request 'initialize - (0)'.
Params: {
"processId": 35928,
"rootPath": "/Users/pine/Code/work/lsp-inspector/inspector",
"rootUri": "file:///Users/pine/Code/work/lsp-inspector/inspector",
"capabilities": {
"workspace": {
"applyEdit": true,
"workspaceEdit": {
"documentChanges": true
},
"didChangeConfiguration": {
"dynamicRegistration": true
},
"didChangeWatchedFiles": {
"dynamicRegistration": true
},
"symbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"executeCommand": {
"dynamicRegistration": true
},
"configuration": true,
"workspaceFolders": true
},
"textDocument": {
"publishDiagnostics": {
"relatedInformation": true
},
"synchronization": {
"dynamicRegistration": true,
"willSave": true,
"willSaveWaitUntil": true,
"didSave": true
},
"completion": {
"dynamicRegistration": true,
"contextSupport": true,
"completionItem": {
"snippetSupport": true,
"commitCharactersSupport": true,
"documentationFormat": [
"markdown",
"plaintext"
],
"deprecatedSupport": true
},
"completionItemKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25
]
}
},
"hover": {
"dynamicRegistration": true,
"contentFormat": [
"markdown",
"plaintext"
]
},
"signatureHelp": {
"dynamicRegistration": true,
"signatureInformation": {
"documentationFormat": [
"markdown",
"plaintext"
]
}
},
"definition": {
"dynamicRegistration": true
},
"references": {
"dynamicRegistration": true
},
"documentHighlight": {
"dynamicRegistration": true
},
"documentSymbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
]
}
},
"codeAction": {
"dynamicRegistration": true
},
"codeLens": {
"dynamicRegistration": true
},
"formatting": {
"dynamicRegistration": true
},
"rangeFormatting": {
"dynamicRegistration": true
},
"onTypeFormatting": {
"dynamicRegistration": true
},
"rename": {
"dynamicRegistration": true
},
"documentLink": {
"dynamicRegistration": true
},
"typeDefinition": {
"dynamicRegistration": true
},
"implementation": {
"dynamicRegistration": true
},
"colorProvider": {
"dynamicRegistration": true
},
"foldingRange": {
"dynamicRegistration": false,
"rangeLimit": 5000,
"lineFoldingOnly": true
}
}
},
"initializationOptions": {
"embeddedLanguages": {
"css": true,
"javascript": true
}
},
"trace": "verbose",
"workspaceFolders": [
{
"uri": "file:///Users/pine/Code/work/lsp-inspector/inspector",
"name": "inspector"
}
]
}
[Trace - 18:47:29] Received response 'initialize - (0)' in 510ms.
Result: {
"capabilities": {
"textDocumentSync": 1,
"completionProvider": {
"resolveProvider": true,
"triggerCharacters": [
".",
":",
"<",
"\"",
"=",
"/"
]
},
"hoverProvider": true,
"documentHighlightProvider": true,
"documentRangeFormattingProvider": false,
"documentLinkProvider": {
"resolveProvider": false
},
"documentSymbolProvider": true,
"definitionProvider": true,
"signatureHelpProvider": {
"triggerCharacters": [
"("
]
},
"referencesProvider": true,
"colorProvider": {},
"foldingRangeProvider": true
}
}
[Trace - 18:47:29] Sending notification 'initialized'.
Params: {}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,25 @@
import * as fs from 'fs-extra'
import * as path from 'path'
import { parseLSPLog } from '@/logParser/rawLogParser'
describe('HelloWorld', () => {
it('parses raw log fine', async () => {
await testFixture('helloworld')
await testFixture('html')
await testFixture('10-tslint-dirty-trace')
await testFixture('11-crlf')
})
})
async function testFixture(fixtureName: string) {
const log = await fs.readFile(path.resolve(__dirname, `fixture/${fixtureName}.log`), 'utf-8')
const expectedJson = await fs.readFile(
path.resolve(__dirname, `fixture/${fixtureName}.json`),
'utf-8'
)
const expected = JSON.parse(expectedJson)
const actual = parseLSPLog(log)
expect(actual).toEqual(expected)
}

39
tsconfig.json Normal file
Просмотреть файл

@ -0,0 +1,39 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"strict": false,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"node",
"jest"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"es2015",
"dom",
"dom.iterable",
"scripthost",
"es2016.array.include"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

22
tslint.json Normal file
Просмотреть файл

@ -0,0 +1,22 @@
{
"defaultSeverity": "warning",
"extends": [
"tslint:recommended"
],
"linterOptions": {
"exclude": [
"node_modules/**"
]
},
"rules": {
"quotemark": [true, "single"],
"indent": [true, "spaces", 2],
"interface-name": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"no-consecutive-blank-lines": false,
"semicolon": false,
"trailing-comma": false,
}
}

4
vue.config.js Normal file
Просмотреть файл

@ -0,0 +1,4 @@
module.exports = {
lintOnSave: false,
baseUrl: '/language-server-protocol/inspector'
}

8057
yarn.lock Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу