--- name: advpl-to-tlpp-migration description: "Guide the migration of legacy AdvPL (Advanced Programming Language) code to modern TLPP (TOTVS Language Plus Plus). Covers feature comparison, syntax transformation, include/namespace adoption, typing, Try-Catch, REST migration, long identifiers, JSON inline, named parameters, access modifiers, and StaticCall removal. Use when user says 'migrate to TLPP', 'convert AdvPL', 'modernize .prw to .tlpp', 'add typing'." license: MIT metadata: domain: Protheus maintainer: Customizações ADVPL/TLPP author: Thalion Starforge version: '4.1.0' category: Migration and Modernization --- # AdvPL-to-TLPP Migration ## Overview Migrate legacy AdvPL source files (`.prw`, `.prx`) to modern TLPP (`.tlpp`) incrementally and safely. TLPP is an evolution of AdvPL that introduces modern language features while maintaining full backward compatibility with existing AdvPL constructs. This skill provides a structured migration path that can be applied gradually — no forced rewrite is required. ## When to Use Use this skill when: - Modernizing legacy AdvPL code to TLPP - Converting `.prw` files to `.tlpp` - Adopting TLPP-exclusive features (typing, try-catch, namespace, etc.) - Replacing prohibited constructs (e.g., `StaticCall`) in TLPP sources - Preparing code for TLPP REST migration from WsRESTful - Onboarding developers transitioning from AdvPL to TLPP --- ## Feature Comparison: AdvPL vs. TLPP For the complete feature-by-feature comparison table (19 features covering scoping, control structures, typing, namespaces, Try-Catch, JSON inline, class modifiers, REST, and StaticCall status), see [advpl-tlpp-feature-comparison.md](references/advpl-tlpp-feature-comparison.md). --- ## Migration Process > **MANDATORY RULE — File Extension:** Any source file that includes `#include "tlpp-core.th"` or uses TLPP-exclusive features **must** use the `.tlpp` extension. If a `.prw` or `.prx` file is being migrated or modified to adopt TLPP constructs, rename it to `.tlpp` as part of the same change. The AdvPL compiler silently ignores TLPP directives in `.prw`/`.prx` files, which leads to hard-to-diagnose failures. **Always change the extension first.** The migration involves 15 steps, each addressing a specific AdvPL → TLPP transformation: 1. **File Extension and Includes** — `.prw` → `.tlpp`, add `#include "tlpp-core.th"` 2. **Add Namespace** — Organize code with `Namespace company.module.feature` 3. **Add Type Annotations** — Variables, parameters, return values (`as Type`) 4. **Replace ErrorBlock with Try-Catch** — Modern exception handling 5. **Replace StaticCall** — Use `FWLoadMenuDef`, `FWLoadModel`, namespace calls 6. **Use Long Identifier Names** — TLPP removes the 10-char limit 7. **Use Named Parameters** — Improve readability at call sites 8. **Use JSON Inline** — Replace `JsonObject():New()` chains 9. **Add Class Access Modifiers** — `Private`, `Protected`, `Public` 10. **Migrate WsRESTful to TLPP REST** — Annotation-based `@Get`, `@Post`, etc. 11. **Fix Incorrect Inheritance** — `LongNameClass` (not `LongClassName`) 12. **Remove ISAM Driver Usage** — Migrate to `FWTemporaryTable` 13. **Migrate Console APIs to FWLogMsg** — Replace `ConOut`, `OutErr`, `?` 14. **Remove IIF Usage** — Replace with `If/Else/EndIf` 15. **Migrate FormCommit Override to FWModelEvent** — Use `FWFormCommit(oModel)` For complete before/after diff examples for all 15 steps, see [tlpp-migration-patterns.md](references/tlpp-migration-patterns.md). --- ## Migration Checklist ### Pre-Migration - [ ] Source file is under version control with a clean commit - [ ] Existing tests pass (or tests exist for the code) - [ ] Dependencies on the file are identified (callers, includes) - [ ] Team is aware of the migration (naming changes affect callers) ### File Transformation - [ ] File extension changed from `.prw` to `.tlpp` - [ ] `#include "tlpp-core.th"` added as the first include - [ ] `Namespace` declaration added - [ ] All `StaticCall()` replaced with direct calls or `FWLoad*` functions - [ ] User Function return types added (`as Type`) - [ ] Parameter types added (`as Type`) - [ ] Variable types added (`as Type`) ### Modernization (Incremental) - [ ] `ErrorBlock` patterns replaced with `Try-Catch` where appropriate - [ ] Short identifier names expanded to descriptive names - [ ] `Private` variable scope replaced with `Local` where possible - [ ] Class access modifiers added (`Private`, `Protected`, `Public`) - [ ] Named parameters used for functions with 3+ parameters - [ ] JSON inline syntax used for JSON object construction - [ ] WsRESTful services migrated to TLPP REST annotations - [ ] `LongNameClass` used for inheritance (not `LongClassName`) - [ ] ISAM drivers (`MSCREATE`, `DBCREATE`, `CRIATRAB`) replaced with `FWTemporaryTable` - [ ] `ConOut()` / `OutErr()` / `?` replaced with `FWLogMsg()` - [ ] `IIF()` replaced with `If/Else/EndIf` blocks - [ ] `FormCommit` overrides migrated to `FWModelEvent` / `FWFormCommit(oModel)` pattern > Refer to [references/sonarqube-rules-reference.md](../references/sonarqube-rules-reference.md) for the complete SonarQube rules reference. ### Post-Migration - [ ] Source compiles without errors - [ ] All unit/integration tests pass - [ ] Callers updated if function signatures changed - [ ] RPO recompiled and tested in development environment - [ ] No regression in existing functionality --- ## Common Migration Pitfalls | Pitfall | Symptom | Resolution | | ------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------ | | Using `#include "tlpp-core.th"` in a `.prw`/`.prx` file | TLPP features silently ignored; unexpected runtime behavior | Rename the file to `.tlpp` before adding TLPP includes or features | | Using long identifiers in `.prw` files | Silent truncation, wrong function calls | Only use long names in `.tlpp` files | | `StaticCall` in `.tlpp` file | Compilation error | Replace with `FWLoadMenuDef`, `FWLoadModel`, or namespace call | | Missing `#include "tlpp-core.th"` | TLPP features not recognized | Add as the first include | | Default access modifier changed | Class members inaccessible from outside | Explicitly add `Public` to members that need external access | | `Try-Catch` around non-TLPP calls | ErrorBlock still needed for pure AdvPL error flows | Use `Try-Catch` regardless — it captures AdvPL throws too | | JSON inline without line continuations | Compilation error | Use `;` at end of each line in JSON inline blocks | | Access modifiers or `static` in method implementation | Compilation error or unexpected behavior | Method implementations use bare `method` — NEVER `public method`, `static method`, etc. Modifiers are ONLY in the class declaration | --- ## Incremental Migration Strategy Migration does not need to be all-or-nothing. Follow this priority order: 1. **Mandatory for TLPP:** File extension + `tlpp-core.th` include + remove `StaticCall` 2. **High value:** Add `Namespace` + type annotations (catches bugs at compile time) 3. **Medium value:** Replace `ErrorBlock` with `Try-Catch`, add class access modifiers, fix `LongNameClass` inheritance 4. **SonarQube compliance:** Remove `IIF`, `ConOut` → `FWLogMsg`, ISAM → `FWTemporaryTable`, `FormCommit` → `FWModelEvent` 5. **Nice to have:** Long identifiers, named parameters, JSON inline > **AdvPL and TLPP coexist.** A `.tlpp` file can call AdvPL functions and vice versa. You don't need to migrate everything at once. --- ## Troubleshooting - **`StaticCall` not compiling in TLPP**: `StaticCall` is prohibited in TLPP. Replace `StaticCall(TClass, Method, params)` with `TClass():Method(params)`. - **Include conflicts after renaming to `.tlpp`**: Replace `#include "protheus.ch"` with `#include "tlpp-core.th"`. Add `#include "totvs.ch"` if the source uses Protheus framework functions. Do not keep `protheus.ch` — use `totvs.ch` instead. - **Namespace resolution errors**: Ensure the `Namespace` declaration matches the directory structure and that callers use the fully qualified name or a `Using` directive. - **Functions not found after migration**: AdvPL and TLPP can coexist. If a `.tlpp` file calls an AdvPL function, the AdvPL source must still be compiled in the RPO. - **Type mismatch at compile time**: TLPP type annotations are strict. Ensure parameter types and return types match exactly — implicit conversions allowed in AdvPL may fail in TLPP.