La barra Avanti/Indietro era un footer bianco a tutta larghezza con una linea di separazione da 1px. Ora è una card bianca staccata su tutti e 4 i lati dalla finestra (UiStile.FloatBar, angoli arrotondati, bordo sottile), riusata anche in PrtMancantiForm per Chiudi/Apri cartella raw. Avanti e Indietro avevano dimensioni diverse (testi di lunghezza diversa, più il grassetto di Primario che richiede più altezza del testo normale) ed erano visivamente disomogenei (bordo sottile quasi invisibile su sfondo bianco per Indietro contro il blu pieno di Avanti). Aggiunti UiStile.SecondarioPieno (variante piena, senza bordo, stessa costruzione di Primario ma grigio chiaro) e UiStile.LarghezzaUguale (stessa larghezza e altezza tra due bottoni, chiamata PRIMA di arrotondare gli angoli: arrotondare e poi ridimensionare lasciava un bordo residuo della Region vecchia). Doc aggiornati nello stesso commit: docs/architettura.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
296 lines
20 KiB
Markdown
296 lines
20 KiB
Markdown
# Architettura di PrepStep (Cevolani StepPrep)
|
|
|
|
Panoramica di tutti i file sorgente e di come collaborano. `PrepStep` è il nome
|
|
tecnico del progetto (cartella, namespace, csproj, eseguibile `PrepStep.exe`);
|
|
**Cevolani StepPrep** è il nome mostrato all'utente finale (titolo finestra, icona,
|
|
versione — vedi `<Version>`/`<Product>` in `PrepStep.csproj`). Per il "come si usa" vedi il `README.md` in root; per il
|
|
formato binario `.asm` vedi `docs/formato-asm.md` (euristica testuale) e
|
|
`docs/formato-asm-record.md` (parser esatto dei record); per la parallelizzazione della
|
|
copia in `raw/` vedi `docs/copia-raw-parallela.md`.
|
|
|
|
## Vista d'insieme
|
|
|
|
Un solo eseguibile WinForms (nessuna CLI, nessun processo esterno): indicizza i file CAD di
|
|
una share di rete in un DB SQLite locale, poi guida l'utente in un wizard a 5 fasi che, a
|
|
partire da una distinta base esportata dal gestionale, raccoglie in locale (`raw/`) tutti i
|
|
file CAD dei componenti e dei loro sotto-assiemi e verifica che l'indice li copra, come
|
|
pre-process prima dell'esportazione STEP con Creo Distributed Batch (manuale, fuori
|
|
dall'app: i file esportati finiscono in `step/`, dentro la cartella di lavoro).
|
|
|
|
```
|
|
Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati dall'indice)
|
|
│
|
|
scansione .asm ─────┘ (sotto-assiemi/parti mancanti)
|
|
│
|
|
drag&drop .asm su Creo → Distributed Batch → step/ (esportazione manuale)
|
|
```
|
|
|
|
## Il processo, dall'inizio alla fine
|
|
|
|
Le 5 fasi sono una pipeline: ognuna consuma quello che ha prodotto la precedente, e il
|
|
bottone "Avanti" si sblocca solo quando il risultato c'è (`AvantiConsentito`). Sotto, cosa
|
|
entra e cosa esce da ciascuna — il dettaglio dei metodi è nella tabella della sezione
|
|
successiva.
|
|
|
|
**1. Indice della share → `cad_index.db`.** `Indexer.ScanAsync` cammina tutte le cartelle di
|
|
primo livello sotto `X:\`, riconosce i nomi Pro-E `<codice>.<tipo>.<versione>` e fa un upsert
|
|
incrementale (confronto su percorso+dimensione+data), così i giri successivi costano solo il
|
|
delta. Qui si sceglie anche la **cartella di lavoro**, che da qui in poi ospita tutto il resto.
|
|
|
|
**2. Distinta del gestionale → CSV.** `DistintaBaseImporter.ConvertiInCsv` riduce l'export a
|
|
due colonne `componente;descrizione`. Se il nome del file segue la convenzione
|
|
`DBP_<codice>_<timestamp>` aggiunge l'assieme generale come riga in più: da quel momento è un
|
|
componente come tutti gli altri, nessun caso speciale a valle.
|
|
|
|
**3. Componenti del CSV → `raw/`.** Per ogni codice del CSV `TrovaPercorsiCad` cerca
|
|
nell'indice l'ultima versione (vista `files_ultima_versione`) e `CopiaFileTrovati` la copia in
|
|
`raw/` in parallelo. Finisce qui il livello "distinta": in `raw/` ci sono i componenti
|
|
elencati dal gestionale, non ancora quello che serve ad aprirli.
|
|
|
|
**4. Chiusura ricorsiva dell'albero → `raw/` completa.** È il cuore del programma, ed è
|
|
l'unica fase che deve ragionare come Creo invece che come il gestionale.
|
|
`RisolviAlberoComponenti` tiene una coda di `.asm` da leggere, partendo da quelli già in
|
|
`raw/`, e per ognuno raccoglie **tre liste diverse**, che non vanno confuse (vedi
|
|
`docs/formato-asm-record.md` §7.3 e §7.5):
|
|
|
|
| Lista | Da dove | Ricorsione | Se non è nell'indice |
|
|
|---|---|---|---|
|
|
| Componenti della distinta | sezione `members` (`EstraiCodiciReferenziati`) | sì | va nei "non trovati" |
|
|
| Componenti **soppressi** | stringhe di piazzamento (`EstraiCodiciSoppressi`) | no — Creo non carica i figli di un soppresso | ignorato: non è un componente, segnalarlo sarebbe un falso allarme |
|
|
| **Riferimenti esterni** | tabella dei modelli citati (`EstraiCodiciRiferimentiEsterni`) | sì — Creo carica il modello citato con tutto il suo albero | ignorato, stesso motivo |
|
|
|
|
Ogni codice trovato viene copiato in `raw/` scegliendo **quale** copia con `ScegliPerCartella`
|
|
(§7.4: lo stesso codice esiste in più cartelle della share nel 13% dei casi, e vince quella
|
|
nella stessa cartella dell'assieme che lo referenzia); se è un `.asm` torna in coda e il giro
|
|
ricomincia, finché restano solo foglie. I rami raggiunti per riferimento esterno viaggiano con
|
|
un flag `Esterno` che li tiene fuori dall'elenco dei "non trovati": quell'elenco continua a
|
|
parlare solo della distinta, che è quello che l'utente si aspetta di leggerci.
|
|
|
|
Il motivo per cui questa fase è più complicata di come sembra: **la lista dei componenti e la
|
|
lista dei file necessari al caricamento non coincidono**, e la seconda è più lunga. Quando si
|
|
sbaglia, Creo Distributed Batch non dice quale file manca — dice solo `[-4] Dati di input non
|
|
completi`.
|
|
|
|
**5. Verifica e consegna a Creo.** `AggiornaAnteprimaAsm` mostra i `.asm` della distinta già
|
|
in `raw/` come icone trascinabili. L'esportazione STEP vera è manuale e fuori dall'app: si
|
|
trascinano i `.asm` su Creo Distributed Batch, che scrive in `step/`.
|
|
|
|
## Entry point
|
|
|
|
- **Program.cs** — `Main()` standard WinForms: `Application.Run(new Form1())`. Nessuna logica.
|
|
|
|
## Finestra principale (wizard)
|
|
|
|
- **Form1.cs** — tutta la UI è costruita in codice (`BuildUi`/`BuildFase*`), non con il
|
|
designer visuale. È un wizard: `_panelFasi[]` contiene un `Panel` per fase, uno solo
|
|
visibile alla volta (`VaiAllaFase`); si avanza con "Avanti" solo se `AvantiConsentito`
|
|
ritorna vero per la fase corrente. `Form1.Designer.cs` contiene solo lo scheletro minimo
|
|
generato dal template (`InitializeComponent`/`Dispose`), non è usato per costruire i
|
|
controlli.
|
|
|
|
Le 5 fasi e i metodi principali dietro ciascuna:
|
|
|
|
| # | Fase | Bottone → metodo | Cosa fa |
|
|
|---|---|---|---|
|
|
| 1 | Database | "Aggiorna indice" → `Indexer.ScanAsync` | Crea/aggiorna `cad_index.db` scansionando la share; un pallino verde/rosso accanto al titolo indica se un DB è caricato. La cartella di lavoro non è mostrata qui (cambiabile in qualunque momento da "File → Scegli cartella di lavoro...") |
|
|
| 2 | Importa Distinta Base | selezione file/drag&drop → `ImportaDistinta` → `DistintaBaseImporter.ConvertiInCsv`, poi "Verifica presenza" → `VerificaCodiciNelDb` | Xls/Xml gestionale → CSV componente;descrizione, scritto nella cartella di lavoro; "Verifica presenza" (visibile solo dopo un import riuscito) cerca i componenti nell'indice e colora le righe della griglia — è quella che sblocca "Avanti", non il solo import |
|
|
| 3 | Crea cartella raw | "Crea cartella raw" → `CreaCartellaRaw` | `TrovaPercorsiCad` + `CopiaFileTrovati` (parallela) → `raw/` dentro la cartella di lavoro |
|
|
| 4 | Trova componenti referenziati | "Trova componenti referenziati" → `TrovaPrtReferenziati` → `RisolviAlberoComponenti` | Legge i `.asm` in `raw/`, risolve ricorsivamente sotto-assiemi/parti nell'indice e li copia anch'essi in `raw/`, insieme ai componenti soppressi e ai modelli citati per riferimento esterno che servono a Creo per aprire l'assieme |
|
|
| 5 | Verifica completezza | (ingresso in fase) → `AggiornaAnteprimaAsm` | Mostra le icone trascinabili dei `.asm` della distinta già in `raw/`, da trascinare su Creo per l'esportazione STEP (Distributed Batch) |
|
|
|
|
Stato condiviso tra le fasi (campi privati di `Form1`): `_dbPath`, `_cartellaLavoro`,
|
|
`_percorsoInputCorrente`, `_righeCorrenti` (righe del CSV), `_ultimaVerifica` (cache percorsi
|
|
CAD), `_ultimaCartellaRaw`.
|
|
|
|
Menu (`MenuStrip`, in cima alla finestra): "File → Nuovo" (Ctrl+N) azzera lo
|
|
stato delle fasi 2-5 (`NuovaEstrazione`) e va direttamente alla fase 2, senza passare dalla
|
|
fase 1: database e cartella di lavoro restano quelli già caricati, non serve rifare lo scan;
|
|
"File → Scegli cartella di lavoro..." → `ScegliCartellaLavoro`, cambia in qualunque momento
|
|
la destinazione di CSV/`raw/`/`step/`; "File → Pulisci raw e step..." svuota le cartelle
|
|
`raw/`/`step/` nella cartella di lavoro (`PulisciRawEStep`, non tocca l'indice); "Aiuto →
|
|
Guida" (F1) apre `GuidaForm`, sintesi interattiva delle 5 fasi per chi non ha letto questi
|
|
docs.
|
|
|
|
Altre responsabilità in Form1.cs:
|
|
- `TrovaPercorsiCad` / `CaricaCodiciNoti` — query sul DB (`files_ultima_versione`), la
|
|
seconda carica tutti i codici prt/asm noti in un colpo solo (usata sia per risolvere i
|
|
componenti sia da `AssemblyComponentScanner` per validare i token generici).
|
|
- `CopiaFileTrovati` — copia (in parallelo, grado 6) i file trovati in `raw/`, saltando
|
|
silenziosamente quelli irraggiungibili (share offline/permessi).
|
|
- `PulisciRawEStep` — svuota `raw/` e `step/` nella cartella di lavoro (manutenzione,
|
|
richiede conferma).
|
|
- `InizializzaDatabase` / `ScegliDatabase` — localizzazione del DB (ultimo usato, salvato in
|
|
`%AppData%/PrepStep/ultimo_db.txt`, o `cad_index.db` accanto all'eseguibile).
|
|
- `InizializzaCartellaLavoro` / `ScegliCartellaLavoro` — stesso pattern per la cartella di
|
|
lavoro (`ultima_cartella_lavoro.txt`), fallback `AppContext.BaseDirectory` se non c'è
|
|
ancora nulla di salvato: nessuna dipendenza da un marker di repo, funziona identica
|
|
sull'exe pubblicato standalone spostato su un'altra macchina.
|
|
|
|
## Indicizzazione
|
|
|
|
- **Indexer.cs** — `ScanAsync` cammina tutte le cartelle di primo livello sotto la radice
|
|
(scoperte dinamicamente, non un elenco fisso) con un walk manuale a stack (`Walk`, più
|
|
veloce di `EnumerateFiles(..., AllDirectories)` su share con centinaia di migliaia di
|
|
file), esclude le cartelle `temp_*`, estrae da ogni nome file il pattern Pro-E
|
|
`<codice>.<tipo>.<versione>` (`ParseFilename`, regex), e fa un upsert incrementale riga per
|
|
riga confrontando `percorso_completo` + dimensione + data modifica. Progresso riportato via
|
|
`IProgress<ScanProgress>` (marshalato sul thread UI). Contiene anche lo schema SQL: tabella
|
|
`files` e vista `files_ultima_versione` (ultima versione per `codice`+`tipo_file` via
|
|
`ROW_NUMBER() OVER (...)`, non self-join+`GROUP BY` per evitare tempi quasi quadratici su
|
|
~200k righe).
|
|
|
|
## Lettura dei componenti referenziati in un `.asm`
|
|
|
|
`Form1.EstraiCodiciReferenziati` (usata da `RisolviAlberoComponenti`, fase 4) prova prima
|
|
`AsmRecordReader.EstraiCodiciReferenziati` e ripiega su
|
|
`AssemblyComponentScanner.EstraiCodiciReferenziati` solo se il primo lancia
|
|
`InvalidDataException` (file che non rispetta il formato validato dal reverse engineering).
|
|
|
|
- **AsmRecordReader.cs** — legge esattamente la sezione `members` del binario `.asm` (id/tipo/
|
|
nome dei componenti diretti, con risoluzione del nome istanza di family table dal parametro
|
|
`ConfigName`): nessuna euristica, struttura a record. Lancia `InvalidDataException` se il
|
|
file non ha una sezione `members` o se il conteggio dichiarato non torna. Espone anche le
|
|
due liste "non di distinta": `EstraiCodiciSoppressi` (che passa da `members` per sapere
|
|
quali codici sono già noti, quindi può lanciare la stessa eccezione — `Form1.CodiciSoppressi`
|
|
la intercetta e restituisce vuoto) e `EstraiCodiciRiferimentiEsterni` (scansione a sé, non
|
|
lancia). Dettagli in `docs/formato-asm-record.md`. Condivisa con `scripts/CreoBom.cs` via
|
|
`#:project`.
|
|
- **AssemblyComponentScanner.cs** — estrae euristicamente i codici componente referenziati
|
|
contando le occorrenze di stringhe candidate nel testo binario. Due strategie: codici
|
|
numerici Pro-E riconosciuti da soli via regex (come nei nomi file), e nomi alfabetici di
|
|
parti commerciali tokenizzati genericamente e validati contro l'elenco di codici noti del DB
|
|
(altrimenti il rumore binario sarebbe ingestibile). Dettagli sull'euristica e i falsi
|
|
positivi noti in `docs/formato-asm.md`. Resta il fallback per i file che il parser esatto
|
|
non copre, e la fonte di verità per `ExtractCreoStrings.cs`/`BomViaDb.cs`.
|
|
|
|
Quella lista è **la distinta**, e non coincide con i file che servono a Creo per aprire
|
|
l'assieme: ne restano fuori due categorie, che il loro file serve comunque, altrimenti il
|
|
caricamento fallisce (`docs/formato-asm-record.md` §7.3). `AsmRecordReader` le restituisce a
|
|
parte, e la fase 4 le copia in `raw/` senza contarle fra i "non trovati":
|
|
|
|
- `EstraiCodiciSoppressi` — i componenti **soppressi**: spariti da `members`, ancora citati
|
|
dalla feature che li posiziona. Non si ricorre dentro (Creo non carica i figli di un
|
|
componente soppresso).
|
|
- `EstraiCodiciRiferimentiEsterni` — i modelli legati da **riferimento esterno** (assembly
|
|
feature, datum copiati), elencati in una tabella a parte del binario (§7.5). Qui si ricorre
|
|
dentro, perché Creo carica il modello citato con tutto il suo albero.
|
|
|
|
## Quale copia di un componente si copia in `raw/`
|
|
|
|
Lo stesso codice esiste spesso in più cartelle della share, con contenuto diverso e pari
|
|
versione (13% dei codici, vedi `docs/formato-asm-record.md` §7.4). Il `.asm` non registra
|
|
quale copia usa, quindi `RisolviAlberoComponenti` replica la regola di Creo:
|
|
`Form1.ScegliPerCartella` preferisce la copia nella **stessa cartella dell'assieme che la
|
|
referenzia** (`Form1.CartellaDiOrigine` ricostruisce quella cartella per gli assiemi di
|
|
partenza), e solo in mancanza ripiega su versione più alta e data più recente. Sbagliare copia
|
|
non dà un errore comprensibile: Creo non apre l'assieme e dice solo "dati di input non
|
|
completi".
|
|
|
|
## Import distinta base
|
|
|
|
- **DistintaBaseImporter.cs** — converte l'export del gestionale (SpreadsheetML XML con
|
|
estensione `.xls`/`.xml`, oppure `.xls`/`.xlsx` binario vero, distinti dai primi byte del
|
|
file) nelle sole colonne Componente/Descrizione, foglio `"Distinta Base"`. Se il nome del
|
|
file segue la convenzione `DBP_<codice>_<timestamp>`, aggiunge l'assieme generale come riga
|
|
in più (il foglio elenca solo i componenti sotto l'assieme). Scrive il CSV nella cartella
|
|
passata da `Form1` (la cartella di lavoro, impostabile da "File → Scegli cartella di lavoro..."),
|
|
non necessariamente accanto al file di input.
|
|
|
|
## Finestre di dialogo (modali, mostrate a fine step)
|
|
|
|
- **ProgressForm.cs** — durante l'aggiornamento indice: barra di progresso, conteggi
|
|
nuovi/aggiornati/invariati/rimossi, tempo trascorso e stima del tempo rimanente (dal ritmo
|
|
file/secondo rispetto al totale atteso, preso dal conteggio della scansione precedente
|
|
salvato nel DB).
|
|
- **ProgressoComponentiForm.cs** — dialog minimale (etichetta + barra) durante
|
|
`RisolviAlberoComponenti` in fase 4.
|
|
|
|
## Stile UI condiviso
|
|
|
|
- **UiStile.cs** — `Primario`/`Secondario`: stile piatto per i bottoni (bordo sottile
|
|
per i secondari, blu pieno per l'azione principale di ogni fase), entrambi con
|
|
`AutoSize`+`Padding`+`MinimumSize` invece di una `Size` fissa in pixel indovinata a
|
|
mano (altrimenti il testo va a capo e si taglia in verticale se non ci sta nella
|
|
larghezza scelta). `SecondarioPieno` è la variante senza bordo (sfondo grigio chiaro
|
|
pieno) per i bottoni secondari sopra le card bianche di `Card`/`FloatBar`, dove il
|
|
bordo sottile di `Secondario` è troppo poco visibile su sfondo bianco. `Arrotonda`
|
|
applica angoli arrotondati a un `Control` qualsiasi (bottone o card) via `Region`
|
|
calcolata su `SizeChanged`, non una volta sola: con `AutoSize` la dimensione finale si
|
|
conosce solo a layout avvenuto — va chiamata dopo aver fissato le dimensioni finali del
|
|
controllo (es. dopo `LarghezzaUguale`), altrimenti la `Region` vecchia resta visibile
|
|
come bordo residuo finché non arriva un repaint completo. `Card` costruisce una card di
|
|
stato (sfondo/bordo distinti, angoli arrotondati), usata in fase 1 per il riepilogo
|
|
Database. `FloatBar` costruisce la barra di navigazione "flottante" in fondo alle
|
|
finestre (card bianca staccata su tutti e 4 i lati, non un footer a tutta larghezza):
|
|
usata per Avanti/Indietro nel wizard e per Chiudi/Apri cartella raw in
|
|
`PrtMancantiForm`. `LarghezzaUguale` forza la stessa larghezza e altezza tra due
|
|
bottoni della stessa barra (es. Avanti/Indietro, che altrimenti avrebbero dimensioni
|
|
diverse: testi di lunghezza diversa, e il font in grassetto di `Primario` richiede più
|
|
altezza di quello normale di `Secondario`/`SecondarioPieno`).
|
|
- **app.ico** — icona dell'app, referenziata da `<ApplicationIcon>` nel csproj (icona
|
|
dell'exe in Esplora risorse/taskbar) e riletta esplicitamente in `Form1.BuildUi()`
|
|
con `Icon.ExtractAssociatedIcon(Application.ExecutablePath)` per la titlebar, senza
|
|
copiare il file `.ico` nell'output. Sfondo trasparente (nessuna card bianca), 7
|
|
risoluzioni da 16 a 256px.
|
|
- **PrtMancantiForm.cs** — esito della risoluzione ricorsiva dell'albero componenti: PRT e
|
|
sotto-assiemi trovati e copiati in `raw/`, più i codici referenziati che non corrispondono a
|
|
nessun file indicizzato (possono essere disegni, componenti davvero mancanti, o falsi
|
|
positivi della scansione `.asm`).
|
|
- **GuidaForm.cs** — guida interattiva ("Aiuto → Guida"/F1): lista delle 5 fasi a sinistra,
|
|
testo a destra; sintesi, il dettaglio resta solo in questi docs.
|
|
|
|
## Persistenza
|
|
|
|
- **DB** (`cad_index.db`, SQLite) — vedi tabella `files`/vista `files_ultima_versione` sopra.
|
|
Percorso ricordato tra un avvio e l'altro in `%AppData%/PrepStep/ultimo_db.txt`
|
|
(`SalvaUltimoDbUsato`/`LeggiUltimoDbUsato`), scritto ogni volta che si carica un DB
|
|
(all'avvio se già noto, oppure da "Apri DB..." o al termine di "Aggiorna indice"); se il
|
|
file non c'è o punta a un percorso cancellato, `InizializzaDatabase` ripiega su
|
|
`cad_index.db` accanto all'eseguibile o nella working directory. Radice disco di scansione
|
|
di default `X:\` (`Form1.RadiceDiscoDefault`, hardcoded).
|
|
- **Cartella di lavoro** — stesso meccanismo del DB sopra, salvata in
|
|
`%AppData%/PrepStep/ultima_cartella_lavoro.txt`; se non c'è una preferenza salvata (o punta
|
|
a una cartella cancellata) si propone la cartella del DB caricato, o in ultima istanza
|
|
`AppContext.BaseDirectory`; cambiabile in qualunque momento da "File → Scegli cartella di
|
|
lavoro...". Tutti i file generati a valle ci finiscono dentro: il CSV della distinta, `raw/`
|
|
(CAD dei componenti e sotto-componenti); `step/` non è scritta dall'app ma è dove l'utente
|
|
esporta gli STEP a mano con Creo Distributed Batch, a partire dai file trascinati da `raw/`
|
|
in fase 5.
|
|
|
|
## Script standalone (`scripts/`)
|
|
|
|
C# file-based apps (.NET 10, `dotnet run scripts/Nome.cs -- arg1 arg2`, nessun `.csproj`,
|
|
dipendenze extra con `#:package Nome@versione` in testa al file):
|
|
|
|
- **ExtractCreoStrings.cs** — BOM di un `.asm` risolvendo ricorsivamente i sotto-assiemi
|
|
contro `cad_index.db` (stessa logica di `AssiemeCompleto` in Form1, solo codici numerici
|
|
Pro-E).
|
|
- **BomViaDb.cs** — come sopra ma con la tokenizzazione generica validata contro il DB, per
|
|
intercettare anche i nomi alfabetici delle parti commerciali.
|
|
- **CreoBom.cs** — usa `AsmRecordReader` (stesso lettore esatto della GUI, fase 4/5, via
|
|
`#:project`) invece dell'euristica testuale. Risolve i sottoassiemi cercandoli in cartelle
|
|
locali (`-p`), non contro `cad_index.db` come `ExtractCreoStrings.cs`/`BomViaDb.cs`.
|
|
- **Analyze.cs** — dump del contesto testo/hex attorno a un pattern in un file binario, per
|
|
investigare a mano nuovi falsi positivi prima di toccare la regex di
|
|
`AssemblyComponentScanner`.
|
|
- **Query.cs** — query SQL ad-hoc contro `cad_index.db` da riga di comando.
|
|
|
|
> ⚠️ Nota importante di sicurezza: se `dotnet run` viene lanciato dentro `PrepStep/`
|
|
> (che contiene un `.csproj` di tipo `WinExe`), esegue l'app GUI vera invece dello script
|
|
> standalone e resta bloccato in attesa che una finestra si chiuda. Lanciare gli script da
|
|
> una cartella senza `.csproj` (es. la root del repo o `scripts/` stessa).
|
|
|
|
## Test
|
|
|
|
- **PrepStep.Tests/** (xUnit) — riferimento al progetto principale via `ProjectReference`
|
|
+ `InternalsVisibleTo` (in `PrepStep.csproj`), così i test chiamano direttamente
|
|
`Indexer.ParseFilename` e `AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli
|
|
come API pubblica. File: `IndexerParseFilenameTests.cs`, `IndexerScanTests.cs`,
|
|
`AssemblyComponentScannerTests.cs`, `AsmRecordReaderTests.cs`,
|
|
`DistintaBaseImporterTests.cs`, `CaseInsensitiveLookupIntegrationTests.cs`,
|
|
`PipelineEndToEndTests.cs`.
|
|
|
|
`AsmRecordReaderTests.cs` costruisce i `.asm` byte per byte con dei piccoli helper
|
|
(`Membro`, `ConfigName`, `ObjName`, `Riferimenti`): ogni caso strano trovato sulla share
|
|
diventa un test minimale invece di un file binario da versionare.
|