package analyzer import ( "five/compiler/parser" "strings" "testing" ) func analyze(t *testing.T, source string) []Diagnostic { t.Helper() file, errs := parser.Parse("test.prg", source) if len(errs) > 0 { t.Fatalf("parse error: %s", errs[0]) } return Analyze(file) } func TestCleanCode(t *testing.T) { diags := analyze(t, ` PROCEDURE Main() LOCAL cName, nAge cName := "Charles" nAge := 30 ? cName, nAge RETURN `) for _, d := range diags { if d.Severity == SevError || d.Severity == SevWarning { t.Errorf("unexpected diagnostic: %s", d) } } } func TestUndeclaredVariable(t *testing.T) { diags := analyze(t, ` PROCEDURE Main() LOCAL cName cName := "Charles" ? cName, nAge RETURN `) found := false for _, d := range diags { if strings.Contains(d.Message, "undeclared") && strings.Contains(d.Message, "nAge") { found = true } } if !found { t.Error("expected 'undeclared variable nAge' warning") } } func TestUnusedVariable(t *testing.T) { diags := analyze(t, ` PROCEDURE Main() LOCAL cUsed, cNeverTouched cUsed := "hello" ? cUsed RETURN `) found := false for _, d := range diags { if strings.Contains(d.Message, "unused") && strings.Contains(d.Message, "cNeverTouched") { found = true } } if !found { t.Error("expected 'unused variable cNeverTouched' hint") } } func TestParamsDeclared(t *testing.T) { diags := analyze(t, ` FUNCTION Add(a, b) LOCAL nResult nResult := a + b RETURN nResult `) for _, d := range diags { if d.Severity == SevError || d.Severity == SevWarning { t.Errorf("unexpected: %s", d) } } } func TestMultiFunction(t *testing.T) { diags := analyze(t, ` PROCEDURE Main() LOCAL n n := GetValue() ? n RETURN FUNCTION GetValue() LOCAL x x := 42 RETURN x `) for _, d := range diags { if d.Severity == SevWarning { t.Errorf("unexpected warning: %s", d) } } } func TestForLoopVar(t *testing.T) { diags := analyze(t, ` PROCEDURE Main() LOCAL i, aData aData := {1, 2, 3} FOR i := 1 TO Len(aData) ? aData[i] NEXT RETURN `) for _, d := range diags { if d.Severity == SevWarning { t.Errorf("unexpected: %s", d) } } } func TestMultiAssignDeclared(t *testing.T) { diags := analyze(t, ` PROCEDURE Main() LOCAL cName, nAge cName, nAge := "Charles", 30 ? cName, nAge RETURN `) for _, d := range diags { if d.Severity == SevWarning { t.Errorf("unexpected: %s", d) } } }