firefly-compiler 0.6.24 → 0.6.30
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/.vscode/settings.json +1 -1
- package/compiler/Inference.ff +1 -17
- package/compiler/LspHook.ff +5 -15
- package/core/Ordering.ff +1 -1
- package/lsp/.firefly/package.ff +0 -1
- package/lsp/CompletionHandler.ff +6 -112
- package/lsp/Handler.ff +7 -205
- package/lsp/LanguageServer.ff +0 -5
- package/output/js/ff/compiler/Builder.mjs +2 -2
- package/output/js/ff/compiler/Builder.mjs.map +1 -1
- package/output/js/ff/compiler/Dependencies.mjs +2 -2
- package/output/js/ff/compiler/Dependencies.mjs.map +1 -1
- package/output/js/ff/compiler/Inference.mjs +16 -36
- package/output/js/ff/compiler/Inference.mjs.map +2 -4
- package/output/js/ff/compiler/LspHook.mjs +10 -10
- package/output/js/ff/compiler/LspHook.mjs.map +3 -4
- package/output/js/ff/compiler/Main.mjs +4 -4
- package/output/js/ff/compiler/Main.mjs.map +1 -1
- package/output/js/ff/core/Ordering.mjs +2 -2
- package/output/js/ff/core/Ordering.mjs.map +1 -1
- package/package.json +1 -1
- package/postgresql/Pg.ff +26 -49
- package/vscode/client/src/extension.ts +0 -5
- package/vscode/package.json +1 -7
- package/experimental/inceptron/Run.ff +0 -47
- package/experimental/mattis/Tree.ff +0 -44
- package/experimental/tests/TestListOrdering.ff +0 -7
- package/experimental/tests/TestOrder.ff +0 -4
- package/experimental/tests/TestSql.ff +0 -18
- package/lsp/SemanticTokenTypes.ff +0 -62
- package/lsp/Sql.ff +0 -1395
- package/lsp/SqlStatement.ff +0 -34
- package/lsp/SqlSuggestion.ff +0 -295
package/.vscode/settings.json
CHANGED
package/compiler/Inference.ff
CHANGED
|
@@ -819,28 +819,12 @@ extend self: Inference {
|
|
|
819
819
|
self.unification.unify(term.at, selfParameter.valueType, recordType)
|
|
820
820
|
let arguments = self.inferArguments(term.at, name, environment, signature.parameters.dropFirst(), e.arguments)
|
|
821
821
|
self.unification.affect(term.at, signature.effect, environment.effect)
|
|
822
|
-
|
|
822
|
+
e.ECall(
|
|
823
823
|
target = StaticCall(name, instanceCall = False, tailCall = tailCall)
|
|
824
824
|
typeArguments = instantiation.map {_.second}
|
|
825
825
|
arguments = [selfArgument, ...arguments]
|
|
826
826
|
effect = signature.effect
|
|
827
827
|
)
|
|
828
|
-
if(self.lspHook.sql) {
|
|
829
|
-
if(name == "ff:postgresql/Pg.PgConnection_statement") {
|
|
830
|
-
self.lspHook.sqlStrings.push(result)
|
|
831
|
-
} elseIf {name == "ff:postgresql/Pg.PgStatement_map"} {
|
|
832
|
-
self.lspHook.sqlStrings.push(result)
|
|
833
|
-
} elseIf {name == "ff:postgresql/Pg.PgStatement_each"} {
|
|
834
|
-
self.lspHook.sqlStrings.push(result)
|
|
835
|
-
} elseIf {name == "ff:postgresql/Pg.PgStatement_any"} {
|
|
836
|
-
self.lspHook.sqlStrings.push(result)
|
|
837
|
-
} elseIf {name == "ff:postgresql/Pg.PgStatement_all"} {
|
|
838
|
-
self.lspHook.sqlStrings.push(result)
|
|
839
|
-
} elseIf {name == "ff:postgresql/Pg.PgStatement_run"} {
|
|
840
|
-
self.lspHook.sqlStrings.push(result)
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
result
|
|
844
828
|
| _ => fail(term.at, "Call expected")
|
|
845
829
|
}
|
|
846
830
|
}
|
package/compiler/LspHook.ff
CHANGED
|
@@ -8,29 +8,19 @@ class LspHook(
|
|
|
8
8
|
insertIdentifier: Bool
|
|
9
9
|
trackSymbols: Bool
|
|
10
10
|
arrayOfResults: Array[ResultHook]
|
|
11
|
-
sql: Bool
|
|
12
|
-
sqlStrings: Array[Term]
|
|
13
11
|
)
|
|
14
12
|
|
|
15
|
-
disabled(
|
|
16
|
-
new(None, None, False, False
|
|
13
|
+
disabled(): LspHook {
|
|
14
|
+
new(None, None, False, False)
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
new(
|
|
20
|
-
at: Option[Location]
|
|
21
|
-
definedAt: Option[Location]
|
|
22
|
-
insertIdentifier: Bool
|
|
23
|
-
trackSymbols: Bool
|
|
24
|
-
sql: Bool = False
|
|
25
|
-
): LspHook {
|
|
17
|
+
new(at: Option[Location], definedAt: Option[Location], insertIdentifier: Bool, trackSymbols: Bool): LspHook {
|
|
26
18
|
LspHook( // Default dummy values instead of Option[Location] to speed up location hit check
|
|
27
19
|
at = at.else {Location("^lsp", -7, -7)}
|
|
28
20
|
definedAt = definedAt.else {Location("^lsp", -7, -7)}
|
|
29
21
|
insertIdentifier = insertIdentifier
|
|
30
22
|
trackSymbols = trackSymbols
|
|
31
|
-
arrayOfResults =
|
|
32
|
-
sql = sql
|
|
33
|
-
sqlStrings = Array.new()
|
|
23
|
+
arrayOfResults = [].toArray()
|
|
34
24
|
)
|
|
35
25
|
}
|
|
36
26
|
|
|
@@ -210,4 +200,4 @@ showHook(hook: ResultHook): String {
|
|
|
210
200
|
| ResolveSymbolHook(symbol, annotation, _) => "ResolveSymbolHook(...)"
|
|
211
201
|
| ResolveTypeHook(types, typeGenerics, symbol, explicitType) => "ResolveTypeHook(...)"
|
|
212
202
|
| ResolveVariantFieldHook(symbol, type, commonField) => "ResolveVariantFieldHook(...)"
|
|
213
|
-
}
|
|
203
|
+
}
|
package/core/Ordering.ff
CHANGED
package/lsp/.firefly/package.ff
CHANGED
package/lsp/CompletionHandler.ff
CHANGED
|
@@ -3,9 +3,6 @@ import Unification from ff:compiler
|
|
|
3
3
|
import Environment from ff:compiler
|
|
4
4
|
import Syntax from ff:compiler
|
|
5
5
|
import Handler
|
|
6
|
-
import Sql
|
|
7
|
-
import SqlSuggestion
|
|
8
|
-
import SqlStatement
|
|
9
6
|
|
|
10
7
|
data CompletionInfo(
|
|
11
8
|
label: String
|
|
@@ -18,7 +15,6 @@ data CompletionInfo(
|
|
|
18
15
|
expectedType: Option[Type]
|
|
19
16
|
secondarySort: Int = 5
|
|
20
17
|
insertion: Option[Pair[Int, String]] = None
|
|
21
|
-
sql: Bool = False
|
|
22
18
|
)
|
|
23
19
|
|
|
24
20
|
data ImportSymbolsInfo(
|
|
@@ -39,10 +35,7 @@ handleCompletion(
|
|
|
39
35
|
toplevel: Bool
|
|
40
36
|
followedByOpenBracket: Bool
|
|
41
37
|
importSymbols: ImportSymbolsInfo
|
|
42
|
-
sqlStatement: Option[Pair[Location, SqlStatement]]
|
|
43
|
-
sqlData: SqlData
|
|
44
38
|
): Json {
|
|
45
|
-
sqlStatement.map {| Pair(l, s) => completionsToJson(sqlCompletion(l, s, sqlData))}.else:
|
|
46
39
|
let topLevelCompletions = if(!toplevel) {[]} else {toplevelCompletion(lspHook)}
|
|
47
40
|
let patternCompletions = lspHook.results().collectFirst {
|
|
48
41
|
| InferPatternHook h =>
|
|
@@ -202,14 +195,10 @@ completionsToJson(completions: List[CompletionInfo]): Json {
|
|
|
202
195
|
let isDefinition = ["let ", "mutable ", "function "].any {i.snippet.startsWith(_)}
|
|
203
196
|
let isParameter = i.snippet.endsWith(" = ")
|
|
204
197
|
let isImport = i.documentation == "// Imports this module"
|
|
205
|
-
let sortText = if(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
isVariable.toInt() + isUnqualified.toInt() +
|
|
210
|
-
isAlpha.toInt() + isLower.toInt() + isMember.toInt()
|
|
211
|
-
)} + if(isMember) {"1"} else {"0"} + i.secondarySort + i.label.lower()
|
|
212
|
-
}
|
|
198
|
+
let sortText = if(isParameter || isDefinition || isImport) {0} else {9 - (
|
|
199
|
+
isVariable.toInt() + isUnqualified.toInt() +
|
|
200
|
+
isAlpha.toInt() + isLower.toInt() + isMember.toInt()
|
|
201
|
+
)} + if(isMember) {"1"} else {"0"} + i.secondarySort + i.label.lower()
|
|
213
202
|
let preselect = !isDefinition && Pair(i.type, i.expectedType).{
|
|
214
203
|
| Pair(TConstructor(_, n1, _), Some(TConstructor(_, n2, _))) => n1 == n2
|
|
215
204
|
| _ => False
|
|
@@ -217,16 +206,6 @@ completionsToJson(completions: List[CompletionInfo]): Json {
|
|
|
217
206
|
Json.object()
|
|
218
207
|
// Namespace or Property or Constructor or EnumMember or Constructor or Method/Function or Field/Variable
|
|
219
208
|
.with("kind"
|
|
220
|
-
if(i.sql) {
|
|
221
|
-
if(i.secondarySort == 1) {15} else:
|
|
222
|
-
if(i.secondarySort == 2) {23} else:
|
|
223
|
-
if(i.secondarySort == 3) {7} else:
|
|
224
|
-
if(i.secondarySort == 4) {5} else:
|
|
225
|
-
if(i.secondarySort == 5) {6} else:
|
|
226
|
-
if(i.secondarySort == 8) {3} else:
|
|
227
|
-
if(i.secondarySort == 9) {15} else:
|
|
228
|
-
9
|
|
229
|
-
} else:
|
|
230
209
|
if(isImport) {2} else:
|
|
231
210
|
if(shownType == "") {3} else:
|
|
232
211
|
if(isParameter) {10} else:
|
|
@@ -239,18 +218,14 @@ completionsToJson(completions: List[CompletionInfo]): Json {
|
|
|
239
218
|
.with("preselect", preselect)
|
|
240
219
|
.with("label", i.label)
|
|
241
220
|
.with("labelDetails", Json.object()
|
|
242
|
-
.with("detail", if(
|
|
243
|
-
i.extra + if(shownType == "") {""} else {": " + shownType}
|
|
244
|
-
})
|
|
221
|
+
.with("detail", i.extra + if(shownType == "") {""} else {": " + shownType})
|
|
245
222
|
.with("description", i.more)
|
|
246
223
|
)
|
|
247
224
|
.with("insertText", i.snippet)
|
|
248
225
|
.with("insertTextFormat", 2 /* Snippet */)
|
|
249
226
|
.with("documentation", Json.object()
|
|
250
227
|
.with("kind", "markdown")
|
|
251
|
-
.with("value",
|
|
252
|
-
if(i.sql) {"```sql\n"} else {"```\n"} + i.documentation + "\n```"
|
|
253
|
-
)
|
|
228
|
+
.with("value", "```\n" + i.documentation + "\n```")
|
|
254
229
|
)
|
|
255
230
|
.with("additionalTextEdits", i.insertion.toList().map {| Pair(line, text) => Json.object()
|
|
256
231
|
.with("range", Json->(
|
|
@@ -262,87 +237,6 @@ completionsToJson(completions: List[CompletionInfo]): Json {
|
|
|
262
237
|
})
|
|
263
238
|
}
|
|
264
239
|
|
|
265
|
-
sqlCompletion(at: Location, sqlStatement: SqlStatement, data: SqlData): List[CompletionInfo] {
|
|
266
|
-
let tokens = Sql.tokenize(sqlStatement.string)
|
|
267
|
-
let line = 1 + at.line - sqlStatement.at.line
|
|
268
|
-
let column = if(at.line == sqlStatement.at.line) {1 + at.column - sqlStatement.at.column} else {at.column}
|
|
269
|
-
let suggestions = SqlSuggestion.suggest(data, tokens, line, column)
|
|
270
|
-
function fixQuotes(snippet: String): String {
|
|
271
|
-
if(suggestions.second) {snippet.replace("\"", "")} else {snippet}
|
|
272
|
-
}
|
|
273
|
-
suggestions.first.map {
|
|
274
|
-
| SqlSuggestionFunction(l, signature, documentation)@suggestion =>
|
|
275
|
-
CompletionInfo(
|
|
276
|
-
label = l
|
|
277
|
-
extra = signature
|
|
278
|
-
more = ""
|
|
279
|
-
snippet = fixQuotes(Sql.quote(l) + "($0)")
|
|
280
|
-
member = False
|
|
281
|
-
type = TConstructor(Location("", 0, 0), "", [])
|
|
282
|
-
documentation = documentation
|
|
283
|
-
expectedType = None
|
|
284
|
-
sql = True
|
|
285
|
-
secondarySort = suggestion.secondarySort()
|
|
286
|
-
)
|
|
287
|
-
| SqlSuggestionJoin(l, schema, snippet)@suggestion =>
|
|
288
|
-
CompletionInfo(
|
|
289
|
-
label = l
|
|
290
|
-
extra = ""
|
|
291
|
-
more = schema
|
|
292
|
-
snippet = fixQuotes(snippet)
|
|
293
|
-
member = False
|
|
294
|
-
type = TConstructor(Location("", 0, 0), "", [])
|
|
295
|
-
documentation = snippet
|
|
296
|
-
expectedType = None
|
|
297
|
-
sql = True
|
|
298
|
-
secondarySort = suggestion.secondarySort()
|
|
299
|
-
)
|
|
300
|
-
| SqlSuggestionRegular(l, display, documentation)@suggestion =>
|
|
301
|
-
CompletionInfo(
|
|
302
|
-
label = l
|
|
303
|
-
extra = ""
|
|
304
|
-
more = display
|
|
305
|
-
snippet = fixQuotes(Sql.quote(l))
|
|
306
|
-
member = False
|
|
307
|
-
type = TConstructor(Location("", 0, 0), "", [])
|
|
308
|
-
documentation = documentation
|
|
309
|
-
expectedType = None
|
|
310
|
-
sql = True
|
|
311
|
-
secondarySort = suggestion.secondarySort()
|
|
312
|
-
)
|
|
313
|
-
| SqlSuggestionColumnNames(required, columns)@suggestion =>
|
|
314
|
-
let comment =
|
|
315
|
-
if(required) {"-- required columns\n"} elseIf {columns.size() > 1} {"-- all columns\n"} else {""}
|
|
316
|
-
CompletionInfo(
|
|
317
|
-
label = columns.map {_.first}.join(", ")
|
|
318
|
-
extra = ""
|
|
319
|
-
more = ""
|
|
320
|
-
snippet = fixQuotes(columns.map {Sql.quote(_.first)}.join(", "))
|
|
321
|
-
member = False
|
|
322
|
-
type = TConstructor(Location("", 0, 0), "", [])
|
|
323
|
-
documentation = comment + columns.map {_.second}.join("\n")
|
|
324
|
-
expectedType = None
|
|
325
|
-
sql = True
|
|
326
|
-
secondarySort = suggestion.secondarySort()
|
|
327
|
-
)
|
|
328
|
-
| SqlSuggestionColumnSetters(columns)@suggestion =>
|
|
329
|
-
CompletionInfo(
|
|
330
|
-
label = columns.map {_.first + " = "}.join(", ")
|
|
331
|
-
extra = ""
|
|
332
|
-
more = ""
|
|
333
|
-
snippet = fixQuotes(columns.pairs().map {| Pair(i, c) =>
|
|
334
|
-
Sql.quote(c.first) + " = " + if(i == 0) {"$0"} else {""}
|
|
335
|
-
}.join(",\n"))
|
|
336
|
-
member = False
|
|
337
|
-
type = TConstructor(Location("", 0, 0), "", [])
|
|
338
|
-
documentation = columns.map {_.second}.join("\n")
|
|
339
|
-
expectedType = None
|
|
340
|
-
sql = True
|
|
341
|
-
secondarySort = suggestion.secondarySort()
|
|
342
|
-
)
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
240
|
importCompletion(moduleKeys: List[ModuleKey]): List[CompletionInfo] {
|
|
347
241
|
moduleKeys.map {moduleKey =>
|
|
348
242
|
let label = moduleKey.folders.map {_ + "."}.join() + moduleKey.name
|
package/lsp/Handler.ff
CHANGED
|
@@ -10,15 +10,10 @@ import Unification from ff:compiler
|
|
|
10
10
|
import LspHook from ff:compiler
|
|
11
11
|
import ModuleCache from ff:compiler
|
|
12
12
|
import DependencyLock from ff:compiler
|
|
13
|
-
import Pg from ff:postgresql
|
|
14
13
|
import HoverHandler
|
|
15
14
|
import CompletionHandler
|
|
16
15
|
import SignatureHelpHandler
|
|
17
16
|
import SymbolHandler
|
|
18
|
-
import SemanticTokenTypes
|
|
19
|
-
import Sql
|
|
20
|
-
import SqlStatement
|
|
21
|
-
|
|
22
17
|
|
|
23
18
|
capability Handler(
|
|
24
19
|
fireflyPath: Path
|
|
@@ -28,20 +23,10 @@ capability Handler(
|
|
|
28
23
|
mutable responseCache: Map[TokenRequestCacheKey, ResultOrError]
|
|
29
24
|
mutable fileSymbolsCache: Map[String, List[DocumentSymbol]]
|
|
30
25
|
mutable importSymbolsCache: Pair[String, List[ImportSymbolInfo]]
|
|
31
|
-
mutable sqlConnectionString: Option[String]
|
|
32
|
-
mutable sqlData: Option[SqlData]
|
|
33
|
-
mutable sqlConnectionPool: Option[PgPool]
|
|
34
|
-
sqlDiagnosticsCache: StringMap[Map[String, Option[SqlError]]]
|
|
35
|
-
sqlLock: Lock
|
|
36
26
|
moduleCache: ModuleCache
|
|
37
27
|
dependencyLock: DependencyLock
|
|
38
28
|
)
|
|
39
29
|
|
|
40
|
-
data SqlCacheKey(
|
|
41
|
-
sql: String
|
|
42
|
-
parameters: Option[List[SqlParameter]]
|
|
43
|
-
)
|
|
44
|
-
|
|
45
30
|
data TokenRequestCacheKey(
|
|
46
31
|
method: String
|
|
47
32
|
targetAt: Location
|
|
@@ -72,12 +57,8 @@ data TokenLocation(
|
|
|
72
57
|
|
|
73
58
|
data Definition(at: Location, name: String, local: Bool)
|
|
74
59
|
|
|
75
|
-
data SqlError(token: SqlToken, message: String)
|
|
76
60
|
|
|
77
61
|
extend self: Handler {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
62
|
|
|
82
63
|
handleNotification(system: NodeSystem, method: String, parameters: Map[String, Json], version: Int): List[Pair[String, Json]] {
|
|
83
64
|
method.{
|
|
@@ -145,8 +126,6 @@ extend self: Handler {
|
|
|
145
126
|
self.printTime(system.mainTask(), "handleWorkspaceSymbol") {
|
|
146
127
|
self.handleWorkspaceSymbol(system, parameters)
|
|
147
128
|
}
|
|
148
|
-
| "textDocument/semanticTokens/full" =>
|
|
149
|
-
self.handleSemanticTokensFull(system, parameters, version)
|
|
150
129
|
| "shutdown" =>
|
|
151
130
|
Result(Json.null().write())
|
|
152
131
|
| _ =>
|
|
@@ -181,10 +160,6 @@ extend self: Handler {
|
|
|
181
160
|
|
|
182
161
|
handleInitialize(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
183
162
|
self.rootPath = parameters.grab("rootUri").getString().map {system.pathFromUrl(_)}
|
|
184
|
-
self.sqlConnectionString = parameters.get("initializationOptions").{
|
|
185
|
-
| Some(opts) => opts.getField("sqlConnectionString").map {_.grabString()}.filter {_ != ""}
|
|
186
|
-
| None => None
|
|
187
|
-
}
|
|
188
163
|
|
|
189
164
|
let anyFireflyFile = Json.object()
|
|
190
165
|
.with("filters", [
|
|
@@ -237,15 +212,6 @@ extend self: Handler {
|
|
|
237
212
|
)
|
|
238
213
|
)*/
|
|
239
214
|
.with("renameProvider", True)
|
|
240
|
-
.with("semanticTokensProvider", Json.object()
|
|
241
|
-
.with("legend", Json.object()
|
|
242
|
-
.with("tokenTypes", SemanticTokenTypes.new().second)
|
|
243
|
-
.with("tokenModifiers", Json.array([]))
|
|
244
|
-
)
|
|
245
|
-
.with("full", Json.object()
|
|
246
|
-
.with("delta", False)
|
|
247
|
-
)
|
|
248
|
-
)
|
|
249
215
|
)
|
|
250
216
|
.with("serverInfo", Json.object()
|
|
251
217
|
.with("name", "Firefly Language Server")
|
|
@@ -278,8 +244,7 @@ extend self: Handler {
|
|
|
278
244
|
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
279
245
|
let path = system.pathFromUrl(uri)
|
|
280
246
|
let fireflyPath = system.path(".")
|
|
281
|
-
let
|
|
282
|
-
let errors = self.check(system, fireflyPath, path, None, Set.new(), self.virtualFiles, version, lspHook, True)
|
|
247
|
+
let errors = self.check(system, fireflyPath, path, None, Set.new(), self.virtualFiles, version, LspHook.disabled(), True)
|
|
283
248
|
let diagnostics = errors.filter {_.at.file == path.absolute()}.map {| CompileError(at, message) =>
|
|
284
249
|
let tokenLocation = self.findToken(system, at)
|
|
285
250
|
Json.object()
|
|
@@ -287,101 +252,10 @@ extend self: Handler {
|
|
|
287
252
|
.with("severity", 1)
|
|
288
253
|
.with("message", message)
|
|
289
254
|
}
|
|
290
|
-
|
|
291
|
-
let sqlStatements = SqlStatement.extractStatements(lspHook.sqlStrings.toList())
|
|
292
|
-
let sqlDiagnistics = if(sqlStatements.isEmpty()) {[]} else {
|
|
293
|
-
if(self.sqlConnectionString.isEmpty()) {
|
|
294
|
-
sqlStatements.map {
|
|
295
|
-
| SqlStatement(_, at, _, _) =>
|
|
296
|
-
let tokenLocation = self.findToken(system, at)
|
|
297
|
-
Json.object()
|
|
298
|
-
.with("range", self.tokenLocationToLspRange(tokenLocation))
|
|
299
|
-
.with("severity", 3)
|
|
300
|
-
.with("message", "Configure firefly.sqlConnectionString to enable SQL diagnostics")
|
|
301
|
-
.with("source", "firefly")
|
|
302
|
-
}
|
|
303
|
-
} else:
|
|
304
|
-
self.sqlLock.do {
|
|
305
|
-
mutable sqlCache = self.sqlDiagnosticsCache.getOrSet(path.absolute()) {Map.new()}
|
|
306
|
-
mutable seenSql = Set.new()
|
|
307
|
-
let issues = try {
|
|
308
|
-
let pool = self.getSqlConnectionPool(system)
|
|
309
|
-
pool.transaction(readOnly = True, body = {connection =>
|
|
310
|
-
sqlStatements.collect {
|
|
311
|
-
| SqlStatement(_, at, sql, parameters) =>
|
|
312
|
-
let cacheKey = Show.show(SqlCacheKey(sql, parameters))
|
|
313
|
-
seenSql = seenSql.add(cacheKey)
|
|
314
|
-
let sqlError = sqlCache.get(cacheKey).else {
|
|
315
|
-
let error = Sql.buildExplainStatement(sql, parameters).flatMap {
|
|
316
|
-
| ExplainedStatement(explainSql, deltas, usedParameters) =>
|
|
317
|
-
let missingParameters = parameters.map {parsedParameters =>
|
|
318
|
-
usedParameters.filter {| Pair(used, o) => parsedParameters.all {passed => passed.name != used}}
|
|
319
|
-
}.else {[]}
|
|
320
|
-
try {
|
|
321
|
-
connection.statement(explainSql).map {_ => }
|
|
322
|
-
missingParameters.first().map {| Pair(name, position) =>
|
|
323
|
-
let tokens = Sql.tokenize(sql)
|
|
324
|
-
let t = tokens.find {_.startOffset >= position - 1}.else {tokens.grabLast()} // TODO
|
|
325
|
-
SqlError(t, "Parameter not defined: " + name)
|
|
326
|
-
}
|
|
327
|
-
} catchAny {e =>
|
|
328
|
-
let errorMessage = e.message()
|
|
329
|
-
system.writeErrorLine(Json(e!).write())
|
|
330
|
-
let errorPosition = if(e!->position.nullish()) {0} else {
|
|
331
|
-
let position = e!->position.grabString().grabInt()
|
|
332
|
-
position + deltas.filter {_.first < position}.map {_.second}.foldLeft(0) {_ + _}
|
|
333
|
-
}
|
|
334
|
-
let tokens = Sql.tokenize(sql)
|
|
335
|
-
let t = tokens.find {_.startOffset >= errorPosition - 1}.else {tokens.grabLast()} // TODO
|
|
336
|
-
Some(SqlError(t, errorMessage))
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
sqlCache = sqlCache.add(cacheKey, error)
|
|
340
|
-
error
|
|
341
|
-
}
|
|
342
|
-
sqlError.map {e =>
|
|
343
|
-
let absoluteLine = at.line - 1 + e.token.startLine - 1 + 1
|
|
344
|
-
let absoluteColumnExtra = if(e.token.at().line == 1) {at.column - 1} else {0}
|
|
345
|
-
let absoluteColumn = e.token.startOffset - e.token.startLineOffset + absoluteColumnExtra + 1
|
|
346
|
-
let tokenLocation = TokenLocation(
|
|
347
|
-
file = at.file
|
|
348
|
-
startLine = absoluteLine
|
|
349
|
-
startColumn = absoluteColumn
|
|
350
|
-
endLine = absoluteLine
|
|
351
|
-
endColumn = absoluteColumn + (e.token.stopOffset - e.token.startOffset)
|
|
352
|
-
raw = e.token.raw()
|
|
353
|
-
followedByLeftBracket = False
|
|
354
|
-
)
|
|
355
|
-
Json.object()
|
|
356
|
-
.with("range", self.tokenLocationToLspRange(tokenLocation))
|
|
357
|
-
.with("severity", 1)
|
|
358
|
-
.with("message", e.message)
|
|
359
|
-
}
|
|
360
|
-
| _ => None
|
|
361
|
-
}
|
|
362
|
-
})
|
|
363
|
-
} catchAny {error =>
|
|
364
|
-
system.writeErrorLine("Error while running SQL diagnostics: " + error.message())
|
|
365
|
-
system.writeErrorLine(error.stack())
|
|
366
|
-
[]
|
|
367
|
-
}
|
|
368
|
-
if(seenSql.size() == 0) {
|
|
369
|
-
self.sqlDiagnosticsCache.remove(path.absolute())
|
|
370
|
-
} else {
|
|
371
|
-
sqlCache.keys().each {
|
|
372
|
-
| cachedSql {!seenSql.contains(cachedSql)} => sqlCache = sqlCache.remove(cachedSql)
|
|
373
|
-
| _ =>
|
|
374
|
-
}
|
|
375
|
-
self.sqlDiagnosticsCache.set(path.absolute(), sqlCache)
|
|
376
|
-
}
|
|
377
|
-
issues
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
255
|
Json.object()
|
|
382
256
|
.with("uri", uri)
|
|
383
257
|
.with("version", parameters.grab("textDocument").field("version"))
|
|
384
|
-
.with("diagnostics",
|
|
258
|
+
.with("diagnostics", diagnostics)
|
|
385
259
|
}
|
|
386
260
|
|
|
387
261
|
handleClearDiagnostic(system: NodeSystem, parameters: Map[String, Json]): List[Json] {
|
|
@@ -436,63 +310,6 @@ extend self: Handler {
|
|
|
436
310
|
symbols
|
|
437
311
|
}
|
|
438
312
|
}
|
|
439
|
-
|
|
440
|
-
handleSemanticTokensFull(system: NodeSystem, parameters: Map[String, Json], version: Int): ResultOrError {
|
|
441
|
-
let js = system.js()
|
|
442
|
-
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
443
|
-
let path = system.pathFromUrl(uri)
|
|
444
|
-
let fireflyPath = system.path(".")
|
|
445
|
-
let lspHook = LspHook.disabled(sql = True)
|
|
446
|
-
self.check(system, fireflyPath, path, None, Set.new(), self.virtualFiles, version, lspHook, True)
|
|
447
|
-
let sqlStatements = SqlStatement.extractStatements(lspHook.sqlStrings.toList())
|
|
448
|
-
if(!sqlStatements.isEmpty() && self.sqlData.isEmpty()) {
|
|
449
|
-
self.sqlData = Some(SqlData([], [], [], []))
|
|
450
|
-
system.mainTask().spawn {_ =>
|
|
451
|
-
try {
|
|
452
|
-
let pool = self.getSqlConnectionPool(system)
|
|
453
|
-
let data = Sql.load(system, pool)
|
|
454
|
-
self.sqlData = Some(data)
|
|
455
|
-
} catchAny {error =>
|
|
456
|
-
system.writeErrorLine("Error while running Sql.load: " + error.message())
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
mutable lastAbsoluteLine = -1
|
|
461
|
-
mutable lastAbsoluteColumn = 0
|
|
462
|
-
let tokens = sqlStatements.flatMap {
|
|
463
|
-
| SqlStatement(_, at, sql, _) =>
|
|
464
|
-
let tokens = Sql.tokenize(sql)
|
|
465
|
-
tokens.map {token =>
|
|
466
|
-
let absoluteLine = at.line - 1 + token.startLine - 1
|
|
467
|
-
let absoluteColumnExtra = if(token.at().line == 1) {at.column - 1} else {0}
|
|
468
|
-
let absoluteColumn = token.startOffset - token.startLineOffset + absoluteColumnExtra
|
|
469
|
-
let length = token.stopOffset - token.startOffset
|
|
470
|
-
let relativeLine = if(lastAbsoluteLine != -1) {absoluteLine - lastAbsoluteLine} else {absoluteLine}
|
|
471
|
-
let relativeColumn = if(lastAbsoluteLine == absoluteLine) {absoluteColumn - lastAbsoluteColumn} else {absoluteColumn}
|
|
472
|
-
let tokenTypes = SemanticTokenTypes.new().first
|
|
473
|
-
let tokenType = token.kind.{
|
|
474
|
-
| SqlReserved => tokenTypes.keyword.second
|
|
475
|
-
| SqlUnreserved => tokenTypes.macro.second
|
|
476
|
-
| SqlIdentifier => tokenTypes.variable.second
|
|
477
|
-
| SqlNumber => tokenTypes.number.second
|
|
478
|
-
| SqlString => tokenTypes.string.second
|
|
479
|
-
| SqlOperator => tokenTypes.operator.second
|
|
480
|
-
| SqlPunctuation => tokenTypes.operator.second
|
|
481
|
-
| SqlComment => tokenTypes.comment.second
|
|
482
|
-
| SqlPlaceholder => tokenTypes.typeParameter.second
|
|
483
|
-
}
|
|
484
|
-
let tokenModifiers = 0
|
|
485
|
-
lastAbsoluteLine = absoluteLine
|
|
486
|
-
lastAbsoluteColumn = absoluteColumn
|
|
487
|
-
[relativeLine, relativeColumn, length, tokenType, tokenModifiers]
|
|
488
|
-
}
|
|
489
|
-
| _ => []
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
let o = Json.object()
|
|
493
|
-
.with("data", Json.array(tokens.flatten().map(Json.int)))
|
|
494
|
-
Result(o.write())
|
|
495
|
-
}
|
|
496
313
|
|
|
497
314
|
handleWorkspaceSymbol(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
498
315
|
self.rootPath.or {Error(-32803 /*Request Failed*/, "Open a folder to enable workspace symbols")}: rootPath =>
|
|
@@ -590,9 +407,7 @@ extend self: Handler {
|
|
|
590
407
|
line = token.startLine
|
|
591
408
|
column = token.startColumn
|
|
592
409
|
)
|
|
593
|
-
let lspHook = LspHook.new(
|
|
594
|
-
at = Some(completionAt), definedAt = None, insertIdentifier = True, trackSymbols = False, sql = True
|
|
595
|
-
)
|
|
410
|
+
let lspHook = LspHook.new(at = Some(completionAt), definedAt = None, insertIdentifier = True, trackSymbols = False)
|
|
596
411
|
let path = system.path(completionAt.file)
|
|
597
412
|
let errors = self.check(system, self.fireflyPath, path, None, Set.new(), self.virtualFiles, version, lspHook, True)
|
|
598
413
|
errors.each {| CompileError(at, message) =>
|
|
@@ -601,7 +416,6 @@ extend self: Handler {
|
|
|
601
416
|
let importSymbols = self.printTime(system.mainTask(), "findModulesToImport") {
|
|
602
417
|
self.findModulesToImport(system, path, lspHook)
|
|
603
418
|
}
|
|
604
|
-
let sqlStatement = SqlStatement.extractStatements(lspHook.sqlStrings.toList()).find {_.termAt == completionAt}
|
|
605
419
|
let o = CompletionHandler.handleCompletion(
|
|
606
420
|
lspHook = lspHook
|
|
607
421
|
toplevel = completionAt.column == 1
|
|
@@ -611,8 +425,6 @@ extend self: Handler {
|
|
|
611
425
|
importSymbols = importSymbols.first
|
|
612
426
|
importLine = importSymbols.second
|
|
613
427
|
)
|
|
614
|
-
sqlStatement = sqlStatement.map {Pair(location, _)}
|
|
615
|
-
sqlData = self.sqlData.else {SqlData([], [], [], [])}
|
|
616
428
|
)
|
|
617
429
|
Result(o.write())
|
|
618
430
|
}
|
|
@@ -980,19 +792,9 @@ extend self: Handler {
|
|
|
980
792
|
infer
|
|
981
793
|
)
|
|
982
794
|
}
|
|
983
|
-
|
|
984
|
-
getSqlConnectionPool(system: NodeSystem): PgPool {
|
|
985
|
-
let connectionString = self.sqlConnectionString.else {
|
|
986
|
-
throw(LanguageServerException("No SQL connection string configured. Set firefly.sqlConnectionString in VS Code settings."))
|
|
987
|
-
}
|
|
988
|
-
self.sqlLock.do {
|
|
989
|
-
self.sqlConnectionPool.else {
|
|
990
|
-
let pool = Pg.newPoolFromConnectionString(system, connectionString)
|
|
991
|
-
self.sqlConnectionPool = Some(pool)
|
|
992
|
-
pool
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
795
|
|
|
998
796
|
}
|
|
797
|
+
|
|
798
|
+
foo(bb: Int): Int {
|
|
799
|
+
bb
|
|
800
|
+
}
|
package/lsp/LanguageServer.ff
CHANGED
|
@@ -39,11 +39,6 @@ main(system: NodeSystem) {
|
|
|
39
39
|
responseCache = Map.new()
|
|
40
40
|
fileSymbolsCache = Map.new()
|
|
41
41
|
importSymbolsCache = Pair("", [])
|
|
42
|
-
sqlConnectionString = None
|
|
43
|
-
sqlData = None
|
|
44
|
-
sqlConnectionPool = None
|
|
45
|
-
sqlLock = system.mainTask().lock()
|
|
46
|
-
sqlDiagnosticsCache = StringMap.new()
|
|
47
42
|
moduleCache = cache
|
|
48
43
|
dependencyLock = DependencyLock.new(system.mainTask())
|
|
49
44
|
)
|
|
@@ -123,7 +123,7 @@ return {root_, packageFile_, files_};
|
|
|
123
123
|
|
|
124
124
|
export function build_(system_, emitTarget_, mainModules_, resolvedDependencies_, jsOutputPath_, printMeasurements_, moduleCache_) {
|
|
125
125
|
ff_core_Path.Path_createDirectory(jsOutputPath_, true);
|
|
126
|
-
const compiler_ = ff_compiler_Compiler.new_(emitTarget_, ff_core_NodeSystem.NodeSystem_mainTask(system_), jsOutputPath_, resolvedDependencies_, ff_core_Map.new_(), moduleCache_, ff_compiler_LspHook.disabled_(
|
|
126
|
+
const compiler_ = ff_compiler_Compiler.new_(emitTarget_, ff_core_NodeSystem.NodeSystem_mainTask(system_), jsOutputPath_, resolvedDependencies_, ff_core_Map.new_(), moduleCache_, ff_compiler_LspHook.disabled_());
|
|
127
127
|
for(let for_a = mainModules_, for_i = 0, for_l = for_a.length; for_i < for_l; for_i++) {
|
|
128
128
|
const moduleKey_ = for_a[for_i];
|
|
129
129
|
ff_compiler_Compiler.Compiler_emit(compiler_, moduleKey_, true)
|
|
@@ -377,7 +377,7 @@ pkg_.exec([packageFile_.absolutePath_, "--out-path", outputPath_.absolutePath_,
|
|
|
377
377
|
|
|
378
378
|
export async function build_$(system_, emitTarget_, mainModules_, resolvedDependencies_, jsOutputPath_, printMeasurements_, moduleCache_, $task) {
|
|
379
379
|
(await ff_core_Path.Path_createDirectory$(jsOutputPath_, true, $task));
|
|
380
|
-
const compiler_ = (await ff_compiler_Compiler.new_$(emitTarget_, (await ff_core_NodeSystem.NodeSystem_mainTask$(system_, $task)), jsOutputPath_, resolvedDependencies_, ff_core_Map.new_(), moduleCache_, ff_compiler_LspHook.disabled_(
|
|
380
|
+
const compiler_ = (await ff_compiler_Compiler.new_$(emitTarget_, (await ff_core_NodeSystem.NodeSystem_mainTask$(system_, $task)), jsOutputPath_, resolvedDependencies_, ff_core_Map.new_(), moduleCache_, ff_compiler_LspHook.disabled_(), $task));
|
|
381
381
|
for(let for_a = mainModules_, for_i = 0, for_l = for_a.length; for_i < for_l; for_i++) {
|
|
382
382
|
const moduleKey_ = for_a[for_i];
|
|
383
383
|
(await ff_compiler_Compiler.Compiler_emit$(compiler_, moduleKey_, true, $task))
|