fix: incorrect lint error position (#16526)
* perform string search using original binding * Add jest test * Improve code for better readability
This commit is contained in:
parent
a706ad3160
commit
16b04f33a6
|
|
@ -44,8 +44,8 @@ describe("getLintAnnotations()", () => {
|
|||
const { LINT, PARSE } = PropertyEvaluationErrorType;
|
||||
const { ERROR, WARNING } = Severity;
|
||||
it("should return proper annotations", () => {
|
||||
const value = `Hello {{ world == test }}`;
|
||||
const errors: EvaluationError[] = [
|
||||
const value1 = `Hello {{ world == test }}`;
|
||||
const errors1: EvaluationError[] = [
|
||||
{
|
||||
errorType: LINT,
|
||||
raw:
|
||||
|
|
@ -87,8 +87,8 @@ describe("getLintAnnotations()", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const res = getLintAnnotations(value, errors, {});
|
||||
expect(res).toEqual([
|
||||
const res1 = getLintAnnotations(value1, errors1, {});
|
||||
expect(res1).toEqual([
|
||||
{
|
||||
from: {
|
||||
line: 0,
|
||||
|
|
@ -126,6 +126,40 @@ describe("getLintAnnotations()", () => {
|
|||
severity: "warning",
|
||||
},
|
||||
]);
|
||||
|
||||
/// 2
|
||||
const value2 = `hss{{hss}}`;
|
||||
const errors2: EvaluationError[] = [
|
||||
{
|
||||
errorType: LINT,
|
||||
raw:
|
||||
"\n function closedFunction () {\n const result = hss\n return result;\n }\n closedFunction.call(THIS_CONTEXT)\n ",
|
||||
severity: ERROR,
|
||||
errorMessage: "'hss' is not defined.",
|
||||
errorSegment: " const result = hss",
|
||||
originalBinding: "{{hss}}",
|
||||
variables: ["hss", null, null, null],
|
||||
code: "W117",
|
||||
line: 0,
|
||||
ch: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const res2 = getLintAnnotations(value2, errors2, {});
|
||||
expect(res2).toEqual([
|
||||
{
|
||||
from: {
|
||||
line: 0,
|
||||
ch: 5,
|
||||
},
|
||||
to: {
|
||||
line: 0,
|
||||
ch: 8,
|
||||
},
|
||||
message: "'hss' is not defined.",
|
||||
severity: "error",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("should return correct annotation with newline in original binding", () => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { last, isNumber, isEmpty } from "lodash";
|
|||
import { Annotation, Position } from "codemirror";
|
||||
import {
|
||||
EvaluationError,
|
||||
isDynamicValue,
|
||||
PropertyEvaluationErrorType,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import { Severity } from "entities/AppsmithConsole";
|
||||
|
|
@ -117,6 +118,11 @@ export const getLintAnnotations = (
|
|||
const annotations: Annotation[] = [];
|
||||
const lintErrors = filterLintErrors(errors, contextData);
|
||||
const lines = value.split("\n");
|
||||
|
||||
// The binding position of every valid JS Object is constant, so we need not
|
||||
// waste time checking for position of binding.
|
||||
// For JS Objects not starting with the expected "export default" statement, we return early
|
||||
// with a "invalid start statement" lint error
|
||||
if (
|
||||
isJSObject &&
|
||||
!isEmpty(lines) &&
|
||||
|
|
@ -167,8 +173,19 @@ export const getLintAnnotations = (
|
|||
for (const bindingLocation of bindingPositions) {
|
||||
const currentLine = bindingLocation.line + line;
|
||||
const lineContent = lines[currentLine] || "";
|
||||
const currentCh =
|
||||
bindingLocation.line !== currentLine ? ch : bindingLocation.ch + ch;
|
||||
let currentCh: number;
|
||||
|
||||
// for case where "{{" is in the same line as the lint error
|
||||
if (bindingLocation.line === currentLine) {
|
||||
currentCh =
|
||||
bindingLocation.ch +
|
||||
ch +
|
||||
// Add 2 to account for "{{", if binding is a dynamicValue (NB: JS Objects are dynamicValues without "{{}}")
|
||||
(isDynamicValue(originalBinding) ? 2 : 0);
|
||||
} else {
|
||||
currentCh = ch;
|
||||
}
|
||||
|
||||
// Jshint counts \t as two characters and codemirror counts it as 1.
|
||||
// So we need to subtract number of tabs to get accurate position
|
||||
const tabs = lineContent.slice(0, currentCh).match(/\t/g)?.length || 0;
|
||||
|
|
|
|||
|
|
@ -15,11 +15,7 @@ import {
|
|||
removeLintErrorsFromEntityProperty,
|
||||
} from "workers/evaluationUtils";
|
||||
|
||||
import {
|
||||
getJSSnippetToLint,
|
||||
getLintingErrors,
|
||||
pathRequiresLinting,
|
||||
} from "./utils";
|
||||
import { getJSToLint, getLintingErrors, pathRequiresLinting } from "./utils";
|
||||
|
||||
interface LintTreeArgs {
|
||||
unEvalTree: DataTree;
|
||||
|
|
@ -136,19 +132,21 @@ const lintBindingPath = (
|
|||
);
|
||||
|
||||
if (stringSegments) {
|
||||
jsSnippets.map((jsSnippet) => {
|
||||
const jsSnippetToLint = getJSSnippetToLint(
|
||||
entity,
|
||||
jsSnippet,
|
||||
propertyPath,
|
||||
);
|
||||
jsSnippets.map((jsSnippet, index) => {
|
||||
if (jsSnippet) {
|
||||
const jsSnippetToLint = getJSToLint(entity, jsSnippet, propertyPath);
|
||||
// {{user's code}}
|
||||
const originalBinding = getJSToLint(
|
||||
entity,
|
||||
stringSegments[index],
|
||||
propertyPath,
|
||||
);
|
||||
const scriptType = getScriptType(false, false);
|
||||
const scriptToLint = getScriptToEval(jsSnippetToLint, scriptType);
|
||||
lintErrors = getLintingErrors(
|
||||
scriptToLint,
|
||||
globalData,
|
||||
jsSnippetToLint,
|
||||
originalBinding,
|
||||
scriptType,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ export const pathRequiresLinting = (
|
|||
return requiresLinting;
|
||||
};
|
||||
|
||||
export const getJSSnippetToLint = (
|
||||
// Removes "export default" statement from js Object
|
||||
export const getJSToLint = (
|
||||
entity: DataTreeEntity,
|
||||
snippet: string,
|
||||
propertyPath: string,
|
||||
|
|
@ -97,6 +98,7 @@ function getEvaluationScriptPosition(scriptType: EvaluationScriptType) {
|
|||
export const getLintingErrors = (
|
||||
script: string,
|
||||
data: Record<string, unknown>,
|
||||
// {{user's code}}
|
||||
originalBinding: string,
|
||||
scriptType: EvaluationScriptType,
|
||||
): EvaluationError[] => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user