Files
flora2roa/Teste/verifica_sintaxa.ps1
Marius Mutu 2736cbd525 Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP git-ignored)
Include si sistemul de depanare/testare headless din Teste\ (harness UI cu capturi, verificare de sintaxa prin compilare, wrappere text<->binar) si docs\depanare_testare_flora2roa.md.
2026-08-02 08:56:52 +03:00

129 lines
5.7 KiB
PowerShell

<#
.SYNOPSIS
Verificare de sintaxa prin compilare headless a fisierelor .prg din FLORA2ROA.
.DESCRIPTION
Cel mai ieftin test dupa orice editare de .prg (vezi COMUN\docs\depanare_testare_vfp.md, sect. 4).
Compileaza COPII ale fisierelor intr-un folder temporar, ca .fxp-urile si .err-urile generate
sa nu murdareasca arborele proiectului. VFP nu rezolva simboluri externe la compilare, deci
copia izolata e suficienta pentru sintaxa.
Toate fisierele se compileaza intr-o SINGURA rulare vfp9: lansarile repetate de vfp9 din
aceeasi sesiune PowerShell esueaza tacut (procesul porneste dar nu executa - vezi
COMUN\docs\testare-ui-vfp.md, capcana d).
Verdict per fisier: existenta unui <nume>.err dupa compilare. Se raporteaza si liniile mai
lungi de 250 de caractere (capcana VFP: literal/linie prea lunga = eroare de compilare sau
eroare 11 derutanta la runtime).
NU inlocuieste testul functional: prinde sintaxa, nu apeluri catre metode inexistente.
.PARAMETER Files
Fisiere .prg de verificat. Implicit toate .prg-urile din radacina proiectului si din Teste\.
.PARAMETER ProjectRoot
Radacina proiectului (implicit folderul parinte al acestui script).
.EXAMPLE
powershell -ExecutionPolicy Bypass -File Teste\verifica_sintaxa.ps1
.EXAMPLE
powershell -ExecutionPolicy Bypass -File Teste\verifica_sintaxa.ps1 -Files myutils.prg,app.prg
#>
[CmdletBinding()]
param(
[string[]]$Files,
[string]$ProjectRoot,
[int]$MaxLineLen = 250,
[string]$Vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe'
)
$ErrorActionPreference = 'Stop'
if (-not $ProjectRoot) { $ProjectRoot = Split-Path $PSScriptRoot -Parent }
if (-not (Test-Path $Vfp)) { throw "Nu gasesc vfp9.exe: $Vfp" }
if (-not $Files) {
$Files = @(Get-ChildItem -Path $ProjectRoot -Filter '*.prg' -File | ForEach-Object { $_.FullName })
$Files += @(Get-ChildItem -Path (Join-Path $ProjectRoot 'Teste') -Filter '*.prg' -File -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName })
}
$Files = $Files | ForEach-Object { if ([IO.Path]::IsPathRooted($_)) { $_ } else { Join-Path $ProjectRoot $_ } }
$work = Join-Path $env:TEMP ('flora2roa_syntax_' + [Guid]::NewGuid().ToString('N').Substring(0,8))
New-Item -ItemType Directory -Force -Path $work | Out-Null
# fisierele .h referite prin #INCLUDE trebuie sa fie langa copie, altfel compilarea da eroare
Get-ChildItem -Path $ProjectRoot -Filter '*.h' -File -ErrorAction SilentlyContinue |
ForEach-Object { Copy-Item $_.FullName (Join-Path $work $_.Name) -Force }
# omoara doar instantele vfp9 proprii (linia de comanda contine folderul de lucru temporar)
function Stop-VfpProprii([string]$Marker) {
Get-CimInstance Win32_Process -Filter "Name='vfp9.exe'" -ErrorAction SilentlyContinue | ForEach-Object {
if ($_.CommandLine -and $_.CommandLine.ToLower().Contains($Marker.ToLower())) {
Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
}
}
}
# copiaza sursele + strange liniile prea lungi (analiza statica, fara VFP)
$copii = @()
$liniiLungi = @{}
foreach ($f in $Files) {
if (-not (Test-Path $f)) { Write-Warning "lipsa: $f"; continue }
$nume = [IO.Path]::GetFileName($f)
$copie = Join-Path $work $nume
Copy-Item -LiteralPath $f -Destination $copie -Force
$copii += [pscustomobject]@{ Nume = $nume; Sursa = $f; Copie = $copie }
$lungi = @()
$linii = [IO.File]::ReadAllLines($f, [Text.Encoding]::GetEncoding(1252))
for ($i = 0; $i -lt $linii.Length; $i++) {
if ($linii[$i].Length -gt $MaxLineLen) { $lungi += ('{0} (len={1})' -f ($i + 1), $linii[$i].Length) }
}
if ($lungi) { $liniiLungi[$nume] = ($lungi -join '; ') }
}
if (-not $copii) { Write-Host 'Nimic de verificat.'; return }
# un singur .prg care compileaza toate copiile (SAFETY OFF: fara dialog "overwrite?" headless)
$linii = @('SET SAFETY OFF', 'SET TALK OFF')
foreach ($c in $copii) { $linii += ('lcT = "{0}"' -f $c.Copie); $linii += 'COMPILE (lcT)' }
$linii += 'STRTOFILE("gata", "' + (Join-Path $work '_gata.txt') + '")'
$linii += 'QUIT'
$tmpPrg = Join-Path $work '_compile_all.prg'
Set-Content -Path $tmpPrg -Value (($linii -join "`r`n") + "`r`n") -Encoding ascii
# -A ignora config.fpw implicit, -T sare peste splash; ambele obligatorii headless
$p = Start-Process -FilePath $Vfp -ArgumentList @('-A', '-T', "`"$tmpPrg`"") -PassThru -WindowStyle Minimized
if (-not $p.WaitForExit(180000)) { Write-Warning 'Timeout la compilare (180s).'; try { $p.Kill() } catch {} }
Stop-VfpProprii $work
if (-not (Test-Path (Join-Path $work '_gata.txt'))) {
Write-Warning 'Compilarea nu a ajuns la final - verdictul per fisier poate fi incomplet.'
}
$rezultate = foreach ($c in $copii) {
$err = [IO.Path]::ChangeExtension($c.Copie, 'err')
$fxp = [IO.Path]::ChangeExtension($c.Copie, 'fxp')
$erori = if (Test-Path $err) { (Get-Content -Raw $err).Trim() } else { '' }
[pscustomobject]@{
Fisier = $c.Nume
Sintaxa = if ($erori) { 'ERORI' } elseif (Test-Path $fxp) { 'OK' } else { 'NECOMPILAT' }
Erori = $erori
LiniiLungi = $(if ($liniiLungi.ContainsKey($c.Nume)) { $liniiLungi[$c.Nume] } else { '' })
}
}
Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue
$rezultate | Format-Table Fisier, Sintaxa -AutoSize
foreach ($r in $rezultate | Where-Object { $_.Erori }) {
Write-Host ''
Write-Warning ("ERORI in {0}:`n{1}" -f $r.Fisier, $r.Erori)
}
foreach ($r in $rezultate | Where-Object { $_.LiniiLungi }) {
Write-Host ''
Write-Warning ("Linii peste $MaxLineLen caractere in {0}: {1}" -f $r.Fisier, $r.LiniiLungi)
}
$nrProbleme = @($rezultate | Where-Object { $_.Sintaxa -ne 'OK' }).Count
Write-Host ''
Write-Host ("Gata. Fisiere verificate: {0} Cu probleme: {1}" -f @($rezultate).Count, $nrProbleme)
exit ([int]($nrProbleme -gt 0))