Skip to content

Commit

Permalink
fixes KXI-47774
Browse files Browse the repository at this point in the history
  • Loading branch information
ecmel committed Jun 4, 2024
1 parent 6384374 commit 7de4870
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 16 deletions.
9 changes: 4 additions & 5 deletions server/src/linter/checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
inLambda,
inParam,
ordered,
qualified,
} from "../parser";

export function deprecatedDatetime(tokens: Token[]): Token[] {
Expand All @@ -41,7 +42,6 @@ export function unusedParam(tokens: Token[]): Token[] {
!tokens.find(
(target) =>
!assigned(target) &&
assignable(target) &&
inLambda(target) === inLambda(token) &&
identifier(target) === identifier(token),
),
Expand All @@ -51,15 +51,15 @@ export function unusedParam(tokens: Token[]): Token[] {
export function unusedVar(tokens: Token[]): Token[] {
return tokens.filter(
(token) =>
!amended(token) &&
!inParam(token) &&
!amended(token) &&
!qualified(token) &&
inLambda(token) &&
assigned(token) &&
assignable(token) &&
!tokens.find(
(target) =>
!assigned(target) &&
assignable(target) &&
inLambda(target) === inLambda(token) &&
identifier(target) === identifier(token),
),
Expand All @@ -70,8 +70,8 @@ export function declaredAfterUse(tokens: Token[]): Token[] {
return tokens
.filter(
(token) =>
!inParam(token) &&
!amended(token) &&
!qualified(token) &&
assigned(token) &&
assignable(token),
)
Expand All @@ -87,7 +87,6 @@ export function declaredAfterUse(tokens: Token[]): Token[] {
tokens.find(
(target) =>
!assigned(target) &&
assignable(target) &&
inLambda(target) === inLambda(token) &&
identifier(target) === identifier(token) &&
ordered(target, token),
Expand Down
7 changes: 6 additions & 1 deletion server/src/parser/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
StringEscape,
TestBlock,
TestLambdaBlock,
Cond,
} from "./tokens";
import { TokenType } from "chevrotain";
import { writeFileSync } from "fs";
Expand Down Expand Up @@ -208,6 +209,10 @@ const repository = {
name: "keyword.other.iterator.q",
match: _(Iterator),
},
{
name: "keyword.operator.arithmetic.q",
match: _(Comparator),
},
{
name: "punctuation.assignment.q",
match: _(DoubleColon),
Expand All @@ -218,7 +223,7 @@ const repository = {
},
{
name: "keyword.operator.arithmetic.q",
match: _(Comparator),
match: _(Cond),
},
{
name: "punctuation.assignment.q",
Expand Down
4 changes: 3 additions & 1 deletion server/src/parser/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
TestBlock,
CommentEndOfLine,
TestLambdaBlock,
Cond,
} from "./tokens";
import {
CommentEnd,
Expand Down Expand Up @@ -89,9 +90,10 @@ const Language = [
Reserved,
Identifier,
Iterator,
Comparator,
DoubleColon,
Operator,
Comparator,
Cond,
Colon,
SemiColon,
LParen,
Expand Down
67 changes: 61 additions & 6 deletions server/src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ import {
TestLambdaBlock,
Colon,
DoubleColon,
Iterator,
Operator,
Cond,
} from "./tokens";
import {
CommentBegin,
CommentEnd,
ExitCommentBegin,
StringBegin,
StringEnd,
TestBegin,
} from "./ranges";
import { CharLiteral, CommentLiteral } from "./literals";
Expand Down Expand Up @@ -68,6 +73,7 @@ function peek(tokens: Token[]): Token | undefined {

interface State {
order: number;
exprs: number;
stack: Token[];
}

Expand All @@ -76,6 +82,7 @@ function assignment(state: State, token: Token) {

if (inParam(token)) {
token.assignment = [token, token];
token.order = 1;
} else {
let top = peek(stack);
if (top?.tokenType === Colon || top?.tokenType === DoubleColon) {
Expand All @@ -88,8 +95,8 @@ function assignment(state: State, token: Token) {
}
}
stack.push(token);
token.order = state.order++;
}
token.order = state.order++;
}

function block(state: State, tokens: Token[], scopped = true) {
Expand Down Expand Up @@ -162,6 +169,7 @@ function expression(state: State, tokens: Token[]) {
case LParen:
case LCurly:
case Control:
case Cond:
case Colon:
case DoubleColon:
case SemiColon:
Expand Down Expand Up @@ -193,6 +201,7 @@ export function parse(text: string): Token[] {

const state: State = {
order: 1,
exprs: 1,
stack: [],
};

Expand All @@ -214,6 +223,7 @@ export function parse(text: string): Token[] {
}
scope.push(token);
cache.push(token);
token.exprs = state.exprs;
break;
case TestBegin:
case TestBlock:
Expand All @@ -223,6 +233,7 @@ export function parse(text: string): Token[] {
case LSql:
scope.push(token);
cache.push(token);
token.exprs = state.exprs;
break;
case RParen:
case RBracket:
Expand All @@ -231,14 +242,39 @@ export function parse(text: string): Token[] {
next = scope.pop();
if (next) {
cache.push(token);
token.exprs = state.exprs;
}
break;
case StringBegin:
scope.push(token);
cache.push(token);
token.exprs = state.exprs;
token.escaped = '\\"';
break;
case StringEnd:
next = scope.pop();
if (next) {
cache.push(token);
token.exprs = state.exprs;
token.escaped = '\\"';
}
break;
case SemiColon:
token.exprs = state.exprs;
if (token.scope) {
cache.push(token);
} else {
expression(state, cache);
state.exprs++;
}
break;
case Operator:
case Iterator:
if (token.image.startsWith("\\")) {
token.escaped = `\\${token.image}`;
}
cache.push(token);
token.exprs = state.exprs;
break;
case EndOfLine:
next = tokens[i + 1];
Expand All @@ -250,7 +286,28 @@ export function parse(text: string): Token[] {
} else {
expression(state, cache);
}
token.escaped = ";";
token.exprs = state.exprs;
state.exprs++;
} else if (token.scope?.tokenType === StringBegin) {
token.exprs = state.exprs;
}
break;
case StringEscape:
checkEscape(token);
if (token.image === '\\"' || token.image === "\\\\") {
token.escaped = `\\\\${token.image}`;
}
token.exprs = state.exprs;
break;
case CharLiteral:
token.exprs = state.exprs;
break;
case WhiteSpace:
if (token.scope?.tokenType !== StringBegin) {
token.escaped = " ";
}
token.exprs = state.exprs;
break;
case Command: {
const [cmd, arg] = token.image.split(/[ \t]+/, 2);
Expand All @@ -261,16 +318,14 @@ export function parse(text: string): Token[] {
}
break;
}
token.exprs = state.exprs;
token.escaped = `system \\"${token.image.slice(1)}\\"`;
break;
}
case StringEscape:
checkEscape(token);
break;
case CharLiteral:
break;
default:
if (isExpression(token)) {
cache.push(token);
token.exprs = state.exprs;
}
break;
}
Expand Down
7 changes: 6 additions & 1 deletion server/src/parser/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ export const Comparator = createToken({

export const Operator = createToken({
name: "Operator",
pattern: /[\\.,'|^$?!#@&_%*+-]/,
pattern: /[\\.,'|^?!#@&_%*+-]/,
});

export const Cond = createToken({
name: "Cond",
pattern: /\$/,
});

export const Colon = createToken({
Expand Down
6 changes: 6 additions & 0 deletions server/src/parser/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export const enum SyntaxError {
export interface Token extends IToken {
index?: number;
order?: number;
exprs?: number;
escaped?: string;
namespace?: string;
scope?: Token;
tangled?: Token;
Expand Down Expand Up @@ -137,6 +139,10 @@ export function local(token: Token, tokens: Token[]) {
);
}

export function qualified(token: Token) {
return token.image.startsWith(".");
}

export function ordered(token: Token, next: Token) {
return (token.order && next.order && next.order > token.order) || false;
}
Expand Down
8 changes: 6 additions & 2 deletions syntaxes/q.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,21 @@
"name": "keyword.other.iterator.q",
"match": "[\\\\'/]:"
},
{
"name": "keyword.operator.arithmetic.q",
"match": "(?:<=|>=|<>|[>=<~])"
},
{
"name": "punctuation.assignment.q",
"match": "::"
},
{
"name": "keyword.operator.arithmetic.q",
"match": "[\\\\.,'|^$?!#@&_%*+-]"
"match": "[\\\\.,'|^?!#@&_%*+-]"
},
{
"name": "keyword.operator.arithmetic.q",
"match": "(?:<=|>=|<>|[>=<~])"
"match": "\\$"
},
{
"name": "punctuation.assignment.q",
Expand Down
20 changes: 20 additions & 0 deletions test/suite/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ describe("TSQLint", () => {
assert.strictEqual(result.length, 1);
assert.strictEqual(result[0].code, "UNUSED_PARAM");
});
it("should not lint unusedParam", () => {
const text = "{[a];([]b:a)}";
const result = lint(parse(text));
assert.strictEqual(result.length, 0);
});
it("should lint unusedVar", () => {
const text = "{a:1}";
const result = lint(parse(text));
Expand All @@ -70,6 +75,16 @@ describe("TSQLint", () => {
const result = lint(parse(text));
assert.strictEqual(result.length, 0);
});
it("should not lint unusedVar", () => {
const text = "{a:1;([]b:a)}";
const result = lint(parse(text));
assert.strictEqual(result.length, 0);
});
it("should not lint unusedVar", () => {
const text = "{.foo.a:1}";
const result = lint(parse(text));
assert.strictEqual(result.length, 0);
});
it("should lint declaredAfterUse", () => {
const text = "a;a:1";
const result = lint(parse(text));
Expand All @@ -96,4 +111,9 @@ describe("TSQLint", () => {
const result = lint(parse(text));
assert.strictEqual(result.length, 0);
});
it("should not lint declaredAfterUse", () => {
const text = "{[a]a;a:1}";
const result = lint(parse(text));
assert.strictEqual(result.length, 0);
});
});

0 comments on commit 7de4870

Please sign in to comment.