Skip to content

Commit

Permalink
feat: add diagnostics for unused evrs (#395)
Browse files Browse the repository at this point in the history
* Add diagnostics for unused evrs
  • Loading branch information
vetlek authored Nov 22, 2023
1 parent ece8ade commit 19ee438
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 12 deletions.
38 changes: 38 additions & 0 deletions server/src/language-service/diagnosticsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
formatDataType,
RefValidationFunction,
SepticReference,
ReferenceType,
} from "../septic";
import { SettingsManager } from "../settings";
import { isPureJinja } from "../util";
Expand Down Expand Up @@ -82,6 +83,7 @@ export enum DiagnosticCode {
missingParentObject = "W402",
missingReference = "W501",
invalidReference = "W502",
unusedEvr = "W503",
invalidComment = "W601",
}

Expand Down Expand Up @@ -671,6 +673,9 @@ export function validateObjectReferences(
return [];
}
const diagnostics: Diagnostic[] = [];
if (obj.isType("Evr")) {
diagnostics.push(...validateEvrReferences(obj, refProvider, doc));
}
if (shouldValidateIdentifier(objectMetaInfo, obj)) {
if (obj.isType("CalcPvr")) {
diagnostics.push(
Expand Down Expand Up @@ -803,6 +808,39 @@ const hasReferenceToEvr: RefValidationFunction = (refs: SepticReference[]) => {
return false;
};

export function validateEvrReferences(
obj: SepticObject,
refProvider: SepticReferenceProvider,
doc: ITextDocument
) {
const userInputAttrValue = obj.getAttribute("UserInput")?.getAttrValue();
if (userInputAttrValue && userInputAttrValue.getValue() !== "OFF") {
return [];
}
const name = obj.identifier?.name;
if (!name) {
return [];
}
const refs = refProvider.getXvrRefs(name);
const calcPvrRef = refs?.find((ref) => {
return ref.type === ReferenceType.calc;
});
if (!calcPvrRef) {
return [
createDiagnostic(
DiagnosticSeverity.Warning,
{
start: doc.positionAt(obj.identifier!.start),
end: doc.positionAt(obj.identifier!.end),
},
"Unused Evr. Evr not used in calcs or enabled user input",
DiagnosticCode.unusedEvr
),
];
}
return [];
}

export function validateAttribute(
attr: Attribute,
doc: ITextDocument,
Expand Down
12 changes: 11 additions & 1 deletion server/src/septic/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export interface SepticReference {
end: number;
};
obj?: SepticObject;
type: ReferenceType;
}

export enum ReferenceType {
xvr,
calc,
identifier,
attribute,
}

export function createSepticReference(
Expand All @@ -23,12 +31,14 @@ export function createSepticReference(
start: number;
end: number;
},
obj: SepticObject | undefined = undefined
obj: SepticObject | undefined = undefined,
type: ReferenceType
): SepticReference {
return {
identifier: identifier.replace(/\s/g, ""),
location: location,
obj: obj,
type: type,
};
}

Expand Down
39 changes: 28 additions & 11 deletions server/src/septic/septicCnfg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
RefValidationFunction,
defaultRefValidationFunction,
createSepticReference,
ReferenceType,
} from "./reference";
import { removeSpaces } from "../util";
import { updateParentObjects } from "./hierarchy";
Expand Down Expand Up @@ -195,14 +196,20 @@ export function extractXvrRefs(obj: SepticObject): SepticReference[] {

if (objectDef.refs.identifier && obj.identifier) {
let isObjRef = obj.isXvr() || obj.isSopcXvr();
let isCalcPvr = obj.isType("CalcPvr");
let ref: SepticReference = createSepticReference(
obj.identifier.name,
{
uri: "",
start: obj.identifier.start,
end: obj.identifier.end,
},
isObjRef ? obj : undefined
isObjRef ? obj : undefined,
isObjRef
? ReferenceType.xvr
: isCalcPvr
? ReferenceType.calc
: ReferenceType.identifier
);
xvrRefs.push(ref);
}
Expand Down Expand Up @@ -234,11 +241,16 @@ function calcPvrXvrRefs(obj: SepticObject): SepticReference[] {

visitor.variables.forEach((xvr) => {
let identifier = xvr.value.split(".")[0];
const ref: SepticReference = createSepticReference(identifier, {
uri: "",
start: alg!.getAttrValue()!.start + xvr.start + 1,
end: alg!.getAttrValue()!.start + xvr.end + 1,
});
const ref: SepticReference = createSepticReference(
identifier,
{
uri: "",
start: alg!.getAttrValue()!.start + xvr.start + 1,
end: alg!.getAttrValue()!.start + xvr.end + 1,
},
undefined,
ReferenceType.calc
);
xvrs.push(ref);
});
return xvrs;
Expand All @@ -257,10 +269,15 @@ function attrXvrRefs(obj: SepticObject, attrName: string): SepticReference[] {
);
});
return refs.map((ref) => {
return createSepticReference(ref.getValue(), {
uri: "",
start: ref.start + 1,
end: ref.end - 1,
});
return createSepticReference(
ref.getValue(),
{
uri: "",
start: ref.start + 1,
end: ref.end - 1,
},
undefined,
ReferenceType.attribute
);
});
}
70 changes: 70 additions & 0 deletions server/src/test/diagnostics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,76 @@ describe("Test validation of object references", () => {
);
expect(diag.length).to.equal(0);
});
it("Expect diagnostics for unused evr", () => {
const text = `
Evr: TestEvr
UserInput= OFF
`;
const doc = new MockDocument(text);
const cnfg = parseSeptic(doc.getText());
const objectInfo = metaInfoProvider.getObject("MvrList");
let diag = validateObjectReferences(
cnfg.objects[0],
doc,
cnfg,
objectInfo!
);
expect(diag.length).to.equal(1);
expect(diag[0].code).to.equal(DiagnosticCode.unusedEvr);
});
it("Expect no diagnostics for evr with user input enabled", () => {
const text = `
Evr: TestEvr
UserInput= DOUBLE
`;
const doc = new MockDocument(text);
const cnfg = parseSeptic(doc.getText());
const objectInfo = metaInfoProvider.getObject("MvrList");
let diag = validateObjectReferences(
cnfg.objects[0],
doc,
cnfg,
objectInfo!
);
expect(diag.length).to.equal(0);
});
it("Expect no diagnostics for evr used in calc", () => {
const text = `
Evr: TestEvr
UserInput= DOUBLE
CalcPvr: TestEvr
`;
const doc = new MockDocument(text);
const cnfg = parseSeptic(doc.getText());
const objectInfo = metaInfoProvider.getObject("MvrList");
let diag = validateObjectReferences(
cnfg.objects[0],
doc,
cnfg,
objectInfo!
);
expect(diag.length).to.equal(0);
});
it("Expect no diagnostics for evr used in calc", () => {
const text = `
Evr: TestEvr
UserInput= DOUBLE
CalcPvr: Test
Alg= "TestEvr"
`;
const doc = new MockDocument(text);
const cnfg = parseSeptic(doc.getText());
const objectInfo = metaInfoProvider.getObject("MvrList");
let diag = validateObjectReferences(
cnfg.objects[0],
doc,
cnfg,
objectInfo!
);
expect(diag.length).to.equal(0);
});
});

describe("Test validation of object structure", () => {
Expand Down

0 comments on commit 19ee438

Please sign in to comment.