├── .github └── workflows │ ├── release.yaml │ ├── test.yaml │ └── webpack.yaml ├── .gitignore ├── .gitmodules ├── LICENCE ├── cli ├── .gitignore ├── .npmignore ├── .vscode │ └── launch.json ├── package-lock.json ├── package.json ├── readme.md ├── src │ ├── builders │ │ ├── actions │ │ │ └── index.ts │ │ ├── bob.ts │ │ ├── environment.ts │ │ ├── iProject.ts │ │ ├── imd.ts │ │ └── make │ │ │ ├── customRules.ts │ │ │ ├── folderSettings.ts │ │ │ └── index.ts │ ├── cli.ts │ ├── extensions.ts │ ├── index.ts │ ├── languages │ │ ├── rpgle.ts │ │ └── sql.ts │ ├── logger.ts │ ├── readFileSystem.ts │ ├── targets.ts │ └── utils.ts ├── test │ ├── autofix.test.ts │ ├── autofix2.test.ts │ ├── bobLongNames.test.ts │ ├── bobWithExistingFiles.test.ts │ ├── cldclf.test.ts │ ├── cs_srvpgm.test.ts │ ├── cs_with_bnddir.test.ts │ ├── dclcase.test.ts │ ├── ddsDeps.test.ts │ ├── ddsDepsWithRefFile.test.ts │ ├── environment.test.ts │ ├── fixtures │ │ ├── auto_rename1 │ │ │ ├── LICENSE │ │ │ └── src │ │ │ │ ├── BBSADMMNUR.rpgle │ │ │ │ └── CBKOPTIMIZ.rpgle │ │ ├── bob_long_names │ │ │ └── ART301D-Function_Select_an_article.DSPF │ │ ├── cldclf │ │ │ ├── apgm.pgm.clle │ │ │ └── department.table │ │ ├── company_system │ │ │ ├── qddssrc │ │ │ │ ├── department.table │ │ │ │ ├── depts.dspf │ │ │ │ ├── employee.table │ │ │ │ └── emps.dspf │ │ │ ├── qrpgleref │ │ │ │ ├── constants.rpgleinc │ │ │ │ └── utils.rpgleinc │ │ │ ├── qrpglesrc │ │ │ │ ├── banking.sqlrpgle │ │ │ │ ├── depts.pgm.sqlrpgle │ │ │ │ ├── employees.pgm.sqlrpgle │ │ │ │ ├── mypgm.pgm.rpgle │ │ │ │ └── utils.sqlrpgle │ │ │ ├── qsqlsrc │ │ │ │ ├── getDouble.sql │ │ │ │ ├── getTotalSalary.sqludf │ │ │ │ └── showemps.sql │ │ │ └── qsrvsrc │ │ │ │ ├── banking.bnd │ │ │ │ └── utils.bnd │ │ ├── company_system_no_pgm_ext │ │ │ ├── qddssrc │ │ │ │ ├── department.table │ │ │ │ ├── depts.dspf │ │ │ │ ├── employee.table │ │ │ │ └── emps.dspf │ │ │ ├── qrpgleref │ │ │ │ ├── constants.rpgleinc │ │ │ │ └── utils.rpgleinc │ │ │ ├── qrpglesrc │ │ │ │ ├── banking.sqlrpgle │ │ │ │ ├── depts.sqlrpgle │ │ │ │ ├── employees.sqlrpgle │ │ │ │ ├── mypgm.rpgle │ │ │ │ └── utils.sqlrpgle │ │ │ ├── qsqlsrc │ │ │ │ ├── getDouble.sql │ │ │ │ ├── getTotalSalary.sqludf │ │ │ │ └── showemps.sql │ │ │ └── qsrvsrc │ │ │ │ ├── banking.bnd │ │ │ │ └── utils.bnd │ │ ├── cs_srvpgm │ │ │ ├── .vscode │ │ │ │ └── actions.json │ │ │ ├── qddssrc │ │ │ │ ├── actions.json │ │ │ │ ├── department.table │ │ │ │ ├── depts.dspf │ │ │ │ ├── employee.table │ │ │ │ ├── emps.dspf │ │ │ │ ├── nemp.dspf │ │ │ │ ├── popdept.sql │ │ │ │ └── popemp.sql │ │ │ ├── qrpgleref │ │ │ │ ├── constants.rpgleinc │ │ │ │ └── empdet.rpgleinc │ │ │ ├── qrpglesrc │ │ │ │ ├── depts.pgm.sqlrpgle │ │ │ │ ├── empdet.sqlrpgle │ │ │ │ ├── employees.pgm.sqlrpgle │ │ │ │ ├── mypgm.pgm.rpgle │ │ │ │ └── newemp.pgm.sqlrpgle │ │ │ └── qtestsrc │ │ │ │ └── emptest.test.sqlrpgle │ │ ├── cs_with_bnddir │ │ │ ├── qddssrc │ │ │ │ ├── Rules.mk │ │ │ │ ├── depts.dspf │ │ │ │ ├── emps.dspf │ │ │ │ └── nemp.dspf │ │ │ ├── qrpgleref │ │ │ │ ├── constants.rpgleinc │ │ │ │ └── empdet.rpgleinc │ │ │ ├── qrpglesrc │ │ │ │ ├── app.bnddir │ │ │ │ ├── depts.pgm.sqlrpgle │ │ │ │ ├── empdet.bnd │ │ │ │ ├── empdet.sqlrpgle │ │ │ │ ├── employees.pgm.sqlrpgle │ │ │ │ ├── mypgm.pgm.rpgle │ │ │ │ └── newemp.pgm.sqlrpgle │ │ │ ├── qsqlsrc │ │ │ │ ├── department.table │ │ │ │ ├── employee.table │ │ │ │ ├── popdept.sqlprc │ │ │ │ └── popemp.sqlprc │ │ │ └── qtestsrc │ │ │ │ ├── empdett.test.sqlrpgle │ │ │ │ └── testing.json │ │ ├── dclcase │ │ │ └── qrpglesrc │ │ │ │ ├── apival01s.pgm.rpgle │ │ │ │ └── apival01s.rpgleinc │ │ ├── dds_deps │ │ │ ├── PRO250D.DSPF │ │ │ ├── PROVIDE1.LF │ │ │ └── PROVIDER.PF │ │ ├── dds_deps_with_refs │ │ │ ├── .objrefs │ │ │ ├── PRO250D.DSPF │ │ │ ├── PROVIDE1.LF │ │ │ └── PROVIDER.PF │ │ ├── from_qsys │ │ │ ├── qddssrc │ │ │ │ └── mstdsp.dspf │ │ │ ├── qprotosrc │ │ │ │ └── errortable.rpgle │ │ │ ├── qrpglesrc │ │ │ │ └── payroll.rpgle │ │ │ └── qsqlsrc │ │ │ │ ├── dept.sql │ │ │ │ ├── emp.sql │ │ │ │ ├── empmst.sql │ │ │ │ ├── prjmst.table │ │ │ │ └── rsnmst.table │ │ ├── include_fix │ │ │ └── QRPGLESRC │ │ │ │ ├── ERRORTABLE.rpgleinc │ │ │ │ └── PAYROLL.pgm.rpgle │ │ ├── include_mismatch_fix │ │ │ ├── QDDSSRC │ │ │ │ └── ARTICLE.PF │ │ │ ├── QPROTOSRC │ │ │ │ └── ARTICLE.RPGLE │ │ │ └── QRPGLESRC │ │ │ │ └── ART201.PGM.RPGLE │ │ ├── metadata │ │ │ ├── qobjs │ │ │ │ ├── .ibmi.json │ │ │ │ └── mything.dtaara │ │ │ └── qrpglesrc │ │ │ │ └── tester.pgm.rpgle │ │ ├── mixedCaseExport │ │ │ ├── qrpglesrc │ │ │ │ └── modexcept.sqlrpgle │ │ │ └── qsrvsrc │ │ │ │ └── modexcept.bnd │ │ ├── multi_module │ │ │ ├── qrpgleref │ │ │ │ ├── dataarea.rpgleinc │ │ │ │ ├── system.rpgleinc │ │ │ │ └── utils.rpgleinc │ │ │ └── qrpglesrc │ │ │ │ ├── gitbrg.pgm.rpgle │ │ │ │ ├── objects.rpgle │ │ │ │ └── utils.sqlrpgle │ │ ├── multi_module_two │ │ │ ├── rpgle │ │ │ │ ├── data.rpgle │ │ │ │ ├── db.sqlrpgle │ │ │ │ └── runner.pgm.rpgle │ │ │ └── sql │ │ │ │ └── customer.table │ │ ├── override_objref │ │ │ ├── .objrefs │ │ │ ├── PRO250D.DSPF │ │ │ ├── PROVIDE1.LF │ │ │ ├── PROVIDER.PF │ │ │ └── SAMREF.PF │ │ ├── projects.ts │ │ ├── pseudo │ │ │ ├── qobjs │ │ │ │ ├── .ibmi.json │ │ │ │ ├── Rules.mk │ │ │ │ ├── mstdsp.dspf │ │ │ │ └── mything.dtaara │ │ │ └── qrpglesrc │ │ │ │ ├── .ibmi.json │ │ │ │ ├── Rules.mk │ │ │ │ ├── other.pgm.sqlrpgle │ │ │ │ └── tester.pgm.rpgle │ │ ├── sql_long_names │ │ │ ├── rpgle │ │ │ │ └── db.sqlrpgle │ │ │ └── sql │ │ │ │ └── trans.table │ │ ├── sql_ref_with │ │ │ └── sqlwithpgm.pgm.sqlrpgle │ │ ├── sql_references │ │ │ ├── qddssrc │ │ │ │ └── stock.table │ │ │ └── qrpglesrc │ │ │ │ └── sqlrefpgm.pgm.sqlrpgle │ │ └── targets.ts │ ├── includeMismatchFix.test.ts │ ├── make.test.ts │ ├── mixedCaseExport.test.ts │ ├── multiModule.test.ts │ ├── multiModule2.test.ts │ ├── overrideObjRef.test.ts │ ├── project.test.ts │ ├── project2.test.ts │ ├── pseudo.test.ts │ ├── setup.ts │ ├── sqlLongNames.test.ts │ ├── sqlReference.test.ts │ ├── sqlReferenceWith.test.ts │ └── targets.test.ts ├── todo.md ├── tsconfig.json ├── vitest.config.ts └── webpack.config.js ├── docs ├── .nojekyll ├── README.md ├── _sidebar.md ├── assets │ ├── Extension_01.png │ ├── Extension_02.png │ ├── Extension_03.png │ ├── Installation_03.png │ └── Migrating_01.png ├── index.html └── pages │ ├── cli │ ├── gha.md │ ├── index.md │ ├── installation.md │ └── make.md │ ├── extension │ ├── index.md │ └── installation.md │ └── general │ ├── migrating.md │ ├── rules.md │ └── structure.md ├── sourceorbit.code-workspace └── vs ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── LICENSE ├── README.md ├── client ├── package-lock.json ├── package.json ├── src │ ├── ProjectExplorer.ts │ ├── api.ts │ ├── environmentManager.ts │ ├── extension.ts │ ├── git │ │ ├── git.ts │ │ └── index.ts │ ├── gitEventHandler.ts │ ├── languageClientManager.ts │ ├── tasks.ts │ └── views │ │ ├── impactView │ │ ├── ileImpactedObjectTreeItem.ts │ │ └── index.ts │ │ ├── projectExplorer │ │ ├── ileObjectTreeItem.ts │ │ ├── noticeTreeItem.ts │ │ └── sourceOrbitTreeItem.ts │ │ └── utils.ts ├── tsconfig.json └── webpack.config.js ├── icon.png ├── jsconfig.json ├── package-lock.json ├── package.json ├── server ├── package-lock.json ├── package.json ├── src │ ├── TargetsManager.ts │ ├── fileSystemListener.ts │ ├── readFileSystem.ts │ ├── requests.ts │ ├── server.ts │ └── setup.ts ├── tsconfig.json └── webpack.config.js ├── shared.webpack.config.js ├── tsconfig.base.json └── tsconfig.json /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release CLI and Extension 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | release: 7 | types: [created] 8 | 9 | jobs: 10 | cli: 11 | name: Release CLI 12 | 13 | runs-on: ubuntu-latest 14 | 15 | permissions: 16 | packages: write 17 | contents: read 18 | 19 | defaults: 20 | run: 21 | working-directory: ./cli 22 | 23 | strategy: 24 | matrix: 25 | node-version: [20.x] 26 | 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v4 30 | 31 | - name: Use Node.js ${{ matrix.node-version }} 32 | uses: actions/setup-node@v4 33 | with: 34 | node-version: ${{ matrix.node-version }} 35 | registry-url: 'https://registry.npmjs.org' 36 | 37 | - name: Publish CLI 38 | run: | 39 | npm ci 40 | npm run test 41 | npm run webpack 42 | npm publish --access public 43 | env: 44 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 45 | 46 | extension: 47 | name: Release Extension 48 | 49 | runs-on: ubuntu-latest 50 | 51 | permissions: 52 | packages: write 53 | contents: read 54 | 55 | defaults: 56 | run: 57 | working-directory: ./vs 58 | 59 | strategy: 60 | matrix: 61 | node-version: [20.x] 62 | 63 | steps: 64 | - name: Checkout 65 | uses: actions/checkout@v4 66 | 67 | - name: Use Node.js ${{ matrix.node-version }} 68 | uses: actions/setup-node@v4 69 | with: 70 | node-version: ${{ matrix.node-version }} 71 | registry-url: 'https://registry.npmjs.org' 72 | 73 | - name: Install NPM Dependencies 74 | run: | 75 | npm install 76 | npm install -g vsce ovsx 77 | 78 | - name: Publish to Open VSX 79 | run: npx ovsx publish -p $OPENVSX_TOKEN 80 | env: 81 | OPENVSX_TOKEN: ${{ secrets.OPENVSX_TOKEN }} 82 | 83 | - name: Publish to Marketplace 84 | run: vsce publish -p $PUBLISHER_TOKEN 85 | env: 86 | PUBLISHER_TOKEN: ${{ secrets.PUBLISHER_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test with Vitest 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | push: 7 | branches: ["main"] 8 | paths: 9 | - 'cli/**' 10 | 11 | pull_request: 12 | branches: ["main"] 13 | paths: 14 | - 'cli/**' 15 | 16 | jobs: 17 | build: 18 | strategy: 19 | matrix: 20 | os: [macos-latest, ubuntu-latest, windows-latest] 21 | node-version: [18.x] 22 | 23 | runs-on: ${{ matrix.os }} 24 | defaults: 25 | run: 26 | working-directory: ./cli 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v3 30 | 31 | - name: Use Node.js ${{ matrix.node-version }} 32 | uses: actions/setup-node@v3 33 | with: 34 | node-version: ${{ matrix.node-version }} 35 | 36 | - name: Install NPM Dependencies 37 | run: npm install 38 | 39 | - name: Run Test 40 | run: npm run test 41 | 42 | - name: Pack 43 | run: | 44 | npm run webpack 45 | npm pack 46 | -------------------------------------------------------------------------------- /.github/workflows/webpack.yaml: -------------------------------------------------------------------------------- 1 | name: NodeJS with Webpack 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | push: 7 | branches: ["main"] 8 | paths: 9 | - 'vs/**' 10 | 11 | pull_request: 12 | branches: ["main"] 13 | paths: 14 | - 'vs/**' 15 | 16 | jobs: 17 | build: 18 | name: Build and Package 19 | 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | matrix: 24 | node-version: [18.x] 25 | 26 | defaults: 27 | run: 28 | working-directory: ./vs 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Use Node.js ${{ matrix.node-version }} 35 | uses: actions/setup-node@v4 36 | with: 37 | node-version: ${{ matrix.node-version }} 38 | registry-url: 'https://registry.npmjs.org' 39 | 40 | - name: Install NPM Dependencies 41 | run: | 42 | npm install 43 | npm install -g vsce 44 | 45 | - name: Build and Package 46 | run: | 47 | npm run webpack 48 | vsce package 49 | 50 | - name: Upload VSIX 51 | uses: actions/upload-artifact@v4 52 | with: 53 | name: VSIX 54 | path: ./vs/*.vsix 55 | if-no-files-found: error 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.vsix 3 | 4 | testData 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ibmi-company_system-rmake"] 2 | path = ibmi-company_system-rmake 3 | url = https://github.com/worksofliam/ibmi-company_system-rmake.git 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /cli/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .DS_Store 4 | 5 | !from_qsys 6 | !include_fix 7 | !company_system -------------------------------------------------------------------------------- /cli/.npmignore: -------------------------------------------------------------------------------- 1 | index.ts 2 | tsconfig.json 3 | webpack.config.js 4 | test 5 | src 6 | !dist/src 7 | node_modules 8 | .vscode -------------------------------------------------------------------------------- /cli/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Debug rmake", 9 | "type": "node", 10 | "request": "launch", 11 | "cwd": "${workspaceFolder:cli}", 12 | "program": "${workspaceFolder:cli}/dist/index.js", 13 | "sourceMaps": true, 14 | "args": ["-d", "/Users/barry/Downloads/stevefiles2", "--verbose"], 15 | "preLaunchTask": { 16 | "type": "npm", 17 | "script": "webpack:dev" 18 | }, 19 | }, 20 | ] 21 | } -------------------------------------------------------------------------------- /cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ibm/sourceorbit", 3 | "version": "1.1.0", 4 | "description": "IBM i dependency management tool", 5 | "bin": { 6 | "so": "./dist/index.js" 7 | }, 8 | "publisher": "IBM", 9 | "main": "./dist/index.js", 10 | "types": "./dist/src/index.d.ts", 11 | "scripts": { 12 | "test": "vitest", 13 | "webpack:dev": "webpack --mode none --config ./webpack.config.js", 14 | "webpack": "webpack --mode production --config ./webpack.config.js", 15 | "local": "npm run webpack:dev && npm i -g", 16 | "deploy": "npm run webpack && npm i && npm publish --access public" 17 | }, 18 | "keywords": [ 19 | "ibmi", 20 | "iseries", 21 | "as400" 22 | ], 23 | "categories": [ 24 | "Other" 25 | ], 26 | "author": "IBM", 27 | "license": "Apache 2", 28 | "repository": { 29 | "url": "https://github.com/IBM/sourceorbit" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/IBM/sourceorbit/issues" 33 | }, 34 | "homepage": "https://ibm.github.io/sourceorbit/#/", 35 | "devDependencies": { 36 | "glob": "^7.2.0", 37 | "merge-options": "^3.0.4", 38 | "ts-loader": "^9.4.4", 39 | "typescript": "^5.8.2", 40 | "vitest": "^3.0.8", 41 | "vscode-clle": "github:IBM/vscode-clle", 42 | "vscode-db2i": "github:halcyon-tech/vscode-db2i", 43 | "vscode-displayfile": "github:halcyon-tech/vscode-displayfile", 44 | "vscode-rpgle": "github:halcyon-tech/vscode-rpgle", 45 | "webpack": "^5.24.3", 46 | "webpack-cli": "^4.5.0" 47 | }, 48 | "dependencies": { 49 | "crc-32": "https://cdn.sheetjs.com/crc-32-latest/crc-32-latest.tgz" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /cli/readme.md: -------------------------------------------------------------------------------- 1 | # Source Orbit 2 | 3 | 4 | 5 | Source Orbit is a dependency management tool. As IBM i developers start using Git for their RPGLE, CL, DDS and SQL, we want to provide them with excellent tools to help them understand their source code. Source orbit is available for use as both a VS Code extension and CLI tool. 6 | 7 | * 💻 [Install from VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 8 | * 📦 [Download from Open VSX Registry](https://open-vsx.org/extension/IBM/vscode-sourceorbit) 9 | * ⚡[Install CLI from NPM](https://www.npmjs.com/package/@ibm/sourceorbit) 10 | * 📖 [View Documentation](https://ibm.github.io/sourceorbit/#/) 11 | * 🔎 [See Releases](https://github.com/IBM/sourceorbit/releases) 12 | 13 | [![Extension Version](https://img.shields.io/visual-studio-marketplace/v/IBM.vscode-sourceorbit?label=Extension)](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 14 | [![Extension Installs](https://img.shields.io/visual-studio-marketplace/i/IBM.vscode-sourceorbit)](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 15 | 16 | [![NPM Version](https://img.shields.io/npm/v/@ibm/sourceorbit.svg?label=CLI)](https://www.npmjs.com/package/@ibm/sourceorbit) 17 | [![NPM Downloads](https://img.shields.io/npm/dm/@ibm/sourceorbit.svg)](https://www.npmjs.com/package/@ibm/sourceorbit) 18 | 19 | ## General Usage 20 | 21 | Source Orbit will scan the sources in the current working directory (CWD) and can do a few things: 22 | 23 | * Show object dependencies with `-l` 24 | * Generate a different file formats based on the dependency tree to build the project 25 | * Rename files easily (`.rpgle`/`.clle`/`.clp` -> `.pgm.rpgle`/`.pgm.clle`/`.clle`) with `-ar` 26 | * Fix RPGLE includes if the source is found locally (useful for converting from member include style) with `-fi` 27 | * List detailed information with `--verbose` 28 | * Want to only scan a specific source? Use the `-s` option: `so -s qrpglesrc/employees.pgm.sqlrpgle` 29 | 30 | ```sh 31 | cd myibmiproject 32 | so -h 33 | so -bf make && gmake BIN_LIB=libname 34 | ``` 35 | 36 | ## Getting Started 37 | 38 | Check out these pages to dive in: 39 | 40 | 1. [As a CLI](https://ibm.github.io/sourceorbit/#/./pages/cli/index): Run Source Orbit as part of an automated pipeline, or anywhere really! 41 | 2. [As a VS Code Extension](https://ibm.github.io/sourceorbit/#/./pages/extension/index): Leverage Source Orbit as you develop applications in VS Code 42 | 3. [Project Structure](https://ibm.github.io/sourceorbit/#/./pages/general/structure): Learn how to structure your code when stored in git 43 | 4. [Source Code Rules](https://ibm.github.io/sourceorbit/#/./pages/general/rules): Learn what rules to abide by when using Source Orbit -------------------------------------------------------------------------------- /cli/src/builders/actions/index.ts: -------------------------------------------------------------------------------- 1 | import { ReadFileSystem } from "../../readFileSystem"; 2 | import { Targets } from "../../targets"; 3 | import path from "path"; 4 | 5 | export interface Action { 6 | name: string, 7 | command: string, 8 | environment: "ile", 9 | extensions: string[], 10 | } 11 | 12 | export class ProjectActions { 13 | private actions: { [relativePath: string]: Action[] } = {}; 14 | 15 | constructor(private readonly targets: Targets, private readonly readFileSystem: ReadFileSystem) {} 16 | 17 | get getActionPaths() { 18 | return Object.keys(this.actions); 19 | } 20 | 21 | public async loadAllActions() { 22 | const cwd = this.targets.getCwd(); 23 | const files = await this.readFileSystem.getFiles(cwd, `**/actions.json`, {dot: true}); 24 | 25 | for (const file of files) { 26 | const relativePath = path.relative(cwd, file); 27 | const contents = await this.readFileSystem.readFile(file); 28 | try { 29 | const possibleActions = JSON.parse(contents) as Partial; 30 | 31 | for (const possibleAction of possibleActions) { 32 | if (!possibleAction.name || !possibleAction.command || !possibleAction.environment || !possibleAction.extensions) { 33 | // TODO: Log a warning about missing required fields 34 | continue; // Skip if required fields are missing 35 | } 36 | 37 | possibleAction.extensions = possibleAction.extensions.map(ext => ext.toLowerCase()); 38 | } 39 | 40 | this.actions[relativePath] = possibleActions as Action[]; 41 | } catch (e) { 42 | console.log(`Error parsing actions.json at ${relativePath}:`, e); 43 | } 44 | } 45 | 46 | const vscodePath = path.join(`.vscode`, `actions.json`); 47 | if (this.actions[vscodePath]) { 48 | // If there is a .vscode/actions.json, it is the project actions 49 | this.actions[`actions.json`] = this.actions[vscodePath]; 50 | delete this.actions[vscodePath]; 51 | } 52 | } 53 | 54 | getActionForPath(relativeSourcePath: string): Action|undefined { 55 | let allPossibleActions: Action[] = []; 56 | let parent: string = relativeSourcePath; 57 | 58 | while (true) { 59 | parent = path.dirname(parent); 60 | 61 | const actionFile = path.join(parent, `actions.json`); 62 | 63 | if (this.actions[actionFile]) { 64 | allPossibleActions.push(...this.actions[actionFile]); 65 | } 66 | 67 | if (parent === `.`) { 68 | // Reached the root directory, stop searching 69 | break; 70 | } 71 | } 72 | 73 | let extension = path.extname(relativeSourcePath).toLowerCase(); 74 | 75 | if (extension.startsWith(`.`)) { 76 | extension = extension.slice(1); 77 | } 78 | 79 | allPossibleActions = allPossibleActions.filter((action) => { 80 | return action.extensions.includes(extension); 81 | }); 82 | 83 | return allPossibleActions[0]; 84 | } 85 | } -------------------------------------------------------------------------------- /cli/src/builders/iProject.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { ObjectType } from "../targets"; 3 | import { CommandParameters, CompileAttribute, getDefaultCompiles } from "./environment"; 4 | 5 | export class iProject { 6 | includePaths?: string[] = []; 7 | compiles?: CompileAttribute = getDefaultCompiles(); 8 | objectAttributes?: { 9 | [object: string]: CommandParameters 10 | } = {}; 11 | binders?: string[] = []; 12 | 13 | constructor() { 14 | 15 | } 16 | 17 | getCompileDataForType(type: ObjectType) { 18 | return Object.values(this.compiles).find(data => data.becomes === type); 19 | } 20 | 21 | getCompileDataForSource(relativePath: string) { 22 | const parseA = path.parse(relativePath); 23 | let ext = parseA.ext.toLowerCase(); 24 | 25 | 26 | if (parseA.name.includes(`.`)) { 27 | const parseB = path.parse(parseA.name); 28 | ext = parseB.ext.toLowerCase() + ext; 29 | } 30 | 31 | if (ext.startsWith(`.`)) { 32 | ext = ext.substring(1); 33 | } 34 | 35 | return this.compiles[ext]; 36 | } 37 | 38 | applySettings(input: Partial) { 39 | if (input.includePaths && input.includePaths.length > 0) { 40 | this.includePaths = input.includePaths; 41 | } 42 | 43 | if (input.binders && input.binders.length > 0) { 44 | this.binders = input.binders; 45 | } 46 | 47 | if (input.compiles) { 48 | for (const [ext, data] of Object.entries(input.compiles)) { 49 | // We don't want to fully overwrite the default settings, 50 | // perhaps the user is only changing the `dir`? 51 | this.compiles[ext] = { 52 | ...(this.compiles[ext] || {}), 53 | ...data 54 | }; 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /cli/src/builders/make/folderSettings.ts: -------------------------------------------------------------------------------- 1 | import * as path from "path"; 2 | import { readFileSync } from "fs"; 3 | import { warningOut } from "../../cli"; 4 | import { ReadFileSystem } from "../../readFileSystem"; 5 | import { getFiles } from "../../utils"; 6 | 7 | export interface FolderOptions { 8 | version?: "0.0.1", 9 | build?: { 10 | // objlib?: string, We don't support objlib 11 | tgtCcsid?: string 12 | } 13 | } 14 | 15 | /** 16 | * Fetch the folder specific settings for a project 17 | */ 18 | export function getFolderOptions(cwd: string) { 19 | // Then fetch the directory specific settings 20 | const ibmiFiles = getFiles(cwd, `**/.ibmi.json`); 21 | 22 | let folderSettings: { [key: string]: FolderOptions } = {}; 23 | 24 | for (const ibmiFile of ibmiFiles) { 25 | const relative = path.relative(cwd, ibmiFile); 26 | const folder = path.dirname(relative); 27 | 28 | try { 29 | folderSettings[folder] = JSON.parse(readFileSync(ibmiFile, { encoding: `utf-8` })); 30 | } catch (e) { 31 | warningOut(`make: Failed to read ${relative}.`); 32 | } 33 | } 34 | 35 | return folderSettings; 36 | } -------------------------------------------------------------------------------- /cli/src/cli.ts: -------------------------------------------------------------------------------- 1 | 2 | export type BuildFiles = "none" | "make" | "bob" | "imd" | "json"; 3 | 4 | export let cliSettings = { 5 | cliMode: false, 6 | infoMessages: false, 7 | buildFile: "none" as BuildFiles, 8 | fixIncludes: false, 9 | autoRename: false, 10 | fileList: false, 11 | lookupFiles: [] as string[], 12 | userBranch: ``, 13 | makeFileNoChildren: false, 14 | assumeSourcesArePrograms: false, 15 | }; 16 | 17 | export function infoOut(message: string) { 18 | if (cliSettings.cliMode && cliSettings.infoMessages) console.log(message); 19 | } 20 | 21 | export function warningOut(message: string) { 22 | if (cliSettings.cliMode) console.log(message); 23 | } 24 | 25 | export function error(message: string) { 26 | console.log(`[ERROR] ${message}`); 27 | } -------------------------------------------------------------------------------- /cli/src/extensions.ts: -------------------------------------------------------------------------------- 1 | 2 | export const rpgExtensions = [`sqlrpgle`, `rpgle`]; 3 | export const clExtensions = [`clle`, `cl`, `clp`]; 4 | export const ddsExtension = [`pf`, `lf`, `dspf`, `prtf`]; 5 | export const sqlExtensions = [`sql`, `table`, `view`, `index`, `alias`, `sqlprc`, `sqludf`, `sqludt`, `sqltrg`, `sqlalias`, `sqlseq`]; 6 | export const srvPgmExtensions = [`binder`, `bnd`]; 7 | export const cmdExtensions = [`cmd`]; 8 | export const objectExtensions = [`dtaara`, `mnucmd`, `msgf`, `dtaq`, `bnddir`]; 9 | 10 | export const allExtensions = [...rpgExtensions, ...clExtensions, ...ddsExtension, ...sqlExtensions, ...srvPgmExtensions, ...cmdExtensions, ...objectExtensions]; 11 | export const scanGlob = `**/*.{${allExtensions.join(`,`)},${allExtensions.map(e => e.toUpperCase()).join(`,`)}}`; 12 | 13 | export const referencesFileName = `.objrefs`; -------------------------------------------------------------------------------- /cli/src/languages/rpgle.ts: -------------------------------------------------------------------------------- 1 | 2 | import { readFileSync } from 'fs'; 3 | import * as path from 'path'; 4 | 5 | import Parser from "vscode-rpgle/language/parser"; 6 | import { Targets } from '../targets'; 7 | 8 | let includeFileCache: { [path: string]: string } = {}; 9 | 10 | export function setupParser(targets: Targets): Parser { 11 | const parser = new Parser(); 12 | 13 | parser.setIncludeFileFetch(async (baseFile: string, includeFile: string) => { 14 | if (includeFile.startsWith(`'`) && includeFile.endsWith(`'`)) { 15 | includeFile = includeFile.substring(1, includeFile.length - 1); 16 | } 17 | 18 | let file: string; 19 | 20 | if (includeFile.includes(`,`)) { 21 | // If the member include path is qualified with a source file 22 | // then we should convert to be a unix style path so we can 23 | // search the explicit directories. 24 | includeFile = includeFile.replace(/,/g, `/`) + `.*`; 25 | 26 | // Keep making the path less specific until we find a possible include 27 | let parts = includeFile.split(`/`); 28 | while (!file && parts.length > 0) { 29 | file = targets.resolveLocalFile(includeFile); 30 | 31 | if (!file) { 32 | parts.shift(); 33 | includeFile = parts.join(`/`); 34 | } 35 | } 36 | } else if (!includeFile.includes(`/`)) { 37 | const parent = path.basename(path.dirname(baseFile)); 38 | console.log(parent); 39 | includeFile = `${parent}/${includeFile}`; 40 | 41 | 42 | file = targets.resolveLocalFile(includeFile); 43 | } else { 44 | file = targets.resolveLocalFile(includeFile); 45 | } 46 | 47 | if (file) { 48 | if (includeFileCache[file]) { 49 | return { 50 | found: true, 51 | uri: file, 52 | content: includeFileCache[file] 53 | } 54 | 55 | } else { 56 | const content = readFileSync(file, { encoding: `utf-8` }); 57 | includeFileCache[file] = content; 58 | 59 | return { 60 | found: true, 61 | uri: file, 62 | content: content 63 | } 64 | } 65 | } 66 | 67 | return { 68 | found: false 69 | }; 70 | }); 71 | 72 | parser.setTableFetch(async (table: string, aliases = false) => { 73 | // Can't support tables in CLI mode I suppose? 74 | return []; 75 | }); 76 | 77 | return parser; 78 | } -------------------------------------------------------------------------------- /cli/src/logger.ts: -------------------------------------------------------------------------------- 1 | import { infoOut, warningOut } from "./cli"; 2 | 3 | type LogType = "info"|"warning"|"includeFix"|"rename"; 4 | 5 | type FileLogs = {[path: string]: FileLog[]}; 6 | 7 | interface ChangeSuggestion { 8 | rename?: { 9 | path: string; 10 | newName: string; 11 | }, 12 | lineContent?: string; 13 | } 14 | 15 | export interface FileLog { 16 | type: LogType; 17 | message: string; 18 | line?: number; 19 | range?: { 20 | start: number, 21 | end: number 22 | } 23 | change?: ChangeSuggestion; 24 | } 25 | 26 | export class Logger { 27 | private logs: FileLogs = {}; 28 | 29 | constructor() {} 30 | 31 | flush(specificPath?: string) { 32 | if (specificPath) { 33 | this.logs[specificPath] = []; 34 | } else { 35 | this.logs = {} 36 | } 37 | } 38 | 39 | fileLog(path: string, log: FileLog) { 40 | switch (log.type) { 41 | case `info`: infoOut(`${path}${log.line ? `:${log.line}` : ``} - ${log.message}`); break; 42 | case `warning`: warningOut(`${path}${log.line ? `:${log.line}` : ``} - ${log.message}`); break; 43 | } 44 | 45 | if (!this.logs[path]) { 46 | this.logs[path] = []; 47 | } 48 | 49 | if (log.type === `rename`) { 50 | // If this path already contains a rename, ignore this 51 | if (this.logs[path].some(l => l.type === `rename`)) return; 52 | } 53 | 54 | this.logs[path].push(log); 55 | } 56 | 57 | exists(path: string, type: LogType) { 58 | return this.logs[path] && this.logs[path].some(l => l.type === type) 59 | } 60 | 61 | getAllLogs() { 62 | return this.logs; 63 | } 64 | 65 | getLogsFor(path: string): FileLog[]|undefined { 66 | return this.logs[path]; 67 | } 68 | } -------------------------------------------------------------------------------- /cli/src/readFileSystem.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs/promises'; 2 | import ffs from 'fs'; 3 | import glob from "glob"; 4 | import path from 'path'; 5 | import os from 'os'; 6 | import { getFiles } from './utils'; 7 | import { scanGlob } from './extensions'; 8 | 9 | export class ReadFileSystem { 10 | constructor() {} 11 | 12 | async getFiles(cwd: string, globPath = scanGlob, additionalOpts: any = {}): Promise { 13 | return getFiles(cwd, globPath, additionalOpts); 14 | } 15 | 16 | readFile(filePath: string): Promise { 17 | return fs.readFile(filePath, { encoding: `utf8` }); 18 | } 19 | 20 | async exists(filePath: string): Promise { 21 | return ffs.existsSync(filePath); 22 | } 23 | } -------------------------------------------------------------------------------- /cli/test/autofix2.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "vitest"; 2 | import { setupFixture } from "./fixtures/projects"; 3 | 4 | import { Targets } from '../src/targets' 5 | import { renameFiles } from "../src/utils"; 6 | import { scanGlob } from "../src/extensions"; 7 | 8 | import * as path from "path"; 9 | import { ReadFileSystem } from "../src/readFileSystem"; 10 | 11 | test(`Auto rename RPGLE program and include and fix-include infos`, async () => { 12 | const project = setupFixture(`auto_rename1`); 13 | project.copy(); 14 | 15 | const fs = new ReadFileSystem(); 16 | 17 | // First step is to rename the files 18 | let targets = new Targets(project.cwd, fs); 19 | targets.setSuggestions({renames: true}); 20 | 21 | await targets.loadProject(); 22 | 23 | targets.resolveBinder(); 24 | 25 | let allLogs = targets.logger.getAllLogs(); 26 | expect(Object.keys(allLogs).length).toBeGreaterThan(0); 27 | 28 | const pgmSource = allLogs[path.join(`src`, `BBSADMMNUR.rpgle`)].filter(log => log.type === `rename`); 29 | const cbkSource = allLogs[path.join(`src`, `CBKOPTIMIZ.rpgle`)]; 30 | 31 | expect(pgmSource.length).toBe(1); 32 | expect(cbkSource.length).toBe(1); 33 | 34 | expect(pgmSource[0].message).toBe(`Rename suggestion`); 35 | expect(pgmSource[0].type).toBe(`rename`); 36 | expect(pgmSource[0].change.rename.newName).toBe(`BBSADMMNUR.pgm.rpgle`); 37 | 38 | expect(cbkSource[0].message).toBe(`Rename suggestion`); 39 | expect(cbkSource[0].type).toBe(`rename`); 40 | expect(cbkSource[0].change.rename.newName).toBe(`CBKOPTIMIZ.rpgleinc`); 41 | 42 | // Trigger the rename 43 | renameFiles(targets.logger); 44 | 45 | // Next, scan the project again and check the logs 46 | targets = new Targets(project.cwd, fs); 47 | targets.setSuggestions({includes: true}); 48 | 49 | await targets.loadProject(); 50 | 51 | allLogs = targets.logger.getAllLogs(); 52 | 53 | const newPgmSource = allLogs[path.join(`src`, `BBSADMMNUR.pgm.rpgle`)].filter(log => log.type === `includeFix`); 54 | 55 | expect(newPgmSource.length).toBe(1); 56 | 57 | expect(newPgmSource[0].message).toBe(`Will update to use unix style path.`); 58 | expect(newPgmSource[0].type).toBe(`includeFix`); 59 | expect(newPgmSource[0].change.lineContent).toBe(` /copy 'src/CBKOPTIMIZ.rpgleinc'`); 60 | expect(newPgmSource[0].line).toBe(11); 61 | }); 62 | -------------------------------------------------------------------------------- /cli/test/bobLongNames.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import { setupFixture } from './fixtures/projects'; 5 | import { ReadFileSystem } from '../src/readFileSystem'; 6 | 7 | const fs = new ReadFileSystem(); 8 | 9 | describe(`long name test`, () => { 10 | const project = setupFixture(`bob_long_names`); 11 | 12 | const targets = new Targets(project.cwd, fs); 13 | targets.setSuggestions({ renames: true, includes: true }) 14 | 15 | beforeAll(async () => { 16 | project.setup(); 17 | await targets.loadProject(); 18 | 19 | expect(targets.getTargets().length).toBeGreaterThan(0); 20 | targets.resolveBinder(); 21 | }); 22 | 23 | test(`Ensure objects are defined`, async () => { 24 | expect(targets.getTargets().length).toBe(1); 25 | expect(targets.getResolvedObjects(`FILE`).length).toBe(1); 26 | expect(targets.binderRequired()).toBe(false); 27 | 28 | const dspf = targets.searchForObject({ systemName: `ART301D`, type: `FILE` }); 29 | expect(dspf).toBeDefined(); 30 | }); 31 | }); -------------------------------------------------------------------------------- /cli/test/bobWithExistingFiles.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import path from 'path'; 5 | import { setupFixture } from './fixtures/projects'; 6 | import { BobProject } from '../src'; 7 | import { ReadFileSystem } from '../src/readFileSystem'; 8 | 9 | // This issue was occuring when you had two files with the same name, but different extensions. 10 | 11 | describe(`bob Rules.mk tests`, () => { 12 | const project = setupFixture(`pseudo`); 13 | 14 | const fs = new ReadFileSystem(); 15 | const targets = new Targets(project.cwd, fs); 16 | targets.setSuggestions({ renames: true, includes: true }) 17 | 18 | beforeAll(async () => { 19 | project.setup(); 20 | await targets.loadProject(); 21 | 22 | expect(targets.getTargets().length).toBeGreaterThan(0); 23 | targets.resolveBinder(); 24 | }); 25 | 26 | test(`bob to not overwrite any pre-existing rules for targets`, () => { 27 | const project = new BobProject(targets); 28 | 29 | const files = project.createRules(); 30 | 31 | const baseRules = files[`Rules.mk`].split(/\r?\n/); 32 | 33 | expect(baseRules).toBeDefined(); 34 | expect(baseRules[0]).toContain(`SUBDIRS =`); 35 | expect(baseRules[0]).toContain(`qobjs`); 36 | expect(baseRules[0]).toContain(`qrpglesrc`); 37 | 38 | const qobjRules = files[path.join(`qobjs`, `Rules.mk`)].split(/\r?\n/); 39 | 40 | expect(qobjRules).toBeDefined(); 41 | expect(qobjRules).toContain(`MYTHING.DTAARA:text=Hello world`); 42 | expect(qobjRules).toContain(`MSTDSP.FILE: mstdsp.dspf`); 43 | 44 | const qrpglesrcRules = files[path.join(`qrpglesrc`, `Rules.mk`)].split(/\r?\n/); 45 | 46 | expect(qrpglesrcRules).toBeDefined(); 47 | expect(qrpglesrcRules).toContain(`TESTER.PGM: tester.pgm.rpgle MYTHING.DTAARA`); 48 | expect(qrpglesrcRules).toContain(`TESTER.PGM: text = My program`); 49 | expect(qrpglesrcRules).toContain(`# Other assignment`); 50 | expect(qrpglesrcRules).toContain(`TESTER.PGM: bnddir:=MYBND`); 51 | expect(qrpglesrcRules).toContain(`OTHER.PGM: other.pgm.sqlrpgle MSTDSP.FILE`); 52 | }); 53 | }); -------------------------------------------------------------------------------- /cli/test/cldclf.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import { setupFixture } from './fixtures/projects'; 5 | import { ReadFileSystem } from '../src/readFileSystem'; 6 | 7 | describe(`CL with DCLF`, () => { 8 | const project = setupFixture(`cldclf`); 9 | 10 | const fs = new ReadFileSystem(); 11 | const targets = new Targets(project.cwd, fs); 12 | 13 | beforeAll(async () => { 14 | project.setup(); 15 | await targets.loadProject(); 16 | 17 | expect(targets.getTargets().length).toBeGreaterThan(0); 18 | targets.resolveBinder(); 19 | }); 20 | 21 | test(`Objects are loaded`, () => { 22 | expect(targets).toBeDefined(); 23 | expect(targets.binderRequired()).toBeFalsy(); 24 | 25 | const targetObjects = targets.getTargets(); 26 | 27 | expect(targetObjects.length).toBe(2); 28 | 29 | expect(targetObjects.some(t => t.systemName === `APGM` && t.type === `PGM` && t.extension === `clle`)).toBeTruthy(); 30 | expect(targetObjects.some(t => t.systemName === `DEPARTMENT` && t.type === `FILE` && t.extension === `table`)).toBeTruthy(); 31 | }); 32 | 33 | test(`CL has valid dependency`, () => { 34 | const apgm = targets.getTarget({systemName: `APGM`, type: `PGM`}); 35 | expect(apgm).toBeDefined(); 36 | 37 | const logs = targets.logger.getLogsFor(apgm.relativePath); 38 | console.log(logs); 39 | expect(logs.length).toBe(0); 40 | 41 | expect(apgm.deps.length).toBe(1); 42 | expect(apgm.deps[0].systemName).toBe(`DEPARTMENT`); 43 | expect(apgm.deps[0].type).toBe(`FILE`); 44 | }); 45 | }); -------------------------------------------------------------------------------- /cli/test/dclcase.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "vitest"; 2 | import { setupFixture } from "./fixtures/projects"; 3 | 4 | import { Targets } from '../src/targets' 5 | import { ReadFileSystem } from "../src/readFileSystem"; 6 | 7 | 8 | test(`Check that dclcase is being imported correctly`, async () => { 9 | const project = setupFixture(`dclcase`); 10 | 11 | // First step is to rename the files 12 | 13 | const fs = new ReadFileSystem(); 14 | const targets = new Targets(project.cwd, fs); 15 | targets.setSuggestions({renames: true}); 16 | 17 | project.setup(); 18 | await targets.loadProject(); 19 | 20 | const pgmObject = targets.getTarget({systemName: `APIVAL01S`, type: `PGM`}); 21 | 22 | expect(pgmObject).toBeDefined(); 23 | expect(pgmObject.systemName).toBe(`APIVAL01S`); 24 | expect(pgmObject.type).toBe(`PGM`); 25 | expect(pgmObject.imports.length).toBe(1); 26 | expect(pgmObject.imports[0]).toBe(`APIVAL01S_iws_validate`); 27 | 28 | 29 | targets.resolveBinder(); 30 | }); 31 | -------------------------------------------------------------------------------- /cli/test/fixtures/auto_rename1/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Dave Asta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cli/test/fixtures/auto_rename1/src/CBKOPTIMIZ.rpgle: -------------------------------------------------------------------------------- 1 | * Level optimisation FULL 2 | * The most efficient code is generated. 3 | * Translation time is the longest. 4 | H OPTIMIZE(*FULL) 5 | -------------------------------------------------------------------------------- /cli/test/fixtures/cldclf/apgm.pgm.clle: -------------------------------------------------------------------------------- 1 | PGM 2 | DCLF FILE(*LIBL/DEPARTMENT) OPNID(SAVRSTLIB) 3 | ENDPGM -------------------------------------------------------------------------------- /cli/test/fixtures/cldclf/department.table: -------------------------------------------------------------------------------- 1 | --https://www.ibm.com/docs/en/i/7.3?topic=tables-department-table-department 2 | 3 | CREATE OR REPLACE TABLE DEPARTMENT 4 | (DEPTNO CHAR(3) NOT NULL, 5 | DEPTNAME VARCHAR(36) NOT NULL, 6 | MGRNO CHAR(6) NOT NULL, 7 | ADMRDEPT CHAR(3) NOT NULL, 8 | LOCATION CHAR(16) NOT NULL, 9 | PRIMARY KEY (DEPTNO)); 10 | 11 | ALTER TABLE DEPARTMENT 12 | ADD FOREIGN KEY ROD (ADMRDEPT) 13 | REFERENCES DEPARTMENT 14 | ON DELETE CASCADE; 15 | 16 | -- Remove circular reference 17 | --ALTER TABLE DEPARTMENT 18 | -- ADD FOREIGN KEY RDE (MGRNO) 19 | -- REFERENCES EMPLOYEE 20 | -- ON DELETE SET NULL; 21 | 22 | -- CREATE UNIQUE INDEX XDEPT1 23 | -- ON DEPARTMENT (DEPTNO); 24 | 25 | -- CREATE INDEX XDEPT2 26 | -- ON DEPARTMENT (MGRNO); 27 | 28 | -- CREATE INDEX XDEPT3 29 | -- ON DEPARTMENT (ADMRDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qddssrc/department.table: -------------------------------------------------------------------------------- 1 | --https://www.ibm.com/docs/en/i/7.3?topic=tables-department-table-department 2 | 3 | CREATE OR REPLACE TABLE long_department_name for system name department 4 | (DEPTNO CHAR(3) NOT NULL, 5 | DEPTNAME VARCHAR(36) NOT NULL, 6 | MGRNO CHAR(6) , 7 | ADMRDEPT CHAR(3) NOT NULL, 8 | LOCATION CHAR(16), 9 | PRIMARY KEY (DEPTNO)); 10 | 11 | ALTER TABLE DEPARTMENT 12 | ADD FOREIGN KEY ROD (ADMRDEPT) 13 | REFERENCES DEPARTMENT 14 | ON DELETE CASCADE; 15 | 16 | -- Remove circular reference 17 | --ALTER TABLE DEPARTMENT 18 | -- ADD FOREIGN KEY RDE (MGRNO) 19 | -- REFERENCES EMPLOYEE 20 | -- ON DELETE SET NULL; 21 | 22 | -- CREATE UNIQUE INDEX XDEPT1 23 | -- ON DEPARTMENT (DEPTNO); 24 | 25 | -- CREATE INDEX XDEPT2 26 | -- ON DEPARTMENT (MGRNO); 27 | 28 | -- CREATE INDEX XDEPT3 29 | -- ON DEPARTMENT (ADMRDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qddssrc/depts.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA03(03) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 3A O 7 12 8 | A XNAME 38A O 7 16 9 | A* COLOR HELLO 10 | A R SFLCTL SFLCTL(SFLDTA) 11 | A SFLPAG(0014) 12 | A SFLSIZ(9999) 13 | A OVERLAY 14 | A 85 SFLDSPCTL 15 | A 95 SFLDSP 16 | A N85 SFLCLR 17 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 18 | A* 19 | A 6 6'Opt' 20 | A DSPATR(HI) 21 | A DSPATR(UL) 22 | A 6 12'ID' 23 | A DSPATR(HI) 24 | A DSPATR(UL) 25 | A 6 16'Name' 26 | A DSPATR(UL) 27 | A COLOR(WHT) 28 | A R FOOTER_FMT 29 | A OVERLAY 30 | A 3 6'F3=Exit' 31 | A COLOR(BLU) 32 | A 2 35'Departments' 33 | A DSPATR(UL) 34 | A COLOR(WHT) 35 | A 4 6'5=View' 36 | A COLOR(BLU) 37 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qddssrc/employee.table: -------------------------------------------------------------------------------- 1 | -- https://www.ibm.com/docs/en/i/7.3?topic=tables-employee-table-employee 2 | 3 | --%METADATA * 4 | -- %TEXT Employee File * 5 | --%EMETADATA * 6 | 7 | CREATE OR REPLACE TABLE EMPLOYEE 8 | (EMPNO CHAR(6) NOT NULL, 9 | FIRSTNME VARCHAR(12) NOT NULL, 10 | MIDINIT CHAR(1) NOT NULL, 11 | LASTNAME VARCHAR(15) NOT NULL, 12 | WORKDEPT CHAR(3) , 13 | PHONENO CHAR(4) , 14 | HIREDATE DATE , 15 | JOB CHAR(8) , 16 | EDLEVEL SMALLINT NOT NULL, 17 | SEX CHAR(1) , 18 | BIRTHDATE DATE , 19 | SALARY DECIMAL(9,2) , 20 | BONUS DECIMAL(9,2) , 21 | COMM DECIMAL(9,2) , 22 | PRIMARY KEY (EMPNO)); 23 | 24 | ALTER TABLE EMPLOYEE 25 | ADD FOREIGN KEY RED (WORKDEPT) 26 | REFERENCES DEPARTMENT 27 | ON DELETE SET NULL; 28 | 29 | ALTER TABLE EMPLOYEE 30 | ADD CONSTRAINT NUMBER 31 | CHECK (PHONENO >= '0000' AND PHONENO <= '9999'); 32 | 33 | -- CREATE UNIQUE INDEX XEMP1 34 | -- ON EMPLOYEE (EMPNO); 35 | 36 | -- CREATE INDEX XEMP2 37 | -- ON EMPLOYEE (WORKDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qddssrc/emps.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA12(12) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 6A O 7 12 8 | A XNAME 30A O 7 20 9 | A XJOB 8A O 7 52 10 | A* COLOR HELLO 11 | A R SFLCTL SFLCTL(SFLDTA) 12 | A SFLPAG(0014) 13 | A SFLSIZ(9999) 14 | A OVERLAY 15 | A 85 SFLDSPCTL 16 | A 95 SFLDSP 17 | A N85 SFLCLR 18 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 19 | A* 20 | A 6 6'Opt' 21 | A DSPATR(HI) 22 | A DSPATR(UL) 23 | A 6 12'ID' 24 | A DSPATR(HI) 25 | A DSPATR(UL) 26 | A 6 20'Name' 27 | A DSPATR(UL) 28 | A COLOR(WHT) 29 | A 6 52'Job' 30 | A DSPATR(UL) 31 | A COLOR(WHT) 32 | A R FOOTER_FMT 33 | A OVERLAY 34 | A 3 06'F12=Back' 35 | A COLOR(BLU) 36 | A 2 35'Employees' 37 | A DSPATR(UL) 38 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qrpgleref/constants.rpgleinc: -------------------------------------------------------------------------------- 1 | Dcl-C F01 X'31'; 2 | Dcl-C F02 X'32'; 3 | Dcl-C F03 X'33'; 4 | Dcl-C F04 X'34'; 5 | Dcl-C F05 X'35'; 6 | Dcl-C F06 X'36'; 7 | Dcl-C F07 X'37'; 8 | Dcl-C F08 X'38'; 9 | Dcl-C F09 X'39'; 10 | Dcl-C F10 X'3A'; 11 | Dcl-C F11 X'3B'; 12 | Dcl-C F12 X'3C'; 13 | Dcl-C F13 X'B1'; 14 | Dcl-C F14 X'B2'; 15 | Dcl-C F15 X'B3'; 16 | Dcl-C F16 X'B4'; 17 | Dcl-C F17 X'B5'; 18 | Dcl-C F18 X'B6'; 19 | Dcl-C F19 X'B7'; 20 | Dcl-C F20 X'B8'; 21 | Dcl-C F21 X'B9'; 22 | Dcl-C F22 X'BA'; 23 | Dcl-C F24 X'BC'; 24 | Dcl-C ENTER X'F1'; 25 | Dcl-C HELP X'F3'; 26 | Dcl-C PRINT X'F6'; 27 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qrpgleref/utils.rpgleinc: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-pr ToLower char(50) extproc; 4 | inputString char(50) value; 5 | end-pr; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qrpglesrc/banking.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-proc doubleIt export; 6 | dcl-pi *n packed(11:2); 7 | inputNum packed(11:2) value; 8 | end-pi; 9 | 10 | return inputNum * 2; 11 | end-proc; 12 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qrpglesrc/employees.pgm.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | Ctl-Opt DFTACTGRP(*no); 3 | 4 | Dcl-Pi EMPLOYEES; 5 | DEPTNO Char(3); 6 | End-Pi; 7 | 8 | //---------------------------------------------------------------* 9 | 10 | /include 'qrpgleref/constants.rpgleinc' 11 | 12 | //---------------------------------------------------------------* 13 | 14 | Dcl-F emps WORKSTN Sfile(SFLDta:Rrn) IndDS(WkStnInd) InfDS(fileinfo); 15 | 16 | Dcl-S Exit Ind Inz(*Off); 17 | 18 | Dcl-S Rrn Zoned(4:0) Inz; 19 | 20 | Dcl-DS WkStnInd; 21 | ProcessSCF Ind Pos(21); 22 | ReprintScf Ind Pos(22); 23 | Error Ind Pos(25); 24 | PageDown Ind Pos(30); 25 | PageUp Ind Pos(31); 26 | SflEnd Ind Pos(40); 27 | SflBegin Ind Pos(41); 28 | NoRecord Ind Pos(60); 29 | SflDspCtl Ind Pos(85); 30 | SflClr Ind Pos(75); 31 | SflDsp Ind Pos(95); 32 | End-DS; 33 | 34 | Dcl-DS FILEINFO; 35 | FUNKEY Char(1) Pos(369); 36 | End-DS; 37 | 38 | //---------------------------------------------------------------* 39 | // 40 | Dcl-S Index Int(5); 41 | 42 | Dcl-Ds Employee ExtName('EMPLOYEE') Alias Qualified; 43 | End-Ds; 44 | 45 | //------------------------------------------------------------reb04 46 | Exit = *Off; 47 | LoadSubfile(); 48 | 49 | Dow (Not Exit); 50 | Write FOOTER_FMT; 51 | Exfmt SFLCTL; 52 | 53 | Select; 54 | When (Funkey = F12); 55 | Exit = *On; 56 | When (Funkey = ENTER); 57 | HandleInputs(); 58 | 59 | Endsl; 60 | Enddo; 61 | 62 | *INLR = *ON; 63 | Return; 64 | 65 | //------------------------------------------------------------ 66 | 67 | Dcl-Proc ClearSubfile; 68 | SflDspCtl = *Off; 69 | SflDsp = *Off; 70 | 71 | Write SFLCTL; 72 | 73 | SflDspCtl = *On; 74 | 75 | rrn = 0; 76 | End-Proc; 77 | 78 | Dcl-Proc LoadSubfile; 79 | Dcl-S lCount Int(5); 80 | Dcl-S Action Char(1); 81 | Dcl-S LongAct Char(3); 82 | 83 | ClearSubfile(); 84 | 85 | EXEC SQL DECLARE empCur CURSOR FOR 86 | SELECT EMPNO, FIRSTNME, LASTNAME, JOB 87 | FROM EMPLOYEE 88 | WHERE WORKDEPT = :DEPTNO; 89 | 90 | EXEC SQL OPEN empCur; 91 | 92 | if (sqlstate = '00000'); 93 | 94 | dou (sqlstate <> '00000'); 95 | EXEC SQL 96 | FETCH NEXT FROM empCur 97 | INTO :Employee.EMPNO, 98 | :Employee.FIRSTNME, 99 | :Employee.LASTNAME, 100 | :Employee.JOB; 101 | 102 | if (sqlstate = '00000'); 103 | XID = Employee.EMPNO; 104 | XNAME = %TrimR(Employee.LASTNAME) + ', ' 105 | + %TrimR(Employee.FIRSTNME); 106 | XJOB = Employee.JOB; 107 | 108 | rrn += 1; 109 | Write SFLDTA; 110 | endif; 111 | enddo; 112 | 113 | endif; 114 | 115 | EXEC SQL CLOSE empCur; 116 | 117 | If (rrn > 0); 118 | SflDsp = *On; 119 | SFLRRN = 1; 120 | Endif; 121 | End-Proc; 122 | 123 | Dcl-Proc HandleInputs; 124 | Dcl-S SelVal Char(1); 125 | 126 | Dou (%EOF(emps)); 127 | ReadC SFLDTA; 128 | If (%EOF(emps)); 129 | Iter; 130 | Endif; 131 | 132 | SelVal = %Trim(XSEL); 133 | 134 | Select; 135 | When (SelVal = '5'); 136 | DSPLY XID; 137 | Endsl; 138 | 139 | If (XSEL <> *Blank); 140 | XSEL = *Blank; 141 | Update SFLDTA; 142 | SFLRRN = rrn; 143 | Endif; 144 | Enddo; 145 | End-Proc; 146 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qrpglesrc/mypgm.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt dftactgrp(*no); 4 | 5 | /INCLUDE 'qrpgleref/constants.rpgleinc' 6 | 7 | dcl-s mytext char(50); 8 | 9 | Dcl-PR printf Int(10) extproc('printf'); 10 | input Pointer value options(*string); 11 | End-PR; 12 | 13 | mytext = 'Hello to all you people'; 14 | printf(mytext); 15 | 16 | dsply mytext; 17 | 18 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qrpglesrc/utils.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-proc ToLower export; 6 | dcl-pi ToLower char(50); 7 | inputString char(50) value; 8 | end-pi; 9 | 10 | exec sql set :inputString = LOWER(:inputString); 11 | 12 | return inputString; 13 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qsqlsrc/getDouble.sql: -------------------------------------------------------------------------------- 1 | Create function getDouble (inputNumber decimal(11, 2)) 2 | returns decimal(11, 2) 3 | language rpgle 4 | external name BANKING(doubleIt) 5 | parameter style general; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qsqlsrc/getTotalSalary.sqludf: -------------------------------------------------------------------------------- 1 | create or replace function getTotalSalary () 2 | returns decimal(9, 2) 3 | specific GETTOTSAL 4 | begin 5 | declare total decimal(9, 2); 6 | 7 | select sum(salary) into total from employee; 8 | 9 | return total; 10 | end; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qsqlsrc/showemps.sql: -------------------------------------------------------------------------------- 1 | create or replace procedure SHOWEMPS (IN dept char(3)) 2 | LANGUAGE RPGLE 3 | EXTERNAL NAME EMPLOYEES GENERAL; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qsrvsrc/banking.bnd: -------------------------------------------------------------------------------- 1 | STRPGMEXP PGMLVL(*CURRENT) 2 | EXPORT SYMBOL(DOUBLEIT) 3 | ENDPGMEXP -------------------------------------------------------------------------------- /cli/test/fixtures/company_system/qsrvsrc/utils.bnd: -------------------------------------------------------------------------------- 1 | strpgmexp pgmlvl(*current) 2 | export symbol('TOLOWER') 3 | endpgmexp -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qddssrc/department.table: -------------------------------------------------------------------------------- 1 | --https://www.ibm.com/docs/en/i/7.3?topic=tables-department-table-department 2 | 3 | CREATE OR REPLACE TABLE long_department_name for system name department 4 | (DEPTNO CHAR(3) NOT NULL, 5 | DEPTNAME VARCHAR(36) NOT NULL, 6 | MGRNO CHAR(6) , 7 | ADMRDEPT CHAR(3) NOT NULL, 8 | LOCATION CHAR(16), 9 | PRIMARY KEY (DEPTNO)); 10 | 11 | ALTER TABLE DEPARTMENT 12 | ADD FOREIGN KEY ROD (ADMRDEPT) 13 | REFERENCES DEPARTMENT 14 | ON DELETE CASCADE; 15 | 16 | -- Remove circular reference 17 | --ALTER TABLE DEPARTMENT 18 | -- ADD FOREIGN KEY RDE (MGRNO) 19 | -- REFERENCES EMPLOYEE 20 | -- ON DELETE SET NULL; 21 | 22 | -- CREATE UNIQUE INDEX XDEPT1 23 | -- ON DEPARTMENT (DEPTNO); 24 | 25 | -- CREATE INDEX XDEPT2 26 | -- ON DEPARTMENT (MGRNO); 27 | 28 | -- CREATE INDEX XDEPT3 29 | -- ON DEPARTMENT (ADMRDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qddssrc/depts.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA03(03) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 3A O 7 12 8 | A XNAME 38A O 7 16 9 | A* COLOR HELLO 10 | A R SFLCTL SFLCTL(SFLDTA) 11 | A SFLPAG(0014) 12 | A SFLSIZ(9999) 13 | A OVERLAY 14 | A 85 SFLDSPCTL 15 | A 95 SFLDSP 16 | A N85 SFLCLR 17 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 18 | A* 19 | A 6 6'Opt' 20 | A DSPATR(HI) 21 | A DSPATR(UL) 22 | A 6 12'ID' 23 | A DSPATR(HI) 24 | A DSPATR(UL) 25 | A 6 16'Name' 26 | A DSPATR(UL) 27 | A COLOR(WHT) 28 | A R FOOTER_FMT 29 | A OVERLAY 30 | A 3 6'F3=Exit' 31 | A COLOR(BLU) 32 | A 2 35'Departments' 33 | A DSPATR(UL) 34 | A COLOR(WHT) 35 | A 4 6'5=View' 36 | A COLOR(BLU) 37 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qddssrc/employee.table: -------------------------------------------------------------------------------- 1 | -- https://www.ibm.com/docs/en/i/7.3?topic=tables-employee-table-employee 2 | 3 | --%METADATA * 4 | -- %TEXT Employee File * 5 | --%EMETADATA * 6 | 7 | CREATE OR REPLACE TABLE EMPLOYEE 8 | (EMPNO CHAR(6) NOT NULL, 9 | FIRSTNME VARCHAR(12) NOT NULL, 10 | MIDINIT CHAR(1) NOT NULL, 11 | LASTNAME VARCHAR(15) NOT NULL, 12 | WORKDEPT CHAR(3) , 13 | PHONENO CHAR(4) , 14 | HIREDATE DATE , 15 | JOB CHAR(8) , 16 | EDLEVEL SMALLINT NOT NULL, 17 | SEX CHAR(1) , 18 | BIRTHDATE DATE , 19 | SALARY DECIMAL(9,2) , 20 | BONUS DECIMAL(9,2) , 21 | COMM DECIMAL(9,2) , 22 | PRIMARY KEY (EMPNO)); 23 | 24 | ALTER TABLE EMPLOYEE 25 | ADD FOREIGN KEY RED (WORKDEPT) 26 | REFERENCES DEPARTMENT 27 | ON DELETE SET NULL; 28 | 29 | ALTER TABLE EMPLOYEE 30 | ADD CONSTRAINT NUMBER 31 | CHECK (PHONENO >= '0000' AND PHONENO <= '9999'); 32 | 33 | -- CREATE UNIQUE INDEX XEMP1 34 | -- ON EMPLOYEE (EMPNO); 35 | 36 | -- CREATE INDEX XEMP2 37 | -- ON EMPLOYEE (WORKDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qddssrc/emps.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA12(12) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 6A O 7 12 8 | A XNAME 30A O 7 20 9 | A XJOB 8A O 7 52 10 | A* COLOR HELLO 11 | A R SFLCTL SFLCTL(SFLDTA) 12 | A SFLPAG(0014) 13 | A SFLSIZ(9999) 14 | A OVERLAY 15 | A 85 SFLDSPCTL 16 | A 95 SFLDSP 17 | A N85 SFLCLR 18 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 19 | A* 20 | A 6 6'Opt' 21 | A DSPATR(HI) 22 | A DSPATR(UL) 23 | A 6 12'ID' 24 | A DSPATR(HI) 25 | A DSPATR(UL) 26 | A 6 20'Name' 27 | A DSPATR(UL) 28 | A COLOR(WHT) 29 | A 6 52'Job' 30 | A DSPATR(UL) 31 | A COLOR(WHT) 32 | A R FOOTER_FMT 33 | A OVERLAY 34 | A 3 06'F12=Back' 35 | A COLOR(BLU) 36 | A 2 35'Employees' 37 | A DSPATR(UL) 38 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qrpgleref/constants.rpgleinc: -------------------------------------------------------------------------------- 1 | Dcl-C F01 X'31'; 2 | Dcl-C F02 X'32'; 3 | Dcl-C F03 X'33'; 4 | Dcl-C F04 X'34'; 5 | Dcl-C F05 X'35'; 6 | Dcl-C F06 X'36'; 7 | Dcl-C F07 X'37'; 8 | Dcl-C F08 X'38'; 9 | Dcl-C F09 X'39'; 10 | Dcl-C F10 X'3A'; 11 | Dcl-C F11 X'3B'; 12 | Dcl-C F12 X'3C'; 13 | Dcl-C F13 X'B1'; 14 | Dcl-C F14 X'B2'; 15 | Dcl-C F15 X'B3'; 16 | Dcl-C F16 X'B4'; 17 | Dcl-C F17 X'B5'; 18 | Dcl-C F18 X'B6'; 19 | Dcl-C F19 X'B7'; 20 | Dcl-C F20 X'B8'; 21 | Dcl-C F21 X'B9'; 22 | Dcl-C F22 X'BA'; 23 | Dcl-C F24 X'BC'; 24 | Dcl-C ENTER X'F1'; 25 | Dcl-C HELP X'F3'; 26 | Dcl-C PRINT X'F6'; 27 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qrpgleref/utils.rpgleinc: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-pr ToLower char(50) extproc; 4 | inputString char(50) value; 5 | end-pr; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qrpglesrc/banking.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-proc doubleIt export; 6 | dcl-pi *n packed(11:2); 7 | inputNum packed(11:2) value; 8 | end-pi; 9 | 10 | return inputNum * 2; 11 | end-proc; 12 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qrpglesrc/employees.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | Ctl-Opt DFTACTGRP(*no); 3 | 4 | Dcl-Pi EMPLOYEES; 5 | DEPTNO Char(3); 6 | End-Pi; 7 | 8 | //---------------------------------------------------------------* 9 | 10 | /include 'qrpgleref/constants.rpgleinc' 11 | 12 | //---------------------------------------------------------------* 13 | 14 | Dcl-F emps WORKSTN Sfile(SFLDta:Rrn) IndDS(WkStnInd) InfDS(fileinfo); 15 | 16 | Dcl-S Exit Ind Inz(*Off); 17 | 18 | Dcl-S Rrn Zoned(4:0) Inz; 19 | 20 | Dcl-DS WkStnInd; 21 | ProcessSCF Ind Pos(21); 22 | ReprintScf Ind Pos(22); 23 | Error Ind Pos(25); 24 | PageDown Ind Pos(30); 25 | PageUp Ind Pos(31); 26 | SflEnd Ind Pos(40); 27 | SflBegin Ind Pos(41); 28 | NoRecord Ind Pos(60); 29 | SflDspCtl Ind Pos(85); 30 | SflClr Ind Pos(75); 31 | SflDsp Ind Pos(95); 32 | End-DS; 33 | 34 | Dcl-DS FILEINFO; 35 | FUNKEY Char(1) Pos(369); 36 | End-DS; 37 | 38 | //---------------------------------------------------------------* 39 | // 40 | Dcl-S Index Int(5); 41 | 42 | Dcl-Ds Employee ExtName('EMPLOYEE') Alias Qualified; 43 | End-Ds; 44 | 45 | //------------------------------------------------------------reb04 46 | Exit = *Off; 47 | LoadSubfile(); 48 | 49 | Dow (Not Exit); 50 | Write FOOTER_FMT; 51 | Exfmt SFLCTL; 52 | 53 | Select; 54 | When (Funkey = F12); 55 | Exit = *On; 56 | When (Funkey = ENTER); 57 | HandleInputs(); 58 | 59 | Endsl; 60 | Enddo; 61 | 62 | *INLR = *ON; 63 | Return; 64 | 65 | //------------------------------------------------------------ 66 | 67 | Dcl-Proc ClearSubfile; 68 | SflDspCtl = *Off; 69 | SflDsp = *Off; 70 | 71 | Write SFLCTL; 72 | 73 | SflDspCtl = *On; 74 | 75 | rrn = 0; 76 | End-Proc; 77 | 78 | Dcl-Proc LoadSubfile; 79 | Dcl-S lCount Int(5); 80 | Dcl-S Action Char(1); 81 | Dcl-S LongAct Char(3); 82 | 83 | ClearSubfile(); 84 | 85 | EXEC SQL DECLARE empCur CURSOR FOR 86 | SELECT EMPNO, FIRSTNME, LASTNAME, JOB 87 | FROM EMPLOYEE 88 | WHERE WORKDEPT = :DEPTNO; 89 | 90 | EXEC SQL OPEN empCur; 91 | 92 | if (sqlstate = '00000'); 93 | 94 | dou (sqlstate <> '00000'); 95 | EXEC SQL 96 | FETCH NEXT FROM empCur 97 | INTO :Employee.EMPNO, 98 | :Employee.FIRSTNME, 99 | :Employee.LASTNAME, 100 | :Employee.JOB; 101 | 102 | if (sqlstate = '00000'); 103 | XID = Employee.EMPNO; 104 | XNAME = %TrimR(Employee.LASTNAME) + ', ' 105 | + %TrimR(Employee.FIRSTNME); 106 | XJOB = Employee.JOB; 107 | 108 | rrn += 1; 109 | Write SFLDTA; 110 | endif; 111 | enddo; 112 | 113 | endif; 114 | 115 | EXEC SQL CLOSE empCur; 116 | 117 | If (rrn > 0); 118 | SflDsp = *On; 119 | SFLRRN = 1; 120 | Endif; 121 | End-Proc; 122 | 123 | Dcl-Proc HandleInputs; 124 | Dcl-S SelVal Char(1); 125 | 126 | Dou (%EOF(emps)); 127 | ReadC SFLDTA; 128 | If (%EOF(emps)); 129 | Iter; 130 | Endif; 131 | 132 | SelVal = %Trim(XSEL); 133 | 134 | Select; 135 | When (SelVal = '5'); 136 | DSPLY XID; 137 | Endsl; 138 | 139 | If (XSEL <> *Blank); 140 | XSEL = *Blank; 141 | Update SFLDTA; 142 | SFLRRN = rrn; 143 | Endif; 144 | Enddo; 145 | End-Proc; 146 | -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qrpglesrc/mypgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt dftactgrp(*no); 4 | 5 | /INCLUDE 'qrpgleref/constants.rpgleinc' 6 | 7 | dcl-s mytext char(50); 8 | 9 | Dcl-PR printf Int(10) extproc('printf'); 10 | input Pointer value options(*string); 11 | End-PR; 12 | 13 | mytext = 'Hello to all you people'; 14 | printf(mytext); 15 | 16 | dsply mytext; 17 | 18 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qrpglesrc/utils.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-proc ToLower export; 6 | dcl-pi ToLower char(50); 7 | inputString char(50) value; 8 | end-pi; 9 | 10 | exec sql set :inputString = LOWER(:inputString); 11 | 12 | return inputString; 13 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qsqlsrc/getDouble.sql: -------------------------------------------------------------------------------- 1 | Create function getDouble (inputNumber decimal(11, 2)) 2 | returns decimal(11, 2) 3 | language rpgle 4 | external name BANKING(doubleIt) 5 | parameter style general; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qsqlsrc/getTotalSalary.sqludf: -------------------------------------------------------------------------------- 1 | create or replace function getTotalSalary () 2 | returns decimal(9, 2) 3 | specific GETTOTSAL 4 | begin 5 | declare total decimal(9, 2); 6 | 7 | select sum(salary) into total from employee; 8 | 9 | return total; 10 | end; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qsqlsrc/showemps.sql: -------------------------------------------------------------------------------- 1 | create or replace procedure SHOWEMPS (IN dept char(3)) 2 | LANGUAGE RPGLE 3 | EXTERNAL NAME EMPLOYEES GENERAL; -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qsrvsrc/banking.bnd: -------------------------------------------------------------------------------- 1 | STRPGMEXP PGMLVL(*CURRENT) 2 | EXPORT SYMBOL(DOUBLEIT) 3 | ENDPGMEXP -------------------------------------------------------------------------------- /cli/test/fixtures/company_system_no_pgm_ext/qsrvsrc/utils.bnd: -------------------------------------------------------------------------------- 1 | STRPGMEXP PGMLVL(*CURRENT) 2 | EXPORT SYMBOL('TOLOWER') 3 | ENDPGMEXP -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/.vscode/actions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Create an RPG program", 4 | "environment": "ile", 5 | "extensions": [ 6 | "rpgle" 7 | ], 8 | "command": "CRTBNDRPG NAME(&NAME) THEPARM('&RELATIVEPATH')" 9 | }, 10 | { 11 | "name": "Global run SQL", 12 | "environment": "ile", 13 | "extensions": [ 14 | "sql" 15 | ], 16 | "command": "RUNSQL SRCSTMF('&RELATIVEPATH')" 17 | } 18 | ] -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/actions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Run SQL stuff", 4 | "environment": "ile", 5 | "extensions": [ 6 | "sql", "table" 7 | ], 8 | "command": "RUNSQLSTM SRCSTMF('&RELATIVEPATH')" 9 | } 10 | ] -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/department.table: -------------------------------------------------------------------------------- 1 | --https://www.ibm.com/docs/en/i/7.3?topic=tables-department-table-department 2 | 3 | CREATE OR REPLACE TABLE DEPARTMENT 4 | (DEPTNO CHAR(3) NOT NULL, 5 | DEPTNAME VARCHAR(36) NOT NULL, 6 | MGRNO CHAR(6) NOT NULL, 7 | ADMRDEPT CHAR(3) NOT NULL, 8 | LOCATION CHAR(16) NOT NULL, 9 | PRIMARY KEY (DEPTNO)); 10 | 11 | ALTER TABLE DEPARTMENT 12 | ADD FOREIGN KEY ROD (ADMRDEPT) 13 | REFERENCES DEPARTMENT 14 | ON DELETE CASCADE; 15 | 16 | -- Remove circular reference 17 | --ALTER TABLE DEPARTMENT 18 | -- ADD FOREIGN KEY RDE (MGRNO) 19 | -- REFERENCES EMPLOYEE 20 | -- ON DELETE SET NULL; 21 | 22 | -- CREATE UNIQUE INDEX XDEPT1 23 | -- ON DEPARTMENT (DEPTNO); 24 | 25 | -- CREATE INDEX XDEPT2 26 | -- ON DEPARTMENT (MGRNO); 27 | 28 | -- CREATE INDEX XDEPT3 29 | -- ON DEPARTMENT (ADMRDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/depts.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA03(03) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 3A O 7 12 8 | A XNAME 38A O 7 16 9 | A* COLOR HELLO 10 | A R SFLCTL SFLCTL(SFLDTA) 11 | A SFLPAG(0014) 12 | A SFLSIZ(9999) 13 | A OVERLAY 14 | A 85 SFLDSPCTL 15 | A 95 SFLDSP 16 | A N85 SFLCLR 17 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 18 | A* 19 | A 6 6'Opt' 20 | A DSPATR(HI) 21 | A DSPATR(UL) 22 | A 6 12'ID' 23 | A DSPATR(HI) 24 | A DSPATR(UL) 25 | A 6 16'Name' 26 | A DSPATR(UL) 27 | A COLOR(WHT) 28 | A R FOOTER_FMT 29 | A OVERLAY 30 | A 3 6'F3=Exit' 31 | A COLOR(BLU) 32 | A 2 35'Departments' 33 | A DSPATR(UL) 34 | A COLOR(WHT) 35 | A 4 6'5=View 8=New Employee' 36 | A COLOR(BLU) 37 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/employee.table: -------------------------------------------------------------------------------- 1 | -- https://www.ibm.com/docs/en/i/7.3?topic=tables-employee-table-employee 2 | 3 | CREATE OR REPLACE TABLE EMPLOYEE 4 | (EMPNO CHAR(6) NOT NULL, 5 | FIRSTNME VARCHAR(12) NOT NULL, 6 | MIDINIT CHAR(1) NOT NULL, 7 | LASTNAME VARCHAR(15) NOT NULL, 8 | WORKDEPT CHAR(3) , 9 | PHONENO CHAR(4) , 10 | HIREDATE DATE , 11 | JOB CHAR(8) , 12 | EDLEVEL SMALLINT NOT NULL, 13 | SEX CHAR(1) , 14 | BIRTHDATE DATE , 15 | SALARY DECIMAL(9,2) , 16 | BONUS DECIMAL(9,2) , 17 | COMM DECIMAL(9,2) , 18 | PRIMARY KEY (EMPNO)); 19 | 20 | -- Remove circular reference 21 | -- ALTER TABLE EMPLOYEE 22 | -- ADD FOREIGN KEY RED (WORKDEPT) 23 | -- REFERENCES DEPARTMENT 24 | -- ON DELETE SET NULL; 25 | 26 | ALTER TABLE EMPLOYEE 27 | ADD CONSTRAINT NUMBER 28 | CHECK (PHONENO >= '0000' AND PHONENO <= '9998'); 29 | 30 | -- CREATE UNIQUE INDEX XEMP1 31 | -- ON EMPLOYEE (EMPNO); 32 | 33 | -- CREATE INDEX XEMP2 34 | -- ON EMPLOYEE (WORKDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/emps.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA12(12) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 6A O 7 12 8 | A XNAME 30A O 7 20 9 | A XJOB 8A O 7 52 10 | A* COLOR HELLO 11 | A R SFLCTL SFLCTL(SFLDTA) 12 | A SFLPAG(0014) 13 | A SFLSIZ(9999) 14 | A OVERLAY 15 | A 85 SFLDSPCTL 16 | A 95 SFLDSP 17 | A N85 SFLCLR 18 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 19 | A* 20 | A 6 6'Opt' 21 | A DSPATR(HI) 22 | A DSPATR(UL) 23 | A 6 12'ID' 24 | A DSPATR(HI) 25 | A DSPATR(UL) 26 | A 6 20'Name' 27 | A DSPATR(UL) 28 | A COLOR(WHT) 29 | A 6 52'Job' 30 | A DSPATR(UL) 31 | A COLOR(WHT) 32 | A 5 52'Total' 33 | A DSPATR(UL) 34 | A COLOR(WHT) 35 | A XTOT 9S 2O 5 61 36 | A R FOOTER_FMT 37 | A OVERLAY 38 | A 3 06'F12=Back' 39 | A COLOR(BLU) 40 | A 2 35'Employees' 41 | A DSPATR(UL) 42 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/nemp.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA12(12) 3 | A R DETAIL 4 | A 6 10'ID' 5 | A DSPATR(HI) 6 | A DSPATR(UL) 7 | A XID 6A O 6 14 8 | 9 | A 7 7'First' 10 | A DSPATR(UL) 11 | A COLOR(WHT) 12 | A XFIRST 12A B 7 14 13 | 14 | A 8 5'Initial' 15 | A DSPATR(UL) 16 | A COLOR(WHT) 17 | A XINIT 1A B 8 14 18 | 19 | A 9 8'Last' 20 | A DSPATR(UL) 21 | A COLOR(WHT) 22 | A XLAST 15A B 9 14 23 | 24 | A 10 2'Department' 25 | A DSPATR(UL) 26 | A COLOR(WHT) 27 | A XDEPT 3A O 10 14 28 | 29 | A 11 9'Job' 30 | A DSPATR(UL) 31 | A COLOR(WHT) 32 | A XJOB 8A B 11 14 33 | 34 | A 12 6'Salary' 35 | A DSPATR(UL) 36 | A COLOR(WHT) 37 | A XSAL 10A B 12 14 38 | 39 | A 13 7'Phone' 40 | A DSPATR(UL) 41 | A COLOR(WHT) 42 | A XTEL 4A B 13 14 43 | 44 | A XERR 50A O 15 14COLOR(RED) 45 | A R HEADER_FMT 46 | A OVERLAY 47 | A 3 06'F12=Back Enter=Create' 48 | A COLOR(BLU) 49 | A 2 33'New Employee' 50 | A DSPATR(UL) -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/popdept.sql: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- This procedure will create 5 records into the department table 3 | ------------------------------------------------------------------------------- 4 | 5 | create or replace procedure popdept() 6 | language sql 7 | Result Sets 0 8 | Modifies SQL Data 9 | Specific popdept 10 | begin 11 | declare i int default 1; 12 | declare deptno char(3); 13 | declare deptname varchar(36); 14 | declare mgrno char(6); 15 | declare admrdept char(3); 16 | declare loc char(16); 17 | 18 | while i <= 5 do 19 | -- Generate random data (you can adjust this as needed) 20 | set deptno = right('000' || cast(rand()*1000 as int), 3); 21 | set mgrno = right('00000' || cast(rand()*1000000 as int), 6); 22 | set admrdept = right('000' || cast(rand()*1000 as int), 3); 23 | set loc = 'Location ' || deptno; 24 | 25 | -- Assign department names based on specified categories 26 | case 27 | when i = 1 then set deptname = 'Admin'; 28 | when i = 2 then set deptname = 'IT'; 29 | when i = 3 then set deptname = 'Finance'; 30 | when i = 4 then set deptname = 'Management'; 31 | when i = 5 then set deptname = 'HR'; 32 | end case; 33 | 34 | -- Insert into department table 35 | insert into department (deptno, deptname, mgrno, admrdept, location) 36 | values (deptno, deptname, mgrno, admrdept, loc) with nc; 37 | 38 | set i = i + 1; 39 | end while; 40 | end; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qddssrc/popemp.sql: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- This procedure will use HTTP_GET api to fetch data from randomuser.me/api 3 | -- You may specify the Nationality to generate country specific data like ('fr') or ('in') 4 | -- The default nationality is ('gb'). 5 | -- For every run, this procedure will add 200 records to the employee table. 6 | ------------------------------------------------------------------------------- 7 | create or replace procedure popemp( 8 | in Nationality char(2) default 'gb' 9 | ) 10 | language sql 11 | Result Sets 0 12 | Modifies SQL Data 13 | Specific popemp 14 | 15 | P1: BEGIN 16 | declare v_url CLOB(10M); 17 | declare v_response CLOB(10M); 18 | declare v_dept_name varchar(36); 19 | declare v_mgr_no char(6); 20 | declare v_admr_dept char(3); 21 | declare v_location char(16); 22 | declare v_emp_no char(6); 23 | declare v_first_name varchar(12); 24 | declare v_mid_init char(1); 25 | declare v_last_name varchar(15); 26 | declare v_work_dept char(3); 27 | declare v_phone_no char(4); 28 | declare v_hire_date date; 29 | declare v_job char(8); 30 | declare v_ed_level SMALLint; 31 | declare v_sex char(1); 32 | declare v_birth_date date; 33 | declare v_salary decimal(9,2); 34 | declare v_bonus decimal(9,2); 35 | declare v_comm decimal(9,2); 36 | declare i int; 37 | declare j int; 38 | 39 | -- Get the latest Employee number available in the table 40 | select count(empno)+1, count(1)+200 41 | into i, j 42 | from employee; 43 | 44 | -- Populate EMPLOYEE table 45 | while i <= j do 46 | set v_url = 'https://randomuser.me/api/?nat=' || Nationality ; 47 | 48 | --------------------------------------------------------------- 49 | --Note: If you're getting a run time error as below: 50 | -- HTTP_GET in SYSTOOLS type *N not found. 51 | --then you're probably on IBMi version 7.4 or below, so use HTTPGETCLOB instead of HTTP_GET 52 | --------------------------------------------------------------- 53 | set v_response = SYSTOOLS.HTTP_GET(v_url, NULL); 54 | -- set v_response = SYSTOOLS.HTTPGETCLOB(v_url, NULL); 55 | 56 | 57 | set v_emp_no = i; 58 | set v_first_name = json_value(v_response, '$.results[0].name.first'); 59 | set v_mid_init = substr(json_value(v_response, '$.results[0].name.first'), 1, 1); 60 | set v_last_name = json_value(v_response, '$.results[0].name.last'); 61 | 62 | -- Assign a random department from DEPARTMENT table 63 | select deptno 64 | into v_work_dept 65 | from department 66 | order by rand() 67 | fetch first row only; 68 | 69 | set v_phone_no = substr(HEX(rand()), 1, 4); 70 | set v_hire_date = date('2023-01-01') + int(rand() * 365 * 10) DAYS; 71 | set v_job = 'JOB' || substr(HEX(rand()), 1, 4); 72 | set v_ed_level = 12 + int(rand() * 8); 73 | set v_sex = substr(json_value(v_response, '$.results[0].gender'),1,1); 74 | set v_birth_date = date('1960-01-01') + int(rand() * 365 * 50) DAYS; 75 | set v_salary = decimal(30000 + rand() * 70000, 9, 2); 76 | set v_bonus = decimal(rand() * 10000, 9, 2); 77 | set v_comm = decimal(rand() * 5000, 9, 2); 78 | 79 | 80 | insert into EMPLOYEE 81 | (EMPNO, FIRSTNME, MIDINIT, LASTNAME, WORKDEPT, PHONENO, HIREdate, JOB, EDLEVEL, SEX, BIRTHdate, SALARY, BONUS, COMM) 82 | VALUES (v_emp_no, v_first_name, v_mid_init, v_last_name, v_work_dept, v_phone_no, v_hire_date, v_job, v_ed_level, 83 | v_sex, v_birth_date, v_salary, v_bonus, v_comm) with nc; 84 | 85 | set i = i + 1; 86 | 87 | end while; 88 | end P1; 89 | 90 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qrpgleref/constants.rpgleinc: -------------------------------------------------------------------------------- 1 | Dcl-C F01 X'31'; 2 | Dcl-C F02 X'32'; 3 | Dcl-C F03 X'33'; 4 | Dcl-C F04 X'34'; 5 | Dcl-C F05 X'35'; 6 | Dcl-C F06 X'36'; 7 | Dcl-C F07 X'37'; 8 | Dcl-C F08 X'38'; 9 | Dcl-C F09 X'39'; 10 | Dcl-C F10 X'3A'; 11 | Dcl-C F11 X'3B'; 12 | Dcl-C F12 X'3C'; 13 | Dcl-C F13 X'B1'; 14 | Dcl-C F14 X'B2'; 15 | Dcl-C F15 X'B3'; 16 | Dcl-C F16 X'B4'; 17 | Dcl-C F17 X'B5'; 18 | Dcl-C F18 X'B6'; 19 | Dcl-C F19 X'B7'; 20 | Dcl-C F20 X'B8'; 21 | Dcl-C F21 X'B9'; 22 | Dcl-C F22 X'BA'; 23 | Dcl-C F24 X'BC'; 24 | Dcl-C ENTER X'F1'; 25 | Dcl-C HELP X'F3'; 26 | Dcl-C PRINT X'F6'; 27 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qrpgleref/empdet.rpgleinc: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-ds employee_detail_t qualified template; 4 | found ind; 5 | name varchar(50); 6 | netincome packed(9:2); 7 | end-ds; 8 | 9 | dcl-ds department_detail_t qualified template; 10 | found ind; 11 | deptname varchar(50); 12 | location varchar(50); 13 | totalsalaries packed(9:2); 14 | end-ds; 15 | 16 | dcl-pr getDeptDetail like(department_detail_t) extproc('GETDEPTDETAIL'); 17 | deptno char(3) const; 18 | end-pr; 19 | 20 | dcl-pr getEmployeeDetail like(employee_detail_t) extproc('GETEMPLOYEEDETAIL'); 21 | empno char(6) const; 22 | end-pr; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qrpglesrc/empdet.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | /copy 'qrpgleref/empdet.rpgleinc' 6 | 7 | dcl-proc getEmployeeDetail export; 8 | dcl-pi *n like(employee_detail_t); 9 | empno char(6) const; 10 | end-pi; 11 | 12 | dcl-ds employee_detail likeds(employee_detail_t); 13 | 14 | exec sql 15 | select 16 | rtrim(firstnme) || ' ' || rtrim(lastname), 17 | salary + bonus + comm 18 | into 19 | :employee_detail.name, 20 | :employee_detail.netincome 21 | from 22 | employee 23 | where 24 | empno = :empno; 25 | 26 | if (sqlcode = 0); 27 | employee_detail.found = *on; 28 | else; 29 | employee_detail.found = *off; 30 | endif; 31 | 32 | return employee_detail; 33 | end-proc; 34 | 35 | dcl-proc getDeptDetail export; 36 | dcl-pi *n like(department_detail_t); 37 | deptno char(3) const; 38 | end-pi; 39 | 40 | dcl-ds department_detail likeds(department_detail_t); 41 | 42 | exec sql 43 | select 44 | rtrim(deptname), 45 | coalesce(location, 'N/A'), 46 | (select sum(salary + bonus + comm) 47 | from employee 48 | where workdept = :deptno) 49 | into 50 | :department_detail.deptname, 51 | :department_detail.location, 52 | :department_detail.totalsalaries 53 | from 54 | department 55 | where 56 | deptno = :deptno; 57 | 58 | if (sqlcode = 0); 59 | department_detail.found = *on; 60 | else; 61 | department_detail.found = *off; 62 | endif; 63 | 64 | return department_detail; 65 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qrpglesrc/mypgm.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt dftactgrp(*no); 4 | 5 | /INCLUDE 'qrpgleref/constants.rpgleinc' 6 | 7 | dcl-s mytext char(50); 8 | 9 | Dcl-PR printf Int(10) extproc('printf'); 10 | input Pointer value options(*string); 11 | End-PR; 12 | 13 | mytext = 'Hello to all you people'; 14 | printf(mytext); 15 | 16 | dsply mytext; 17 | 18 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_srvpgm/qtestsrc/emptest.test.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain bnddir('APP'); 4 | 5 | /include 'qrpgleref/empdet.rpgleinc' 6 | /include qinclude,TESTCASE 7 | 8 | dcl-proc setUpSuite export; 9 | // Insert sample data into employee 10 | exec sql 11 | insert into employee ( 12 | empno, firstnme, midinit, lastname, workdept, phoneno, 13 | hiredate, job, edlevel, sex, birthdate, salary, bonus, comm 14 | ) values 15 | ('000010', 'CHRISTINE', 'I', 'HAAS', 'A00', '3978', '01/01/65', 'PRES', 18, 'F', null, 52750, 1000, 4220), 16 | ('000020', 'MICHAEL', 'L', 'THOMPSON', 'B01', '3476', '10/10/73', 'MANAGER', 18, 'M', '02/02/48', 41250, 800, 3300), 17 | ('200120', 'GREG', '', 'ORLANDO', 'A00', '2167', '05/05/72', 'CLERK', 14, 'M', '10/18/42', 29250, 600, 2340); 18 | 19 | if (sqlcode <> 0 and sqlcode <> -803); 20 | fail('Failed to insert into employee table'); 21 | endif; 22 | 23 | // Insert sample data in department table 24 | exec sql 25 | insert into department ( 26 | deptno, deptname, mgrno, admrdept, location 27 | ) values 28 | ('A00', 'SPIFFY COMPUTER SERVICE DIV.', '000010', 'A00', 'NEW YORK'), 29 | ('B01', 'PLANNING', '000020', 'A00', 'ATLANTA'); 30 | 31 | if (sqlcode <> 0 and sqlcode <> -803); 32 | fail('Failed to insert into department table'); 33 | endif; 34 | end-proc; 35 | 36 | dcl-proc tearDownSuite export; 37 | // Delete sample data from employee 38 | exec sql 39 | delete from employee 40 | where empno in ('000010', '000020', '200120'); 41 | 42 | if (sqlcode <> 0); 43 | fail('Failed to delete from employee table'); 44 | return; 45 | endif; 46 | 47 | // Delete sample data from department 48 | exec sql 49 | delete from department 50 | where deptno in ('A00', 'B01'); 51 | 52 | if (sqlcode <> 0); 53 | fail('Failed to delete from department table'); 54 | return; 55 | endif; 56 | end-proc; 57 | 58 | dcl-proc test_getEmployeeDetail_found export; 59 | dcl-pi *n extproc(*dclcase) end-pi; 60 | 61 | dcl-s empno char(6); 62 | dcl-ds actual likeDS(employee_detail_t); 63 | dcl-ds expected likeDS(employee_detail_t); 64 | 65 | // Input 66 | empno = '000010'; 67 | 68 | // Actual results 69 | actual = getEmployeeDetail(empno); 70 | 71 | // Expected results 72 | expected.found = *on; 73 | expected.name = 'CHRISTINE I HAAS'; 74 | expected.netincome = 57970; 75 | 76 | // Assertions 77 | nEqual(expected.found : actual.found : 'found'); 78 | aEqual(expected.name : actual.name : 'name'); 79 | assert(expected.netincome = actual.netincome : 'netincome' ); 80 | end-proc; 81 | 82 | dcl-proc test_getDeptDetail_found export; 83 | dcl-pi *n extproc(*dclcase) end-pi; 84 | 85 | dcl-s deptno char(3); 86 | dcl-ds actual likeDS(department_detail_t); 87 | dcl-ds expected likeDS(department_detail_t); 88 | 89 | // Input 90 | deptno = 'A00'; 91 | 92 | // Actual results 93 | actual = getDeptDetail(deptno); 94 | 95 | // Expected results 96 | expected.found = *on; 97 | expected.deptname = 'SPIFFY COMPUTER SERVICE DIV.'; 98 | expected.location = 'NEW YORK'; 99 | expected.totalsalaries = 90160; 100 | 101 | // Assertions 102 | nEqual(expected.found : actual.found : 'found'); 103 | aEqual(expected.deptname : actual.deptname : 'deptname'); 104 | aEqual(expected.location : actual.location : 'location'); 105 | assert(expected.totalsalaries = actual.totalsalaries : 'totalsalaries'); 106 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qddssrc/Rules.mk: -------------------------------------------------------------------------------- 1 | DEPTS.FILE: depts.dspf 2 | EMPS.FILE: emps.dspf 3 | NEMP.FILE: nemp.dspf -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qddssrc/depts.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA03(03) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 3A O 7 12 8 | A XNAME 38A O 7 16 9 | A* COLOR HELLO 10 | A R SFLCTL SFLCTL(SFLDTA) 11 | A SFLPAG(0014) 12 | A SFLSIZ(9999) 13 | A OVERLAY 14 | A 85 SFLDSPCTL 15 | A 95 SFLDSP 16 | A N85 SFLCLR 17 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 18 | A* 19 | A 6 6'Opt' 20 | A DSPATR(HI) 21 | A DSPATR(UL) 22 | A 6 12'ID' 23 | A DSPATR(HI) 24 | A DSPATR(UL) 25 | A 6 16'Name' 26 | A DSPATR(UL) 27 | A COLOR(WHT) 28 | A R FOOTER_FMT 29 | A OVERLAY 30 | A 3 6'F3=Exit' 31 | A COLOR(BLU) 32 | A 2 35'Departments' 33 | A DSPATR(UL) 34 | A COLOR(WHT) 35 | A 4 6'5=View 8=New Employee' 36 | A COLOR(BLU) 37 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qddssrc/emps.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA12(12) 3 | A R SFLDTA SFL 4 | A RRN 4Y 0H 5 | A* DISPLAY DTA 6 | A XSEL 1A B 7 8 7 | A XID 6A O 7 12 8 | A XNAME 30A O 7 20 9 | A XJOB 8A O 7 52 10 | A* COLOR HELLO 11 | A R SFLCTL SFLCTL(SFLDTA) 12 | A SFLPAG(0014) 13 | A SFLSIZ(9999) 14 | A OVERLAY 15 | A 85 SFLDSPCTL 16 | A 95 SFLDSP 17 | A N85 SFLCLR 18 | A SFLRRN 4S 0H SFLRCDNBR(CURSOR) 19 | A* 20 | A 6 6'Opt' 21 | A DSPATR(HI) 22 | A DSPATR(UL) 23 | A 6 12'ID' 24 | A DSPATR(HI) 25 | A DSPATR(UL) 26 | A 6 20'Name' 27 | A DSPATR(UL) 28 | A COLOR(WHT) 29 | A 6 52'Job' 30 | A DSPATR(UL) 31 | A COLOR(WHT) 32 | A 5 52'Total' 33 | A DSPATR(UL) 34 | A COLOR(WHT) 35 | A XTOT 9S 2O 5 61 36 | A R FOOTER_FMT 37 | A OVERLAY 38 | A 3 06'F12=Back' 39 | A COLOR(BLU) 40 | A 2 35'Employees' 41 | A DSPATR(UL) 42 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qddssrc/nemp.dspf: -------------------------------------------------------------------------------- 1 | A INDARA 2 | A CA12(12) 3 | A R DETAIL 4 | A 6 10'ID' 5 | A DSPATR(HI) 6 | A DSPATR(UL) 7 | A XID 6A O 6 14 8 | 9 | A 7 7'First' 10 | A DSPATR(UL) 11 | A COLOR(WHT) 12 | A XFIRST 12A B 7 14 13 | 14 | A 8 5'Initial' 15 | A DSPATR(UL) 16 | A COLOR(WHT) 17 | A XINIT 1A B 8 14 18 | 19 | A 9 8'Last' 20 | A DSPATR(UL) 21 | A COLOR(WHT) 22 | A XLAST 15A B 9 14 23 | 24 | A 10 2'Department' 25 | A DSPATR(UL) 26 | A COLOR(WHT) 27 | A XDEPT 3A O 10 14 28 | 29 | A 11 9'Job' 30 | A DSPATR(UL) 31 | A COLOR(WHT) 32 | A XJOB 8A B 11 14 33 | 34 | A 12 6'Salary' 35 | A DSPATR(UL) 36 | A COLOR(WHT) 37 | A XSAL 10A B 12 14 38 | 39 | A 13 7'Phone' 40 | A DSPATR(UL) 41 | A COLOR(WHT) 42 | A XTEL 4A B 13 14 43 | 44 | A XERR 50A O 15 14COLOR(RED) 45 | A R HEADER_FMT 46 | A OVERLAY 47 | A 3 06'F12=Back Enter=Create' 48 | A COLOR(BLU) 49 | A 2 33'New Employee' 50 | A DSPATR(UL) -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qrpgleref/constants.rpgleinc: -------------------------------------------------------------------------------- 1 | Dcl-C F01 X'31'; 2 | Dcl-C F02 X'32'; 3 | Dcl-C F03 X'33'; 4 | Dcl-C F04 X'34'; 5 | Dcl-C F05 X'35'; 6 | Dcl-C F06 X'36'; 7 | Dcl-C F07 X'37'; 8 | Dcl-C F08 X'38'; 9 | Dcl-C F09 X'39'; 10 | Dcl-C F10 X'3A'; 11 | Dcl-C F11 X'3B'; 12 | Dcl-C F12 X'3C'; 13 | Dcl-C F13 X'B1'; 14 | Dcl-C F14 X'B2'; 15 | Dcl-C F15 X'B3'; 16 | Dcl-C F16 X'B4'; 17 | Dcl-C F17 X'B5'; 18 | Dcl-C F18 X'B6'; 19 | Dcl-C F19 X'B7'; 20 | Dcl-C F20 X'B8'; 21 | Dcl-C F21 X'B9'; 22 | Dcl-C F22 X'BA'; 23 | Dcl-C F24 X'BC'; 24 | Dcl-C ENTER X'F1'; 25 | Dcl-C HELP X'F3'; 26 | Dcl-C PRINT X'F6'; 27 | -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qrpgleref/empdet.rpgleinc: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-ds employee_detail_t qualified template; 4 | found ind; 5 | name varchar(50); 6 | netincome packed(9:2); 7 | end-ds; 8 | 9 | dcl-ds department_detail_t qualified template; 10 | found ind; 11 | deptname varchar(50); 12 | location varchar(50); 13 | totalsalaries packed(9:2); 14 | end-ds; 15 | 16 | dcl-pr getDeptDetail like(department_detail_t) extproc('GETDEPTDETAIL'); 17 | deptno char(3) const; 18 | end-pr; 19 | 20 | dcl-pr getEmployeeDetail like(employee_detail_t) extproc('GETEMPLOYEEDETAIL'); 21 | empno char(6) const; 22 | end-pr; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qrpglesrc/app.bnddir: -------------------------------------------------------------------------------- 1 | /* Have to delete the BNDDIR, or it will always be older than the source */ 2 | /* because the CRTBNDDIR will fail the second time and only the ADDBNDDIRE is executed */ 3 | !DLTOBJ OBJ(&O/&N) OBJTYPE(*BNDDIR) 4 | CRTBNDDIR BNDDIR(&O/&N) 5 | ADDBNDDIRE BNDDIR(&O/&N) OBJ((*LIBL/EMPDET *SRVPGM)) -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qrpglesrc/empdet.bnd: -------------------------------------------------------------------------------- 1 | STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('V1') 2 | EXPORT SYMBOL('GETEMPLOYEEDETAIL') 3 | EXPORT SYMBOL('GETDEPTDETAIL') 4 | ENDPGMEXP -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qrpglesrc/empdet.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | /copy 'qrpgleref/empdet.rpgleinc' 6 | 7 | dcl-proc getEmployeeDetail export; 8 | dcl-pi *n like(employee_detail_t); 9 | empno char(6) const; 10 | end-pi; 11 | 12 | dcl-ds employee_detail likeds(employee_detail_t); 13 | 14 | exec sql 15 | select 16 | rtrim(firstnme) || ' ' || rtrim(midinit) || ' ' || rtrim(lastname), 17 | salary + bonus + comm 18 | into 19 | :employee_detail.name, 20 | :employee_detail.netincome 21 | from 22 | employee 23 | where 24 | empno = :empno; 25 | 26 | if (sqlcode = 0); 27 | employee_detail.found = *on; 28 | else; 29 | employee_detail.found = *off; 30 | endif; 31 | 32 | return employee_detail; 33 | end-proc; 34 | 35 | dcl-proc getDeptDetail export; 36 | dcl-pi *n like(department_detail_t); 37 | deptno char(3) const; 38 | end-pi; 39 | 40 | dcl-ds department_detail likeds(department_detail_t); 41 | 42 | exec sql 43 | select 44 | rtrim(deptname), 45 | coalesce(location, 'N/A'), 46 | (select sum(salary + bonus + comm) 47 | from employee 48 | where workdept = :deptno) 49 | into 50 | :department_detail.deptname, 51 | :department_detail.location, 52 | :department_detail.totalsalaries 53 | from 54 | department 55 | where 56 | deptno = :deptno; 57 | 58 | if (sqlcode = 0); 59 | department_detail.found = *on; 60 | else; 61 | department_detail.found = *off; 62 | endif; 63 | 64 | return department_detail; 65 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qrpglesrc/mypgm.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt dftactgrp(*no); 4 | 5 | /INCLUDE 'qrpgleref/constants.rpgleinc' 6 | 7 | dcl-s mytext char(50); 8 | 9 | Dcl-PR printf Int(10) extproc('printf'); 10 | input Pointer value options(*string); 11 | End-PR; 12 | 13 | mytext = 'Hello to all you people'; 14 | printf(mytext); 15 | 16 | dsply mytext; 17 | 18 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qsqlsrc/department.table: -------------------------------------------------------------------------------- 1 | --https://www.ibm.com/docs/en/i/7.3?topic=tables-department-table-department 2 | 3 | CREATE OR REPLACE TABLE DEPARTMENT 4 | (DEPTNO CHAR(3) NOT NULL, 5 | DEPTNAME VARCHAR(36) NOT NULL, 6 | MGRNO CHAR(6) NOT NULL, 7 | ADMRDEPT CHAR(3) NOT NULL, 8 | LOCATION CHAR(16) NOT NULL, 9 | PRIMARY KEY (DEPTNO)); 10 | 11 | ALTER TABLE DEPARTMENT 12 | ADD FOREIGN KEY ROD (ADMRDEPT) 13 | REFERENCES DEPARTMENT 14 | ON DELETE CASCADE; 15 | 16 | -- Remove circular reference 17 | --ALTER TABLE DEPARTMENT 18 | -- ADD FOREIGN KEY RDE (MGRNO) 19 | -- REFERENCES EMPLOYEE 20 | -- ON DELETE SET NULL; 21 | 22 | -- CREATE UNIQUE INDEX XDEPT1 23 | -- ON DEPARTMENT (DEPTNO); 24 | 25 | -- CREATE INDEX XDEPT2 26 | -- ON DEPARTMENT (MGRNO); 27 | 28 | -- CREATE INDEX XDEPT3 29 | -- ON DEPARTMENT (ADMRDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qsqlsrc/employee.table: -------------------------------------------------------------------------------- 1 | -- https://www.ibm.com/docs/en/i/7.3?topic=tables-employee-table-employee 2 | 3 | CREATE OR REPLACE TABLE EMPLOYEE 4 | (EMPNO CHAR(6) NOT NULL, 5 | FIRSTNME VARCHAR(12) NOT NULL, 6 | MIDINIT CHAR(1) NOT NULL, 7 | LASTNAME VARCHAR(15) NOT NULL, 8 | WORKDEPT CHAR(3) , 9 | PHONENO CHAR(4) , 10 | HIREDATE DATE , 11 | JOB CHAR(8) , 12 | EDLEVEL SMALLINT NOT NULL, 13 | SEX CHAR(1) , 14 | BIRTHDATE DATE , 15 | SALARY DECIMAL(9,2) , 16 | BONUS DECIMAL(9,2) , 17 | COMM DECIMAL(9,2) , 18 | PRIMARY KEY (EMPNO)); 19 | 20 | -- Remove circular reference 21 | -- ALTER TABLE EMPLOYEE 22 | -- ADD FOREIGN KEY RED (WORKDEPT) 23 | -- REFERENCES DEPARTMENT 24 | -- ON DELETE SET NULL; 25 | 26 | ALTER TABLE EMPLOYEE 27 | ADD CONSTRAINT NUMBER 28 | CHECK (PHONENO >= '0000' AND PHONENO <= '9998'); 29 | 30 | -- CREATE UNIQUE INDEX XEMP1 31 | -- ON EMPLOYEE (EMPNO); 32 | 33 | -- CREATE INDEX XEMP2 34 | -- ON EMPLOYEE (WORKDEPT); -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qsqlsrc/popdept.sqlprc: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- This procedure will create 5 records into the department table 3 | ------------------------------------------------------------------------------- 4 | 5 | create or replace procedure popdept() 6 | language sql 7 | Result Sets 0 8 | Modifies SQL Data 9 | Specific popdept 10 | begin 11 | declare i int default 1; 12 | declare deptno char(3); 13 | declare deptname varchar(36); 14 | declare mgrno char(6); 15 | declare admrdept char(3); 16 | declare loc char(16); 17 | 18 | while i <= 5 do 19 | -- Generate random data (you can adjust this as needed) 20 | set deptno = right('000' || cast(rand()*1000 as int), 3); 21 | set mgrno = right('00000' || cast(rand()*1000000 as int), 6); 22 | set admrdept = right('000' || cast(rand()*1000 as int), 3); 23 | set loc = 'Location ' || deptno; 24 | 25 | -- Assign department names based on specified categories 26 | case 27 | when i = 1 then set deptname = 'Admin'; 28 | when i = 2 then set deptname = 'IT'; 29 | when i = 3 then set deptname = 'Finance'; 30 | when i = 4 then set deptname = 'Management'; 31 | when i = 5 then set deptname = 'HR'; 32 | end case; 33 | 34 | -- Insert into department table 35 | insert into department (deptno, deptname, mgrno, admrdept, location) 36 | values (deptno, deptname, mgrno, admrdept, loc) with nc; 37 | 38 | set i = i + 1; 39 | end while; 40 | end; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qtestsrc/empdett.test.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain BNDDIR('APP'); 4 | 5 | /include 'qrpgleref/empdet.rpgleinc' 6 | /include qinclude,TESTCASE 7 | 8 | exec sql 9 | set option commit = *none; 10 | 11 | dcl-proc setUpSuite export; 12 | // Insert sample data into employee 13 | exec sql 14 | insert into employee ( 15 | empno, firstnme, midinit, lastname, workdept, phoneno, 16 | hiredate, job, edlevel, sex, birthdate, salary, bonus, comm 17 | ) values 18 | ('000010', 'CHRISTINE', 'I', 'HAAS', 'A00', '3978', '01/01/65', 'PRES', 18, 'F', null, 52750, 1000, 4220), 19 | ('000020', 'MICHAEL', 'L', 'THOMPSON', 'B01', '3476', '10/10/73', 'MANAGER', 18, 'M', '02/02/48', 41250, 800, 3300), 20 | ('200120', 'GREG', '', 'ORLANDO', 'A00', '2167', '05/05/72', 'CLERK', 14, 'M', '10/18/42', 29250, 600, 2340); 21 | 22 | if (sqlcode <> 0 and sqlcode <> -803); 23 | fail('Failed to insert into employee table with SQL code: ' + %char(sqlcode)); 24 | endif; 25 | 26 | // Insert sample data in department table 27 | exec sql 28 | insert into department ( 29 | deptno, deptname, mgrno, admrdept, location 30 | ) values 31 | ('A00', 'SPIFFY COMPUTER SERVICE DIV.', '000010', 'A00', 'NEW YORK'), 32 | ('B01', 'PLANNING', '000020', 'A00', 'ATLANTA'); 33 | 34 | if (sqlcode <> 0 and sqlcode <> -803); 35 | fail('Failed to insert into department table with SQL code: ' + %char(sqlcode)); 36 | endif; 37 | end-proc; 38 | 39 | dcl-proc test_getEmployeeDetail_found export; 40 | dcl-pi *n extproc(*dclcase) end-pi; 41 | 42 | dcl-s empno char(6); 43 | dcl-ds actual likeDS(employee_detail_t); 44 | dcl-ds expected likeDS(employee_detail_t); 45 | 46 | // Input 47 | empno = '000010'; 48 | 49 | // Actual results 50 | actual = getEmployeeDetail(empno); 51 | 52 | // Expected results 53 | expected.found = *on; 54 | expected.name = 'CHRISTINE I HAAS'; 55 | expected.netincome = 57970; 56 | 57 | // Assertions 58 | nEqual(expected.found : actual.found : 'found'); 59 | aEqual(expected.name : actual.name : 'name'); 60 | assert(expected.netincome = actual.netincome : 'netincome' ); 61 | end-proc; 62 | 63 | dcl-proc test_getDeptDetail_found export; 64 | dcl-pi *n extproc(*dclcase) end-pi; 65 | 66 | dcl-s deptno char(3); 67 | dcl-ds actual likeDS(department_detail_t); 68 | dcl-ds expected likeDS(department_detail_t); 69 | 70 | // Input 71 | deptno = 'A00'; 72 | 73 | // Actual results 74 | actual = getDeptDetail(deptno); 75 | 76 | // Expected results 77 | expected.found = *on; 78 | expected.deptname = 'SPIFFY COMPUTER SERVICE DIV.'; 79 | expected.location = 'NEW YORK'; 80 | expected.totalsalaries = 90160; 81 | 82 | // Assertions 83 | nEqual(expected.found : actual.found : 'found'); 84 | aEqual(expected.deptname : actual.deptname : 'deptname'); 85 | aEqual(expected.location : actual.location : 'location'); 86 | assert(expected.totalsalaries = actual.totalsalaries : 'totalsalaries'); 87 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/cs_with_bnddir/qtestsrc/testing.json: -------------------------------------------------------------------------------- 1 | { 2 | "RPGUnit": { 3 | "RUCRTRPG": { 4 | "tgtCcsid": 37, 5 | "dbgView": "*SOURCE", 6 | "cOption": [ 7 | "*EVENTF" 8 | ] 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /cli/test/fixtures/dclcase/qrpglesrc/apival01s.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | //%METADATA * 3 | // %TEXT API main validation procedure (IWS) * 4 | //%EMETADATA * 5 | /// 6 | // @Program APIVAL01S 7 | // 8 | // @Purpose IWS API validation procedures 9 | // 10 | // @author JHEI 11 | // @Date 22 May 2024 12 | // 13 | /// 14 | ctl-opt option(*srcstmt:*nodebugio); 15 | ctl-opt debug(*retval:*constants); 16 | ctl-opt reqprexp(*require); 17 | 18 | // includes 19 | /copy 'apival01s.rpgleinc' 20 | 21 | dsply 'hello'; 22 | 23 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/dclcase/qrpglesrc/apival01s.rpgleinc: -------------------------------------------------------------------------------- 1 | **free 2 | // Constants 3 | // --------- 4 | // field & array sizes 5 | dcl-c APIVAL01S_MAX_DIM 1000; // max array size 6 | dcl-c APIVAL01S_DATA_LEN 100; // max field data length 7 | dcl-c APIVAL01S_FIELD_LEN 50; // max field name length 8 | dcl-c APIVAL01S_VALID_LEN 500; // max validation length 9 | dcl-c APIVAL01S_JSON_LEN 1000; // JSON error response size 10 | // type constants 11 | dcl-c APIVAL01S_TYPE_STRING 'string'; 12 | dcl-c APIVAL01S_TYPE_NUMERIC 'numeric'; 13 | dcl-c APIVAL01S_TYPE_DATE 'date'; 14 | 15 | // DS templates 16 | // ------------ 17 | // list of validations to perform 18 | dcl-ds APIVAL01S_validationsDs qualified template; 19 | field varchar(APIVAL01S_FIELD_LEN); 20 | type varchar(50); 21 | validations varchar(APIVAL01S_VALID_LEN) dim(6); 22 | end-ds; 23 | 24 | // perform validation for the given list of validations (validationDs) 25 | // with the given input data (note: required char!) 26 | // returns the number of errors found (if any) 27 | // if errors returned = 0 then the validation succeeded 28 | // in case of validation failure o_errorJson will contain a list of errors in JSON format 29 | dcl-pr APIVAL01S_iws_validate int(10) extproc(*dclcase); 30 | i_validationsDs likeds(APIVAL01S_validationsDs) dim(APIVAL01S_MAX_DIM); 31 | i_data varchar(APIVAL01S_DATA_LEN) dim(APIVAL01S_MAX_DIM); 32 | o_errorJson varchar(APIVAL01S_JSON_LEN); 33 | end-pr; 34 | 35 | -------------------------------------------------------------------------------- /cli/test/fixtures/dds_deps/PROVIDE1.LF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Provider file * 3 | *%EMETADATA * 4 | UNIQUE 5 | R FPROV PFILE(PROVIDER) 6 | K PRID 7 | -------------------------------------------------------------------------------- /cli/test/fixtures/dds_deps/PROVIDER.PF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Provider file * 3 | *%EMETADATA * 4 | REF(SAMREF) 5 | R FPROV 6 | PRID R 7 | PROVNM R 8 | PRCONT 30 TEXT('CONTACT PERSON') 9 | PRPHONE R REFFLD(PHONE) 10 | PRVAT R REFFLD(VATNUM) 11 | PRMAIL R REFFLD(EMAIL) 12 | PRLINE1 R REFFLD(ADRLINE) 13 | PRLINE2 R REFFLD(ADRLINE) 14 | PRLINE3 R REFFLD(ADRLINE) 15 | PRZIP R REFFLD(ZIPCOD) 16 | PRCITY R REFFLD(CITY) 17 | PRCOUN R REFFLD(COID) 18 | PRCREA L TEXT('CREATION DATE') 19 | COLHDG('CREAETION' 'DATE') 20 | PRMOD Z TEXT('LAST MODIFICATION') 21 | COLHDG('LAST' 'MODIFICATION') 22 | PRMODID 10 TEXT('LAS MOD BY') 23 | COLHDG('LAST' 'MODIF.' 'BY') 24 | PRDEL R REFFLD(DLCODE) 25 | -------------------------------------------------------------------------------- /cli/test/fixtures/dds_deps_with_refs/.objrefs: -------------------------------------------------------------------------------- 1 | # cool comment 2 | 3 | SAMREF.FILE 4 | 5 | # other comment -------------------------------------------------------------------------------- /cli/test/fixtures/dds_deps_with_refs/PROVIDE1.LF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Provider file * 3 | *%EMETADATA * 4 | UNIQUE 5 | R FPROV PFILE(PROVIDER) 6 | K PRID 7 | -------------------------------------------------------------------------------- /cli/test/fixtures/dds_deps_with_refs/PROVIDER.PF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Provider file * 3 | *%EMETADATA * 4 | REF(SAMREF) 5 | R FPROV 6 | PRID R 7 | PROVNM R 8 | PRCONT 30 TEXT('CONTACT PERSON') 9 | PRPHONE R REFFLD(PHONE) 10 | PRVAT R REFFLD(VATNUM) 11 | PRMAIL R REFFLD(EMAIL) 12 | PRLINE1 R REFFLD(ADRLINE) 13 | PRLINE2 R REFFLD(ADRLINE) 14 | PRLINE3 R REFFLD(ADRLINE) 15 | PRZIP R REFFLD(ZIPCOD) 16 | PRCITY R REFFLD(CITY) 17 | PRCOUN R REFFLD(COID) 18 | PRCREA L TEXT('CREATION DATE') 19 | COLHDG('CREAETION' 'DATE') 20 | PRMOD Z TEXT('LAST MODIFICATION') 21 | COLHDG('LAST' 'MODIFICATION') 22 | PRMODID 10 TEXT('LAS MOD BY') 23 | COLHDG('LAST' 'MODIF.' 'BY') 24 | PRDEL R REFFLD(DLCODE) 25 | -------------------------------------------------------------------------------- /cli/test/fixtures/from_qsys/qprotosrc/errortable.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | // This contains global constants, variables and prototypes 3 | // for the Payroll Maintainance app 4 | 5 | // 6 | // Compile time array containing error descriptions. 7 | Dcl-S ERR Char(50) DIM(10) CTDATA PERRCD(1); 8 | 9 | Dcl-C INVALID_MAINTENANCE_SELECTION 1; 10 | Dcl-C INVALID_ACTION_CODE 4; 11 | 12 | -------------------------------------------------------------------------------- /cli/test/fixtures/from_qsys/qsqlsrc/dept.sql: -------------------------------------------------------------------------------- 1 | -- Employee Master 2 | -- Generated on: 11/03/21 14:32:20 3 | CREATE OR REPLACE TABLE super_long_dept_name FOR SYSTEM NAME DEPT ( 4 | -- SQL150B 10 REUSEDLT(*NO) in table EMPMST in PAYROLL1 ignored. 5 | COL_B CHAR(1) CCSID 37 NOT NULL DEFAULT '' , 6 | PRIMARY KEY( COL_B ) ); -------------------------------------------------------------------------------- /cli/test/fixtures/from_qsys/qsqlsrc/emp.sql: -------------------------------------------------------------------------------- 1 | -- Employee Master 2 | -- Generated on: 11/03/21 14:32:20 3 | CREATE OR REPLACE TABLE super_long_emp_name ( 4 | -- SQL150B 10 REUSEDLT(*NO) in table EMPMST in PAYROLL1 ignored. 5 | COL_A CHAR(1) CCSID 37 NOT NULL DEFAULT '' , 6 | PRIMARY KEY( COL_A ) ); -------------------------------------------------------------------------------- /cli/test/fixtures/from_qsys/qsqlsrc/empmst.sql: -------------------------------------------------------------------------------- 1 | -- Employee Master 2 | -- Generated on: 11/03/21 14:32:20 3 | CREATE OR REPLACE TABLE EMPMST ( 4 | -- SQL150B 10 REUSEDLT(*NO) in table EMPMST in PAYROLL1 ignored. 5 | ACREC CHAR(1) CCSID 37 NOT NULL DEFAULT '' , 6 | EMPNO DECIMAL(6, 0) NOT NULL DEFAULT 0 , 7 | ENAME CHAR(30) CCSID 37 NOT NULL DEFAULT '' , 8 | EMCAT CHAR(1) CCSID 37 NOT NULL DEFAULT '' , 9 | EDEPT CHAR(5) CCSID 37 NOT NULL DEFAULT '' , 10 | ELOCN CHAR(30) CCSID 37 NOT NULL DEFAULT '' , 11 | EUSRI CHAR(8) CCSID 37 NOT NULL DEFAULT '' , 12 | ENHRS DECIMAL(3, 1) NOT NULL DEFAULT 0 , 13 | EPHRC DECIMAL(5, 1) NOT NULL DEFAULT 0 , 14 | EPHRY DECIMAL(7, 1) NOT NULL DEFAULT 0 , 15 | EPHRP DECIMAL(7, 1) NOT NULL DEFAULT 0 , 16 | EPNRC DECIMAL(5, 1) NOT NULL DEFAULT 0 , 17 | EPNRY DECIMAL(7, 1) NOT NULL DEFAULT 0 , 18 | EPNRP DECIMAL(7, 1) NOT NULL DEFAULT 0 , 19 | PRIMARY KEY( EMPNO ) ) 20 | 21 | RCDFMT RCEMP ; 22 | 23 | LABEL ON COLUMN EMPMST 24 | ( EMPNO IS 'EMPLOYEE NUMBER' , 25 | ENAME IS 'EMPLOYEE NAME' , 26 | EMCAT IS 'EMP CAT' , 27 | EDEPT IS 'EMPL DEPT' , 28 | ELOCN IS 'EMPLOYEE LOCATION' , 29 | EUSRI IS 'EMPLOYEE USRID' , 30 | ENHRS IS 'NORMAL WK HRS' , 31 | EPHRC IS 'PRJ HRS CUR MTH' , 32 | EPHRY IS 'PRJ HRS YTD' , 33 | EPHRP IS 'PRJ HRS PRIOR YR' , 34 | EPNRC IS 'NON PRJ HRS CUR MTH' , 35 | EPNRY IS 'NON PRJ HRS YTD' , 36 | EPNRP IS 'NON PRJ HRS PRIOR YR' ) ; 37 | 38 | LABEL ON COLUMN EMPMST 39 | ( ACREC TEXT IS 'ACTIVE RECORD CODE' , 40 | EMPNO TEXT IS 'EMPLOYEE NUMBER' , 41 | ENAME TEXT IS 'EMPLOYEE NAME' , 42 | EMCAT TEXT IS 'EMPLOYEE CATEGORY' , 43 | EDEPT TEXT IS 'EMPLOYEE DEPARTMENT' , 44 | ELOCN TEXT IS 'EMPLOYEE LOCATION' , 45 | EUSRI TEXT IS 'EMPLOYEE USRID' , 46 | ENHRS TEXT IS 'EMPLOYEE NORMAL WEEK HOURS' , 47 | EPHRC TEXT IS 'PROJECT HOURS CURRENT MONTH' , 48 | EPHRY TEXT IS 'PROJECT HOURS YEAR TO DATE' , 49 | EPHRP TEXT IS 'PROJECT HOURS PRIOR YEAR' , 50 | EPNRC TEXT IS 'NON PROJECT HOURS CURR MONTH' , 51 | EPNRY TEXT IS 'NON PROJECT HOURS YTD' , 52 | EPNRP TEXT IS 'NON PROJECT HOURS PRIOR YEAR' ) ; 53 | 54 | GRANT DELETE , INSERT , SELECT , UPDATE 55 | ON EMPMST TO PUBLIC ; 56 | 57 | -- GRANT ALTER , DELETE , INDEX , INSERT , REFERENCES , SELECT , UPDATE 58 | -- ON EMPMST TO USRPRF(*OWNER) WITH GRANT OPTION ; 59 | 60 | -------------------------------------------------------------------------------- /cli/test/fixtures/from_qsys/qsqlsrc/prjmst.table: -------------------------------------------------------------------------------- 1 | -- Project Master 2 | CREATE OR REPLACE TABLE PRJMST ( 3 | -- SQL150B 10 REUSEDLT(*NO) in table PRJMST in PAYROLL1 ignored. 4 | ACREC CHAR(1) CCSID 37 NOT NULL DEFAULT '' , 5 | PRCDE CHAR(8) CCSID 37 NOT NULL DEFAULT '' , 6 | PRDSC CHAR(50) CCSID 37 NOT NULL DEFAULT '' , 7 | PRRSP CHAR(30) CCSID 37 NOT NULL DEFAULT '' , 8 | PRSTR DECIMAL(6, 0) NOT NULL DEFAULT 0 , 9 | PREND DECIMAL(6, 0) NOT NULL DEFAULT 0 , 10 | PRCMP DECIMAL(6, 0) NOT NULL DEFAULT 0 , 11 | PREST DECIMAL(9, 1) NOT NULL DEFAULT 0 , 12 | PRHRC DECIMAL(7, 1) NOT NULL DEFAULT 0 , 13 | PRHRY DECIMAL(9, 1) NOT NULL DEFAULT 0 , 14 | PRHRP DECIMAL(9, 1) NOT NULL DEFAULT 0 , 15 | PRIMARY KEY( PRCDE ) ) 16 | 17 | RCDFMT RCPRJ ; 18 | 19 | LABEL ON COLUMN PRJMST 20 | ( PRCDE IS 'PROJECT CODE' , 21 | PRDSC IS 'PROJECT DESCRIPTION' , 22 | PRRSP IS 'PROJECT RESPONSIBILITY' , 23 | PRSTR IS 'PRJ START DATE' , 24 | PREND IS 'PRJ EST END DATE' , 25 | PRCMP IS 'PRJ CMP DATE' , 26 | PREST IS 'PRJ EST TOT HRS' , 27 | PRHRC IS 'PRJ HRS CUR MTH' , 28 | PRHRY IS 'PRJ HRS YTD' , 29 | PRHRP IS 'PRJ HRS PRIOR YR' ) ; 30 | 31 | LABEL ON COLUMN PRJMST 32 | ( ACREC TEXT IS 'ACTIVE RECORD CODE' , 33 | PRCDE TEXT IS 'PROJECT CODE' , 34 | PRDSC TEXT IS 'PROJECT DESCRIPTION' , 35 | PRRSP TEXT IS 'PROJECT RESPONSIBILITY' , 36 | PRSTR TEXT IS 'PROJECT START DATE' , 37 | PREND TEXT IS 'PROJECT ESTIMATED END DATE' , 38 | PRCMP TEXT IS 'PROJECT COMPLETION DATE' , 39 | PREST TEXT IS 'PROJECT ESTIMATED TOTAL HRS' , 40 | PRHRC TEXT IS 'PROJECT HOURS CURRENT MONTH' , 41 | PRHRY TEXT IS 'PROJECT HOURS YEAR TO DATE' , 42 | PRHRP TEXT IS 'PROJECT HOURS PRIOR YEAR' ) ; 43 | 44 | GRANT DELETE , INSERT , SELECT , UPDATE 45 | ON PRJMST TO PUBLIC ; 46 | 47 | -- GRANT ALTER , DELETE , INDEX , INSERT , REFERENCES , SELECT , UPDATE 48 | -- ON PRJMST TO WDSCTEST WITH GRANT OPTION ; 49 | -------------------------------------------------------------------------------- /cli/test/fixtures/from_qsys/qsqlsrc/rsnmst.table: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE TABLE RSNMST ( 2 | -- SQL150B 10 REUSEDLT(*NO) in table RSNMST in PAYROLL1 ignored. 3 | ACREC CHAR(1) CCSID 37 NOT NULL DEFAULT '' , 4 | RSCDE CHAR(8) CCSID 37 NOT NULL DEFAULT '' , 5 | RSDSC CHAR(50) CCSID 37 NOT NULL DEFAULT '' , 6 | RSHRC DECIMAL(7, 1) NOT NULL DEFAULT 0 , 7 | RSHRY DECIMAL(9, 1) NOT NULL DEFAULT 0 , 8 | RSHRP DECIMAL(9, 1) NOT NULL DEFAULT 0 , 9 | PRIMARY KEY( RSCDE ) ) 10 | 11 | RCDFMT RCRSN ; 12 | 13 | LABEL ON COLUMN RSNMST 14 | ( RSCDE IS 'REASON CODE' , 15 | RSDSC IS 'REASON CODE DESCRIPTION' , 16 | RSHRC IS 'RSN CDE HRS CUR MTH' , 17 | RSHRY IS 'RSN CDE HRS YTD' , 18 | RSHRP IS 'RSN CDE HRS PRIOR YR' ) ; 19 | 20 | LABEL ON COLUMN RSNMST 21 | ( ACREC TEXT IS 'ACTIVE RECORD CODE' , 22 | RSCDE TEXT IS 'REASON CODE' , 23 | RSDSC TEXT IS 'REASON CODE DESCRIPTION' , 24 | RSHRC TEXT IS 'REASON CODE HRS CURR MONTH' , 25 | RSHRY TEXT IS 'REASON CODE HRS YEAR TO DATE' , 26 | RSHRP TEXT IS 'REASON CODE HOURS PRIOR YEAR' ) ; 27 | 28 | GRANT DELETE , INSERT , SELECT , UPDATE 29 | ON RSNMST TO PUBLIC ; 30 | 31 | -- GRANT ALTER , DELETE , INDEX , INSERT , REFERENCES , SELECT , UPDATE 32 | -- ON RSNMST TO WDSCTEST WITH GRANT OPTION ; 33 | 34 | -------------------------------------------------------------------------------- /cli/test/fixtures/include_fix/QRPGLESRC/ERRORTABLE.rpgleinc: -------------------------------------------------------------------------------- 1 | **free 2 | // This contains global constants, variables and prototypes 3 | // for the Payroll Maintainance app 4 | 5 | // 6 | // Compile time array containing error descriptions. 7 | Dcl-S ERR Char(50) DIM(10) CTDATA PERRCD(1); 8 | 9 | Dcl-C INVALID_MAINTENANCE_SELECTION 1; 10 | Dcl-C INVALID_ACTION_CODE 4; 11 | 12 | -------------------------------------------------------------------------------- /cli/test/fixtures/include_mismatch_fix/QDDSSRC/ARTICLE.PF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Article File * 3 | *%EMETADATA * 4 | REF(SAMREF) 5 | R FARTI 6 | ARID R 7 | ARDESC R 8 | ARSALEPR R REFFLD(UNITPRICE) 9 | TEXT('REF SALE PRICE') 10 | COLHDG('REF' 'SALE' 'PRICE') 11 | EDTCDE(2) 12 | ARWHSPR R REFFLD(UNITPRICE) 13 | TEXT('STOCK PRICE') 14 | COLHDG('STOCK' 'PRICE') 15 | EDTCDE(2) 16 | ARTIFA R REFFLD(FAID) 17 | ARSTOCK R REFFLD(QUANTITY) 18 | TEXT('STOCK') 19 | COLHDG('STOCK') 20 | EDTCDE(2) 21 | ARMINQTY R REFFLD(QUANTITY) 22 | TEXT('MINIMUM STOCK') 23 | COLHDG('MINIMUM' 'STOCK') 24 | EDTCDE(2) 25 | ARCUSQTY R REFFLD(QUANTITY) 26 | TEXT('CUSTOMER ORDER QUANTITY') 27 | COLHDG('CUSTOMER' 'ORDER' 'QTY') 28 | ARPURQTY R REFFLD(QUANTITY) 29 | TEXT('PURCHASE ORDER QUANTITY') 30 | COLHDG('PRUCHASE' 'ORDER' 'QTY') 31 | EDTCDE(2) 32 | ARVATCD R REFFLD(VATCODE) 33 | ARCREA L TEXT('CREATION DATE') 34 | COLHDG('CREAETION' 'DATE') 35 | ARMOD Z TEXT('LAST MODIFICATION') 36 | COLHDG('LAST' 'MODIFICATION') 37 | ARMODID 10 TEXT('LAS MOD BY') 38 | COLHDG('LAST' 'MODIF.' 'BY') 39 | ARDEL R REFFLD(DLCODE) 40 | -------------------------------------------------------------------------------- /cli/test/fixtures/include_mismatch_fix/QPROTOSRC/ARTICLE.RPGLE: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Function Article * 3 | *%EMETADATA * 4 | *============================================= 5 | * Get ARTICLE DESCRPTION 6 | *============================================= 7 | DGetArtDesc PR 50A 8 | D ARID 6A value 9 | *============================================= 10 | * Get REF SALE PRICE 11 | *============================================= 12 | DGetArtRefSalPrice... 13 | D pr 7P 2 14 | D ARID 6A value 15 | *============================================= 16 | * Get STOCK PRICE 17 | *============================================= 18 | DGetArtStockPrice... 19 | D PR 7P 2 20 | D ARID 6A value 21 | *============================================= 22 | * Get FAMILLY ID 23 | *============================================= 24 | DGetArtFam PR 3A 25 | D ARID 6A value 26 | *============================================= 27 | * Get STOCK 28 | *============================================= 29 | DGetArtStock PR 5P 0 30 | D ARID 6A value 31 | *============================================= 32 | * Get MINIMUM STOCK 33 | *============================================= 34 | DGetArtMinStock PR 5P 0 35 | D ARID 6A value 36 | *============================================= 37 | * Get VAT code 38 | *============================================= 39 | DGetArtVatCode Pr 1A 40 | D P_ARID 6A value 41 | *============================================= 42 | * Check if article exist 43 | *============================================= 44 | D ExistArt PR n 45 | D ARID 6A value 46 | *============================================= 47 | * Get DELETE CODE X=DELETED 48 | *============================================= 49 | DIsArtDeleted PR n 50 | D ARID 6A value 51 | *============================================= 52 | * Select an article 53 | *============================================= 54 | D SltArticle PR 6 55 | D ARID 6A value 56 | *============================================= 57 | * Get ARTICLE Info 58 | *============================================= 59 | DGetArtInfo PR 1520A 60 | D ARID 6A value 61 | *============================================= 62 | * Close ARTICLE1 63 | *============================================= 64 | D CloseARTICLE1 PR 65 | -------------------------------------------------------------------------------- /cli/test/fixtures/metadata/qobjs/.ibmi.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1", 3 | "build": { 4 | "objlib": "OTHER", 5 | "tgtCcsid": "37" 6 | } 7 | } -------------------------------------------------------------------------------- /cli/test/fixtures/metadata/qobjs/mything.dtaara: -------------------------------------------------------------------------------- 1 | CRTDTAARA DTARA(MYTHING) TYPE(*CHAR) LEN(15) VALUE('HELLO') TEXT('MY DATA AREA') -------------------------------------------------------------------------------- /cli/test/fixtures/metadata/qrpglesrc/tester.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-s thearea char(15) dtaara('MYTHING'); 4 | 5 | thearea = 'Hello world'; 6 | 7 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/mixedCaseExport/qrpglesrc/modexcept.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | //%METADATA * 3 | // %TEXT module for exceptions. * 4 | //%EMETADATA * 5 | ctl-opt nomain ; 6 | 7 | dcl-pr getRandomMethodA char(10); 8 | inProdCode char(10) const; 9 | inState char(2) const; 10 | inEffectiveDate date const; 11 | inSignedDate date const; 12 | inReceivedDate date const; 13 | inIssuedDate date const; 14 | inExceptionID char(10) const; 15 | inExceptionCode char(10) const; 16 | END-PR; 17 | //************************************************************************************************* 18 | dcl-proc getRandomMethodA export; 19 | dcl-pi getRandomMethodA char(10); 20 | inProdCode char(10) const; 21 | inState char(2) const; 22 | inEffectiveDate date const; 23 | inSignedDate date const; 24 | inReceivedDate date const; 25 | inIssuedDate date const; 26 | inExceptionID char(10) const; 27 | inExceptionCode char(10) const; 28 | END-PI; 29 | dcl-s rtAction char(10); 30 | 31 | if sqlstt = '00000'; 32 | return rtAction; 33 | else; 34 | return ''; 35 | ENDIF; 36 | END-PROC; 37 | 38 | dcl-proc BigFootLivesInSc export; 39 | dcl-pi BigFootLivesInSc ind; 40 | inProdCode char(10) const; 41 | inState char(2) const; 42 | inEffectiveDate date const; 43 | inStrategy char(10) const; 44 | END-PI; 45 | dcl-s authCode char(10); 46 | 47 | authCode = getRandomMethodA(inProdCode:inState:inEffectiveDate: 48 | inEffectiveDate:inEffectiveDate:inEffectiveDate:'STRATEGY':inStrategy); 49 | 50 | if authCode = '' or authCode = 'ALLOW'; 51 | return *on; 52 | else; 53 | return *off; 54 | ENDIF; 55 | END-PROC; 56 | 57 | dcl-proc validateCoolness export; 58 | dcl-pi validateCoolness ind; 59 | inPolYear packed(3:0) const; 60 | inPolMon packed(2:0) const; 61 | inPolSeq packed(6:0) const; 62 | inProdCode char(10) const; 63 | inStateCode char(2) const; 64 | inTheDate date const; 65 | END-PI; 66 | dcl-s strategyID char(10); 67 | dcl-s rtError ind inz(*on); 68 | 69 | ENDIF; 70 | exec sql fetch next from allocCheck into :strategyID; 71 | dow sqlstt = '00000'; 72 | if not BigFootLivesInSc(inProdCode:inStateCode:inTheDate:strategyID); 73 | rtError = *off; 74 | ENDIF; 75 | ENDDO; 76 | 77 | return rtError; 78 | 79 | END-PROC; 80 | 81 | -------------------------------------------------------------------------------- /cli/test/fixtures/mixedCaseExport/qsrvsrc/modexcept.bnd: -------------------------------------------------------------------------------- 1 | strpgmexp signature( 'V2021.02') 2 | export symbol(getRandomMethodA) 3 | export symbol(BigFootLivesInSc) 4 | export symbol(validateCoolness) 5 | endpgmexp 6 | -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module/qrpgleref/dataarea.rpgleinc: -------------------------------------------------------------------------------- 1 | **FREE 2 | 3 | // Returned Data Structure 4 | Dcl-DS DSResult_T Qualified Template; 5 | BytesAvail Int(10); 6 | BytesReturned Int(10); 7 | DataType Char(10); 8 | Library Char(10); 9 | RtnLength Int(10); 10 | DecPos Int(10); 11 | Data Char(300); 12 | End-DS; 13 | 14 | // Retrieve Data Area API 15 | Dcl-PR getDataArea ExtPgm('QWCRDTAA'); 16 | ReturnVar LikeDS(DSResult_T); 17 | ReturnLen Int(10) Const; 18 | QualDataArea Char(20) Const; 19 | StartPos Int(10) Const; 20 | DataLen Int(10) Const; 21 | ErrorCode Char(300) Options(*VarSize); 22 | End-PR; 23 | 24 | Dcl-Ds Error_T Qualified Template; 25 | Content Char(300); 26 | Code Char(7) Pos(9); 27 | End-Ds; -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module/qrpgleref/system.rpgleinc: -------------------------------------------------------------------------------- 1 | **FREE 2 | 3 | Dcl-PR printf_jl Int(10) extproc('Qp0zLprintf'); 4 | format Pointer value options(*string); 5 | End-PR; 6 | 7 | Dcl-PR printf Int(10) extproc('printf'); 8 | format Pointer value options(*string); 9 | End-PR; 10 | 11 | Dcl-PR QzshSystem Int(10) extproc('QzshSystem'); 12 | format Pointer value options(*string); 13 | End-PR; 14 | 15 | Dcl-PR system Int(10) extproc('system'); 16 | *N Pointer value options(*string); 17 | End-PR; 18 | 19 | Dcl-PR QCmdExc extpgm('QCMDEXC'); 20 | *N Char(1024) options(*varsize) const; 21 | *N Packed(15:5) const; 22 | End-PR; 23 | 24 | dcl-pr getenv pointer extproc('getenv'); 25 | *n pointer value options(*string:*trim); 26 | end-pr; -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module/qrpgleref/utils.rpgleinc: -------------------------------------------------------------------------------- 1 | **FREE 2 | 3 | Dcl-Pr Utils_Lower Char(10) ExtProc; 4 | *N Char(10) Value; 5 | End-Pr; 6 | 7 | Dcl-Pr Utils_Print ExtProc; 8 | Command VARCHAR(512) CONST; 9 | End-Pr; 10 | 11 | Dcl-Pr Utils_Qsh IND ExtProc; 12 | Command VARCHAR(512) CONST; 13 | End-Pr; 14 | 15 | Dcl-Pr Utils_JobType Char(1) ExtProc; 16 | End-Pr; -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module/qrpglesrc/utils.sqlrpgle: -------------------------------------------------------------------------------- 1 | **FREE 2 | 3 | Ctl-Opt NoMain; 4 | 5 | /copy 'qrpgleref/system.rpgleinc' 6 | /copy 'qrpgleref/utils.rpgleinc' 7 | 8 | Dcl-S JobTypeGlobal Char(1); 9 | 10 | Dcl-Proc Utils_Lower Export; 11 | Dcl-Pi *N Char(10); 12 | pValue Char(10) Value; 13 | End-Pi; 14 | 15 | EXEC SQL SET :pValue = LOWER(:pValue); 16 | 17 | Return pValue; 18 | End-Proc; 19 | 20 | Dcl-Proc Utils_Print Export; 21 | Dcl-Pi *N; 22 | Text Varchar(512) Const; 23 | End-Pi; 24 | 25 | Dcl-s Type Char(1); 26 | 27 | Type = Utils_JobType(); 28 | 29 | If (Type = 'I'); 30 | printf_jl(%trim(Text) + x'25'); 31 | Else; 32 | printf(%trim(Text) + x'25'); 33 | Endif; 34 | End-Proc; 35 | 36 | Dcl-Proc Utils_Qsh Export; 37 | Dcl-Pi *N Ind; 38 | Command Varchar(512) Const; 39 | End-Pi; 40 | 41 | return system('QSH CMD(''' + %Trim(Command) + ''')') = 0; 42 | End-Proc; 43 | 44 | dcl-proc Utils_JobType export; 45 | dcl-pi *n char(1) end-pi; 46 | dcl-pr QUSRJOBI extpgm; 47 | *n char(32766) options(*varsize); 48 | *n int(10:0) const; 49 | *n char(8) const; 50 | *n char(26) const; 51 | *n char(16) const; 52 | end-pr; 53 | 54 | dcl-ds Returned len(86); 55 | JobType char(1) pos(61); 56 | end-ds; 57 | 58 | If (JobTypeGlobal = *BLANK); 59 | QUSRJOBI(Returned:%size(Returned):'JOBI0100':'*':''); 60 | 61 | JobTypeGlobal = JobType; 62 | Endif; 63 | 64 | Return JobTypeGlobal; 65 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module_two/rpgle/data.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-s names char(15) dim(78) ctdata; 6 | dcl-s surnames char(15) dim(27) ctdata; 7 | dcl-s streetTypes char(3) dim(9) ctdata; 8 | dcl-s states char(2) dim(50) ctdata; 9 | dcl-s cities char(15) dim(15) ctdata; 10 | 11 | dcl-proc random export; 12 | dcl-pi *n int(10); 13 | low packed(7) const; 14 | high packed(7) const; 15 | end-pi; 16 | 17 | dcl-s result float(8); 18 | dcl-s range packed(7); 19 | dcl-s seed int(10); 20 | 21 | dcl-pr ceeran0 extproc('CEERAN0'); 22 | *n int(10); 23 | *n float(8); 24 | *n char(12) options(*omit); 25 | end-pr; 26 | 27 | range = (high - low) + 1; 28 | ceeran0(seed:result:*omit); 29 | 30 | return %int(result * range); 31 | end-proc; 32 | 33 | dcl-proc getFirst export; 34 | dcl-pi *n char(15); 35 | end-pi; 36 | 37 | return names(random(1:%elem(names))); 38 | end-proc; 39 | 40 | dcl-proc getSurname export; 41 | dcl-pi *n char(15); 42 | end-pi; 43 | 44 | return surnames(random(1:%elem(surnames))); 45 | end-proc; 46 | 47 | dcl-proc getStreetType export; 48 | dcl-pi *n char(3); 49 | end-pi; 50 | 51 | return streetTypes(random(1:%elem(streetTypes))); 52 | end-proc; 53 | 54 | dcl-proc getState export; 55 | dcl-pi *n char(2); 56 | end-pi; 57 | 58 | return states(random(1:%elem(states))); 59 | end-proc; 60 | 61 | dcl-proc getCity export; 62 | dcl-pi *n char(15); 63 | end-pi; 64 | 65 | return cities(random(1:%elem(cities))); 66 | end-proc; 67 | 68 | **CTDATA names 69 | DAVID 70 | JAMES 71 | JOHN 72 | ROBERT 73 | MICHAEL 74 | WILLIAM 75 | MARY 76 | PATRICIA 77 | LINDA 78 | BARBARA 79 | ELIZABETH 80 | JENNIFER 81 | MARIA 82 | SUSAN 83 | MARGARET 84 | DOROTHY 85 | LISA 86 | NANCY 87 | KAREN 88 | BETTY 89 | HELEN 90 | SANDRA 91 | DONNA 92 | CAROL 93 | RUTH 94 | SHARON 95 | MICHELLE 96 | LAURA 97 | SARAH 98 | KIMBERLY 99 | DEBORAH 100 | JESSICA 101 | SHIRLEY 102 | CYNTHIA 103 | ANGELA 104 | MELISSA 105 | BRENDA 106 | AMY 107 | ANNA 108 | REBECCA 109 | VIRGINIA 110 | KATHLEEN 111 | PAMELA 112 | MARTHA 113 | DEBRA 114 | AMANDA 115 | STEPHANIE 116 | CAROLYN 117 | CHRISTINE 118 | MARIE 119 | JANET 120 | CATHERINE 121 | FRANCES 122 | ANN 123 | JOYCE 124 | DIANE 125 | ALICE 126 | JULIE 127 | HEATHER 128 | TERESA 129 | DORIS 130 | GLORIA 131 | EVELYN 132 | JEAN 133 | CHERYL 134 | MILDRED 135 | KATHERINE 136 | JOAN 137 | ASHLEY 138 | JUDITH 139 | ROSE 140 | JANICE 141 | KELLY 142 | NICOLE 143 | JUDY 144 | CHRISTINA 145 | KATHY 146 | THERESA 147 | **CTDATA surnames 148 | SMITH 149 | JOHNSON 150 | WILLIAMS 151 | JONES 152 | BROWN 153 | DAVIS 154 | MILLER 155 | WILSON 156 | MOORE 157 | TAYLOR 158 | ANDERSON 159 | THOMAS 160 | JACKSON 161 | WHITE 162 | HARRIS 163 | MARTIN 164 | THOMPSON 165 | GARCIA 166 | MARTINEZ 167 | ROBINSON 168 | CLARK 169 | RODRIGUEZ 170 | LEWIS 171 | LEE 172 | WALKER 173 | HALL 174 | ALLEN 175 | **CTDATA streetTypes 176 | ST 177 | AVE 178 | RD 179 | DR 180 | CIR 181 | BLVD 182 | WAY 183 | CT 184 | LANE 185 | **CTDATA states 186 | AL 187 | AK 188 | AZ 189 | AR 190 | CA 191 | CO 192 | CT 193 | DE 194 | FL 195 | GA 196 | HI 197 | ID 198 | IL 199 | IN 200 | IA 201 | KS 202 | KY 203 | LA 204 | ME 205 | MD 206 | MA 207 | MI 208 | MN 209 | MS 210 | MO 211 | MT 212 | NE 213 | NV 214 | NH 215 | NJ 216 | NM 217 | NY 218 | NC 219 | ND 220 | OH 221 | OK 222 | OR 223 | PA 224 | RI 225 | SC 226 | SD 227 | TN 228 | TX 229 | UT 230 | VT 231 | VA 232 | WA 233 | WV 234 | WI 235 | WY 236 | **CTDATA cities 237 | SPARTANBURG 238 | GREENVILLE 239 | COLUMBIA 240 | CHARLESTON 241 | MYRTLE BEACH 242 | ROCK HILL 243 | FLORENCE 244 | ASHEVILLE 245 | HENDERSONVILLE 246 | ANDERSON 247 | GREENWOOD 248 | GAFFNEY 249 | EASLEY 250 | GREENWOOD -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module_two/rpgle/db.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-pr getFirst char(15) extproc('GETFIRST'); 6 | end-pr; 7 | 8 | dcl-pr getSurname char(15) extproc('GETSURNAME'); 9 | end-pr; 10 | 11 | dcl-pr random int(10) extproc('RANDOM'); 12 | low packed(7) const; 13 | high packed(7) const; 14 | end-pr; 15 | 16 | dcl-pr getStreetType char(3) extproc('GETSTREETTYPE'); 17 | end-pr; 18 | 19 | dcl-pr getCity char(15) extproc('GETCITY'); 20 | end-pr; 21 | 22 | dcl-pr getState char(2) extproc('GETSTATE'); 23 | end-pr; 24 | 25 | dcl-proc createCustomer export; 26 | dcl-pi *n int(10); 27 | type char(1) const; 28 | end-pi; 29 | 30 | dcl-f customer qualified keyed usropn usage(*output); 31 | dcl-ds cust likerec(customer.custfmt); 32 | 33 | cust.FIRSTNME = getFirst(); 34 | cust.LASTNAME = getSurname(); 35 | cust.PHONENO = %char(random(1111:9999)); 36 | cust.CREATED = %date; 37 | cust.ADDR1 = %char(random(1:9999)) + ' ' + %trimr(getSurname()) + ' ' + getStreetType(); 38 | cust.CITY = getCity(); 39 | cust.STATE = getState(); 40 | cust.ZIP = %char(random(10000:99999)); 41 | 42 | select; 43 | when (type = '1'); //RLA 44 | OPEN customer; 45 | write customer.CUSTFMT cust; 46 | CLOSE customer; 47 | when (type = '2'); //SQL 48 | EXEC SQL 49 | INSERT INTO CUSTOMER 50 | VALUES(:cust); 51 | 52 | other; 53 | return -1; 54 | endsl; 55 | 56 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module_two/rpgle/runner.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-pr createCustomer int(10) extproc('CREATECUSTOMER'); 4 | type char(1) const; 5 | end-pr; 6 | 7 | ctl-opt dftactgrp(*no); 8 | 9 | createCustomer('1'); 10 | createCustomer('2'); 11 | 12 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/multi_module_two/sql/customer.table: -------------------------------------------------------------------------------- 1 | -- https://www.ibm.com/docs/en/i/7.3?topic=tables-employee-table-employee 2 | 3 | CREATE OR REPLACE TABLE CUSTOMER 4 | (CUSNO integer not null GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), 5 | FIRSTNME VARCHAR(12) NOT NULL, 6 | LASTNAME VARCHAR(15) NOT NULL, 7 | PHONENO CHAR(4) NOT NULL, 8 | CREATED DATE NOT NULL DEFAULT CURRENT_DATE, 9 | ADDR1 VARCHAR(30) NOT NULL, 10 | ADDR2 VARCHAR(30) NOT NULL, 11 | CITY VARCHAR(20) NOT NULL, 12 | STATE CHAR(2) NOT NULL, 13 | ZIP CHAR(5) NOT NULL, 14 | PRIMARY KEY (CUSNO) 15 | ) RCDFMT CUSTFMT; 16 | 17 | ALTER TABLE CUSTOMER 18 | ADD CONSTRAINT NUMBER 19 | CHECK (PHONENO >= '0000' AND PHONENO <= '9998'); 20 | -------------------------------------------------------------------------------- /cli/test/fixtures/override_objref/.objrefs: -------------------------------------------------------------------------------- 1 | # cool comment 2 | 3 | SAMREF.FILE 4 | 5 | # other comment -------------------------------------------------------------------------------- /cli/test/fixtures/override_objref/PROVIDE1.LF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Provider file * 3 | *%EMETADATA * 4 | UNIQUE 5 | R FPROV PFILE(PROVIDER) 6 | K PRID 7 | -------------------------------------------------------------------------------- /cli/test/fixtures/override_objref/PROVIDER.PF: -------------------------------------------------------------------------------- 1 | *%METADATA * 2 | * %TEXT Provider file * 3 | *%EMETADATA * 4 | REF(SAMREF) 5 | R FPROV 6 | PRID R 7 | PROVNM R 8 | PRCONT 30 TEXT('CONTACT PERSON') 9 | PRPHONE R REFFLD(PHONE) 10 | PRVAT R REFFLD(VATNUM) 11 | PRMAIL R REFFLD(EMAIL) 12 | PRLINE1 R REFFLD(ADRLINE) 13 | PRLINE2 R REFFLD(ADRLINE) 14 | PRLINE3 R REFFLD(ADRLINE) 15 | PRZIP R REFFLD(ZIPCOD) 16 | PRCITY R REFFLD(CITY) 17 | PRCOUN R REFFLD(COID) 18 | PRCREA L TEXT('CREATION DATE') 19 | COLHDG('CREAETION' 'DATE') 20 | PRMOD Z TEXT('LAST MODIFICATION') 21 | COLHDG('LAST' 'MODIFICATION') 22 | PRMODID 10 TEXT('LAS MOD BY') 23 | COLHDG('LAST' 'MODIF.' 'BY') 24 | PRDEL R REFFLD(DLCODE) 25 | -------------------------------------------------------------------------------- /cli/test/fixtures/projects.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from "path"; 3 | 4 | const projectFolder = path.join(__dirname, `..`, `..`, `..`, `testData`); 5 | 6 | export function getAllFixtures(): string[] { 7 | const dirs = fs.readdirSync(__dirname, {withFileTypes: true}) 8 | .filter(dirent => dirent.isDirectory()) 9 | .map(dirent => dirent.name); 10 | 11 | return dirs; 12 | } 13 | 14 | export function setupFixture(folderName: string): {cwd: string, setup: () => void, copy: () => void} { 15 | const fixturePath = path.join(__dirname, folderName); 16 | const projectPath = path.join(projectFolder, folderName); 17 | 18 | return { 19 | cwd: projectPath, 20 | setup: () => { 21 | // fs.cpSync(fixturePath, projectPath, {recursive: true}); 22 | }, 23 | copy: () => { 24 | deleteDir(projectPath); 25 | mkdir(projectPath); 26 | fs.cpSync(fixturePath, projectPath, {recursive: true}); 27 | } 28 | }; 29 | } 30 | 31 | export function createTestBuildScript() { 32 | const lines = [ 33 | `# First build company system`, 34 | `system -qi "DLTLIB LIB(CMPSYSTST)"`, 35 | `cd company_system`, 36 | `gmake BIN_LIB=CMPSYSTST`, 37 | ``, 38 | `# Then build multi module`, 39 | `cd ../multi_module`, 40 | `system -qi "DLTLIB LIB(CMPSYSTST)"`, 41 | `gmake BIN_LIB=MMODTEST`, 42 | ``, 43 | `# Cleanup`, 44 | `system -qi "DLTLIB LIB(CMPSYSTST)"`, 45 | `system -qi "DLTLIB LIB(MMODTEST)"` 46 | ].join(`\n`); 47 | 48 | mkdir(projectFolder); 49 | const scriptPath = path.join(projectFolder, `build.sh`); 50 | fs.writeFileSync(scriptPath, lines); 51 | } 52 | 53 | function mkdir(dirPath: string) { 54 | try { 55 | fs.mkdirSync(dirPath, {recursive: true}); 56 | } catch (e) {}; 57 | } 58 | 59 | function deleteDir(dirPath: string) { 60 | try { 61 | fs.rmSync(dirPath, {recursive: true, force: true}); 62 | } catch (e) {}; 63 | } -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qobjs/.ibmi.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1", 3 | "build": { 4 | "tgtCcsid": "37" 5 | } 6 | } -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qobjs/Rules.mk: -------------------------------------------------------------------------------- 1 | MYTHING.DTAARA:text=Hello world -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qobjs/mything.dtaara: -------------------------------------------------------------------------------- 1 | CRTDTAARA DTARA(MYTHING) TYPE(*CHAR) LEN(15) VALUE('HELLO') -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qrpglesrc/.ibmi.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1", 3 | "build": { 4 | "tgtCcsid": "273" 5 | } 6 | } -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qrpglesrc/Rules.mk: -------------------------------------------------------------------------------- 1 | TESTER.PGM: tester.pgm.rpgle MYTHING.DTAARA NOEXIST.PGM 2 | TESTER.PGM: text = My program 3 | 4 | # Other assignment 5 | TESTER.PGM: bnddir:=MYBND -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qrpglesrc/other.pgm.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-f mstdsp workstn usropn; 4 | 5 | thearea = 'Hello world'; 6 | 7 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/pseudo/qrpglesrc/tester.pgm.rpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | dcl-s thearea char(15) dtaara('MYTHING'); 4 | 5 | thearea = 'Hello world'; 6 | 7 | return; -------------------------------------------------------------------------------- /cli/test/fixtures/sql_long_names/rpgle/db.sqlrpgle: -------------------------------------------------------------------------------- 1 | **free 2 | 3 | ctl-opt nomain; 4 | 5 | dcl-proc getLiveBalance; 6 | dcl-pi *n likeDs(liveResultT); 7 | type char(1) const; 8 | cusno int(10) const; 9 | end-pi; 10 | 11 | dcl-ds liveResult likeds(liveResultT); 12 | 13 | dcl-f trans qualified usropn usage(*input); 14 | dcl-ds transaction likerec(trans.transfmt); 15 | 16 | liveResult.total = 0; 17 | liveResult.count = 0; 18 | 19 | select; 20 | when (type = RLA); 21 | // This RLA check is a bit of a hack. 22 | // In the future, we might want to use 23 | // a keyed field or an LF to look for 24 | // the card by customer id instead of 25 | // manually scanning the file. 26 | 27 | // The larger the file, the longer this will take 28 | 29 | OPEN trans; 30 | 31 | read trans.transfmt transaction; 32 | dow not %eof; 33 | if (transaction.TCUS = cusno); 34 | liveResult.total += transaction.TAMT; 35 | liveResult.count += 1; 36 | endif; 37 | read trans.transfmt transaction; 38 | enddo; 39 | 40 | CLOSE trans; 41 | 42 | when (type = SQL); 43 | EXEC SQL 44 | SELECT count(*), coalesce(sum(TAMT), 0) 45 | INTO :liveResult.count, :liveResult.total 46 | FROM TRANSACTION 47 | WHERE TCUS = :cusno; 48 | endsl; 49 | 50 | return liveResult; 51 | 52 | end-proc; -------------------------------------------------------------------------------- /cli/test/fixtures/sql_long_names/sql/trans.table: -------------------------------------------------------------------------------- 1 | -- https://www.ibm.com/docs/en/i/7.3?topic=tables-employee-table-employee 2 | 3 | CREATE OR REPLACE TABLE TRANSACTION FOR SYSTEM NAME TRANS 4 | (TRID integer not null GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), 5 | TDESC VARCHAR(50) NOT NULL, 6 | TCUS integer NOT NULL, -- reference to customers 7 | TAMT numeric(10,2) NOT NULL default 0, 8 | TWHEN TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 9 | PRIMARY KEY (TRID)) RCDFMT TRANSFMT; -------------------------------------------------------------------------------- /cli/test/fixtures/sql_ref_with/sqlwithpgm.pgm.sqlrpgle: -------------------------------------------------------------------------------- 1 | **FREE 2 | 3 | exec sql declare c1 cursor for 4 | with temp as ( 5 | select 6 | field1, 7 | field2 8 | from table1 9 | ) 10 | Select * from temp; -------------------------------------------------------------------------------- /cli/test/fixtures/sql_references/qddssrc/stock.table: -------------------------------------------------------------------------------- 1 | --%METADATA * 2 | -- %TEXT Stock File * 3 | --%EMETADATA * 4 | 5 | CREATE OR REPLACE TABLE STOCK 6 | (PRDKEY CHAR(6) NOT NULL, 7 | PRDNAM CHAR(12) NOT NULL, 8 | PRIMARY KEY (EMPNO)); 9 | -------------------------------------------------------------------------------- /cli/test/fixtures/sql_references/qrpglesrc/sqlrefpgm.pgm.sqlrpgle: -------------------------------------------------------------------------------- 1 | **FREE 2 | Ctl-Opt Main(SQLREFPGM) dftactgrp(*no) option(*srcstmt); 3 | 4 | dcl-pr SQLREFPGM extpgm('SQLREFPGM'); 5 | end-pr; 6 | 7 | 8 | Dcl-Proc SQLREFPGM; 9 | Dcl-Pi *N; 10 | End-Pi; 11 | DCL-S CNT packed(5); 12 | EXEC SQL SELECT COUNT(1) INTO :CNT FROM STOCK; 13 | DSPLY %CHAR('STOCK: ' + %CHAR(CNT)); 14 | RETURN; 15 | End-Proc; -------------------------------------------------------------------------------- /cli/test/includeMismatchFix.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import path from 'path'; 5 | import { setupFixture } from './fixtures/projects'; 6 | import { ReadFileSystem } from '../src/readFileSystem'; 7 | 8 | // This issue was occuring when you had two files with the same name, but different extensions. 9 | 10 | describe(`include_mismatch_fix tests`, () => { 11 | const project = setupFixture(`include_mismatch_fix`); 12 | 13 | const fs = new ReadFileSystem(); 14 | const targets = new Targets(project.cwd, fs); 15 | targets.setSuggestions({renames: true, includes: true}) 16 | 17 | beforeAll(async () => { 18 | project.setup(); 19 | await targets.loadProject(); 20 | 21 | expect(targets.getTargets().length).toBeGreaterThan(0); 22 | targets.resolveBinder(); 23 | }); 24 | 25 | test(`Ensure rename is against correct file`, async () => { 26 | const articlePf = targets.getTarget({systemName: `ARTICLE`, type: `FILE`}); 27 | expect(articlePf).toBeDefined(); 28 | 29 | const articlePfLogs = targets.logger.getLogsFor(articlePf.relativePath); 30 | expect(articlePfLogs.length).toBe(1); 31 | expect(articlePfLogs[0].message).toBe(`no object found for reference 'SAMREF'`); 32 | expect(articlePfLogs[0].type).toBe(`warning`); 33 | 34 | const articleIncludeLogs = targets.logger.getLogsFor(path.join(`QPROTOSRC`, `ARTICLE.RPGLE`)); 35 | expect(articleIncludeLogs.length).toBe(1); 36 | expect(articleIncludeLogs[0].message).toBe(`Rename suggestion`); 37 | expect(articleIncludeLogs[0].type).toBe(`rename`); 38 | expect(articleIncludeLogs[0].change).toMatchObject({ 39 | rename: { 40 | path: path.join(project.cwd, `QPROTOSRC`, `ARTICLE.RPGLE`), 41 | newName: 'ARTICLE.rpgleinc' 42 | } 43 | }) 44 | }); 45 | }); -------------------------------------------------------------------------------- /cli/test/mixedCaseExport.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import { setupFixture } from './fixtures/projects'; 5 | import { ReadFileSystem } from '../src/readFileSystem'; 6 | 7 | async function setupScopeAnalysis(targets: Targets) { 8 | await targets.loadProject(); 9 | 10 | expect(targets.getTargets().length).toBeGreaterThan(0); 11 | targets.resolveBinder(); 12 | } 13 | 14 | describe(`pr with mixed case exports exports `, () => { 15 | const project = setupFixture(`mixedCaseExport`); 16 | 17 | const fs = new ReadFileSystem(); 18 | const targets = new Targets(project.cwd, fs); 19 | 20 | beforeAll(async () => { 21 | project.setup(); 22 | await setupScopeAnalysis(targets); 23 | }); 24 | 25 | test(`Correct check exports no matter the casing`, async () => { 26 | const allLogs = targets.logger.getAllLogs(); 27 | 28 | const [srvPgmObj] = targets.getResolvedObjects(`SRVPGM`); 29 | expect(srvPgmObj).toBeDefined(); 30 | expect(srvPgmObj.systemName).toBe(`MODEXCEPT`); 31 | expect(srvPgmObj.type).toBe(`SRVPGM`); 32 | 33 | const srvPgmTarget = targets.getTarget({ systemName: `MODEXCEPT`, type: `SRVPGM` }); 34 | expect(srvPgmTarget).toBeDefined(); 35 | 36 | expect(srvPgmTarget.deps.length).toBe(1); 37 | 38 | expect(srvPgmTarget.exports.length).toBe(3); 39 | expect(srvPgmTarget.exports).toStrictEqual(srvPgmTarget.deps[0].exports); 40 | 41 | expect(allLogs[srvPgmObj.relativePath].length).toBe(0); 42 | }); 43 | }); -------------------------------------------------------------------------------- /cli/test/multiModule.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import path from 'path'; 5 | import { MakeProject } from '../src/builders/make'; 6 | import { setupFixture } from './fixtures/projects'; 7 | import { writeFileSync } from 'fs'; 8 | import { ReadFileSystem } from '../src/readFileSystem'; 9 | 10 | describe(`multi_module tests`, () => { 11 | const project = setupFixture(`multi_module`); 12 | 13 | const fs = new ReadFileSystem(); 14 | const targets = new Targets(project.cwd, fs); 15 | 16 | beforeAll(async () => { 17 | project.setup(); 18 | await targets.loadProject(); 19 | 20 | targets.resolveBinder(); 21 | }); 22 | 23 | test(`Check objects are generated`, async () => { 24 | expect(targets.getResolvedObjects().length).toBe(4); 25 | expect(targets.getTargets().length).toBe(4); 26 | expect(targets.getTargetsOfType(`FILE`).length).toBe(0); 27 | expect(targets.getTargetsOfType(`PGM`).length).toBe(1); 28 | expect(targets.getTargetsOfType(`MODULE`).length).toBe(3); 29 | expect(targets.getTargetsOfType(`SRVPGM`).length).toBe(0); 30 | }); 31 | 32 | test(`Check program`, async () => { 33 | const gitBrg = targets.getTarget({systemName: `GITBRG`, type: `PGM`}); 34 | expect(gitBrg).toBeDefined(); 35 | 36 | const deps = gitBrg.deps; 37 | expect(deps.length).toBe(2); 38 | 39 | expect(deps.find(d => d.systemName === `GITBRG` && d.type === `MODULE`)).toBeDefined(); 40 | expect(deps.find(d => d.systemName === `UTILS` && d.type === `MODULE`)).toBeDefined(); 41 | expect(deps.find(d => d.systemName === `OBJECTS` && d.type === `MODULE`)).toBeUndefined(); 42 | }); 43 | 44 | test(`Check solo module`, async () => { 45 | const objectsMod = targets.getTarget({systemName: `OBJECTS`, type: `MODULE`}); 46 | expect(objectsMod).toBeDefined(); 47 | 48 | expect(objectsMod.deps.length).toBe(0); 49 | }); 50 | 51 | test(`Generate makefile`, async () => { 52 | const makeProj = new MakeProject(project.cwd, targets, fs); 53 | await makeProj.setupSettings(); 54 | 55 | writeFileSync(path.join(project.cwd, `makefile`), makeProj.getMakefile().join(`\n`)); 56 | }); 57 | }); -------------------------------------------------------------------------------- /cli/test/multiModule2.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import { MakeProject } from '../src/builders/make'; 5 | import { setupFixture } from './fixtures/projects'; 6 | import { ReadFileSystem } from '../src/readFileSystem'; 7 | 8 | 9 | describe(`multi_module_two tests`, () => { 10 | const project = setupFixture(`multi_module_two`); 11 | const fs = new ReadFileSystem(); 12 | const targets = new Targets(project.cwd, fs); 13 | 14 | beforeAll(async () => { 15 | project.setup(); 16 | 17 | await targets.loadProject(); 18 | 19 | expect(targets.getTargets().length).toBeGreaterThan(0); 20 | targets.resolveBinder(); 21 | }); 22 | 23 | test(`Check objects are generated`, async () => { 24 | expect(targets.getResolvedObjects().length).toBe(5); 25 | expect(targets.getTargets().length).toBe(5); 26 | expect(targets.getTargetsOfType(`FILE`).length).toBe(1); 27 | expect(targets.getTargetsOfType(`PGM`).length).toBe(1); 28 | expect(targets.getTargetsOfType(`MODULE`).length).toBe(3); 29 | expect(targets.getTargetsOfType(`SRVPGM`).length).toBe(0); 30 | }); 31 | 32 | test(`Check program`, async () => { 33 | const runnerPgm = targets.getTarget({systemName: `RUNNER`, type: `PGM`}); 34 | expect(runnerPgm).toBeDefined(); 35 | 36 | const deps = runnerPgm.deps; 37 | expect(deps.length).toBe(3); 38 | 39 | expect(deps.some(d => d.systemName === `DB`)).toBeTruthy(); 40 | expect(deps.some(d => d.systemName === `RUNNER`)).toBeTruthy(); 41 | expect(deps.some(d => d.systemName === `DATA`)).toBeTruthy(); 42 | }); 43 | 44 | test(`Check data module`, async () => { 45 | const dataModule = targets.getTarget({systemName: `DB`, type: `MODULE`}); 46 | expect(dataModule).toBeDefined(); 47 | 48 | const deps = dataModule.deps; 49 | expect(deps.length).toBe(2); 50 | 51 | expect(deps.some(d => d.systemName === `CUSTOMER`)).toBeTruthy(); 52 | expect(deps.some(d => d.systemName === `DATA`)).toBeTruthy(); 53 | }); 54 | 55 | test(`Check makefile result`, async () => { 56 | const makeProject = new MakeProject(project.cwd, targets, fs); 57 | await makeProject.setupSettings(); 58 | 59 | const targetContent = makeProject.getMakefile(); 60 | 61 | const runnerTarget = targetContent.find(t => t.startsWith(`$(PREPATH)/RUNNER.PGM: `) && t.length > 50); 62 | expect(runnerTarget).toBeDefined(); 63 | const runnerDepsString = runnerTarget.substring(runnerTarget.indexOf(`: `) + 2).split(` `); 64 | expect(runnerDepsString.length).toBe(3); 65 | expect(runnerDepsString).toContain(`$(PREPATH)/DB.MODULE`); 66 | expect(runnerDepsString).toContain(`$(PREPATH)/RUNNER.MODULE`); 67 | expect(runnerDepsString).toContain(`$(PREPATH)/DATA.MODULE`); 68 | 69 | expect(targetContent).toContain(`\tsystem "CRTPGM PGM($(BIN_LIB)/RUNNER) ENTMOD(RUNNER) MODULE(DB RUNNER DATA) TGTRLS(*CURRENT) BNDDIR($(BNDDIR)) ACTGRP(*NEW)" > .logs/runner.splf`); 70 | expect(targetContent).toContain(`$(PREPATH)/RUNNER.MODULE: rpgle/runner.pgm.rpgle`); 71 | }); 72 | }); -------------------------------------------------------------------------------- /cli/test/overrideObjRef.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import path from 'path'; 5 | import { MakeProject } from '../src/builders/make'; 6 | import { getFiles } from '../src/utils'; 7 | import { setupFixture } from './fixtures/projects'; 8 | import { referencesFileName, scanGlob } from '../src/extensions'; 9 | import { writeFileSync } from 'fs'; 10 | import { BobProject } from '../src/builders/bob'; 11 | import { ReadFileSystem } from '../src/readFileSystem'; 12 | 13 | const cwd = setupFixture(`override_objref`); 14 | 15 | // This issue was occuring when you had two files with the same name, but different extensions. 16 | 17 | describe(`ensure that objrefs can be overridden`, () => { 18 | const project = setupFixture(`override_objref`); 19 | 20 | const fs = new ReadFileSystem(); 21 | const targets = new Targets(project.cwd, fs); 22 | targets.setSuggestions({renames: true, includes: true}) 23 | 24 | test(`Ensure objects are defined`, async () => { 25 | await targets.handleRefsFile(path.join(project.cwd, referencesFileName)); 26 | expect(targets.getResolvedObjects().length).toBe(1); 27 | expect(targets.getTargets().length).toBe(0); 28 | 29 | await targets.loadProject(); 30 | 31 | expect(targets.getTargets().length).toBeGreaterThan(0); 32 | targets.resolveBinder(); 33 | 34 | expect(targets.getTargets().length).toBe(4); 35 | 36 | expect(targets.getResolvedObjects().length).toBe(4); 37 | expect(targets.getResolvedObjects(`FILE`).length).toBe(4); 38 | 39 | expect(targets.binderRequired()).toBe(false); 40 | 41 | const pro250d = targets.searchForObject({systemName: `PRO250D`, type: `FILE`}); 42 | expect(pro250d).toBeDefined(); 43 | expect(pro250d.reference).toBeUndefined(); 44 | 45 | const provider = targets.searchForObject({systemName: `PROVIDER`, type: `FILE`}); 46 | expect(provider).toBeDefined(); 47 | expect(provider.reference).toBeUndefined(); 48 | 49 | const provide1 = targets.searchForObject({systemName: `PROVIDE1`, type: `FILE`}); 50 | expect(provide1).toBeDefined(); 51 | expect(provide1.reference).toBeUndefined(); 52 | 53 | const samref = targets.searchForObject({systemName: `SAMREF`, type: `FILE`}); 54 | expect(samref).toBeDefined(); 55 | expect(samref.reference).toBeUndefined(); 56 | }); 57 | }); -------------------------------------------------------------------------------- /cli/test/setup.ts: -------------------------------------------------------------------------------- 1 | import type { TestProject } from "vitest/node"; 2 | import { getAllFixtures, setupFixture } from "./fixtures/projects"; 3 | 4 | export async function setup(project: TestProject) { 5 | console.log(`Setting up project....`); 6 | 7 | console.table(getAllFixtures()); 8 | 9 | const fixtures = getAllFixtures(); 10 | for (const fixture of fixtures) { 11 | let proj = setupFixture(fixture); 12 | proj.copy(); 13 | } 14 | } -------------------------------------------------------------------------------- /cli/test/sqlLongNames.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import { setupFixture } from './fixtures/projects'; 5 | import { ReadFileSystem } from '../src/readFileSystem'; 6 | 7 | // This issue was occuring when you had two files with the same name, but different extensions. 8 | 9 | describe(`sql long name lookup`, () => { 10 | const project = setupFixture(`sql_long_names`); 11 | 12 | const fs = new ReadFileSystem(); 13 | const targets = new Targets(project.cwd, fs); 14 | targets.setSuggestions({ renames: true, includes: true }) 15 | 16 | beforeAll(async () => { 17 | project.setup(); 18 | await targets.loadProject(); 19 | 20 | expect(targets.getTargets().length).toBeGreaterThan(0); 21 | targets.resolveBinder(); 22 | }); 23 | 24 | test(`Ensure objects are defined`, async () => { 25 | expect(targets.getTargets().length).toBe(2); 26 | expect(targets.getResolvedObjects(`FILE`).length).toBe(1); 27 | expect(targets.getResolvedObjects(`MODULE`).length).toBe(1); 28 | expect(targets.binderRequired()).toBe(false); 29 | 30 | const trans = targets.searchForObject({ systemName: `TRANS`, type: `FILE` }); 31 | expect(trans).toBeDefined(); 32 | 33 | const transaction = targets.searchForObject({ systemName: `TRANSACTION`, type: `FILE` }); 34 | expect(transaction).toBeDefined(); 35 | 36 | expect(trans).toMatchObject(transaction); 37 | 38 | const moduleLogs = targets.logger.getLogsFor(trans.relativePath); 39 | expect(moduleLogs).toBeUndefined(); 40 | }); 41 | 42 | test(`Ensure deps are correct`, async () => { 43 | const trans = targets.getTarget({ systemName: `DB`, type: `MODULE` }); 44 | expect(trans).toBeDefined(); 45 | 46 | expect(trans.deps.length).toBe(1); 47 | expect(trans.deps[0].systemName).toBe(`TRANS`); 48 | expect(trans.deps[0].longName).toBe(`TRANSACTION`); 49 | }); 50 | 51 | }); -------------------------------------------------------------------------------- /cli/test/sqlReference.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import path from 'path'; 5 | import { setupFixture } from './fixtures/projects'; 6 | import { ReadFileSystem } from '../src/readFileSystem'; 7 | 8 | 9 | async function setupScopeAnalysis(targets: Targets) { 10 | await targets.loadProject(); 11 | 12 | expect(targets.getTargets().length).toBeGreaterThan(0); 13 | targets.resolveBinder(); 14 | } 15 | 16 | describe(`sql_references tests (internal scope analysis)`, () => { 17 | const project = setupFixture(`sql_references`); 18 | 19 | const fs = new ReadFileSystem(); 20 | const targets = new Targets(project.cwd, fs); 21 | 22 | beforeAll(async () => { 23 | project.setup(); 24 | await setupScopeAnalysis(targets); 25 | }); 26 | 27 | test(`Check stock (with internal scope analysis)`, async () => { 28 | const myPgm = targets.getTarget({ systemName: `SQLREFPGM`, type: `PGM` }); 29 | expect(myPgm.relativePath).toBe(path.join(`qrpglesrc`, `sqlrefpgm.pgm.sqlrpgle`)); 30 | expect(myPgm.deps.length).toBe(1); 31 | 32 | const empTable = myPgm.deps[0]; 33 | expect(empTable.systemName).toBe(`STOCK`); 34 | expect(empTable.type).toBe(`FILE`); 35 | expect(empTable.relativePath).toBe(path.join(`qddssrc`, `stock.table`)); 36 | }); 37 | }); -------------------------------------------------------------------------------- /cli/test/sqlReferenceWith.test.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, describe, expect, test } from 'vitest'; 2 | 3 | import { Targets } from '../src/targets' 4 | import path from 'path'; 5 | import { setupFixture } from './fixtures/projects'; 6 | import { ReadFileSystem } from '../src/readFileSystem'; 7 | 8 | async function setupScopeAnalysis(targets: Targets) { 9 | await targets.loadProject(); 10 | 11 | expect(targets.getTargets().length).toBeGreaterThan(0); 12 | targets.resolveBinder(); 13 | } 14 | 15 | describe(`sql_references_with tests`, () => { 16 | const project = setupFixture(`sql_ref_with`) 17 | 18 | const fs = new ReadFileSystem(); 19 | const targets = new Targets(project.cwd, fs); 20 | 21 | beforeAll(async () => { 22 | project.setup(); 23 | await setupScopeAnalysis(targets); 24 | }); 25 | 26 | test(`SQL with clause`, async () => { 27 | const myPgm = targets.getTarget({ systemName: `SQLWITHPGM`, type: `PGM` }); 28 | expect(myPgm.relativePath).toBe(path.join(`sqlwithpgm.pgm.sqlrpgle`)); 29 | 30 | const moduleLogs = targets.logger.getLogsFor(myPgm.relativePath); 31 | expect(moduleLogs.length).toBe(1); 32 | expect(moduleLogs[0].message).toBe(`No object found for reference 'TABLE1'`); 33 | }); 34 | }); -------------------------------------------------------------------------------- /cli/todo.md: -------------------------------------------------------------------------------- 1 | Things to do: 2 | 3 | * ✅ rename project to Source Orbit 4 | * ✅ update readme with new service program understandings 5 | * ✅ Assume binder source is SRVPGM object 6 | * ✅ When service program is built from source, resolve modules based on binder exports matched against module exports 7 | * ✅ Support variables in make build, specifically for multi-module service programs 8 | * Throw warnings when binder source exports is not in sync with exports from found module 9 | * ✅ Create new test case suite based on ibmi-company_system 10 | * Provide sample projects 11 | * Provide CI examples 12 | * Support for `FOR SYSTEM NAME` in SQL 13 | * ✅ Put rename provider into Targets class 14 | * ✅ Put line fixed into Targets class 15 | * ✅ Support passing in multiple seperate files instead of only the glob -------------------------------------------------------------------------------- /cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2019", 5 | "noImplicitAny": false, 6 | "noUnusedParameters": false, 7 | "strict": false, 8 | "allowJs": true, 9 | "outDir": "./dist", 10 | "esModuleInterop": true, 11 | "sourceMap": true, 12 | "declaration": true, 13 | }, 14 | } -------------------------------------------------------------------------------- /cli/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { defineConfig } from 'vite' 3 | 4 | export default defineConfig({ 5 | test: { 6 | // ... Specify options here. 7 | globalSetup: [`test/setup.ts`], 8 | }, 9 | }) -------------------------------------------------------------------------------- /cli/webpack.config.js: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | // @ts-nocheck 7 | 8 | 'use strict'; 9 | 10 | const path = require(`path`); 11 | const webpack = require(`webpack`); 12 | 13 | /** @typedef {import('webpack').Configuration} WebpackConfig **/ 14 | 15 | /**@type WebpackConfig*/ 16 | module.exports = { 17 | mode: `none`, // this leaves the source code as close as possible to the original (when packaging we set this to 'production') 18 | target: `node`, // extensions run in a node context 19 | node: { 20 | __dirname: false // leave the __dirname-behaviour intact 21 | }, 22 | context: path.join(__dirname), 23 | resolve: { 24 | // Add `.ts` as a resolvable extension. 25 | extensions: [".ts", ".js"], 26 | // Add support for TypeScripts fully qualified ESM imports. 27 | extensionAlias: { 28 | ".js": [".js", ".ts"], 29 | ".cjs": [".cjs", ".cts"], 30 | ".mjs": [".mjs", ".mts"] 31 | } 32 | }, 33 | module: { 34 | rules: [ 35 | // all files with a `.ts`, `.cts`, `.mts` or `.tsx` extension will be handled by `ts-loader` 36 | { test: /\.([cm]?ts|tsx)$/, loader: "ts-loader", options: {allowTsInNodeModules: true} } 37 | ] 38 | }, 39 | entry: { 40 | extension: `./src/index.ts`, 41 | }, 42 | output: { 43 | filename: path.join(`index.js`), 44 | path: path.join(__dirname, `dist`), 45 | library: { 46 | "type": "commonjs" 47 | } 48 | }, 49 | // yes, really source maps 50 | devtool: `source-map`, 51 | plugins: [ 52 | new webpack.BannerPlugin({banner: `#! /usr/bin/env node`, raw: true}) 53 | ] 54 | }; -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Source Orbit 4 | 5 | 6 | 7 | Source Orbit is a dependency management tool. As IBM i developers start using Git for their RPGLE, CL, DDS and SQL, we want to provide them with excellent tools to help them understand their source code. Source orbit is available for use as both a VS Code extension and CLI tool. 8 | 9 | * 💻 [Install from VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 10 | * 📦 [Download from Open VSX Registry](https://open-vsx.org/extension/IBM/vscode-sourceorbit) 11 | * ⚡[Install CLI from NPM](https://www.npmjs.com/package/@ibm/sourceorbit) 12 | * 📖 [View Documentation](https://ibm.github.io/sourceorbit/#/) 13 | * 🔎 [See Releases](https://github.com/IBM/sourceorbit/releases) 14 | 15 | [![Extension Version](https://img.shields.io/visual-studio-marketplace/v/IBM.vscode-sourceorbit?label=Extension)](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 16 | [![Extension Installs](https://img.shields.io/visual-studio-marketplace/i/IBM.vscode-sourceorbit)](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 17 | 18 | [![NPM Version](https://img.shields.io/npm/v/@ibm/sourceorbit.svg?label=CLI)](https://www.npmjs.com/package/@ibm/sourceorbit) 19 | [![NPM Downloads](https://img.shields.io/npm/dm/@ibm/sourceorbit.svg)](https://www.npmjs.com/package/@ibm/sourceorbit) 20 | 21 | ## Features 22 | 23 | Source Orbit is equipped to help you with the following tasks: 24 | 25 | 1. Scans all applicable source code to build a dependency tree 26 | 2. Show how objects would be affected as developers write code 27 | 3. Generate JSON, or build scripts, to automatically build your application changes 28 | 4. Generates reports for branches being worked on so project owners can see their application in real time 29 | 5. Migrate your code to git 30 | 31 | ## Getting Started 32 | 33 | Check out these pages to dive in: 34 | 35 | 1. [As a CLI](./pages/cli/index.md): Run Source Orbit as part of an automated pipeline, or anywhere really! 36 | 2. [As a VS Code Extension](./pages/extension/index.md): Leverage Source Orbit as you develop applications in VS Code 37 | 3. [Project Structure](./pages/developing/local/structure): Learn how to structure your code when stored in git 38 | 4. [Source Code Rules](./pages/general/rules.md): Learn what rules to abide by when using Source Orbit -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | * [Home](/) 2 | * Projects 3 | * [Project Structure](./pages/general/structure.md) 4 | * [Source Code Rules](./pages/general/rules.md) 5 | * [Migrating to Git](./pages/general/migrating.md) 6 | * CLI 7 | * [Overview](./pages/cli/index.md) 8 | * [Installation](./pages/cli/installation.md) 9 | * [Make](./pages/cli/make.md) 10 | * [GitHub Actions](./pages/cli/gha.md) 11 | * VS Code Extension 12 | * [Overview](./pages/extension/index.md) 13 | * [Installation](./pages/extension/installation.md) 14 | * Tutorials 15 | * Coming soon -------------------------------------------------------------------------------- /docs/assets/Extension_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/docs/assets/Extension_01.png -------------------------------------------------------------------------------- /docs/assets/Extension_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/docs/assets/Extension_02.png -------------------------------------------------------------------------------- /docs/assets/Extension_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/docs/assets/Extension_03.png -------------------------------------------------------------------------------- /docs/assets/Installation_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/docs/assets/Installation_03.png -------------------------------------------------------------------------------- /docs/assets/Migrating_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/docs/assets/Migrating_01.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Source Orbit Docs 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
Loading...
18 | 19 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/pages/cli/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | This page describes how you can install the [@ibm/sourceorbit](https://www.npmjs.com/package/@ibm/sourceorbit) CLI tool from NPM. 4 | 5 | ## Most Platforms 6 | 7 | 1. Install Source Orbit globally 8 | ```sh 9 | npm i -g @ibm/sourceorbit 10 | ``` 11 | 12 | 2. Use `so` 13 | 14 | > [!TIP] 15 | > We recommend Node.js 18+. 16 | 17 | ## IBM i 18 | 19 | 1. Install Node.js via `yum` and/or use `update-alternatives` to set the Node.js version. 20 | ```sh 21 | yum install nodejsxx 22 | ``` 23 | ```sh 24 | update-alternatives --set node /QOpenSys/pkgs/lib/nodejs18/bin/node 25 | ``` 26 | 27 | 2. Install Source Orbit globally on to the IBM i 28 | ```sh 29 | npm i -g @ibm/sourceorbit 30 | ``` 31 | 32 | 3. Update the `PATH` environment variable to include the `npm` binary directory for installed CLI packages 33 | * `PATH=/QOpenSys/pkgs/lib/nodejs18/bin:$PATH` 34 | * Put in `.bash_profile` for CLI usage, put in `.bashrc` for Code for IBM i usage 35 | 36 | 4. Use `so` -------------------------------------------------------------------------------- /docs/pages/extension/index.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | [Source Orbit](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) is available as a Visual Studio Code extension. It offers the ability to use the same CLI features but with a UI that makes it much more convenient to use and visualize! 4 | 5 | ## View Impacted Objects 6 | 7 | The extension comes built with two views for viewing the impacted objects in your project. 8 | 9 | The `Source Impacts` view in the `Explorer` view container will render the impacted objects for the current active editor. 10 | 11 |
12 | Source Impacts view 13 |
14 | 15 | The `Change Impacts` view in the `Source Control` view container will render the impacted objects for any files changed detected by Git. 16 | 17 |
18 | Change Impacts view 19 |
20 | 21 | ## IBM i Project Explorer Integration 22 | 23 | Source Orbit integrates seemlessly with the [IBM i Project Explorer](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-ibmi-projectexplorer) extension to allow you to visualize an object dependency tree for your IBM i project. It also provides you easy access to following commonly used Source Orbit features: 24 | 25 | * **Auto Fix** (equivalent to [CLI cleanup capabilities](./pages/cli/index?id=cleanup-capabilities)) 26 | * `File Names`: This fixes most extensions for your project. For example, adds the `.pgm` attribute where possible, changes RPGLE headers to use `.rpgleinc` and fixes SQL sources to use right extension based on the `CREATE` statement inside of it. 27 | * `RPGLE Includes`: This will scan all RPGLE source code in your project and change the include statements to use the unix style path if the mapped source member can be found in the current working directory. 28 | * **Generate Build File** (equivalent to [CLI dependency file generation](./pages/cli/index?id=dependency-file-generation)) 29 | * `json`: Generate all dependency info as JSON (`sourceorbit.json` in the root of the project) 30 | * `bob`: Generate the required `Rules.mk` files for Bob 31 | * `make`: Generates a single makefile with the targets and rules 32 | * `imd`: Generate analysis reports for branches (`impact.md` in the root of the project) 33 | 34 | The source migration tool built into IBM i Project Explorer can also automatically perform these tasks after migrating your source from QSYS. Check out more details [here](./pages/general/migrating?id=_1-ibm-i-project-explorer). 35 | 36 |
37 | Project Explorer Integration 38 |
-------------------------------------------------------------------------------- /docs/pages/extension/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## VS Code Marketplace 4 | 5 | The Source Orbit extension can be installed from the VS Code Marketplace: [Source Orbit](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit). 6 | 7 | 8 | ![Source Orbit Installation from the VS Code Marketplace](../../assets/Installation_01.png) 9 | 10 | --- 11 | 12 | ## Open VSX Registry 13 | 14 | The extension can also be downloaded and manually installed from the Open VSX Registry: [Source Orbit](https://open-vsx.org/extension/IBM/vscode-sourceorbit). 15 | 16 | 17 | ![Source Orbit Installation from the Open VSX Registry](../../assets/Installation_02.png) 18 | 19 | --- 20 | 21 | ## Suggested Extensions 22 | 23 | It is recommended to install the IBM i Project Explorer extension as it integrates with the Source Orbit extension. This can be done from the VS Code Marketplace: [IBM i Project Explorer](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-ibmi-projectexplorer). 24 | 25 | ![IBM i Project Explorer Installation from the VS Code Marketplace](../../assets/Installation_03.png) -------------------------------------------------------------------------------- /docs/pages/general/structure.md: -------------------------------------------------------------------------------- 1 | # Project Structure 2 | 3 | See the documentation [here](https://codefori.github.io/docs/developing/local/structure) on project structure in the Code for IBM i documentation, as Source Orbit follows that structure. -------------------------------------------------------------------------------- /sourceorbit.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "cli" 5 | }, 6 | { 7 | "path": "docs" 8 | }, 9 | { 10 | "path": "vs" 11 | } 12 | ], 13 | "extensions": { 14 | "recommendations": ["amodio.tsl-problem-matcher"] 15 | } 16 | } -------------------------------------------------------------------------------- /vs/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | client/node_modules/** 3 | client/out/** 4 | server/node_modules/** 5 | server/out/** -------------------------------------------------------------------------------- /vs/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /**@type {import('eslint').Linter.Config} */ 2 | // eslint-disable-next-line no-undef 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | plugins: [ 7 | '@typescript-eslint', 8 | ], 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | ], 13 | rules: { 14 | 'semi': [2, "always"], 15 | '@typescript-eslint/no-unused-vars': 0, 16 | '@typescript-eslint/no-explicit-any': 0, 17 | '@typescript-eslint/explicit-module-boundary-types': 0, 18 | '@typescript-eslint/no-non-null-assertion': 0, 19 | "@typescript-eslint/no-namespace": 0, 20 | "no-case-declarations": "off", 21 | } 22 | }; -------------------------------------------------------------------------------- /vs/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | client/server 4 | .vscode-test 5 | .DS_Store 6 | *.vsix -------------------------------------------------------------------------------- /vs/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "dbaeumer.vscode-eslint" 8 | ] 9 | } -------------------------------------------------------------------------------- /vs/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "name": "Launch Client", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceFolder:vs}"], 11 | "outFiles": ["${workspaceFolder:vs}/out/**/*.js"], 12 | "sourceMaps": true, 13 | "preLaunchTask": { 14 | "type": "npm", 15 | "script": "webpack:dev" 16 | }, 17 | "sourceMapPathOverrides": { 18 | "webpack://vscode-sourceorbit-client/./*": "${workspaceFolder:vs}/client/*" 19 | }, 20 | }, 21 | { 22 | "type": "node", 23 | "request": "attach", 24 | "name": "Attach to Server", 25 | "port": 8720, 26 | "restart": true, 27 | "outFiles": ["${workspaceFolder:vs}/out/**/*.js"], 28 | "sourceMaps": true, 29 | "sourceMapPathOverrides": { 30 | "webpack://vscode-sourceorbit-server/./*": "${workspaceFolder:vs}/server/*" 31 | }, 32 | }, 33 | 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /vs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": false, 3 | "typescript.tsc.autoDetect": "off", 4 | "typescript.preferences.quoteStyle": "single", 5 | "editor.codeActionsOnSave": { 6 | "source.organizeImports": "always", 7 | "source.fixAll.eslint": "explicit" 8 | } 9 | } -------------------------------------------------------------------------------- /vs/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "compile", 7 | "group": "build", 8 | "presentation": { 9 | "panel": "dedicated", 10 | "reveal": "never" 11 | }, 12 | "problemMatcher": [ 13 | "$tsc" 14 | ] 15 | }, 16 | { 17 | "type": "npm", 18 | "script": "watch", 19 | "isBackground": true, 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "presentation": { 25 | "panel": "dedicated", 26 | "reveal": "never" 27 | }, 28 | "problemMatcher": [ 29 | "$tsc-watch" 30 | ] 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /vs/.vscodeignore: -------------------------------------------------------------------------------- 1 | .github/** 2 | assets/** 3 | **/node_modules 4 | node_modules 5 | scripts 6 | .vscode/** 7 | .gitignore 8 | **/jsconfig.json 9 | **/*.map 10 | **/.eslintrc.json 11 | tests 12 | server 13 | client -------------------------------------------------------------------------------- /vs/README.md: -------------------------------------------------------------------------------- 1 | # Source Orbit 2 | 3 | 4 | 5 | Source Orbit is a dependency management tool. As IBM i developers start using Git for their RPGLE, CL, DDS and SQL, we want to provide them with excellent tools to help them understand their source code. Source orbit is available for use as both a VS Code extension and CLI tool. 6 | 7 | * 💻 [Install from VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 8 | * 📦 [Download from Open VSX Registry](https://open-vsx.org/extension/IBM/vscode-sourceorbit) 9 | * ⚡[Install CLI from NPM](https://www.npmjs.com/package/@ibm/sourceorbit) 10 | * 📖 [View Documentation](https://ibm.github.io/sourceorbit/#/) 11 | * 🔎 [See Releases](https://github.com/IBM/sourceorbit/releases) 12 | 13 | [![Extension Version](https://img.shields.io/visual-studio-marketplace/v/IBM.vscode-sourceorbit?label=Extension)](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 14 | [![Extension Installs](https://img.shields.io/visual-studio-marketplace/i/IBM.vscode-sourceorbit)](https://marketplace.visualstudio.com/items?itemName=IBM.vscode-sourceorbit) 15 | 16 | [![NPM Version](https://img.shields.io/npm/v/@ibm/sourceorbit.svg?label=CLI)](https://www.npmjs.com/package/@ibm/sourceorbit) 17 | [![NPM Downloads](https://img.shields.io/npm/dm/@ibm/sourceorbit.svg)](https://www.npmjs.com/package/@ibm/sourceorbit) 18 | 19 | ## Features 20 | 21 | Source Orbit is equipped to help you with the following tasks: 22 | 23 | 1. Scans all applicable source code to build a dependency tree 24 | 2. Show how objects would be affected as developers write code 25 | 3. Generate JSON, or build scripts, to automatically build your application changes 26 | 4. Generates reports for branches being worked on so project owners can see their application in real time 27 | 5. Migrate your code to git 28 | 29 | ## Getting Started 30 | 31 | Check out these pages to dive in: 32 | 33 | 1. [As a CLI](https://ibm.github.io/sourceorbit/#/./pages/cli/index): Run Source Orbit as part of an automated pipeline, or anywhere really! 34 | 2. [As a VS Code Extension](https://ibm.github.io/sourceorbit/#/./pages/extension/index): Leverage Source Orbit as you develop applications in VS Code 35 | 3. [Project Structure](https://ibm.github.io/sourceorbit/#/./pages/general/structure): Learn how to structure your code when stored in git 36 | 4. [Source Code Rules](https://ibm.github.io/sourceorbit/#/./pages/general/rules): Learn what rules to abide by when using Source Orbit -------------------------------------------------------------------------------- /vs/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-sourceorbit-client", 3 | "description": "Client", 4 | "author": "IBM", 5 | "license": "MIT", 6 | "version": "1.0.1", 7 | "publisher": "vscode", 8 | "engines": { 9 | "vscode": "^1.75.0" 10 | }, 11 | "dependencies": { 12 | "vscode-languageclient": "^8.1.0" 13 | }, 14 | "devDependencies": { 15 | "@ibm/sourceorbit": "file:../../cli", 16 | "@ibm/vscode-ibmi-projectexplorer-types": "^1.1.0", 17 | "@types/node": "^20.5.1", 18 | "@types/vscode": "^1.75.1", 19 | "@vscode/test-electron": "^2.2.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vs/client/src/ProjectExplorer.ts: -------------------------------------------------------------------------------- 1 | import { Extension, extensions } from "vscode"; 2 | import { IBMiProjectExplorer } from "@ibm/vscode-ibmi-projectexplorer-types/ibmiProjectExplorer"; 3 | import { ProjectManager } from "@ibm/vscode-ibmi-projectexplorer-types/projectManager"; 4 | import ProjectExplorer from "@ibm/vscode-ibmi-projectexplorer-types/views/projectExplorer"; 5 | 6 | let baseExtension: Extension | undefined; 7 | 8 | export async function loadIBMiProjectExplorer(): Promise { 9 | if (!baseExtension) { 10 | baseExtension = (extensions ? extensions.getExtension(`IBM.vscode-ibmi-projectexplorer`) : undefined); 11 | } 12 | 13 | if (baseExtension) { 14 | if (!baseExtension.isActive) { 15 | await baseExtension.activate(); 16 | } 17 | } 18 | 19 | return (baseExtension && baseExtension.isActive && baseExtension.exports ? baseExtension.exports : undefined); 20 | } 21 | 22 | /** 23 | * Get the access to the Project Manager APIs. 24 | */ 25 | export function getProjectManager(): typeof ProjectManager | undefined { 26 | return (baseExtension && baseExtension.isActive && baseExtension.exports ? baseExtension.exports.projectManager : undefined); 27 | } 28 | 29 | /** 30 | * Get the access to the Project Explorer APIs. 31 | */ 32 | export function getProjectExplorer(): ProjectExplorer | undefined { 33 | return (baseExtension && baseExtension.isActive && baseExtension.exports ? baseExtension.exports.projectExplorer : undefined); 34 | } -------------------------------------------------------------------------------- /vs/client/src/api.ts: -------------------------------------------------------------------------------- 1 | import { commands, ExtensionContext, WorkspaceFolder } from 'vscode'; 2 | import { LanguageClientManager } from './languageClientManager'; 3 | 4 | /** 5 | * These commands are to be used by other extensions. 6 | */ 7 | export namespace SourceOrbitApi { 8 | export function registerCommands(context: ExtensionContext) { 9 | context.subscriptions.push( 10 | commands.registerCommand(`vscode-sourceorbit.autoFix`, (workspaceFolder: WorkspaceFolder, type: "includes" | "renames") => { 11 | if (workspaceFolder && type) { 12 | return LanguageClientManager.fixProject(workspaceFolder, type); 13 | } 14 | }), 15 | 16 | commands.registerCommand(`vscode-sourceorbit.generateBuildFile`, async (workspaceFolder: WorkspaceFolder, type: string) => { 17 | if (workspaceFolder && type) { 18 | await LanguageClientManager.generateBuildFile(workspaceFolder, type); 19 | } 20 | }) 21 | ); 22 | } 23 | } -------------------------------------------------------------------------------- /vs/client/src/environmentManager.ts: -------------------------------------------------------------------------------- 1 | export class EnvironmentManager { 2 | /** 3 | * Checks if the extension is running Merlin. 4 | * 5 | * @returns True if running in Merlin and false otherwise. 6 | */ 7 | static isInMerlin(): boolean { 8 | const { MACHINE_EXEC_PORT } = process.env; 9 | return MACHINE_EXEC_PORT !== undefined; 10 | } 11 | } -------------------------------------------------------------------------------- /vs/client/src/git/index.ts: -------------------------------------------------------------------------------- 1 | import { Uri, WorkspaceFolder, extensions } from 'vscode'; 2 | import { API, Change, GitExtension, Status } from './git'; 3 | 4 | let gitLookedUp: boolean; 5 | let gitAPI: API | undefined; 6 | 7 | export const lastBranch: {[workspaceUri: string]: string} = {}; 8 | 9 | export function getGitAPI(): API | undefined { 10 | if (!gitLookedUp) { 11 | try { 12 | gitAPI = extensions.getExtension(`vscode.git`)?.exports.getAPI(1); 13 | } 14 | catch (error) { 15 | console.log(`Git extension issue.`, error); 16 | } 17 | finally { 18 | gitLookedUp = true; 19 | } 20 | } 21 | return gitAPI; 22 | } 23 | 24 | export async function getDeployGitFiles(workspaceFolder: WorkspaceFolder, changeType: 'staged' | 'working' | 'both' = 'both'): Promise { 25 | const gitApi = getGitAPI(); 26 | 27 | if (gitApi && gitApi.repositories.length > 0) { 28 | const repository = gitApi.repositories.find(r => r.rootUri.fsPath === workspaceFolder.uri.fsPath); 29 | 30 | if (repository) { 31 | const staged = repository.state.indexChanges; 32 | const working = repository.state.workingTreeChanges; 33 | 34 | let gitFiles: Change[]; 35 | 36 | switch (changeType) { 37 | case `both`: 38 | gitFiles = [...staged, ...working]; 39 | break; 40 | case `staged`: 41 | gitFiles = staged; 42 | break; 43 | case `working`: 44 | gitFiles = working; 45 | break; 46 | } 47 | 48 | // Do not attempt to upload deleted files. 49 | // https://github.com/microsoft/vscode/blob/main/extensions/git/src/api/git.d.ts#L69 50 | gitFiles = gitFiles.filter(change => change.status !== Status.DELETED); 51 | 52 | if (gitFiles.length > 0) { 53 | const uris = gitFiles.map(change => change.uri); 54 | const unique = uris.filter((value, index, array) => array.findIndex(u => u.toString() === value.toString()) === index); 55 | return unique; 56 | } else { 57 | return []; 58 | } 59 | } else { 60 | throw new Error(`No repository found for ${workspaceFolder.uri.fsPath}`); 61 | } 62 | } else { 63 | throw new Error(`No repositories are open.`); 64 | } 65 | } -------------------------------------------------------------------------------- /vs/client/src/gitEventHandler.ts: -------------------------------------------------------------------------------- 1 | 2 | import { ExtensionContext, WorkspaceFolder } from 'vscode'; 3 | import { getDeployGitFiles as getChangedFiles, getGitAPI, lastBranch } from './git'; 4 | import { LanguageClientManager } from './languageClientManager'; 5 | import { ImpactView } from './views/impactView'; 6 | 7 | export namespace GitEventHandler { 8 | export function setup(context: ExtensionContext, gitImpactView: ImpactView, workspaceFolders: WorkspaceFolder[]) { 9 | const gitApi = getGitAPI(); 10 | 11 | if (gitApi) { 12 | for (const workspaceFolder of workspaceFolders) { 13 | const repo = gitApi.getRepository(workspaceFolder.uri); 14 | if (repo) { 15 | const workspaceUri = workspaceFolder.uri.toString(); 16 | const head = repo.state.HEAD; 17 | if (head && head.name) { 18 | lastBranch[workspaceUri] = head.name; 19 | 20 | context.subscriptions.push(repo.state.onDidChange((_e) => { 21 | const currentBranch = head.name; 22 | if (currentBranch) { 23 | if (lastBranch[workspaceUri] && currentBranch !== lastBranch[workspaceUri]) { 24 | gitImpactView.showImpactFor([]); 25 | LanguageClientManager.reloadProject(workspaceFolder); 26 | 27 | } else { 28 | getChangedFiles(workspaceFolder).then(files => { 29 | gitImpactView.showImpactFor(files); 30 | }); 31 | 32 | } 33 | 34 | lastBranch[workspaceUri] = currentBranch; 35 | } 36 | })); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /vs/client/src/tasks.ts: -------------------------------------------------------------------------------- 1 | import { CustomExecution, EventEmitter, ExtensionContext, Pseudoterminal, Task, TaskDefinition, TaskScope, TerminalDimensions, WorkspaceFolder, tasks } from 'vscode'; 2 | import { LanguageClientManager } from './languageClientManager'; 3 | 4 | export namespace SourceOrbitTask { 5 | interface SourceOrbitTask extends TaskDefinition { 6 | builder: "bob" | "make" | "imd" | "json"; 7 | } 8 | 9 | export function initializeTaskProvider(context: ExtensionContext) { 10 | context.subscriptions.push( 11 | tasks.registerTaskProvider('sourceorbit', { 12 | provideTasks: () => { 13 | return []; 14 | }, 15 | resolveTask(_task, _token) { 16 | const task = _task.definition as SourceOrbitTask; 17 | // A Rake task consists of a task and an optional file as specified in RakeTaskDefinition 18 | // Make sure that this looks like a Rake task by checking that there is a task. 19 | if (task) { 20 | // resolveTask requires that the same definition object be used. 21 | const workspaceFolder = _task.scope as WorkspaceFolder; 22 | 23 | return new Task( 24 | task, 25 | TaskScope.Workspace, 26 | `Source Orbit Builder`, 27 | 'sourceorbit', 28 | new CustomExecution(async (e) => { 29 | const writeEmitter = new EventEmitter(); 30 | const closeEmitter = new EventEmitter(); 31 | 32 | const term: Pseudoterminal = { 33 | onDidWrite: writeEmitter.event, 34 | onDidClose: closeEmitter.event, 35 | open: async (_initialDimensions: TerminalDimensions | undefined) => { 36 | writeEmitter.fire(`Generating ${task.builder} files for ${workspaceFolder.name}...\r\n`); 37 | try { 38 | await LanguageClientManager.generateBuildFile(workspaceFolder, task.builder); 39 | 40 | writeEmitter.fire(`Finished\r\n`); 41 | closeEmitter.fire(0); 42 | } catch (_e) { 43 | writeEmitter.fire(`Failed\r\n`); 44 | writeEmitter.fire(JSON.stringify(e, null, 2) + `\r\n`); 45 | closeEmitter.fire(1); 46 | } 47 | }, 48 | close: function (): void { console.log(); } 49 | }; 50 | 51 | return term; 52 | }) 53 | ); 54 | } 55 | return undefined; 56 | }, 57 | }) 58 | ); 59 | } 60 | } -------------------------------------------------------------------------------- /vs/client/src/views/impactView/ileImpactedObjectTreeItem.ts: -------------------------------------------------------------------------------- 1 | import { ImpactedObject } from '@ibm/sourceorbit/dist/src/targets'; 2 | import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder } from "vscode"; 3 | import { TypeIcons } from '../utils'; 4 | import path = require('path'); 5 | 6 | export class ILEImpactedObjectTreeItem extends TreeItem { 7 | constructor(public workspaceFolder: WorkspaceFolder, private impactedObject: ImpactedObject) { 8 | super(`${impactedObject.ileObject.systemName}.${impactedObject.ileObject.type}`, impactedObject.children.length > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None); 9 | // const logs = TargetsManager.getLogs(workspaceFolder, ileObject); 10 | 11 | this.description = impactedObject.ileObject.relativePath || `No source`; 12 | this.iconPath = new ThemeIcon(TypeIcons[impactedObject.ileObject.type] || `unverified`); 13 | 14 | this.contextValue = `ileObject`; 15 | 16 | if (impactedObject.ileObject.relativePath) { 17 | this.resourceUri = Uri.from({ scheme: `file`, path: path.join(this.workspaceFolder.uri.fsPath, impactedObject.ileObject.relativePath) }); 18 | } 19 | } 20 | 21 | async getChildren(): Promise<(ILEImpactedObjectTreeItem)[]> { 22 | return this.impactedObject.children.map(c => new ILEImpactedObjectTreeItem(this.workspaceFolder, c)); 23 | } 24 | } -------------------------------------------------------------------------------- /vs/client/src/views/impactView/index.ts: -------------------------------------------------------------------------------- 1 | import { Event, EventEmitter, TreeDataProvider, TreeItem, Uri, workspace } from "vscode"; 2 | import { LanguageClientManager } from '../../languageClientManager'; 3 | import { ILEImpactedObjectTreeItem } from './ileImpactedObjectTreeItem'; 4 | 5 | export class ImpactView implements TreeDataProvider { 6 | private _onDidChangeTreeData: EventEmitter = new EventEmitter(); 7 | readonly onDidChangeTreeData: Event = this._onDidChangeTreeData.event; 8 | public impactOf: Uri[] = []; 9 | 10 | refresh() { 11 | this._onDidChangeTreeData.fire(); 12 | } 13 | 14 | getTreeItem(element: any): TreeItem | Thenable { 15 | return element; 16 | } 17 | 18 | showImpactFor(uris: Uri[]) { 19 | this.impactOf = uris; 20 | this.refresh(); 21 | } 22 | 23 | async getChildren(element?: ILEImpactedObjectTreeItem): Promise<(ILEImpactedObjectTreeItem | TreeItem)[]> { 24 | if (element && element.getChildren) { 25 | return element.getChildren(); 26 | } else if (this.impactOf && this.impactOf.length > 0) { 27 | const workspaceFolder = workspace.getWorkspaceFolder(this.impactOf[0]); 28 | 29 | if (workspaceFolder) { 30 | const isProjectReady = await LanguageClientManager.isReady(workspaceFolder); 31 | if (!isProjectReady) { 32 | await LanguageClientManager.reloadProject(workspaceFolder); 33 | } 34 | 35 | const impacts = await LanguageClientManager.getImpacts(workspaceFolder, this.impactOf); 36 | if (impacts.length > 0) { 37 | return impacts.map(i => new ILEImpactedObjectTreeItem(workspaceFolder, i)); 38 | } else { 39 | return [new TreeItem(`No impacted objects`)]; 40 | } 41 | } 42 | } 43 | 44 | return []; 45 | } 46 | } -------------------------------------------------------------------------------- /vs/client/src/views/projectExplorer/ileObjectTreeItem.ts: -------------------------------------------------------------------------------- 1 | import { ILEObject } from "@ibm/sourceorbit/dist/src/targets"; 2 | import { ProjectExplorerTreeItem } from "@ibm/vscode-ibmi-projectexplorer-types/views/projectExplorer/projectExplorerTreeItem"; 3 | import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder } from "vscode"; 4 | import { LanguageClientManager } from '../../languageClientManager'; 5 | import { TypeIcons } from '../utils'; 6 | import { NoticeTreeItem } from './noticeTreeItem'; 7 | import path = require('path'); 8 | 9 | export class ILEObjectTreeItem extends TreeItem implements ProjectExplorerTreeItem { 10 | constructor(public workspaceFolder: WorkspaceFolder, private ileObject: ILEObject, canExpand = false) { 11 | super(`${ileObject.systemName}.${ileObject.type}`, canExpand ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None); 12 | // const logs = TargetsManager.getLogs(workspaceFolder, ileObject); 13 | 14 | this.description = [ileObject.text, ileObject.extension ? `(${ileObject.extension})` : undefined].join(` `); 15 | this.iconPath = new ThemeIcon(TypeIcons[ileObject.type] || `unverified`); 16 | this.contextValue = `ileObject`; 17 | 18 | if (ileObject.relativePath) { 19 | this.resourceUri = Uri.from({ scheme: `file`, path: path.join(this.workspaceFolder.uri.fsPath, ileObject.relativePath) }); 20 | } 21 | } 22 | 23 | async getChildren(): Promise<(ILEObjectTreeItem | NoticeTreeItem)[]> { 24 | const deps = await LanguageClientManager.getDeps(this.workspaceFolder, this.ileObject); 25 | if (deps.length > 0) { 26 | return deps.map(d => new ILEObjectTreeItem(this.workspaceFolder, d, false)); 27 | } else { 28 | return [new NoticeTreeItem(this.workspaceFolder, `No dependencies`)]; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /vs/client/src/views/projectExplorer/noticeTreeItem.ts: -------------------------------------------------------------------------------- 1 | import { ProjectExplorerTreeItem } from "@ibm/vscode-ibmi-projectexplorer-types/views/projectExplorer/projectExplorerTreeItem"; 2 | import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; 3 | import { ILEObjectTreeItem } from './ileObjectTreeItem'; 4 | 5 | export class NoticeTreeItem extends TreeItem implements ProjectExplorerTreeItem { 6 | constructor(public workspaceFolder: WorkspaceFolder, message: string) { 7 | super(message, TreeItemCollapsibleState.None); 8 | this.iconPath = new ThemeIcon(`unverified`); 9 | } 10 | 11 | setCommand(command: string, arg?: string) { 12 | this.command = { command: command, title: ``, arguments: [this.workspaceFolder, arg] }; 13 | } 14 | 15 | async getChildren(): Promise { 16 | return []; 17 | } 18 | } -------------------------------------------------------------------------------- /vs/client/src/views/projectExplorer/sourceOrbitTreeItem.ts: -------------------------------------------------------------------------------- 1 | import { ProjectExplorerTreeItem } from "@ibm/vscode-ibmi-projectexplorer-types/views/projectExplorer/projectExplorerTreeItem"; 2 | import { Event, EventEmitter, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; 3 | import { LanguageClientManager } from '../../languageClientManager'; 4 | import { ILEObjectTreeItem } from './ileObjectTreeItem'; 5 | 6 | export class SourceOrbitTreeItem extends TreeItem implements ProjectExplorerTreeItem { 7 | private _onDidChangeTreeData: EventEmitter = new EventEmitter(); 8 | readonly onDidChangeTreeData: Event = this._onDidChangeTreeData.event; 9 | 10 | constructor(public workspaceFolder: WorkspaceFolder) { 11 | super(`Source Orbit`, TreeItemCollapsibleState.Collapsed); 12 | this.iconPath = new ThemeIcon(`globe`); 13 | this.contextValue = `objectsView`; 14 | } 15 | 16 | refresh() { 17 | this._onDidChangeTreeData.fire(); 18 | } 19 | 20 | async getChildren(): Promise { 21 | const isProjectReady = await LanguageClientManager.isReady(this.workspaceFolder); 22 | if (!isProjectReady) { 23 | await LanguageClientManager.reloadProject(this.workspaceFolder); 24 | } 25 | 26 | const objects = await LanguageClientManager.getResolvedObjects(this.workspaceFolder); 27 | return objects.map(o => new ILEObjectTreeItem(this.workspaceFolder, o, true)); 28 | } 29 | } -------------------------------------------------------------------------------- /vs/client/src/views/utils.ts: -------------------------------------------------------------------------------- 1 | 2 | export const TypeIcons = { 3 | "BNDDIR": "book", 4 | "PGM": "terminal", 5 | "FILE": "database", 6 | "CMD": "window", 7 | "SRVPGM": "symbol-constructor", 8 | "MODULE": "symbol-module", 9 | "DTAARA": "file-text", 10 | "MENU": "menu", 11 | "DTAQ": "list-flat" 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /vs/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es2020", 6 | "lib": ["es2020"], 7 | "outDir": "out", 8 | "rootDir": "src", 9 | "sourceMap": true, 10 | "skipLibCheck": true 11 | }, 12 | "include": ["src"], 13 | "exclude": ["node_modules", ".vscode-test"] 14 | } 15 | -------------------------------------------------------------------------------- /vs/client/webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* eslint-disable @typescript-eslint/no-var-requires */ 3 | /*--------------------------------------------------------------------------------------------- 4 | * Copyright (c) Microsoft Corporation. All rights reserved. 5 | * Licensed under the MIT License. See License.txt in the project root for license information. 6 | *--------------------------------------------------------------------------------------------*/ 7 | 8 | //@ts-check 9 | 10 | 'use strict'; 11 | 12 | const withDefaults = require(`../shared.webpack.config.js`); 13 | const path = require(`path`); 14 | 15 | module.exports = withDefaults({ 16 | context: path.join(__dirname), 17 | entry: { 18 | extension: `./src/extension.ts`, 19 | }, 20 | output: { 21 | filename: `extension.js`, 22 | path: path.join(__dirname, `..`, `out`) 23 | } 24 | }); -------------------------------------------------------------------------------- /vs/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/sourceorbit/6413354cf9f9f97f6367ef1ccfe22a17c6da26bd/vs/icon.png -------------------------------------------------------------------------------- /vs/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "checkJs": true, /* Typecheck .js files. */ 6 | "lib": [ 7 | "es6" 8 | ] 9 | }, 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /vs/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-sourceorbit-server", 3 | "description": "Server", 4 | "version": "1.0.1", 5 | "author": "IBM", 6 | "license": "MIT", 7 | "engines": { 8 | "node": "*" 9 | }, 10 | "dependencies": { 11 | "@ibm/sourceorbit": "file:../../cli", 12 | "glob": "^7.2.0", 13 | "vscode-languageserver": "^8.1.0", 14 | "vscode-languageserver-textdocument": "^1.0.8", 15 | "vscode-uri": "^3.0.7" 16 | }, 17 | "scripts": {}, 18 | "devDependencies": { 19 | "@types/glob": "^8.1.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vs/server/src/fileSystemListener.ts: -------------------------------------------------------------------------------- 1 | import { Connection } from 'vscode-languageserver'; 2 | import { initAndRefresh } from './setup'; 3 | import { TargetsManager } from './TargetsManager'; 4 | 5 | export function setupFsListener(connection: Connection) { 6 | 7 | // Commented out since we don't read entire projects on load 8 | // connection.workspace.getWorkspaceFolders().then(workspaceFolders => { 9 | // connection.console.log(`Connected and got workspace folders`); 10 | // if (workspaceFolders) { 11 | // for (const workspaceFolder of workspaceFolders) { 12 | // connection.console.log(JSON.stringify(workspaceFolder, null, 2)); 13 | // initAndRefresh(workspaceFolder.uri); 14 | // } 15 | // } 16 | // }); 17 | 18 | connection.workspace.onDidChangeWorkspaceFolders(_event => { 19 | connection.console.log('Workspace folder change event received.'); 20 | connection.console.log(JSON.stringify(_event, null, 2)); 21 | 22 | for (const removed of _event.removed) { 23 | TargetsManager.destroy(removed.uri); 24 | } 25 | 26 | // Commented out since we don't read entire projects on load 27 | // for (const added of _event.added) { 28 | // initAndRefresh(added.uri); 29 | // } 30 | }); 31 | 32 | connection.onDidSaveTextDocument((params) => { 33 | const uri = params.textDocument.uri; 34 | connection.console.log(JSON.stringify(uri, null, 2)); 35 | 36 | TargetsManager.refreshSingle(uri); 37 | }); 38 | 39 | connection.workspace.onDidDeleteFiles((params) => { 40 | const files = params.files; 41 | connection.console.log(JSON.stringify(files, null, 2)); 42 | 43 | files.map(deleted => TargetsManager.removeSingle(deleted.uri)); 44 | 45 | }); 46 | 47 | connection.workspace.onDidCreateFiles((params) => { 48 | const files = params.files; 49 | connection.console.log(JSON.stringify(files, null, 2)); 50 | 51 | for (const created of files) { 52 | TargetsManager.refreshSingle(created.uri); 53 | } 54 | }); 55 | 56 | connection.workspace.onDidRenameFiles(async (params) => { 57 | const files = params.files; 58 | connection.console.log(JSON.stringify(files, null, 2)); 59 | 60 | const workspaceUris: string[] = []; 61 | 62 | for (const rename of files) { 63 | await TargetsManager.removeSingle(rename.oldUri); 64 | TargetsManager.refreshSingle(rename.newUri); 65 | } 66 | }); 67 | } -------------------------------------------------------------------------------- /vs/server/src/readFileSystem.ts: -------------------------------------------------------------------------------- 1 | import ffs from 'fs'; 2 | import fs from 'fs/promises'; 3 | import { glob } from 'glob'; 4 | 5 | export class ReadFileSystem { 6 | async getFiles(cwd: string, globPath: string): Promise { 7 | return glob.sync(globPath, { 8 | cwd, 9 | absolute: true, 10 | nocase: true, 11 | }); 12 | } 13 | 14 | readFile(filePath: string): Promise { 15 | return fs.readFile(filePath, { encoding: `utf8` }); 16 | } 17 | 18 | async exists(filePath: string): Promise { 19 | return ffs.existsSync(filePath); 20 | } 21 | } -------------------------------------------------------------------------------- /vs/server/src/requests.ts: -------------------------------------------------------------------------------- 1 | import { Connection } from 'vscode-languageserver'; 2 | import { TargetsManager } from './TargetsManager'; 3 | 4 | import { ILEObject, TargetSuggestions } from "@ibm/sourceorbit/dist/src/targets"; 5 | import { URI } from 'vscode-uri'; 6 | import { fixProject, generateBuildFile, initAndRefresh } from './setup'; 7 | 8 | export function setupRequestHandler(connection: Connection) { 9 | connection.onRequest(`isReady`, async (params: [string]) => { 10 | return TargetsManager.isReady(params[0]); 11 | }); 12 | 13 | connection.onRequest(`getResolvedObjects`, async (params: [string]) => { 14 | return TargetsManager.getResolvedObjects(params[0]); 15 | }); 16 | 17 | connection.onRequest(`getDeps`, async (params: [string, ILEObject]) => { 18 | return TargetsManager.getDepsForTarget(params[0], params[1]); 19 | }); 20 | 21 | connection.onRequest(`getImpacts`, async (params: [string, string[]]) => { 22 | const target = TargetsManager.getTargetsForWorkspaceUri(params[0]); 23 | 24 | if (target) { 25 | const uris = params[1]; 26 | 27 | const possibleObjects = uris 28 | .map(fileUri => target.getResolvedObject(URI.parse(fileUri).fsPath.replace(/\\/g, '/'))) 29 | .filter(x => x && x.relativePath); 30 | 31 | return possibleObjects.map(ileObject => target.getImpactFor(ileObject)); 32 | } 33 | 34 | return []; 35 | }); 36 | 37 | connection.onRequest(`reloadProject`, (params: [string]) => { 38 | return initAndRefresh(params[0]); 39 | }); 40 | 41 | connection.onRequest(`fixProject`, (params: [string, keyof TargetSuggestions]) => { 42 | const suggestions: TargetSuggestions = {}; 43 | 44 | suggestions[params[1]] = true; 45 | 46 | return fixProject(params[0], suggestions); 47 | }); 48 | 49 | connection.onRequest(`generateBuildFile`, (params: [string, string]) => { 50 | return generateBuildFile(params[0], params[1]); 51 | }); 52 | } -------------------------------------------------------------------------------- /vs/server/src/server.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createConnection, 3 | Diagnostic, 4 | DiagnosticSeverity, 5 | ProposedFeatures, 6 | InitializeParams, 7 | TextDocumentSyncKind, 8 | InitializeResult, 9 | WorkspaceFolder, 10 | Range, 11 | Position 12 | } from 'vscode-languageserver/node'; 13 | import { SupportedGlob, TargetsManager } from './TargetsManager'; 14 | import { setupRequestHandler } from './requests'; 15 | import { setupFsListener } from './fileSystemListener'; 16 | 17 | // Create a connection for the server, using Node's IPC as a transport. 18 | // Also include all preview / proposed LSP features. 19 | export const connection = createConnection(ProposedFeatures.all); 20 | 21 | let hasWorkspaceFolderCapability = false; 22 | 23 | connection.onInitialize((params: InitializeParams) => { 24 | const capabilities = params.capabilities; 25 | 26 | // Does the client support the `workspace/configuration` request? 27 | // If not, we fall back using global settings. 28 | hasWorkspaceFolderCapability = !!( 29 | capabilities.workspace && !!capabilities.workspace.workspaceFolders 30 | ); 31 | 32 | const result: InitializeResult = { 33 | capabilities: { 34 | textDocumentSync: TextDocumentSyncKind.Incremental, 35 | } 36 | }; 37 | if (hasWorkspaceFolderCapability) { 38 | result.capabilities.workspace = { 39 | fileOperations: { 40 | didCreate: { filters: [{ pattern: { glob: SupportedGlob, options: { ignoreCase: true } } }] }, 41 | didRename: { filters: [{ pattern: { glob: SupportedGlob, options: { ignoreCase: true } } }] }, 42 | didDelete: { filters: [{ pattern: { glob: SupportedGlob, options: { ignoreCase: true } } }] } 43 | }, 44 | workspaceFolders: { 45 | supported: true, 46 | changeNotifications: true 47 | } 48 | }; 49 | } 50 | return result; 51 | }); 52 | 53 | 54 | connection.onInitialized(() => { 55 | if (hasWorkspaceFolderCapability) { 56 | setupFsListener(connection); 57 | } 58 | }); 59 | 60 | // Listen on the connection 61 | connection.listen(); 62 | 63 | setupRequestHandler(connection); -------------------------------------------------------------------------------- /vs/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "target": "es2020", 5 | "lib": ["es2020"], 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "strict": true, 10 | "outDir": "out", 11 | "rootDir": "src", 12 | "esModuleInterop": true 13 | }, 14 | "include": ["src"], 15 | "exclude": ["node_modules", ".vscode-test"] 16 | } 17 | -------------------------------------------------------------------------------- /vs/server/webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* eslint-disable @typescript-eslint/no-var-requires */ 3 | /*--------------------------------------------------------------------------------------------- 4 | * Copyright (c) Microsoft Corporation. All rights reserved. 5 | * Licensed under the MIT License. See License.txt in the project root for license information. 6 | *--------------------------------------------------------------------------------------------*/ 7 | 8 | 'use strict'; 9 | 10 | const withDefaults = require(`../shared.webpack.config.js`); 11 | const path = require(`path`); 12 | const webpack = require(`webpack`); 13 | 14 | module.exports = withDefaults({ 15 | context: path.join(__dirname), 16 | entry: { 17 | extension: `./src/server.ts`, 18 | }, 19 | output: { 20 | filename: `server.js`, 21 | path: path.join(__dirname, `..`, `out`) 22 | }, 23 | plugins: [ 24 | new webpack.DefinePlugin({ 25 | 'process.env.LANGUAGE_TOOLS_ENABLED': process.env.LANGUAGE_TOOLS_ENABLED || `true`, 26 | 'process.env.LINTER_ENABLED': process.env.LINTER_ENABLED || `true`, 27 | 'process.env.FORMATTER_ENABLED': process.env.FORMATTER_ENABLED || `true`, 28 | }), 29 | ], 30 | }); -------------------------------------------------------------------------------- /vs/shared.webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* eslint-disable @typescript-eslint/no-var-requires */ 3 | /*--------------------------------------------------------------------------------------------- 4 | * Copyright (c) Microsoft Corporation. All rights reserved. 5 | * Licensed under the MIT License. See License.txt in the project root for license information. 6 | *--------------------------------------------------------------------------------------------*/ 7 | 8 | //@ts-check 9 | /** @typedef {import('webpack').Configuration} WebpackConfig **/ 10 | 11 | 'use strict'; 12 | 13 | const path = require(`path`); 14 | const merge = require(`merge-options`); 15 | 16 | module.exports = function withDefaults(/**@type WebpackConfig*/extConfig) { 17 | 18 | /** @type WebpackConfig */ 19 | let defaultConfig = { 20 | mode: `none`, // this leaves the source code as close as possible to the original (when packaging we set this to 'production') 21 | target: `node`, // extensions run in a node context 22 | node: { 23 | __dirname: false // leave the __dirname-behaviour intact 24 | }, 25 | resolve: { 26 | mainFields: [`module`, `main`], 27 | extensions: [`.ts`, `.js`] // support ts-files and js-files 28 | }, 29 | module: { 30 | rules: [{ 31 | test: /\.ts$/, 32 | exclude: /node_modules/, 33 | use: [{ 34 | // configure TypeScript loader: 35 | // * enable sources maps for end-to-end source maps 36 | loader: `esbuild-loader` 37 | }] 38 | }] 39 | }, 40 | externals: { 41 | 'vscode': `commonjs vscode`, // ignored because it doesn't exist 42 | }, 43 | output: { 44 | // all output goes into `dist`. 45 | // packaging depends on that and this must always be like it 46 | filename: `[name].js`, 47 | path: path.join(String(extConfig.context), `out`), 48 | libraryTarget: `commonjs`, 49 | }, 50 | // yes, really source maps 51 | devtool: `source-map` 52 | }; 53 | 54 | return merge(defaultConfig, extConfig); 55 | }; -------------------------------------------------------------------------------- /vs/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "noUnusedParameters": true, 5 | "strict": true, 6 | "allowJs": true, 7 | "types": ["node"] 8 | } 9 | } -------------------------------------------------------------------------------- /vs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2020", 5 | "moduleResolution": "node", 6 | "lib": ["es2020"], 7 | "outDir": "out", 8 | "rootDir": "src", 9 | "sourceMap": true, 10 | "allowJs": true, 11 | }, 12 | "include": [ 13 | "src" 14 | ], 15 | "exclude": [ 16 | "node_modules", 17 | ".vscode-test" 18 | ], 19 | "references": [ 20 | { "path": "./client" }, 21 | { "path": "./server" } 22 | ] 23 | } --------------------------------------------------------------------------------