Skip to content

Commit

Permalink
APEX Parsing Support (#421)
Browse files Browse the repository at this point in the history
* feat: add support for APEX parsing and lexing using antlr4ng
* feat: support test impacting in CLI
  • Loading branch information
Codeneos authored Mar 27, 2024
1 parent 106308c commit 61410a9
Show file tree
Hide file tree
Showing 47 changed files with 29,518 additions and 309 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ packages/*/lib
*.tsbuildinfo
/docs
/packages/*/coverage
/packages/apex/src/grammar/*.interp
/packages/apex/src/grammar/*.tokens
21 changes: 19 additions & 2 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"group": {
"kind": "build"
},
"dependsOn": ["watch-vlocity-deploy"]
"dependsOn": ["watch-vlocity-deploy", "watch-apex"]
},
{
"label": "watch-vlocity-deploy",
Expand Down Expand Up @@ -160,7 +160,24 @@
"group": {
"kind": "build"
},
"dependsOn": ["watch-core"]
"dependsOn": ["watch-util", "watch-core"]
},
{
"label": "watch-apex",
"type": "shell",
"problemMatcher": {
"base": "$tsc-watch",
"fileLocation": ["relative", "${workspaceFolder}/packages/vlocity-apex"]
},
"command": "pnpm --filter @vlocode/apex watch",
"isBackground": true,
"presentation": {
"reveal": "always"
},
"group": {
"kind": "build"
},
"dependsOn": ["watch-util", "watch-core"]
},
{
"label": "watch-core",
Expand Down
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "vlocode-project",
"packageManager": "pnpm@8.12.1",
"packageManager": "pnpm@8.15.4+sha256.cea6d0bdf2de3a0549582da3983c70c92ffc577ff4410cbf190817ddc35137c2",
"description": "Vlocode project packages",
"version": "0.21.6",
"license": "MIT",
Expand All @@ -24,15 +24,15 @@
"@types/fs-extra": "^11",
"@types/jest": "^29.5.11",
"@types/node": "^20",
"@typescript-eslint/eslint-plugin": "^5.30.5",
"@typescript-eslint/parser": "^5.30.5",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"chalk": "^4.1.2",
"eslint": "^8.19.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsdoc": "^37.6.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^37.9.7",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-prettier": "^4.2.1",
"fs-extra": "^11",
"husky": "^8.0.1",
"jest": "^29.7.0",
Expand Down Expand Up @@ -75,7 +75,7 @@
"sync-ws-version": "node -e \"fs.writeFileSync('./package.json', JSON.stringify({ ...require('./package.json'), version: require('./lerna.json').version }, undefined, 4));\"",
"test": "jest",
"prepare": "husky install",
"lint": "eslint ./packages/*/src/**/*.ts --ext .ts",
"lint": "eslint ./packages/*/src --no-error-on-unmatched-pattern --ext .ts",
"docs": "pnpm sync-ws-version && typedoc"
},
"resolutions": {
Expand Down
89 changes: 89 additions & 0 deletions packages/apex/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
[![CircleCI](https://circleci.com/gh/Codeneos/vlocode/tree/main.svg?style=svg)](https://circleci.com/gh/Codeneos/vlocode/tree/main)
[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode)
[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode)
[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode)
![NPM Version](https://img.shields.io/npm/v/%40vlocode%5Capex)

# **@vlocode/apex** Salesforce APEX Language Parser

Antlr4 based [APEX Parser](./src/grammar/ApexParser.ts) and [Grammar](./grammar/ApexParser.g4). This library uses [antlr4ng](https://github.com/mike-lischke/antlr4ng) as runtime library which is a port of the original antlr4 runtime library to TypeScript.

The library exposes the APEX Lexer and APEX parser generated from the `.g4` grammar files allowing parsing of APEX source code using Visitor or Listener patterns.

## Features

- Full APEX and SOQL grammar support
- Extract code structure from APEX source code
- Identify classes, fields, methods, properties and access modifiers
- Identify which classes are tested by which test classes

## Example: Identifying test classes for a given class

Below code demonstrates how to identify which classes are tested by which test classes. And prints the test classes for a given class name.

```ts
import { TestIdentifier } from '@vlocode/apex';

const testIdentifier = container.create(TestIdentifier);
await testIdentifier.loadApexClasses(['path/to/apex/classes']);
const testClasses = testIdentifier.getTestClasses('MyClass');
console.log(testClasses);
```

## Example: Extracting class information from APEX source code

Below code demonstrates how to extract class information from an APEX source fragment and prints the class name, fields and methods as well as their access modifiers.

```ts
import { Parser } from '@vlocode/apex';

const sourceCode = `public class Person {
private String name;
private Integer age;
public String nameProperty {
get { return this.name; }
}
public Integer getAge(Integer arg) {
return this.age;
}
public Date getBirthDate() {
return Date.now();
}
}`;

const parser = new Parser(sourceCode);
const struct = parser.getCodeStructure();

for (const classInfo of struct.classes) {
console.log(`Class ${classInfo.name}`);

console.log(` Fields: ${classInfo.fields.length}`);
classInfo.fields.forEach((field, i) =>
console.log(` ${i + 1}) ${field.name} (${field.access})`)
);

console.log(` Methods: ${classInfo.methods.length}`);
classInfo.methods.forEach((method, i) =>
console.log(` ${i + 1}) ${method.name} (${method.access})`)
);
}
```

Outputs the following:

```shell
Class Person
Fields: 2
1) name (private)
2) age (private)
Methods: 2
2) getAge (public)
3) getBirthDate (public)
```

## Credits

The grammar files in this library are based on the grammar files from the `apex-parser` NPM library originally maintained by Andrey Gavrikov. The original library is no longer maintained and the grammar files have been updated to work with the latest version of Salesforce and the antlr4ng runtime library.
Loading

0 comments on commit 61410a9

Please sign in to comment.