138 lines
9.7 KiB
Markdown
138 lines
9.7 KiB
Markdown
# Flux editare .vcx/.scx pe text (comun proiectelor VFP)
|
|
|
|
Textul .vc2/.sc2 e sursa de editare; write-back in binar cu `txt2vcx.ps1`, fara VFP IDE.
|
|
Detalii complete: `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`. Parametrii per proiect (nemigrate):
|
|
`cautare_vcx_vct.md`.
|
|
|
|
**Proiecte migrate (ROACONT, COMUN, …): flux in-arbore.** Textul .??2 sta langa binare, il
|
|
improspateaza `git_sync.ps1 -ProjectRoot <root>` (nu cache extern) — la inceput de sesiune si
|
|
inainte de orice `git commit`. Write-back doar pentru vcx/scx; `frx/mnx/lbx/pjx/dbc/dbf` doar
|
|
in IDE. `txt2vcx.ps1` cu `-CacheRoot` = `-ProjectRoot` (implicit). Pasul 0 de mai jos devine
|
|
rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vcx2txt.ps1` +
|
|
`-CacheRoot` separat) ramane doar pentru proiectele nemigrate.
|
|
|
|
**Capcana: `git_sync.ps1` cu `-ProjectRoot` pe COMUN direct.** Lista implicita
|
|
`-RoundtripExempt` are cai de forma `COMUN\clase\<f>.vcx` (raportate la radacina unei aplicatii,
|
|
unde COMUN e subfolder) si se lipeste de `-ProjectRoot`. Cand radacina E chiar COMUN, caile nu
|
|
mai potrivesc si clasele scutite (FFC/third-party cu `#INCLUDE`, ex. `oinventar.vcx`) raporteaza
|
|
fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
|
|
`git_sync.ps1 -ProjectRoot 'D:\ROA\ROAGEST\COMUN' -RoundtripExempt @('clase\accessibility.vcx',
|
|
'clase\oinventar.vcx','clase\_gdiplus.vcx','clase\_reportlistener.vcx',
|
|
'utile\foxcharts\foxcharts.vcx','utile\web\_webview.vcx')` - si apeleaza scriptul cu `&`, nu cu
|
|
`powershell -File` (acolo lista nu se leaga ca array).
|
|
|
|
## Invariante — se verifica la FIECARE editare, inainte de write-back
|
|
|
|
1. **Membru nou de clasa (proprietate SAU metoda) are intrare in `*<DefinedPropArrayMethod>`**:
|
|
`*p: nume` / `*m: nume`. Sectiunea "Membri noi de clasa" mai jos.
|
|
2. **Ordinea alfabetica FoxBin2Prg**: `_` vine DUPA litere, nu inainte (ASCII). Ordinea canonica se
|
|
citeste din `<staging>\verify\*.vc2`, nu se deduce.
|
|
3. **CRLF, zero LF izolati**:
|
|
`perl -e 'local $/; open F,"<:raw",$ARGV[0]; $d=<F>; $crlf=()=$d=~/\r\n/g; $lf=()=$d=~/\n/g; print $lf-$crlf' <fisier>`
|
|
trebuie sa dea 0.
|
|
4. **Cens de octeti >= 0x80 identic** cu cel de dinainte de editare:
|
|
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`
|
|
(detalii: `conventie_encoding_cp1252.md`).
|
|
|
|
**Nici fidelity-check-ul, nici `-DryRun` nu acopera punctele 1, 3 si 4** — trec cu OK peste toate
|
|
trei. Sunt verificari separate, de facut de mana.
|
|
|
|
## Membri noi de clasa: `*p:` / `*m:`
|
|
|
|
Orice proprietate sau metoda NOUA cere, pe langa valoarea din `*<PropValue>` / corpul `PROCEDURE`,
|
|
o intrare in blocul `*<DefinedPropArrayMethod>` al clasei: `*p: nume` pentru proprietate, `*m: nume`
|
|
pentru metoda. Override-urile de metode mostenite (Init, Show, hook-uri) NU au nevoie de `*m:`.
|
|
|
|
Fara acea intrare, esecul e tacut in patru pasi:
|
|
|
|
1. textul se scrie si `txt2vcx.ps1` **trece fidelity-check-ul** — fidelity compara text-sursa cu
|
|
text-regenerat, deci nu are cum sa observe lipsa; binarul primeste valoarea/corpul ca text;
|
|
2. VFP nu materializeaza membrul pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.`, iar accesul cade cu
|
|
eroarea 1734 "Property ... is not found" (proprietate) sau "Data type mismatch" la
|
|
`Createobject` (metoda). Dovedit in ambele sensuri pe o clasa de proba izolata;
|
|
3. **prima salvare din IDE-ul VFP peste acel binar sterge tacit membrul** — la metode raman doar
|
|
corpurile `PROCEDURE` orfane, la proprietati dispare si valoarea;
|
|
4. urmatorul `git_sync` regenereaza textul din binarul deja ciuntit, deci pierderea intra si in
|
|
`.??2`, si in backup-urile de runda.
|
|
|
|
Pasul 3 loveste si definitii `*m:` **deja existente si corecte** (patit pe ROAGEST:
|
|
`import_adauga_factura.recalc_tva`, `import_nota.do_adauga/do_copie/do_reface`; simptom: crash la
|
|
`Createobject` cu "Data type mismatch" raportat la linia apelanta). Deci dupa ORICE sesiune IDE pe
|
|
o clasa atinsa: `git_sync` + compara lista `*p:`/`*m:` cu starea de dinainte.
|
|
|
|
Verificare inainte de write-back: `grep -n '\*[pm]: <nume>' <fisier>.vc2`.
|
|
Pozitia in fisier nu e libera — FoxBin2Prg regenereaza membrul la pozitia lui alfabetica din
|
|
`*<DefinedPropArrayMethod>` (cu `_` dupa litere); o intrare sau o metoda scrisa in alta parte pica
|
|
fidelity-check-ul. Sursa de adevar pentru ordine si pozitie: textul din `<staging>\verify\*.vc2`.
|
|
|
|
## Pasii unei runde
|
|
|
|
0. Refresh text (obligatoriu la inceput de sesiune si dupa orice sesiune IDE — staleness pe
|
|
mtime): `git_sync.ps1 -ProjectRoot <root>` (proiecte nemigrate: `vcx2txt.ps1 -Project <pjx>
|
|
-ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`).
|
|
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (langa binar, in arbore; la runde
|
|
succesive necomise, diff-ul fata de HEAD ar amesteca rundele).
|
|
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))` -
|
|
doar pentru round-trip pe octeti, NU pentru retastat literal diacritice (antetul zice
|
|
`CPID="1252"`, dar octetii diacriticelor sunt de fapt cp1250: `conventie_encoding_cp1252.md`).
|
|
NU tool-ul Edit/Write (UTF-8 strica diacriticele). Continut nou ASCII, TAB-uri ca in jur,
|
|
fara reflow (format position-sensitive, proprietati alfabetizate). Valabil si pentru `.prg`.
|
|
3. Patch review: `git diff --no-index <bak> <editat> > docs/diff_runda<N>_<subiect>.patch`
|
|
(exit 1 = normal). Utilizatorul revizuieste FISIERUL de patch si aproba — aprobarea
|
|
conditioneaza COMMIT-ul, nu write-back-ul: pasii 5 si 6 se fac imediat, fara sa astepti
|
|
raspunsul (si pe `COMUN`), ca review-ul sa primeasca rezultate de test, nu o propunere
|
|
netestata. Rollback daca patch-ul e respins sau modificarea nu merge: `git checkout` pe
|
|
binare (`.vcx`+`.vct`) sau write-back din `*.pre_runda<N>.bak`.
|
|
Comentariile in cod: conventia din `reguli_lucru.md` (punctul 2).
|
|
Obligatoriu inainte de a preda patch-ul la review: skill-ul de code-review rulat pe bucatile
|
|
de cod din diff (nu doar citire manuala) - prinde defecte gen IIF cu numar gresit de
|
|
argumente, deduplicari care nu se declanseaza niciodata, interogari mai largi decat e nevoie.
|
|
Review-ul verifica si compactitatea/reutilizarea: cod care refoloseste functiile si clasele
|
|
comune existente in loc sa le reinventeze (ex. cursor2lista()/cursor2listac() pentru liste
|
|
dintr-un cursor in loc de Scan manual; butoane din cmd_butoane.vcx in loc de butoane ad-hoc).
|
|
Inventarul comunelor: COMUN\docs\inventar-comun.md - se consulta si la pasul de plan/arhitectura,
|
|
inainte de a scrie cod nou.
|
|
4. Preconditie write-back: binarul tinta sa nu fie blocat. `txt2vcx.ps1` verifica singur
|
|
(`Test-ExclusiveAccess` pe `.vcx`+`.vct`) si refuza cu mesaj clar daca e lock. NU conteaza
|
|
existenta altor instante `vfp9` — utilizatorul poate lucra in paralel in alt proiect VFP —
|
|
si NU se omoara procese: cand lock-ul exista, se cere utilizatorului sa inchida sesiunea.
|
|
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root>` (`-CacheRoot` implicit =
|
|
`-ProjectRoot`; pentru proiecte nemigrate cu cache separat, paseaza-l explicit)
|
|
(+ `-AllowComun` pentru tinte COMUN — afecteaza toate aplicatiile ROA, deci schimbarea in sine
|
|
se propune explicit, dar write-back-ul local nu asteapta aprobarea; nimic nu pleaca la celelalte
|
|
aplicatii pana la commit+push).
|
|
Succes = fidelity-check trecut: binar cu mtime nou; `vcx2txt.ps1` ulterior il vede la zi.
|
|
6. Teste finale pe cerinta initiala (cerinta Marius, valabila in toate proiectele VFP):
|
|
dupa ultima runda, teste e2e (harness UI, pe fluxul real al utilizatorului) care verifica
|
|
ca rezultatul construit *arata si se comporta* conform cerintei initiale — scenariul concret
|
|
dat de Marius, cu valorile lui asteptate — nu doar teste per-fix. Assert-uri pe continutul
|
|
rezultatului (sume, campuri, randuri), nu pe efecte de suprafata ("a aparut un rand" nu e
|
|
suficient).
|
|
7. Curatenie dupa commit (backup-uri `.pre_runda*.bak`, patch-uri, artefacte de test):
|
|
`powershell -File COMUN\utile\curatenie.ps1` — vezi regula 1 din `reguli_lucru.md`.
|
|
|
|
## Capcane
|
|
|
|
- `.mnx`/`.frx` raman read-only (GENMENU in IDE / round-trip fragil).
|
|
- Linii complet goale in metode pica fidelity doar pe whitespace; fix: preia `verify\*.vc2`
|
|
din staging peste cache si reia write-back-ul.
|
|
- Nu folosi *Project > Build* ca sa recompilezi un binar vizat: rebuild-ul recompileaza toate
|
|
`.vcx`/`.vct` din proiect si le rescrie antetul (timestamp compilare) si posibil p-code-ul
|
|
intern si la librarii neatinse efectiv, aparand fals ca "modificate" in diff — de aici
|
|
fluxul text->bin punctual pe binarul vizat.
|
|
- Subagentii delegati primesc regulile 2-5 in prompt si raporteaza unicitatea sirurilor
|
|
inlocuite + rezultatul fidelity-check-ului.
|
|
- Fisierele `.vc2`/`.sc2` sunt CRLF, dar here-string-urile PowerShell (`"...`r`n..."` sau
|
|
`@"..."@`) produc LF simplu pe orice linie noua inserata daca nu incluzi explicit `` `r`n ``
|
|
la fiecare capat de linie - rezultatul e un fisier cu sfarsituri de linie amestecate (CRLF pe
|
|
continutul vechi, LF pe cel nou). Verificare finala obligatorie dupa orice scriere: numara
|
|
octetii `0x0A` neprecedati de `0x0D` (LF izolati) - trebuie sa fie 0.
|
|
- **`-DryRun` NU e plasa de siguranta pentru capete de linie** - fidelity-check-ul compara doar
|
|
continutul text, nu CRLF vs LF, deci un fisier convertit integral la LF de un tool Edit/Write
|
|
(patit si cumulat, pe mai multe runde succesive) trece cu OK/EXITCODE=0. Verificare separata,
|
|
obligatorie dupa fiecare editare, langa censul de octeti non-ASCII deja documentat mai sus:
|
|
`perl -e 'local $/; open F,"<:raw",$ARGV[0]; $d=<F>; $crlf=()=$d=~/\r\n/g; $lf=()=$d=~/\n/g; print $lf-$crlf' <fisier>`
|
|
trebuie sa dea 0. Semnal secundar: daca `git diff --numstat` arata brusc tot fisierul schimbat
|
|
(nu doar liniile atinse), capetele de linie sunt gresite. Reparare (doar dupa ce ai confirmat ca
|
|
fisierul n-are deja niciun `\r`): `perl -pe 's/\n/\r\n/' < f > f.tmp`.
|