firefly-compiler 0.5.65 → 0.5.67

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.
@@ -172,7 +172,12 @@ extend self: Parser {
172
172
  } elseIf {self.current().is(LKeyword) && self.current().rawIs4("data", "class", "capability", "newtype")} {
173
173
  types.push(self.parseTypeDefinition())
174
174
  } elseIf {self.current().is(LKeyword) && self.current().rawIs("import")} {
175
- imports.push(self.parseImportDefinition(self.moduleKey.packagePair))
175
+ if(self.lspHook.isEnabled() && self.ahead().is(LLower) && !self.aheadAhead().is(LDot)) {
176
+ self.skip(LKeyword)
177
+ self.skip(LLower)
178
+ } else {
179
+ imports.push(self.parseImportDefinition(self.moduleKey.packagePair))
180
+ }
176
181
  } elseIf {self.current().is(LKeyword) && self.current().rawIs("include")} {
177
182
  throw(CompileError(self.current().at()
178
183
  "Includes must be at the top of the file or below 'package'"
@@ -14,9 +14,28 @@ data CompletionInfo(
14
14
  documentation: String
15
15
  expectedType: Option[Type]
16
16
  secondarySort: Int = 5
17
+ insertion: Option[Pair[Int, String]] = None
17
18
  )
18
19
 
19
- handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool): Json {
20
+ data ImportSymbolsInfo(
21
+ import: Bool
22
+ importSymbols: List[ImportSymbolInfo]
23
+ importLine: Int
24
+ )
25
+
26
+ data ImportSymbolInfo(
27
+ moduleKey: ModuleKey
28
+ typeNames: List[String]
29
+ variantNames: List[String]
30
+ traitNames: List[String]
31
+ )
32
+
33
+ handleCompletion(
34
+ lspHook: LspHook
35
+ toplevel: Bool
36
+ followedByOpenBracket: Bool
37
+ importSymbols: ImportSymbolsInfo
38
+ ): Json {
20
39
  let topLevelCompletions = if(!toplevel) {[]} else {toplevelCompletion(lspHook)}
21
40
  let patternCompletions = lspHook.results().collectFirst {
22
41
  | InferPatternHook h =>
@@ -30,7 +49,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
30
49
  mutable typeCompletions = []
31
50
  let completions = patternCompletions.else {lspHook.results().flatMap {
32
51
  | ResolveTypeHook h =>
33
- typeCompletions = [...typeCompletions, ...typeCompletion(h.types, h.typeGenerics)]
52
+ typeCompletions = [...typeCompletions, ...typeCompletion(h.types, h.typeGenerics, importSymbols)]
34
53
  []
35
54
  | ResolveVariantFieldHook _ =>
36
55
  sawParameterOrVariantFieldHook = True
@@ -59,10 +78,11 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
59
78
  } {
60
79
  scheme.signature.returnType | TConstructor(_, selfTypeName, _)
61
80
  } =>
62
- let otherCompletions = completion(h.unification, h.environment, "", None, expected)
81
+ let otherCompletions =
82
+ completion(h.unification, h.environment, "", None, expected, importSymbols)
63
83
  let selfCompletions = h.environment.symbols.get(selfName).toList().flatMap {scheme =>
64
84
  let prefix = selfTypeName + "_"
65
- completion(h.unification, h.environment, prefix, None, expected).filter {
85
+ completion(h.unification, h.environment, prefix, None, expected, importSymbols).filter {
66
86
  _.label.first().any {_.isAsciiLower()}
67
87
  }.map {c =>
68
88
  c.CompletionInfo(label = selfName + "." + c.label, snippet = selfName + "." + c.snippet)
@@ -70,7 +90,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
70
90
  }
71
91
  [...otherCompletions, ...selfCompletions]
72
92
  | _ =>
73
- completion(h.unification, h.environment, typePrefix, qualifiedByAlias, expected)
93
+ completion(h.unification, h.environment, typePrefix, qualifiedByAlias, expected, importSymbols)
74
94
  }
75
95
  | InferRecordFieldHook h {h.unification.substitute(h.recordType) | TConstructor(_, n, ts)} =>
76
96
  let fieldNames = n.split('$').dropFirst(1)
@@ -78,7 +98,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
78
98
  let t2 = h.unification.substitute(t)
79
99
  CompletionInfo(name, "", "", name, True, t2, "(...)." + name + ": " + t2.show([]), Some(h.expected))
80
100
  }
81
- [...fieldCompletions, ...completion(h.unification, h.environment, n, None, h.expected)]
101
+ [...fieldCompletions, ...completion(h.unification, h.environment, n, None, h.expected, importSymbols)]
82
102
  | InferArgumentHook h {
83
103
  ![ // Avoids named argument suggestions for operators that become trait method calls, such as ==
84
104
  "ff:core/Equal.equals", "ff:core/Equal.notEquals"
@@ -157,7 +177,9 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
157
177
  } else {c}
158
178
  }
159
179
  }
160
- completionsToJson([...fixedCompletions, ...fixedTypeCompletions, ...topLevelCompletions])
180
+ let importCompletions =
181
+ importCompletion(importSymbols.importSymbols.filter {_ => importSymbols.import}.map {_.moduleKey})
182
+ completionsToJson([...fixedCompletions, ...fixedTypeCompletions, ...topLevelCompletions, ...importCompletions])
161
183
  }
162
184
 
163
185
  completionsToJson(completions: List[CompletionInfo]): Json {
@@ -172,7 +194,8 @@ completionsToJson(completions: List[CompletionInfo]): Json {
172
194
  let isVariable = isLower && !i.extra.contains("(") && !i.extra.contains("{")
173
195
  let isDefinition = ["let ", "mutable ", "function "].any {i.snippet.startsWith(_)}
174
196
  let isParameter = i.snippet.endsWith(" = ")
175
- let sortText = if(isParameter || isDefinition) {0} else {9 - (
197
+ let isImport = i.documentation == "// Imports this module"
198
+ let sortText = if(isParameter || isDefinition || isImport) {0} else {9 - (
176
199
  isVariable.toInt() + isUnqualified.toInt() +
177
200
  isAlpha.toInt() + isLower.toInt() + isMember.toInt()
178
201
  )} + if(isMember) {"1"} else {"0"} + i.secondarySort + i.label.lower()
@@ -183,6 +206,7 @@ completionsToJson(completions: List[CompletionInfo]): Json {
183
206
  Json.object()
184
207
  // Namespace or Property or Constructor or EnumMember or Constructor or Method/Function or Field/Variable
185
208
  .with("kind"
209
+ if(isImport) {2} else:
186
210
  if(shownType == "") {3} else:
187
211
  if(isParameter) {10} else:
188
212
  if(i.type.{| TConstructor(_, "type", _) => True | _ => False}) {9} else:
@@ -203,10 +227,43 @@ completionsToJson(completions: List[CompletionInfo]): Json {
203
227
  .with("kind", "markdown")
204
228
  .with("value", "```\n" + i.documentation + "\n```")
205
229
  )
230
+ .with("additionalTextEdits", i.insertion.toList().map {| Pair(line, text) => Json.object()
231
+ .with("range", Json->(
232
+ start = Json->(line = line - 1, character = 0)
233
+ end = Json->(line = line - 1, character = 0)
234
+ ))
235
+ .with("newText", text)
236
+ })
206
237
  })
207
238
  }
208
239
 
209
- typeCompletion(types: Map[String, String], typeGenerics: Map[String, List[String]]): List[CompletionInfo] {
240
+ importCompletion(moduleKeys: List[ModuleKey]): List[CompletionInfo] {
241
+ moduleKeys.map {moduleKey =>
242
+ let label = moduleKey.folders.map {_ + "."}.join() + moduleKey.name
243
+ let extra = if(moduleKey.packagePair.name == "script" && moduleKey.packagePair.group == "script") {
244
+ ""
245
+ } else {
246
+ " from " + moduleKey.packagePair.groupName(":")
247
+ }
248
+ CompletionInfo(
249
+ label = label
250
+ extra = extra
251
+ more = ""
252
+ snippet = label + extra
253
+ member = False
254
+ type = TConstructor(Location("", 0, 0), "", [])
255
+ documentation = "// Imports this module",
256
+ expectedType = None
257
+ secondarySort = if(extra == "") {1} else {2}
258
+ )
259
+ }
260
+ }
261
+
262
+ typeCompletion(
263
+ types: Map[String, String]
264
+ typeGenerics: Map[String, List[String]]
265
+ importSymbols: ImportSymbolsInfo
266
+ ): List[CompletionInfo] {
210
267
  let completions = types.toList().filter {| Pair(n, full) =>
211
268
  n.all {_.isAsciiLetterOrDigit()}
212
269
  }.map {| Pair(typeName, full) =>
@@ -217,7 +274,11 @@ typeCompletion(types: Map[String, String], typeGenerics: Map[String, List[String
217
274
  let snippet = typeName + if(realGenerics.isEmpty()) {""} else {"[$0]"}
218
275
  CompletionInfo(label, extra, "", snippet, False, TConstructor(Location("", 0, 0), "type", []), full, None)
219
276
  }
220
- completions
277
+ let importCompletions = importSymbols.importSymbols.flatMap {| info =>
278
+ info.typeNames.map: name =>
279
+ makeAutoimportCompletion(info, importSymbols.importLine, name, True)
280
+ }
281
+ [...completions, ...importCompletions]
221
282
  }
222
283
 
223
284
  completion(
@@ -226,6 +287,7 @@ completion(
226
287
  prefix: String
227
288
  qualifiedByAlias: Option[String]
228
289
  expected: Type
290
+ importSymbols: ImportSymbolsInfo
229
291
  ): List[CompletionInfo] {
230
292
 
231
293
  let member = prefix.contains("_")
@@ -299,9 +361,41 @@ completion(
299
361
  members.push(makeCompletion(unification, expected, prefix, memberName, memberScheme, False, member))
300
362
  }
301
363
  }
364
+
365
+ if(prefix == "") {
366
+ importSymbols.importSymbols.each {| info =>
367
+ [info.moduleKey.name, ...info.variantNames].distinct().each: name =>
368
+ members.push(makeAutoimportCompletion(info, importSymbols.importLine, name, False))
369
+ }
370
+ }
371
+
302
372
  members.toList()
303
373
  }
304
374
 
375
+ makeAutoimportCompletion(info: ImportSymbolInfo, importLine: Int, name: String, isType: Bool): CompletionInfo {
376
+ let moduleName = info.moduleKey.folders.map {_ + "."}.join() + info.moduleKey.name
377
+ let fromName = if(
378
+ info.moduleKey.packagePair.name == "script" && info.moduleKey.packagePair.group == "script"
379
+ ) {
380
+ ""
381
+ } else {
382
+ info.moduleKey.packagePair.groupName(":")
383
+ }
384
+ let importName = if(fromName == "") {moduleName} else {moduleName + " from " + fromName}
385
+ CompletionInfo(
386
+ label = name
387
+ extra = ""
388
+ more = if(fromName == "") {moduleName} else {fromName + "/" + moduleName}
389
+ snippet = name
390
+ member = False
391
+ type = TConstructor(Location("", 0, 0), if(isType) {"type"} else {""}, [])
392
+ documentation = "// Will import the following module:\nimport " + importName
393
+ expectedType = None
394
+ secondarySort = 9
395
+ insertion = Some(Pair(importLine, "import " + importName + "\n"))
396
+ )
397
+ }
398
+
305
399
  makeCompletion(
306
400
  unification: Unification
307
401
  expected: Type
package/lsp/Handler.ff CHANGED
@@ -1,5 +1,6 @@
1
1
  import JsEmitter from ff:compiler
2
2
  import Builder from ff:compiler
3
+ import Dependencies from ff:compiler
3
4
  import Syntax from ff:compiler
4
5
  import Tokenizer from ff:compiler
5
6
  import Parser from ff:compiler
@@ -21,6 +22,7 @@ capability Handler(
21
22
  mutable cancelledRequests: Set[MessageId]
22
23
  mutable responseCache: Map[TokenRequestCacheKey, ResultOrError]
23
24
  mutable fileSymbolsCache: Map[String, List[DocumentSymbol]]
25
+ mutable importSymbolsCache: Pair[String, List[ImportSymbolInfo]]
24
26
  moduleCache: ModuleCache
25
27
  dependencyLock: DependencyLock
26
28
  )
@@ -93,11 +95,15 @@ extend self: Handler {
93
95
 
94
96
  handleRequest(system: NodeSystem, method: String, parameters: Map[String, Json], version: Int): ResultOrError {
95
97
  method.{
96
- | "initialize" => self.handleInitialize(system, parameters)
98
+ | "initialize" =>
99
+ self.handleInitialize(system, parameters)
97
100
  //| "textDocument/diagnostic" => self.handleDiagnostic(system, parameters)
98
- | "textDocument/documentSymbol" => self.handleDocumentSymbol(system, parameters)
99
- | "textDocument/completion" => self.handleCompletion(system, parameters, version)
100
- | "textDocument/signatureHelp" => self.handleSignatureHelp(system, parameters, version)
101
+ | "textDocument/documentSymbol" =>
102
+ self.handleDocumentSymbol(system, parameters)
103
+ | "textDocument/completion" =>
104
+ self.handleCompletion(system, parameters, version)
105
+ | "textDocument/signatureHelp" =>
106
+ self.handleSignatureHelp(system, parameters, version)
101
107
  | "textDocument/hover" =>
102
108
  self.handleTokenRequestWithCache(system, method, parameters) {key =>
103
109
  self.handleHover(system, key.targetAt, goToDefinition = False, version)
@@ -110,7 +116,8 @@ extend self: Handler {
110
116
  self.handleTokenRequestWithCache(system, method, parameters) {key =>
111
117
  self.handleReferences(system, key.targetAt, key.includeDeclaration, local = False, version)
112
118
  }
113
- | "textDocument/rename" => self.handleRename(system, parameters, version)
119
+ | "textDocument/rename" =>
120
+ self.handleRename(system, parameters, version)
114
121
  | "textDocument/documentHighlight" =>
115
122
  self.handleTokenRequestWithCache(system, method, parameters) {key =>
116
123
  self.handleReferences(system, key.targetAt, includeDeclaration = True, local = True, version)
@@ -119,8 +126,10 @@ extend self: Handler {
119
126
  self.printTime(system.mainTask(), "handleWorkspaceSymbol") {
120
127
  self.handleWorkspaceSymbol(system, parameters)
121
128
  }
122
- | "shutdown" => Result(Json.null().write())
123
- | _ => self.handleUnsupported()
129
+ | "shutdown" =>
130
+ Result(Json.null().write())
131
+ | _ =>
132
+ self.handleUnsupported()
124
133
  }
125
134
  }
126
135
 
@@ -231,6 +240,7 @@ extend self: Handler {
231
240
  }*/
232
241
 
233
242
  handleFocusDiagnostic(system: NodeSystem, parameters: Map[String, Json], version: Int): Json {
243
+ self.importSymbolsCache = Pair("", [])
234
244
  let js = system.js()
235
245
  let uri = parameters.grab("textDocument").field("uri").grabString()
236
246
  let path = system.pathFromUrl(uri)
@@ -384,6 +394,7 @@ extend self: Handler {
384
394
  handleCompletion(system: NodeSystem, parameters: Map[String, Json], version: Int): ResultOrError {
385
395
  let location = self.findLocationFromParameters(system, parameters)
386
396
  let token = self.findToken(system, location, insertToken = True)
397
+ let toplevelToken = self.findToken(system, location.Location(column = 1), insertToken = False)
387
398
  let completionAt = Location(
388
399
  file = location.file
389
400
  line = token.startLine
@@ -395,7 +406,19 @@ extend self: Handler {
395
406
  errors.each {| CompileError(at, message) =>
396
407
  Log.trace("handleCompletion check error: " + message)
397
408
  }
398
- let o = CompletionHandler.handleCompletion(lspHook, completionAt.column == 1, token.followedByLeftBracket)
409
+ let importSymbols = self.printTime(system.mainTask(), "findModulesToImport") {
410
+ self.findModulesToImport(system, path, lspHook)
411
+ }
412
+ let o = CompletionHandler.handleCompletion(
413
+ lspHook = lspHook
414
+ toplevel = completionAt.column == 1
415
+ followedByOpenBracket = token.followedByLeftBracket
416
+ importSymbols = ImportSymbolsInfo(
417
+ import = toplevelToken.raw == "import" && location.column >= 8
418
+ importSymbols = importSymbols.first
419
+ importLine = importSymbols.second
420
+ )
421
+ )
399
422
  Result(o.write())
400
423
  }
401
424
 
@@ -592,7 +615,55 @@ extend self: Handler {
592
615
  None
593
616
  }
594
617
  }
595
-
618
+
619
+ findModulesToImport(system: NodeSystem, modulePath: Path, lspHook: LspHook): Pair[List[ImportSymbolInfo], Int] {
620
+ let importSymbols = if(self.importSymbolsCache.first == modulePath.absolute()) {
621
+ self.importSymbolsCache.second
622
+ } else {
623
+ let dependencies =
624
+ Dependencies.process(system.httpClient(), DependencyLock.new(system.mainTask()), modulePath)
625
+ let nonCore = dependencies.packagePaths.toList().filter {!_.first.isCore()}
626
+ function parseModule(packagePair: PackagePair, path: Path): Option[Module] {
627
+ dependencies.packagePaths.get(packagePair).flatMap: packagePath =>
628
+ packagePair.moduleKey(packagePath, path).flatMap: moduleKey =>
629
+ self.moduleCache.parsedModules.get(path.absolute()).map {_.first}.orElse:
630
+ try {
631
+ let code = self.virtualFiles.get(path.absolute()).else {path.readText()}
632
+ let tokens = Tokenizer.tokenize(path.absolute(), code, None, True)
633
+ let parser = Parser.new(moduleKey, tokens, True, LspHook.disabled())
634
+ parser.parseModuleWithPackageInfo().module
635
+ }.toOption()
636
+ }
637
+ let symbols = nonCore.flatMap {| Pair(packagePair, packagePath) =>
638
+ let packageFiles = Builder.findPackageFilesForDirectory(packagePath, None, Set.new())
639
+ packageFiles.flatMap {_.files.collect {file =>
640
+ parseModule(packagePair, file).map: module =>
641
+ let typeNames = module.types.map {_.name}
642
+ let variantNames = module.types.flatMap {_.variants.map {_.name}}
643
+ let traitNames = module.traits.map {_.name}
644
+ ImportSymbolInfo(module.moduleKey, typeNames, variantNames, traitNames)
645
+ }}
646
+ }
647
+ self.importSymbolsCache = Pair(modulePath.absolute(), symbols)
648
+ symbols
649
+ }
650
+ mutable importLine = 1
651
+ let imports = try {
652
+ let code = self.virtualFiles.get(modulePath.absolute()).else {modulePath.readText()}
653
+ let tokens = Tokenizer.tokenize(modulePath.absolute(), code, Some(lspHook.at), True)
654
+ let parser = Parser.new(ModuleKey(PackagePair("", ""), [], ""), tokens, True, lspHook)
655
+ tokens.each {token =>
656
+ if(token.is(LKeyword) && token.rawIs4("import", "include", "package", "dependency")) {
657
+ importLine = token.startLine + 1
658
+ }
659
+ }
660
+ parser.parseModuleWithPackageInfo().module
661
+ }.toOption().toList().flatMap {
662
+ _.imports.map {_.moduleKey}
663
+ }.toSet()
664
+ Pair(importSymbols.filter {!imports.contains(_.moduleKey)}, importLine)
665
+ }
666
+
596
667
  makeNotificationMessage(method: String, params: Json): Json {
597
668
  Json.object()
598
669
  .with("jsonrpc", "2.0")
@@ -38,6 +38,7 @@ main(system: NodeSystem) {
38
38
  cancelledRequests = [].toSet()
39
39
  responseCache = Map.new()
40
40
  fileSymbolsCache = Map.new()
41
+ importSymbolsCache = Pair("", [])
41
42
  moduleCache = cache
42
43
  dependencyLock = DependencyLock.new(system.mainTask())
43
44
  )
@@ -8,7 +8,7 @@ nodeMain(system: NodeSystem) {
8
8
  let fireflyPath = system.path(".")
9
9
  Log.debug(fireflyPath.absolute())
10
10
  let cache = ModuleCache.new(0)
11
- let handler = Handler(fireflyPath, None, Map.new(), [].toSet(), Map.new(), Map.new(), cache, DependencyLock.new(system.mainTask()))
11
+ let handler = Handler(fireflyPath, None, Map.new(), [].toSet(), Map.new(), Map.new(), Pair("", []), cache, DependencyLock.new(system.mainTask()))
12
12
  let targetAt = Location("/home/werk/projects/firefly-boot/lsp/TestReferencesCase.ff", 7, 5)
13
13
  let references = handler.findReferences(system, targetAt, local = False, includeDeclaration = True, version = 0)
14
14
  Log.show(references)
@@ -288,7 +288,12 @@ instances_.array.push(ff_compiler_Parser.Parser_parseInstanceDefinition(self_))
288
288
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs4(ff_compiler_Parser.Parser_current(self_), "data", "class", "capability", "newtype"))) {
289
289
  types_.array.push(ff_compiler_Parser.Parser_parseTypeDefinition(self_))
290
290
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "import"))) {
291
+ if(((ff_compiler_LspHook.LspHook_isEnabled(self_.lspHook_) && ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_ahead(self_), ff_compiler_Token.LLower())) && (!ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_aheadAhead(self_), ff_compiler_Token.LDot())))) {
292
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LKeyword());
293
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LLower())
294
+ } else {
291
295
  imports_.array.push(ff_compiler_Parser.Parser_parseImportDefinition(self_, self_.moduleKey_.packagePair_))
296
+ }
292
297
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "include"))) {
293
298
  throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(ff_compiler_Token.Token_at(ff_compiler_Parser.Parser_current(self_)), "Includes must be at the top of the file or below 'package'"), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
294
299
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "dependency"))) {
@@ -1792,7 +1797,12 @@ instances_.array.push(ff_compiler_Parser.Parser_parseInstanceDefinition(self_))
1792
1797
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs4(ff_compiler_Parser.Parser_current(self_), "data", "class", "capability", "newtype"))) {
1793
1798
  types_.array.push(ff_compiler_Parser.Parser_parseTypeDefinition(self_))
1794
1799
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "import"))) {
1800
+ if(((ff_compiler_LspHook.LspHook_isEnabled(self_.lspHook_) && ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_ahead(self_), ff_compiler_Token.LLower())) && (!ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_aheadAhead(self_), ff_compiler_Token.LDot())))) {
1801
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LKeyword());
1802
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LLower())
1803
+ } else {
1795
1804
  imports_.array.push(ff_compiler_Parser.Parser_parseImportDefinition(self_, self_.moduleKey_.packagePair_))
1805
+ }
1796
1806
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "include"))) {
1797
1807
  throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(ff_compiler_Token.Token_at(ff_compiler_Parser.Parser_current(self_)), "Includes must be at the top of the file or below 'package'"), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
1798
1808
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "dependency"))) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly compiler",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.65",
7
+ "version": "0.5.67",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly language support",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.65",
7
+ "version": "0.5.67",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
package/core/Box.ff DELETED
@@ -1,7 +0,0 @@
1
- class Box[T](mutable value: T)
2
-
3
- extend self[T]: Box[T] {
4
- modify(body: T => T): Unit {
5
- self.value = body(self.value)
6
- }
7
- }