diff --git a/README.md b/README.md index 1a87d1e..461bcf4 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,10 @@ package schema #Classes: { MyCustomGAM: { + #meta: { + direction: "INOUT" + multithreaded: true + } Param1: int Param2?: string ... diff --git a/specification.md b/specification.md index d6f1b71..eac44ac 100644 --- a/specification.md +++ b/specification.md @@ -21,11 +21,12 @@ The executable should support the following subcommands: The LSP server should provide the following capabilities: - **Diagnostics**: Report syntax errors and validation issues. +- **Incremental Sync**: Supports `textDocumentSync` kind 2 (Incremental) for better performance with large files. - **Hover Documentation**: - **Objects**: Display `CLASS::Name` and any associated docstrings. - **Signals**: Display `DataSource.Name TYPE (SIZE) [IN/OUT/INOUT]` along with docstrings. - **GAMs**: Show the list of States where the GAM is referenced. - - **Referenced Signals**: Show the list of GAMs where the signal is referenced. + - **Referenced Signals**: Show the list of GAMs where the signal is referenced (indicating Input/Output direction). - **Go to Definition**: Jump to the definition of a reference, supporting navigation across any file in the current project. - **Go to References**: Find usages of a node or field, supporting navigation across any file in the current project. - **Code Completion**: Autocomplete fields, values, and references. @@ -173,6 +174,7 @@ The tool must build an index of the configuration to support LSP features and va - **Conditional Fields**: Validation of fields whose presence or value depends on the values of other fields within the same node or context. - **Schema Definition**: - Class validation rules must be defined in a separate schema file using the **CUE** language. + - **Metadata**: Class properties like direction (`#direction`) and multithreading support (`#multithreaded`) are stored within a `#meta` field in the class definition (e.g., `#meta: { direction: "IN", multithreaded: true }`). - **Project-Specific Classes**: Developers can define their own project-specific classes and corresponding validation rules, expanding the validation capabilities for their specific needs. - **Schema Loading**: - **Default Schema**: The tool should look for a default schema file `marte_schema.cue` in standard system locations: @@ -218,6 +220,7 @@ The LSP and `check` command should report the following: - Field type mismatches. - Grammar errors (e.g., missing closing brackets). - **Invalid Function Reference**: Elements in the `Functions` array of a `State.Thread` must be valid references to defined GAM nodes. + - **Threading Violation**: A DataSource that is not marked as multithreaded (via `#meta.multithreaded`) is used by GAMs running in different threads within the same State. ## Logging diff --git a/test/ast_test.go b/test/ast_test.go new file mode 100644 index 0000000..39d2071 --- /dev/null +++ b/test/ast_test.go @@ -0,0 +1,94 @@ +package integration + +import ( + "testing" + + "github.com/marte-community/marte-dev-tools/internal/parser" +) + +func TestASTCoverage(t *testing.T) { + pos := parser.Position{Line: 1, Column: 1} + + var n parser.Node + // var d parser.Definition // Definition has unexported method, can't assign? + // Yes I can assign if I am using the interface type exported by parser. + // But I cannot call the method. + var d parser.Definition + var v parser.Value + + // Field + f := &parser.Field{Position: pos} + n = f + d = f + if n.Pos() != pos { + t.Error("Field.Pos failed") + } + _ = d + + // ObjectNode + o := &parser.ObjectNode{Position: pos} + n = o + d = o + if n.Pos() != pos { + t.Error("ObjectNode.Pos failed") + } + + // StringValue + sv := &parser.StringValue{Position: pos} + n = sv + v = sv + if n.Pos() != pos { + t.Error("StringValue.Pos failed") + } + _ = v + + // IntValue + iv := &parser.IntValue{Position: pos} + n = iv + v = iv + if n.Pos() != pos { + t.Error("IntValue.Pos failed") + } + + // FloatValue + fv := &parser.FloatValue{Position: pos} + n = fv + v = fv + if n.Pos() != pos { + t.Error("FloatValue.Pos failed") + } + + // BoolValue + bv := &parser.BoolValue{Position: pos} + n = bv + v = bv + if n.Pos() != pos { + t.Error("BoolValue.Pos failed") + } + + // ReferenceValue + rv := &parser.ReferenceValue{Position: pos} + n = rv + v = rv + if n.Pos() != pos { + t.Error("ReferenceValue.Pos failed") + } + + // ArrayValue + av := &parser.ArrayValue{Position: pos} + n = av + v = av + if n.Pos() != pos { + t.Error("ArrayValue.Pos failed") + } + + // Package + pkg := &parser.Package{Position: pos} + // Package implements Node? + // ast.go: func (p *Package) Pos() Position { return p.Position } + // Yes. + n = pkg + if n.Pos() != pos { + t.Error("Package.Pos failed") + } +}