firefly-compiler 0.6.20 → 0.6.24
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 +17 -1
- package/compiler/LspHook.ff +15 -5
- package/core/BuildSystem.ff +1 -1
- package/core/Ordering.ff +1 -1
- package/experimental/inceptron/Run.ff +47 -0
- package/experimental/mattis/Tree.ff +44 -0
- package/experimental/tests/TestListOrdering.ff +7 -0
- package/experimental/tests/TestOrder.ff +4 -0
- package/experimental/tests/TestSql.ff +18 -0
- package/lsp/.firefly/package.ff +1 -0
- package/lsp/CompletionHandler.ff +112 -6
- package/lsp/Handler.ff +205 -7
- package/lsp/LanguageServer.ff +5 -0
- package/lsp/SemanticTokenTypes.ff +62 -0
- package/lsp/Sql.ff +1395 -0
- package/lsp/SqlStatement.ff +34 -0
- package/lsp/SqlSuggestion.ff +295 -0
- 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 +36 -16
- package/output/js/ff/compiler/Inference.mjs.map +4 -2
- package/output/js/ff/compiler/LspHook.mjs +10 -10
- package/output/js/ff/compiler/LspHook.mjs.map +4 -3
- package/output/js/ff/compiler/Main.mjs +4 -4
- package/output/js/ff/compiler/Main.mjs.map +1 -1
- package/output/js/ff/core/BuildSystem.mjs +2 -2
- package/output/js/ff/core/BuildSystem.mjs.map +3 -2
- 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 +49 -26
- package/vscode/client/src/extension.ts +5 -0
- package/vscode/package.json +7 -1
package/postgresql/Pg.ff
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
capability PgPool(jsValue: JsValue)
|
|
2
|
-
capability PgConnection(jsValue: JsValue)
|
|
2
|
+
capability PgConnection(mutable jsValue: Option[JsValue], mutable internalInitializer: Option[Pair[PgPool, String]])
|
|
3
3
|
capability PgRow(jsValue: JsValue) // TODO: Should be a sync class, make deriver not touch those
|
|
4
4
|
capability PgStatement(sql: String, parameters: Map[String, JsValue], connection: Option[PgConnection])
|
|
5
5
|
data PgLevel {
|
|
@@ -61,13 +61,14 @@ internalTypeParsers(pg: JsValue) {
|
|
|
61
61
|
types->setTypeParser(types->builtins->TIMESTAMPTZ, Js->{v =>
|
|
62
62
|
Date(Js->Temporal->Instant->from(v)->toZonedDateTimeISO("UTC"))
|
|
63
63
|
})
|
|
64
|
+
types->setTypeParser(1003, types->getTypeParser(1009)) // handle name[]
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
extend self: PgPool {
|
|
67
68
|
|
|
68
69
|
connect(): PgConnection {
|
|
69
70
|
Js.throwIfCancelled()
|
|
70
|
-
PgConnection(Js.await(self.jsValue->connect()))
|
|
71
|
+
PgConnection(Some(Js.await(self.jsValue->connect())), None)
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
close(): Unit {
|
|
@@ -86,22 +87,33 @@ extend self: PgPool {
|
|
|
86
87
|
self.jsValue->waitingCount.grabInt()
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
transaction[T](
|
|
90
|
-
|
|
90
|
+
transaction[T](
|
|
91
|
+
body: PgConnection => T
|
|
92
|
+
level: PgLevel = PgReadCommitted
|
|
93
|
+
readOnly: Bool = False
|
|
94
|
+
deferrable: Bool = False
|
|
95
|
+
eager: Bool = False
|
|
96
|
+
): T {
|
|
97
|
+
let connection = PgConnection(None, None)
|
|
91
98
|
mutable done = False
|
|
92
99
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
let transactionMode = [
|
|
101
|
+
Some(level.{
|
|
102
|
+
| PgReadCommitted => " isolation level read committed"
|
|
103
|
+
| PgRepeatableRead => " isolation level repeatable read"
|
|
104
|
+
| PgSerializable => " isolation level serializable"
|
|
105
|
+
})
|
|
106
|
+
if(readOnly) {Some(" read only")} else {Some(" read write")}
|
|
107
|
+
if(deferrable) {" deferrable"}
|
|
108
|
+
].collect {_}.join(",")
|
|
109
|
+
connection.internalInitializer = Some(Pair(self, "begin" + transactionMode))
|
|
110
|
+
if(eager) {internalEnsureConnected(connection)}
|
|
99
111
|
let result = body(connection)
|
|
100
112
|
done = True
|
|
101
|
-
connection.statement("commit").run()
|
|
113
|
+
if(!connection.jsValue.isEmpty()) {connection.statement("commit").run()}
|
|
102
114
|
result
|
|
103
115
|
} finally {
|
|
104
|
-
if(!done) {connection.statement("rollback").run()}
|
|
116
|
+
if(!done && !connection.jsValue.isEmpty()) {connection.statement("rollback").run()}
|
|
105
117
|
connection.release()
|
|
106
118
|
}
|
|
107
119
|
}
|
|
@@ -112,10 +124,12 @@ extend self: PgConnection {
|
|
|
112
124
|
|
|
113
125
|
release(): Unit {
|
|
114
126
|
if(Js.cancelled()) {
|
|
115
|
-
self.jsValue->release(True)
|
|
127
|
+
self.jsValue.each {_->release(True)}
|
|
116
128
|
} else {
|
|
117
|
-
self.jsValue->release()
|
|
129
|
+
self.jsValue.each {_->release()}
|
|
118
130
|
}
|
|
131
|
+
self.jsValue = None
|
|
132
|
+
self.internalInitializer = None
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
statement(sql: String): PgStatement {
|
|
@@ -350,11 +364,21 @@ internalGet[T](row: PgRow, name: String, lower: Bool, body: JsValue => T): Optio
|
|
|
350
364
|
if(!value.isNull()) {Some(body(value))} else {None}
|
|
351
365
|
}
|
|
352
366
|
|
|
367
|
+
internalEnsureConnected(connection: PgConnection) {
|
|
368
|
+
connection.internalInitializer.each {| Pair(pool, start) =>
|
|
369
|
+
connection.internalInitializer = None
|
|
370
|
+
connection.jsValue = Some(Js.await(pool.jsValue->connect()))
|
|
371
|
+
connection.jsValue.grab()->query(start)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
353
375
|
internalRunStatement(statement: PgStatement, body: Option[PgRow => Bool]): Int {
|
|
354
376
|
Js.throwIfCancelled()
|
|
355
377
|
let pair = internalParseParameters(statement.sql)
|
|
356
378
|
let parameters = internalCheckParameters(pair.second, statement.parameters)
|
|
357
|
-
let
|
|
379
|
+
let connection = statement.connection.grab()
|
|
380
|
+
internalEnsureConnected(connection)
|
|
381
|
+
let result = Js.await(connection.jsValue.grab()->query(pair.first, parameters))
|
|
358
382
|
body.{
|
|
359
383
|
| None =>
|
|
360
384
|
if(!result.get("rowCount").isNullOrUndefined()) {result.get("rowCount").grabInt()} else {-1}
|
|
@@ -384,6 +408,7 @@ internalBatchStatements(
|
|
|
384
408
|
}
|
|
385
409
|
Pair(sql, (newSql = pair.first, parameterNames = pair.second, prepared = prepared))
|
|
386
410
|
}
|
|
411
|
+
if(!statements.isEmpty()) {internalEnsureConnected(connection)}
|
|
387
412
|
let promises = statements.map {statement =>
|
|
388
413
|
Js.throwIfCancelled()
|
|
389
414
|
let record = sqlCache.grab(statement.sql)
|
|
@@ -391,7 +416,7 @@ internalBatchStatements(
|
|
|
391
416
|
let query = Js.object()
|
|
392
417
|
.with("text", record.newSql)
|
|
393
418
|
.with("values", parameters)
|
|
394
|
-
connection.jsValue->query(record.prepared.map {query.with("name", _)}.else {query})
|
|
419
|
+
connection.jsValue.grab()->query(record.prepared.map {query.with("name", _)}.else {query})
|
|
395
420
|
}
|
|
396
421
|
let results = promises.map {promise =>
|
|
397
422
|
Js.throwIfCancelled()
|
|
@@ -431,7 +456,7 @@ internalParseParameters(statementSql: String): Pair[String, List[String]] {
|
|
|
431
456
|
mutable last = 0
|
|
432
457
|
mutable sql = ""
|
|
433
458
|
while {i < statementSql.size()} {
|
|
434
|
-
if(statementSql.grab(i) == '$') {
|
|
459
|
+
if(statementSql.grab(i) == '$' && i + 1 < statementSql.size() && statementSql.grab(i + 1).isAsciiLetter()) {
|
|
435
460
|
sql = sql + statementSql.slice(last, i)
|
|
436
461
|
i += 1
|
|
437
462
|
last = i
|
|
@@ -442,16 +467,14 @@ internalParseParameters(statementSql: String): Pair[String, List[String]] {
|
|
|
442
467
|
i += 1
|
|
443
468
|
}
|
|
444
469
|
let name = statementSql.slice(last, i)
|
|
445
|
-
|
|
446
|
-
let
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
newIndex
|
|
451
|
-
}
|
|
452
|
-
sql = sql + "$" + index
|
|
453
|
-
last = i
|
|
470
|
+
let index = parameterIndexes.get(name).else {
|
|
471
|
+
let newIndex = parameterIndexes.size() + 1
|
|
472
|
+
parameterIndexes = parameterIndexes.add(name, newIndex)
|
|
473
|
+
parameters = [name, ...parameters]
|
|
474
|
+
newIndex
|
|
454
475
|
}
|
|
476
|
+
sql = sql + "$" + index
|
|
477
|
+
last = i
|
|
455
478
|
}
|
|
456
479
|
} else {
|
|
457
480
|
i += 1
|
|
@@ -67,8 +67,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|
|
67
67
|
debug: runOrDebug
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
+
const sqlConnectionString = vscode.workspace.getConfiguration('firefly').get<string>('sqlConnectionString', '');
|
|
71
|
+
|
|
70
72
|
const clientOptions: LanguageClientOptions = {
|
|
71
73
|
documentSelector: [{ scheme: 'file', language: 'firefly' }],
|
|
74
|
+
initializationOptions: {
|
|
75
|
+
sqlConnectionString
|
|
76
|
+
},
|
|
72
77
|
synchronize: {
|
|
73
78
|
// It would be more portable to send a client/registerCapability from the server for this
|
|
74
79
|
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.ff')
|
package/vscode/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"description": "Firefly language support",
|
|
5
5
|
"author": "Firefly team",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"version": "0.6.
|
|
7
|
+
"version": "0.6.24",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/Ahnfelt/firefly-boot"
|
|
@@ -133,6 +133,12 @@
|
|
|
133
133
|
"type": "string",
|
|
134
134
|
"default": "charts.blue",
|
|
135
135
|
"description": "The color used for Firefly folder decorations."
|
|
136
|
+
},
|
|
137
|
+
"firefly.sqlConnectionString": {
|
|
138
|
+
"type": "string",
|
|
139
|
+
"default": "",
|
|
140
|
+
"scope": "resource",
|
|
141
|
+
"description": "PostgreSQL connection string for SQL diagnostics and completion (e.g. postgres://user:pass@localhost:5432/mydb)."
|
|
136
142
|
}
|
|
137
143
|
}
|
|
138
144
|
},
|