Skip to content
Snippets Groups Projects
Unverified Commit 2f0ef803 authored by Ariya Hidayat's avatar Ariya Hidayat Committed by GitHub
Browse files

Custom expression editor: show error marker (#19520)

parent b989e95b
No related merge requests found
......@@ -16,6 +16,7 @@
--color-black: #2e353b;
--color-success: #84bb4c;
--color-error: #ed6e6e;
--color-error-background: #ed6e6e55;
--color-warning: #f9cf48;
--color-text-dark: #4c5773;
--color-text-medium: #949aab;
......
......@@ -322,7 +322,8 @@ export function tokenize(expression) {
if (error) {
const message = error;
const pos = t.start;
errors.push({ message, pos });
const len = t.end - t.start;
errors.push({ message, pos, len });
}
} else {
const char = source[index];
......@@ -330,6 +331,7 @@ export function tokenize(expression) {
break;
}
const pos = index;
const len = 1;
if (char === "]") {
const prev = tokens[tokens.length - 1];
const ref =
......@@ -339,10 +341,10 @@ export function tokenize(expression) {
const message = ref
? t`Missing an opening bracket for ${ref}`
: t`Missing an opening bracket`;
errors.push({ message, pos });
errors.push({ message, pos, len });
} else {
const message = t`Invalid character: ${char}`;
errors.push({ message, pos });
errors.push({ message, pos, len });
}
++index;
}
......
......@@ -333,6 +333,26 @@ export default class ExpressionEditorTextfield extends React.Component {
});
}
errorAsMarkers(errorMessage = null) {
if (errorMessage) {
const { pos, len } = errorMessage;
// Because not every error message offers location info (yet)
if (typeof pos === "number") {
return [
{
startRow: 0,
startCol: pos,
endRow: 0,
endCol: pos + len,
className: "error",
type: "text",
},
];
}
}
return [];
}
commands = [
{
name: "arrowDown",
......@@ -375,6 +395,7 @@ export default class ExpressionEditorTextfield extends React.Component {
commands={this.commands}
ref={this.input}
value={source}
markers={this.errorAsMarkers(errorMessage)}
focus={true}
highlightActiveLine={false}
wrapEnabled={true}
......
......@@ -27,3 +27,10 @@
.expression-editor-textfield .ace_hidden-cursors .ace_cursor {
opacity: 0;
}
.expression-editor-textfield .ace_content .error {
position: absolute;
border-bottom: 2px solid var(--color-error);
border-radius: 0px;
background-color: var(--color-error-background);
}
......@@ -50,10 +50,12 @@ describe("metabase/lib/expressions/tokenizer", () => {
expect(errors("2e")[0].message).toEqual("Missing exponent");
expect(errors("3e+")[0].message).toEqual("Missing exponent");
expect(errors("4E-")[0].message).toEqual("Missing exponent");
expect(errors("4E-")[0].len).toEqual(3);
});
it("should catch a lone decimal point", () => {
expect(errors(".")[0].message).toEqual("Invalid character: .");
expect(errors(".")[0].len).toEqual(1);
});
it("should tokenize string literals", () => {
......@@ -157,5 +159,6 @@ describe("metabase/lib/expressions/tokenizer", () => {
expect(errors("!")[0].message).toEqual("Invalid character: !");
expect(errors(" % @")[1].message).toEqual("Invalid character: @");
expect(errors(" #")[0].pos).toEqual(4);
expect(errors(" #")[0].len).toEqual(1);
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment