Skip to content

Commit

Permalink
MAT-7784: Associate comments and inline comments with cql definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmcphillips committed Oct 28, 2024
1 parent df9cd73 commit 66b3b64
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 4 deletions.
9 changes: 7 additions & 2 deletions src/CqlAntlr.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CharStreams, CommonTokenStream } from "antlr4ts";
import {BufferedTokenStream, CharStreams, CommonTokenStream} from "antlr4ts";
import { CodePointCharStream } from "antlr4ts/CodePointCharStream";
import { ParseTreeWalker } from "antlr4ts/tree";
import { cqlLexer, cqlParser, LibraryContext, cqlListener } from "../generated";
Expand All @@ -12,7 +12,12 @@ class CqlAntlr {
parse(): CqlResult {
const result = CqlAntlr.initCqlResult();
const tree: LibraryContext = this.buildTree(result);
const listener: cqlListener = new CqlAntlrListener(result);
const charStream: CodePointCharStream = CharStreams.fromString(this.cql);
const lexer: cqlLexer = new cqlLexer(charStream);
const bufferedTokenStream = new BufferedTokenStream(lexer);

Check failure on line 17 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L17

Unsafe assignment of an `any` value.

Check failure on line 17 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L17

Unsafe assignment of an error typed value.

Check failure on line 17 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L17

Unsafe construction of an any type value.

Check failure on line 17 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L17

Unsafe construction of an any type value.
bufferedTokenStream.fill()

Check failure on line 18 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L18

Unsafe call of an `any` typed value.

Check failure on line 18 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L18

Unsafe call of an `error` type typed value.

Check failure on line 18 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L18

Unsafe member access .fill on an `any` value.

Check failure on line 18 in src/CqlAntlr.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlr.ts#L18

Unsafe member access .fill on an `error` typed value.

const listener: cqlListener = new CqlAntlrListener(result, bufferedTokenStream);
ParseTreeWalker.DEFAULT.walk(listener, tree);
/**
* Disabled. Only partially implemented and would be
Expand Down
21 changes: 20 additions & 1 deletion src/CqlAntlrListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
CodeDefinitionContext,
CodesystemDefinitionContext,
ContextDefinitionContext,
cqlLexer,
cqlListener,
ExpressionDefinitionContext,
IncludeDefinitionContext,
Expand Down Expand Up @@ -31,9 +32,14 @@ import CqlIdentifier from "./dto/CqlIdentifier";
import CqlIdentifierCreator from "./CqlIdentifierCreator";
import CqlRetrieve from "./dto/CqlRetrieve";
import CqlRetrieveCreator from "./CqlRetrieveCreator";
import {BufferedTokenStream } from "antlr4ts";

export default class CqlAntlrListener implements cqlListener {
constructor(private cqlResult: CqlResult) {}
// save bufferedTokenStream from lexer
bufferedTokenStream: BufferedTokenStream;
constructor(private cqlResult: CqlResult, tokenStream: BufferedTokenStream) {

Check notice on line 40 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L40

Expected blank line between class members.
this.bufferedTokenStream = tokenStream;

Check failure on line 41 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L41

Unsafe assignment of an `any` value.

Check failure on line 41 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L41

Unsafe assignment of an error typed value.
}

enterLibraryDefinition(ctx: LibraryDefinitionContext): void {
const cqlVersionCreator = new CqlVersionCreator(ctx);
Expand Down Expand Up @@ -102,6 +108,19 @@ export default class CqlAntlrListener implements cqlListener {
new CqlExpressionDefinitionCreator(ctx).buildDao();

if (cqlCode) {
if (ctx.start.inputStream) {

Check failure on line 111 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L111

Unsafe member access .inputStream on an `error` typed value.
const hiddenTokens = this.bufferedTokenStream.getHiddenTokensToLeft(ctx.start.tokenIndex, cqlLexer.HIDDEN)

Check failure on line 112 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L112

Unsafe assignment of an `any` value.

Check failure on line 112 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L112

Unsafe assignment of an error typed value.

Check failure on line 112 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L112

Unsafe call of an `any` typed value.

Check failure on line 112 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L112

Unsafe call of an `error` type typed value.

Check failure on line 112 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L112

Unsafe member access .getHiddenTokensToLeft on an `any` value.

Check failure on line 112 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L112

Unsafe member access .getHiddenTokensToLeft on an `error` typed value.
let comment = "";
hiddenTokens.forEach((token) => {

Check failure on line 114 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L114

Unsafe call of an `any` typed value.

Check failure on line 114 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L114

Unsafe call of an `error` type typed value.

Check failure on line 114 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L114

Unsafe member access .forEach on an `error` typed value.
if (token.text){

Check failure on line 115 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L115

Unsafe member access .text on an `any` value.

Check failure on line 115 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L115

Unsafe member access .text on an `any` value.
comment += token.text;

Check failure on line 116 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L116

Unsafe member access .text on an `any` value.

Check failure on line 116 in src/CqlAntlrListener.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/CqlAntlrListener.ts#L116

Unsafe member access .text on an `any` value.
}
})
comment = comment.trim();
if (comment){
cqlCode.comment = comment;
}
}
this.cqlResult.expressionDefinitions.push(cqlCode);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/dto/CqlExpressionDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export default interface CqlExpressionDefinition extends CqlText {
expression?: string;
expressionClass?: string;
hits: number;
comment?: string;
}
9 changes: 9 additions & 0 deletions test/CqlAntlr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ describe("test antlr", () => {
expect(def.name).toBeDefined();
});
});
it("Can now parse comments and associate them with functions", () => {
const cqlAntlr = new CqlAntlr(simpleDefinitionCql);
const cqlResult: CqlResult = cqlAntlr.parse();
const expressions = cqlResult.expressionDefinitions;
expect(expressions.length).toEqual(4);
expect(expressions[0].comment).toEqual("// ehnicity comment");
expect(expressions[1].comment).toContain("multi line");
expect(expressions[2].comment).toBeUndefined();
});
it("parse fhir cql", () => {
const cqlAntlr = new CqlAntlr(fhirTestCql);

Expand Down
86 changes: 86 additions & 0 deletions test/commentTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
export const commentTestCql = `cql test is library T1 version '0.0.000'
// ignore
using QDM version '5.6'
// ignore
codesystem "SNOMEDCT": 'urn:oid:2.16.840.1.113883.6.96'
valueset "Active Bleeding": 'urn:oid:2.16.840.1.113762.1.4.1206.28'
// ignore
parameter "Measurement Period" Interval<DateTime>
context Patient
// outside
define "SDE Ethnicity":
//inside
["Patient Characteristic Ethnicity": "Ethnicity"]
define "SDE Payer":
//inside
["Patient Characteristic Payer": "Payer Type"]
// define "SDE Payer1":
// //inside
// ["Patient Characteristic Payer": "Payer Type"]
// SDE Race
define "SDE Race":
/* ignore */
["Patient Characteristic Race": "Race"]
/* SDE Sex */
define "SDE Sex":
["Patient Characteristic Sex": "ONC Administrative Sex"]
/*
asdfasdf
*/
define "Initial Population":
"Qualifying Encounters"
define "Qualifying Encounters":
( ["Encounter, Performed": "Encounter Inpatient"]
union ["Encounter, Performed": "Emergency Department Visit"]
union ["Encounter, Performed": "Acute Inpatient"]
union ["Encounter, Performed": "Active Bleeding"]
union ["Encounter, Performed": "Observation Services"] ) Encounter
where Encounter.relevantPeriod ends during "Measurement Period"
define "Denominator":
["Encounter, Performed": "Acute Inpatient"] AcuteInpatient
where AcuteInpatient.lengthOfStay > 10 days
define "Numerator":
["Encounter, Performed": "Active Bleeding"] ActiveBleeding
where ActiveBleeding.relevantPeriod overlaps day of "Measurement Period"
/*
outside of define
*/
define "Denominator 2":
["Encounter, Performed": "Encounter Inpatient"] EncounterInpatient
where EncounterInpatient.lengthOfStay > 15 days
// outside of define
define "Numerator 2":
["Encounter, Performed": "Emergency Department Visit"]
// inside of definition to ignore
EmergencyDepartmentVisit
where EmergencyDepartmentVisit.lengthOfStay > 15 days
/*
multiline comment outside of a funciton with multiple
rows
*/
define function "Denominator Observation"(Encounter "Encounter, Performed" ):
// inside of definition to ignore
duration in hours of Encounter.relevantPeriod
// comment outside of function
define function "Numerator Observation"(Encounter "Encounter, Performed" ):
duration in hours of Encounter.relevantPeriod
`
4 changes: 3 additions & 1 deletion test/testCql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ const simpleDefinitionCql = `
using QICore version '4.1.1'
context Patient
// ehnicity comment
define "SDE Ethnicity":
SDE."SDE Ethnicity"
/* multi line
*/
define InitialPopulation:
"VTE Prophylaxis by Medication Administered or Device Applied"
Expand Down

0 comments on commit 66b3b64

Please sign in to comment.