-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(language-server): Add types for types in LSP API (#1078)
- Loading branch information
Showing
7 changed files
with
363 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
aqua Types | ||
|
||
alias Top: ⊤ | ||
alias Bottom: ⊥ | ||
|
||
alias Number: u32 | ||
alias String: string | ||
alias Array: []string | ||
alias Stream: *string | ||
alias Option: ?string | ||
|
||
data Struct: | ||
a: Number | ||
b: String | ||
c: Array | ||
d: Option | ||
|
||
service Srv("srv"): | ||
noop(srvArg: string) | ||
|
||
ability Ability: | ||
a: Number | ||
b: String | ||
|
||
func nilArrow(): | ||
Srv.noop("") | ||
|
||
func fullArrow(a: string, b: u32) -> string, u32: | ||
<- a, b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
describe("Testing LSP types", () => { | ||
it("dummy", async () => { | ||
expect(true).toBeTruthy() | ||
}) | ||
}) | ||
|
||
// FIXME: these tests work only with LSP ESM build (ModuleKind.ESModule in build.sbt) | ||
/* | ||
import { | ||
AbilityType, | ||
AquaLSP, ArrayType, BottomType, | ||
OptionType, | ||
ScalarType, StreamType, StructType, | ||
TopType, | ||
Type, ServiceType, ArrowType | ||
} from '@fluencelabs/aqua-language-server-api/aqua-lsp-api'; | ||
describe("Testing LSP types", () => { | ||
it("check types in aqua file", async () => { | ||
const compiled = await AquaLSP.compile("lsp-aqua/types.aqua", {}) | ||
const types = compiled.tokens.map(ti => ti.type) | ||
const isTop = (type: Type): type is TopType => type.tag === "top"; | ||
const tops = types.filter(isTop) | ||
expect(tops).toHaveLength(1) | ||
const isBottom = (type: Type): type is BottomType => type.tag === "bottom"; | ||
const bottom = types.filter(isBottom) | ||
expect(bottom).toHaveLength(1) | ||
const isScalar = (type: Type): type is ScalarType => type.tag === "scalar"; | ||
const scalars = types.filter(isScalar) | ||
expect(scalars).toHaveLength(8) | ||
scalars.forEach(sc => expect(sc.name).toBeDefined()) | ||
const isArray = (type: Type): type is ArrayType => type.tag === "array"; | ||
const arrays = types.filter(isArray) | ||
expect(arrays).toHaveLength(2) | ||
arrays.forEach(sc => expect(sc.element).toBeDefined()) | ||
const isOption = (type: Type): type is OptionType => type.tag === "option"; | ||
const options = types.filter(isOption) | ||
expect(options).toHaveLength(2) | ||
options.forEach(sc => expect(sc.element).toBeDefined()) | ||
const isStream = (type: Type): type is StreamType => type.tag === "stream"; | ||
const streams = types.filter(isStream) | ||
expect(streams).toHaveLength(1) | ||
streams.forEach(sc => expect(sc.element).toBeDefined()) | ||
const isAbility = (type: Type): type is AbilityType => type.tag === "ability"; | ||
const abilities = types.filter(isAbility) | ||
expect(abilities).toHaveLength(1) | ||
abilities.forEach((sc) => { | ||
expect(sc.name).toBeDefined() | ||
expect(sc.fields).toBeDefined() | ||
expect(Object.entries(sc.fields)).toHaveLength(2) | ||
}) | ||
const isStruct = (type: Type): type is StructType => type.tag === "struct"; | ||
const structs = types.filter(isStruct) | ||
expect(structs).toHaveLength(1) | ||
structs.forEach((sc) => { | ||
expect(sc.name).toBeDefined() | ||
expect(sc.fields).toBeDefined() | ||
expect(Object.entries(sc.fields)).toHaveLength(4) | ||
}) | ||
const isService = (type: Type): type is ServiceType => type.tag === "service"; | ||
const services = types.filter(isService) | ||
expect(services).toHaveLength(1) | ||
services.forEach((sc) => { | ||
expect(sc.name).toBeDefined() | ||
expect(sc.fields).toBeDefined() | ||
expect(Object.entries(sc.fields)).toHaveLength(1) | ||
}) | ||
const isArrow = (type: Type): type is ArrowType => type.tag === "arrow"; | ||
const arrows = types.filter(isArrow) | ||
expect(arrows).toHaveLength(3) | ||
const fullArrow = arrows[0] | ||
const argA = fullArrow.domain.args["a"] | ||
expect(argA).toEqual({name: "string", tag: "scalar"}) | ||
const argB = fullArrow.domain.args["b"] | ||
expect(argB).toEqual({name: "u32", tag: "scalar"}) | ||
const codomain = fullArrow.codomain.types | ||
expect(codomain[0]).toEqual({name: "string", tag: "scalar"}) | ||
expect(codomain[1]).toEqual({name: "u32", tag: "scalar"}) | ||
const nilArrow = arrows[1] | ||
expect(nilArrow.domain.args).toEqual({}) | ||
expect(nilArrow.codomain.types).toEqual([]) | ||
const srvNoopArrow = arrows[2] | ||
expect(srvNoopArrow.domain.args).toEqual({srvArg: {name: "string", tag: "scalar"}}) | ||
expect(srvNoopArrow.codomain.types).toEqual([]) | ||
}) | ||
})*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
language-server/language-server-api/.js/src/main/scala/aqua/lsp/TypeJs.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package aqua.lsp | ||
|
||
import aqua.types.* | ||
|
||
import scala.scalajs.js.Dictionary | ||
import scala.scalajs.js.JSConverters.* | ||
import scalajs.js | ||
|
||
sealed trait TypeJs extends js.Object { | ||
val tag: String | ||
} | ||
|
||
class ScalarTypeJs(val name: String) extends TypeJs { | ||
val tag: String = "scalar" | ||
} | ||
|
||
class ArrayTypeJs(val element: TypeJs) extends TypeJs { | ||
val tag: String = "array" | ||
} | ||
|
||
class OptionTypeJs(val element: TypeJs) extends TypeJs { | ||
val tag: String = "option" | ||
} | ||
|
||
class StreamTypeJs(val element: TypeJs) extends TypeJs { | ||
val tag: String = "stream" | ||
} | ||
|
||
class StreamMapTypeJs(val element: TypeJs) extends TypeJs { | ||
val tag: String = "streammap" | ||
} | ||
|
||
class CanonStreamTypeJs(val element: TypeJs) extends TypeJs { | ||
val tag: String = "canon" | ||
} | ||
|
||
class AbilityTypeJs(val name: String, val fields: js.Dictionary[TypeJs]) extends TypeJs { | ||
val tag: String = "ability" | ||
} | ||
|
||
class StructTypeJs(val name: String, val fields: js.Dictionary[TypeJs]) extends TypeJs { | ||
val tag: String = "struct" | ||
} | ||
|
||
class ServiceTypeJs(val name: String, val fields: js.Dictionary[TypeJs]) extends TypeJs { | ||
val tag: String = "service" | ||
} | ||
|
||
trait ProductType extends TypeJs | ||
|
||
class LabeledConsTypeJs(val args: js.Dictionary[TypeJs]) extends TypeJs { | ||
val tag: String = "labeled" | ||
} | ||
|
||
class UnlabeledConsTypeJs(val types: js.Array[TypeJs]) extends TypeJs { | ||
val tag: String = "unlabeled" | ||
} | ||
|
||
class ArrowTypeJs(val domain: LabeledConsTypeJs, val codomain: UnlabeledConsTypeJs) extends TypeJs { | ||
val tag: String = "arrow" | ||
} | ||
|
||
class NilTypeJs extends TypeJs { | ||
val tag: String = "nil" | ||
} | ||
|
||
class BottomTypeJs extends TypeJs { | ||
val tag: String = "bottom" | ||
} | ||
|
||
class TopTypeJs extends TypeJs { | ||
val tag: String = "top" | ||
} | ||
|
||
object TypeJs { | ||
|
||
def typeList(types: Iterable[(String, Type)]): Dictionary[TypeJs] = | ||
js.Dictionary(types.map { case (n, t) => | ||
(n, TypeJs.fromType(t)) | ||
}.toSeq: _*) | ||
|
||
def fromType(t: Type): TypeJs = { | ||
t match | ||
case ScalarType(name) => new ScalarTypeJs(name) | ||
case LiteralType(_, name) => new ScalarTypeJs(name) | ||
case ArrayType(el) => new ArrayTypeJs(fromType(el)) | ||
case OptionType(el) => new OptionTypeJs(fromType(el)) | ||
case StreamType(el) => new StreamTypeJs(fromType(el)) | ||
case StreamMapType(el) => new StreamMapTypeJs(fromType(el)) | ||
case CanonStreamType(el) => new CanonStreamTypeJs(fromType(el)) | ||
case StructType(name, fields) => new StructTypeJs(name, typeList(fields.toSortedMap)) | ||
case AbilityType(name, fields) => new AbilityTypeJs(name, typeList(fields.toSortedMap)) | ||
case ServiceType(name, fields) => new ServiceTypeJs(name, typeList(fields.toSortedMap)) | ||
case lct: LabeledConsType => new LabeledConsTypeJs(typeList(lct.toLabelledList())) | ||
case uct: UnlabeledConsType => new UnlabeledConsTypeJs(uct.toList.map(fromType).toJSArray) | ||
case ArrowType(domain, codomain) => | ||
ArrowTypeJs( | ||
new LabeledConsTypeJs(typeList(domain.toLabelledList())), | ||
new UnlabeledConsTypeJs(codomain.toList.map(fromType).toJSArray) | ||
) | ||
case TopType => new TopTypeJs() | ||
case BottomType => new BottomTypeJs() | ||
case NilType => new NilTypeJs() | ||
} | ||
} |
Oops, something went wrong.