linear-ls 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.js +98 -34
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -9,6 +9,41 @@ const teams = new Map();
|
|
|
9
9
|
const issues = new Map();
|
|
10
10
|
const positions = new Map();
|
|
11
11
|
let client;
|
|
12
|
+
async function diagnostics(textDocument) {
|
|
13
|
+
if (!client) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const docPositions = positions.get(textDocument.uri);
|
|
17
|
+
if (!docPositions) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const diagnostics = [];
|
|
21
|
+
for (const p of docPositions) {
|
|
22
|
+
let issue = issues.get(p.issueKey);
|
|
23
|
+
if (!issue) {
|
|
24
|
+
issue = await client.issue(p.issueKey).catch(() => undefined);
|
|
25
|
+
if (issue)
|
|
26
|
+
issues.set(p.issueKey, issue);
|
|
27
|
+
}
|
|
28
|
+
if (issue?.completedAt) {
|
|
29
|
+
diagnostics.push({
|
|
30
|
+
severity: node_1.DiagnosticSeverity.Information,
|
|
31
|
+
range: { start: p.positionStart, end: p.positionEnd },
|
|
32
|
+
message: `${p.issueKey} is completed`,
|
|
33
|
+
source: "Linear",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
else if (issue?.archivedAt) {
|
|
37
|
+
diagnostics.push({
|
|
38
|
+
severity: node_1.DiagnosticSeverity.Information,
|
|
39
|
+
range: { start: p.positionStart, end: p.positionEnd },
|
|
40
|
+
message: `${p.issueKey} is archived`,
|
|
41
|
+
source: "Linear",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
conn.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
|
46
|
+
}
|
|
12
47
|
conn.onInitialize(async () => {
|
|
13
48
|
const apiKey = process.env.LINEAR_API_KEY;
|
|
14
49
|
if (!apiKey) {
|
|
@@ -26,7 +61,7 @@ conn.onInitialize(async () => {
|
|
|
26
61
|
textDocumentSync: node_1.TextDocumentSyncKind.Incremental,
|
|
27
62
|
codeActionProvider: {},
|
|
28
63
|
executeCommandProvider: {
|
|
29
|
-
commands: ["linear-ls.
|
|
64
|
+
commands: ["linear-ls.createIssue", "linear-ls.openIssue"],
|
|
30
65
|
},
|
|
31
66
|
hoverProvider: {},
|
|
32
67
|
completionProvider: { resolveProvider: true },
|
|
@@ -40,29 +75,59 @@ conn.onInitialize(async () => {
|
|
|
40
75
|
},
|
|
41
76
|
};
|
|
42
77
|
});
|
|
43
|
-
conn.onCodeAction((params) => {
|
|
78
|
+
conn.onCodeAction(async (params) => {
|
|
79
|
+
const actions = [];
|
|
44
80
|
if (params.context.triggerKind === node_1.CodeActionTriggerKind.Invoked) {
|
|
45
|
-
const
|
|
46
|
-
if (
|
|
47
|
-
|
|
81
|
+
const doc = docs.get(params.textDocument.uri);
|
|
82
|
+
if (doc) {
|
|
83
|
+
const text = doc.getText(params.range);
|
|
84
|
+
if (text) {
|
|
85
|
+
actions.push({
|
|
86
|
+
title: "Create Issue from Selection",
|
|
87
|
+
kind: node_1.CodeActionKind.RefactorRewrite,
|
|
88
|
+
command: {
|
|
89
|
+
command: "linear-ls.createIssue",
|
|
90
|
+
title: "Create Issue",
|
|
91
|
+
arguments: [params.textDocument.uri, params.range, text.trim()],
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
48
95
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
}
|
|
97
|
+
const docPositions = positions.get(params.textDocument.uri);
|
|
98
|
+
for (const p of docPositions ?? []) {
|
|
99
|
+
if (p.positionStart.line === params.range.start.line) {
|
|
100
|
+
if (params.range.start.character >= p.positionStart.character &&
|
|
101
|
+
params.range.start.character <= p.positionEnd.character) {
|
|
102
|
+
let issue = issues.get(p.issueKey);
|
|
103
|
+
if (!issue) {
|
|
104
|
+
issue = await client.issue(p.issueKey).catch(() => undefined);
|
|
105
|
+
if (issue)
|
|
106
|
+
issues.set(p.issueKey, issue);
|
|
107
|
+
}
|
|
108
|
+
if (issue?.url) {
|
|
109
|
+
actions.push({
|
|
110
|
+
title: `Open ${p.issueKey} in Linear`,
|
|
111
|
+
kind: node_1.CodeActionKind.Empty,
|
|
112
|
+
command: {
|
|
113
|
+
command: "linear-ls.openIssue",
|
|
114
|
+
title: "Open in Linear",
|
|
115
|
+
arguments: [issue.url],
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
52
120
|
}
|
|
53
|
-
const action = {
|
|
54
|
-
title: "Create Ticket from Selection",
|
|
55
|
-
kind: node_1.CodeActionKind.RefactorRewrite,
|
|
56
|
-
command: {
|
|
57
|
-
command: "linear-ls.createTicket",
|
|
58
|
-
title: "Create Ticket",
|
|
59
|
-
arguments: [params.textDocument.uri, params.range, text.trim()],
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
return [action];
|
|
63
121
|
}
|
|
122
|
+
return actions;
|
|
64
123
|
});
|
|
65
124
|
conn.onExecuteCommand(async (params) => {
|
|
125
|
+
if (params.command === "linear-ls.openIssue") {
|
|
126
|
+
const [url] = params.arguments || [];
|
|
127
|
+
if (url) {
|
|
128
|
+
conn.window.showDocument({ uri: url, external: true });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
66
131
|
if (params.command === "linear-ls.createTicket") {
|
|
67
132
|
const [uri, range, title] = params.arguments || [];
|
|
68
133
|
if (!uri || !range || !title) {
|
|
@@ -117,7 +182,7 @@ conn.onExecuteCommand(async (params) => {
|
|
|
117
182
|
let documentChangeTimeout;
|
|
118
183
|
docs.onDidChangeContent((change) => {
|
|
119
184
|
clearTimeout(documentChangeTimeout);
|
|
120
|
-
documentChangeTimeout = setTimeout(() => {
|
|
185
|
+
documentChangeTimeout = setTimeout(async () => {
|
|
121
186
|
const text = change.document.getText();
|
|
122
187
|
const documentPositions = [];
|
|
123
188
|
const teamKeys = Array.from(teams.keys());
|
|
@@ -144,33 +209,32 @@ docs.onDidChangeContent((change) => {
|
|
|
144
209
|
});
|
|
145
210
|
});
|
|
146
211
|
positions.set(change.document.uri, documentPositions);
|
|
147
|
-
|
|
212
|
+
await diagnostics(change.document);
|
|
213
|
+
}, 1000);
|
|
148
214
|
});
|
|
149
215
|
conn.onHover(async (params) => {
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
216
|
+
const docPositions = positions.get(params.textDocument.uri);
|
|
217
|
+
if (!docPositions) {
|
|
152
218
|
return;
|
|
153
219
|
}
|
|
154
|
-
const
|
|
155
|
-
if (!
|
|
220
|
+
const doc = docs.get(params.textDocument.uri);
|
|
221
|
+
if (!doc) {
|
|
156
222
|
return;
|
|
157
223
|
}
|
|
158
|
-
const cursorOffset =
|
|
159
|
-
const
|
|
160
|
-
if (!
|
|
224
|
+
const cursorOffset = doc.offsetAt(params.position);
|
|
225
|
+
const pos = docPositions.find((dp) => dp.offsetStart <= cursorOffset && dp.offsetEnd > cursorOffset);
|
|
226
|
+
if (!pos) {
|
|
161
227
|
return;
|
|
162
228
|
}
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
229
|
+
let issue = issues.get(pos.issueKey);
|
|
230
|
+
if (!issue) {
|
|
231
|
+
issue = await client.issue(pos.issueKey).catch(() => undefined);
|
|
232
|
+
if (issue)
|
|
233
|
+
issues.set(pos.issueKey, issue);
|
|
168
234
|
}
|
|
169
|
-
const issue = await client.issue(targetIssue.issueKey);
|
|
170
235
|
if (!issue) {
|
|
171
236
|
return;
|
|
172
237
|
}
|
|
173
|
-
issues.set(targetIssue.issueKey, issue);
|
|
174
238
|
return {
|
|
175
239
|
contents: issue.description ?? "Not available",
|
|
176
240
|
};
|