Variable reference from $VAR to @VAR to avoid object conflict
This commit is contained in:
@@ -173,10 +173,10 @@ You can define variables using `#var`. The type expression supports CUE syntax.
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
Reference a variable using `$`:
|
Reference a variable using `@`:
|
||||||
|
|
||||||
```marte
|
```marte
|
||||||
Field = $MyVar
|
Field = @MyVar
|
||||||
```
|
```
|
||||||
|
|
||||||
### Expressions
|
### Expressions
|
||||||
@@ -187,7 +187,7 @@ You can use operators in field values. Supported operators:
|
|||||||
```marte
|
```marte
|
||||||
Field1 = 10 + 20 * 2 // 50
|
Field1 = 10 + 20 * 2 // 50
|
||||||
Field2 = "Hello " .. "World"
|
Field2 = "Hello " .. "World"
|
||||||
Field3 = $MyVar + 5
|
Field3 = @MyVar + 5
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build Override
|
### Build Override
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ func (b *Builder) collectVariables(tree *index.ProjectTree) {
|
|||||||
func (b *Builder) evaluate(val parser.Value) parser.Value {
|
func (b *Builder) evaluate(val parser.Value) parser.Value {
|
||||||
switch v := val.(type) {
|
switch v := val.(type) {
|
||||||
case *parser.VariableReferenceValue:
|
case *parser.VariableReferenceValue:
|
||||||
name := strings.TrimPrefix(v.Name, "$")
|
name := strings.TrimPrefix(v.Name, "@")
|
||||||
if res, ok := b.variables[name]; ok {
|
if res, ok := b.variables[name]; ok {
|
||||||
return b.evaluate(res)
|
return b.evaluate(res)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ func (pt *ProjectTree) indexValue(file string, val parser.Value) {
|
|||||||
})
|
})
|
||||||
case *parser.VariableReferenceValue:
|
case *parser.VariableReferenceValue:
|
||||||
pt.References = append(pt.References, Reference{
|
pt.References = append(pt.References, Reference{
|
||||||
Name: strings.TrimPrefix(v.Name, "$"),
|
Name: strings.TrimPrefix(v.Name, "@"),
|
||||||
Position: v.Position,
|
Position: v.Position,
|
||||||
File: file,
|
File: file,
|
||||||
IsVariable: true,
|
IsVariable: true,
|
||||||
|
|||||||
@@ -611,7 +611,7 @@ func HandleHover(params HoverParams) *Hover {
|
|||||||
} else if res.Reference.TargetVariable != nil {
|
} else if res.Reference.TargetVariable != nil {
|
||||||
v := res.Reference.TargetVariable
|
v := res.Reference.TargetVariable
|
||||||
targetName = v.Name
|
targetName = v.Name
|
||||||
fullInfo = fmt.Sprintf("**Variable**: `%s`\nType: `%s`", v.Name, v.TypeExpr)
|
fullInfo = fmt.Sprintf("**Variable**: `@%s`\nType: `%s`", v.Name, v.TypeExpr)
|
||||||
if v.DefaultValue != nil {
|
if v.DefaultValue != nil {
|
||||||
fullInfo += fmt.Sprintf("\nDefault: `%s`", valueToString(v.DefaultValue))
|
fullInfo += fmt.Sprintf("\nDefault: `%s`", valueToString(v.DefaultValue))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const (
|
|||||||
TokenCaret
|
TokenCaret
|
||||||
TokenAmpersand
|
TokenAmpersand
|
||||||
TokenConcat
|
TokenConcat
|
||||||
|
TokenVariableReference
|
||||||
)
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
@@ -184,6 +185,8 @@ func (l *Lexer) NextToken() Token {
|
|||||||
return l.lexString()
|
return l.lexString()
|
||||||
case '#':
|
case '#':
|
||||||
return l.lexHashIdentifier()
|
return l.lexHashIdentifier()
|
||||||
|
case '@':
|
||||||
|
return l.lexVariableReference()
|
||||||
case '$':
|
case '$':
|
||||||
return l.lexObjectIdentifier()
|
return l.lexObjectIdentifier()
|
||||||
}
|
}
|
||||||
@@ -311,3 +314,14 @@ func (l *Lexer) lexHashIdentifier() Token {
|
|||||||
}
|
}
|
||||||
return l.emit(TokenIdentifier)
|
return l.emit(TokenIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Lexer) lexVariableReference() Token {
|
||||||
|
for {
|
||||||
|
r := l.next()
|
||||||
|
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
l.backup()
|
||||||
|
return l.emit(TokenVariableReference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ func (p *Parser) parseAtom() (Value, bool) {
|
|||||||
true
|
true
|
||||||
case TokenIdentifier:
|
case TokenIdentifier:
|
||||||
return &ReferenceValue{Position: tok.Position, Value: tok.Value}, true
|
return &ReferenceValue{Position: tok.Position, Value: tok.Value}, true
|
||||||
case TokenObjectIdentifier:
|
case TokenVariableReference:
|
||||||
return &VariableReferenceValue{Position: tok.Position, Name: tok.Value}, true
|
return &VariableReferenceValue{Position: tok.Position, Name: tok.Value}, true
|
||||||
case TokenLBrace:
|
case TokenLBrace:
|
||||||
arr := &ArrayValue{Position: tok.Position}
|
arr := &ArrayValue{Position: tok.Position}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ func (v *Validator) valueToInterface(val parser.Value, ctx *index.ProjectNode) i
|
|||||||
case *parser.ReferenceValue:
|
case *parser.ReferenceValue:
|
||||||
return t.Value
|
return t.Value
|
||||||
case *parser.VariableReferenceValue:
|
case *parser.VariableReferenceValue:
|
||||||
name := strings.TrimPrefix(t.Name, "$")
|
name := strings.TrimPrefix(t.Name, "@")
|
||||||
if info := v.Tree.ResolveVariable(ctx, name); info != nil {
|
if info := v.Tree.ResolveVariable(ctx, name); info != nil {
|
||||||
if info.Def.DefaultValue != nil {
|
if info.Def.DefaultValue != nil {
|
||||||
return v.valueToInterface(info.Def.DefaultValue, ctx)
|
return v.valueToInterface(info.Def.DefaultValue, ctx)
|
||||||
@@ -525,7 +525,7 @@ func (v *Validator) getFieldValue(f *parser.Field, ctx *index.ProjectNode) strin
|
|||||||
case *parser.BoolValue:
|
case *parser.BoolValue:
|
||||||
return strconv.FormatBool(val.Value)
|
return strconv.FormatBool(val.Value)
|
||||||
case *parser.VariableReferenceValue:
|
case *parser.VariableReferenceValue:
|
||||||
name := strings.TrimPrefix(val.Name, "$")
|
name := strings.TrimPrefix(val.Name, "@")
|
||||||
if info := v.Tree.ResolveVariable(ctx, name); info != nil {
|
if info := v.Tree.ResolveVariable(ctx, name); info != nil {
|
||||||
if info.Def.DefaultValue != nil {
|
if info.Def.DefaultValue != nil {
|
||||||
return v.getFieldValue(&parser.Field{Value: info.Def.DefaultValue}, ctx)
|
return v.getFieldValue(&parser.Field{Value: info.Def.DefaultValue}, ctx)
|
||||||
@@ -1126,7 +1126,7 @@ func (v *Validator) CheckVariables() {
|
|||||||
if ref.IsVariable && ref.TargetVariable == nil {
|
if ref.IsVariable && ref.TargetVariable == nil {
|
||||||
v.Diagnostics = append(v.Diagnostics, Diagnostic{
|
v.Diagnostics = append(v.Diagnostics, Diagnostic{
|
||||||
Level: LevelError,
|
Level: LevelError,
|
||||||
Message: fmt.Sprintf("Unresolved variable reference: '$%s'", ref.Name),
|
Message: fmt.Sprintf("Unresolved variable reference: '@%s'", ref.Name),
|
||||||
Position: ref.Position,
|
Position: ref.Position,
|
||||||
File: ref.File,
|
File: ref.File,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ func TestFormatterVariables(t *testing.T) {
|
|||||||
#var MyStr: string | "A" = "default"
|
#var MyStr: string | "A" = "default"
|
||||||
|
|
||||||
+Obj = {
|
+Obj = {
|
||||||
Field1 = $MyInt
|
Field1 = @MyInt
|
||||||
Field2 = $MyStr
|
Field2 = @MyStr
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
p := parser.NewParser(content)
|
p := parser.NewParser(content)
|
||||||
@@ -35,11 +35,10 @@ func TestFormatterVariables(t *testing.T) {
|
|||||||
t.Errorf("Variable MyInt formatted incorrectly. Got:\n%s", output)
|
t.Errorf("Variable MyInt formatted incorrectly. Got:\n%s", output)
|
||||||
}
|
}
|
||||||
// Note: parser adds space after each token in TypeExpr
|
// Note: parser adds space after each token in TypeExpr
|
||||||
// string | "A" -> "string | \"A\""
|
// string | "A" -> "string | \"A\""
|
||||||
if !strings.Contains(output, "#var MyStr: string | \"A\" = \"default\"") {
|
if !strings.Contains(output, "#var MyStr: string | \"A\" = \"default\"") {
|
||||||
t.Errorf("Variable MyStr formatted incorrectly. Got:\n%s", output)
|
t.Errorf("Variable MyStr formatted incorrectly. Got:\n%s", output)
|
||||||
}
|
}
|
||||||
if !strings.Contains(output, "Field1 = $MyInt") {
|
if !strings.Contains(output, "Field1 = @MyInt") {
|
||||||
t.Errorf("Variable reference $MyInt formatted incorrectly. Got:\n%s", output)
|
t.Errorf("Variable reference @MyInt formatted incorrectly. Got:\n%s", output)
|
||||||
}
|
}}
|
||||||
}
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func TestLSPAppTestRepro(t *testing.T) {
|
|||||||
A = {
|
A = {
|
||||||
DataSource = DDB
|
DataSource = DDB
|
||||||
Type = uint32
|
Type = uint32
|
||||||
Value = $Value
|
Value = @Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutputSignals = {
|
OutputSignals = {
|
||||||
@@ -75,7 +75,7 @@ func TestLSPAppTestRepro(t *testing.T) {
|
|||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
// Check Unresolved Variable
|
// Check Unresolved Variable
|
||||||
if !strings.Contains(output, "Unresolved variable reference: '$Value'") {
|
if !strings.Contains(output, "Unresolved variable reference: '@Value'") {
|
||||||
t.Error("LSP missing unresolved variable error")
|
t.Error("LSP missing unresolved variable error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ diags := params["diagnostics"].([]interface{})
|
|||||||
foundOrdering = true
|
foundOrdering = true
|
||||||
t.Log("Found Ordering error")
|
t.Log("Found Ordering error")
|
||||||
}
|
}
|
||||||
if strings.Contains(m, "Unresolved variable reference: '$Value'") {
|
if strings.Contains(m, "Unresolved variable reference: '@Value'") {
|
||||||
foundVariable = true
|
foundVariable = true
|
||||||
t.Log("Found Variable error")
|
t.Log("Found Variable error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func TestLSPDiagnosticsAppTest(t *testing.T) {
|
|||||||
A = {
|
A = {
|
||||||
DataSource = DDB
|
DataSource = DDB
|
||||||
Type = uint32
|
Type = uint32
|
||||||
Value = $Value
|
Value = @Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutputSignals = {
|
OutputSignals = {
|
||||||
@@ -87,9 +87,9 @@ func TestLSPDiagnosticsAppTest(t *testing.T) {
|
|||||||
t.Fatal("LSP did not publish diagnostics")
|
t.Fatal("LSP did not publish diagnostics")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Check Unresolved Variable Error ($Value)
|
// 1. Check Unresolved Variable Error (@Value)
|
||||||
if !strings.Contains(output, "Unresolved variable reference: '$Value'") {
|
if !strings.Contains(output, "Unresolved variable reference: '@Value'") {
|
||||||
t.Error("Missing diagnostic for unresolved variable '$Value'")
|
t.Error("Missing diagnostic for unresolved variable '@Value'")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Check INOUT Ordering Error (Signal A consumed but not produced)
|
// 2. Check INOUT Ordering Error (Signal A consumed but not produced)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func TestLSPHoverVariable(t *testing.T) {
|
|||||||
content := `
|
content := `
|
||||||
#var MyInt: int = 123
|
#var MyInt: int = 123
|
||||||
+Obj = {
|
+Obj = {
|
||||||
Field = $MyInt
|
Field = @MyInt
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
uri := "file://hover_var.marte"
|
uri := "file://hover_var.marte"
|
||||||
@@ -47,8 +47,8 @@ func TestLSPHoverVariable(t *testing.T) {
|
|||||||
t.Errorf("Hover def missing default value. Got: %s", contentDef)
|
t.Errorf("Hover def missing default value. Got: %s", contentDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Hover on Reference ($MyInt)
|
// 2. Hover on Reference (@MyInt)
|
||||||
// Line 4 (index 3). $MyInt is at col 12.
|
// Line 4 (index 3). @MyInt is at col 12.
|
||||||
paramsRef := lsp.HoverParams{
|
paramsRef := lsp.HoverParams{
|
||||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||||
Position: lsp.Position{Line: 3, Character: 12},
|
Position: lsp.Position{Line: 3, Character: 12},
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestLSPVariableRefs(t *testing.T) {
|
|||||||
content := `
|
content := `
|
||||||
#var MyVar: int = 1
|
#var MyVar: int = 1
|
||||||
+Obj = {
|
+Obj = {
|
||||||
Field = $MyVar
|
Field = @MyVar
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
uri := "file://vars.marte"
|
uri := "file://vars.marte"
|
||||||
@@ -29,11 +29,11 @@ func TestLSPVariableRefs(t *testing.T) {
|
|||||||
lsp.Tree.ResolveReferences()
|
lsp.Tree.ResolveReferences()
|
||||||
|
|
||||||
// 1. Definition from Usage
|
// 1. Definition from Usage
|
||||||
// Line 4: " Field = $MyVar"
|
// Line 4: " Field = @MyVar"
|
||||||
// $ is at col 12 (0-based) ?
|
// @ is at col 12 (0-based) ?
|
||||||
// " Field = " is 4 + 6 + 3 = 13 chars?
|
// " Field = " is 4 + 6 + 3 = 13 chars?
|
||||||
// 4 spaces. Field (5). " = " (3). 4+5+3 = 12.
|
// 4 spaces. Field (5). " = " (3). 4+5+3 = 12.
|
||||||
// So $ is at 12.
|
// So @ is at 12.
|
||||||
paramsDef := lsp.DefinitionParams{
|
paramsDef := lsp.DefinitionParams{
|
||||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||||
Position: lsp.Position{Line: 3, Character: 12},
|
Position: lsp.Position{Line: 3, Character: 12},
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ func TestOperators(t *testing.T) {
|
|||||||
#var S2: string = "World"
|
#var S2: string = "World"
|
||||||
|
|
||||||
+Obj = {
|
+Obj = {
|
||||||
Math = $A + $B
|
Math = @A + @B
|
||||||
Precedence = $A + $B * 2
|
Precedence = @A + @B * 2
|
||||||
Concat = $S1 .. " " .. $S2
|
Concat = @S1 .. " " .. @S2
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
// Check Parser
|
// Check Parser
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestRegexVariable(t *testing.T) {
|
|||||||
#var BadIP: string & =~"^[0-9.]+$" = "abc"
|
#var BadIP: string & =~"^[0-9.]+$" = "abc"
|
||||||
|
|
||||||
+Obj = {
|
+Obj = {
|
||||||
IP = $IP
|
IP = @IP
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
// Test Validator
|
// Test Validator
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func TestVariableValidation(t *testing.T) {
|
|||||||
#var MyStr: string = "hello"
|
#var MyStr: string = "hello"
|
||||||
+MyPID = {
|
+MyPID = {
|
||||||
Class = PIDGAM
|
Class = PIDGAM
|
||||||
Kp = $MyStr
|
Kp = @MyStr
|
||||||
Ki = 0.0
|
Ki = 0.0
|
||||||
Kd = 0.0
|
Kd = 0.0
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ func TestVariableValidation(t *testing.T) {
|
|||||||
#var MyGain: float = 1.5
|
#var MyGain: float = 1.5
|
||||||
+MyPID = {
|
+MyPID = {
|
||||||
Class = PIDGAM
|
Class = PIDGAM
|
||||||
Kp = $MyGain
|
Kp = @MyGain
|
||||||
Ki = 0.0
|
Ki = 0.0
|
||||||
Kd = 0.0
|
Kd = 0.0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ func TestVariables(t *testing.T) {
|
|||||||
|
|
||||||
+Obj = {
|
+Obj = {
|
||||||
Class = Test
|
Class = Test
|
||||||
Field1 = $MyInt
|
Field1 = @MyInt
|
||||||
Field2 = $MyStr
|
Field2 = @MyStr
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
// Test Parsing
|
// Test Parsing
|
||||||
|
|||||||
Reference in New Issue
Block a user