Files
zzet--gortex/internal/parser/languages/pascal_test.go
T
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

176 lines
4.3 KiB
Go

package languages
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zzet/gortex/internal/graph"
)
func TestPascalExtractor_Unit(t *testing.T) {
src := []byte(`unit Shapes;
interface
uses
SysUtils, Classes;
type
TCircle = class
public
constructor Create(R: Double);
function Area: Double;
end;
implementation
constructor TCircle.Create(R: Double);
begin
end;
function TCircle.Area: Double;
begin
Result := 3.14 * 1.0;
end;
procedure Hello;
begin
WriteLn('hi');
end;
end.
`)
e := NewPascalExtractor()
require.Equal(t, "pascal", e.Language())
res, err := e.Extract("Shapes.pas", src)
require.NoError(t, err)
var gotUnit, gotType, gotCreate, gotArea, gotHello bool
for _, n := range res.Nodes {
// Methods carry the bare name and a class-qualified ID — the
// convention shared with every other language — instead of jamming
// the qualified name into Name as the old regex extractor did.
switch n.ID {
case "Shapes.pas::Shapes":
gotUnit = true
case "Shapes.pas::TCircle":
gotType = true
case "Shapes.pas::TCircle.Create":
gotCreate = true
case "Shapes.pas::TCircle.Area":
gotArea = true
case "Shapes.pas::Hello":
gotHello = true
}
}
var gotUses bool
for _, ed := range res.Edges {
if ed.Kind == graph.EdgeImports && ed.To == "unresolved::import::SysUtils" {
gotUses = true
}
}
assert.True(t, gotUnit)
assert.True(t, gotType)
assert.True(t, gotCreate)
assert.True(t, gotArea)
assert.True(t, gotHello)
assert.True(t, gotUses)
}
func TestPascalExtractor_EmptyInput(t *testing.T) {
res, err := NewPascalExtractor().Extract("e.pas", []byte(""))
require.NoError(t, err)
require.Len(t, res.Nodes, 1)
assert.Equal(t, graph.KindFile, res.Nodes[0].Kind)
}
// TestPascalParenlessCallEdges is the C1 named test: the tree-sitter extractor
// emits call edges for both parenthesised (`Compute(x)`) and paren-less (`Baz;`)
// calls — the sharpest regression, since the old regex extractor emitted zero —
// and resolves same-file callees directly to their definition at a higher
// provenance tier than an unresolved external call.
func TestPascalParenlessCallEdges(t *testing.T) {
src := []byte(`unit MyUnit;
interface
type
TFoo = class
public
function Bar(x: Integer): string;
procedure Baz;
end;
implementation
function TFoo.Bar(x: Integer): string;
begin
Result := Compute(x);
Baz;
end;
procedure TFoo.Baz;
begin
DoThing;
end;
end.
`)
res, err := NewPascalExtractor().Extract("MyUnit.pas", src)
require.NoError(t, err)
type edge struct {
from, to string
origin string
}
var calls []edge
for _, e := range res.Edges {
if e.Kind == graph.EdgeCalls {
calls = append(calls, edge{e.From, e.To, e.Origin})
}
}
has := func(from, to, origin string) bool {
for _, c := range calls {
if c.from == from && c.to == to && c.origin == origin {
return true
}
}
return false
}
// Parenthesised call to an external proc — unresolved, name-only tier.
assert.True(t, has("MyUnit.pas::TFoo.Bar", "unresolved::*.Compute", graph.OriginTextMatched),
"parenthesised call Compute(x) should emit an edge; got %v", calls)
// Paren-less call to a same-file method — resolved directly, higher tier.
assert.True(t, has("MyUnit.pas::TFoo.Bar", "MyUnit.pas::TFoo.Baz", graph.OriginASTResolved),
"paren-less call Baz; should resolve in-file to TFoo.Baz; got %v", calls)
// Paren-less call to an external proc — unresolved.
assert.True(t, has("MyUnit.pas::TFoo.Baz", "unresolved::*.DoThing", graph.OriginTextMatched),
"paren-less call DoThing; should emit an edge; got %v", calls)
}
func TestPascalExtractor_FactoryChainReceiver(t *testing.T) {
src := []byte("procedure Run;\nbegin\n Builder().WithX().Build();\nend;\n")
res, err := NewPascalExtractor().Extract("w.pas", src)
if err != nil {
t.Fatal(err)
}
var build *graph.Edge
seen := map[string]int{}
for _, e := range res.Edges {
if e.Kind == graph.EdgeCalls {
seen[e.To]++
if e.To == "unresolved::*.Build" {
build = e
}
}
}
if build == nil {
t.Fatal("Build() call edge not found")
}
if got, _ := build.Meta["receiver_expr"].(string); got != "Builder().WithX()" {
t.Errorf("receiver_expr = %q, want Builder().WithX()", got)
}
if seen["unresolved::*.Build"] != 1 {
t.Errorf("Build() emitted %d times, want exactly 1", seen["unresolved::*.Build"])
}
}