mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CloudWatch Logs: Add getStatementPosition function for Monaco editor (#70724)
* CloudWatch Logs: Add getStatementPosition function for Monaco editor * Add test cases * add command and function arg positions * remove unneeded statement position * remove debug stuff * remove unneeded cases * add filterarg * remove editor changes * fix tests * fix lint * add debug for testing * Revert "add debug for testing" This reverts commit 22dd0e7a77eb43dbed7c065c246da04cddfa1afc.
This commit is contained in:
parent
dd41c7c262
commit
31e142633d
@ -0,0 +1,11 @@
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { LogsTokenTypes } from '../../language/logs/completion/types';
|
||||
import { CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID } from '../../language/logs/definition';
|
||||
|
||||
export const commentOnlyQuery = {
|
||||
query: `# comment ending with whitespace `,
|
||||
tokens: [
|
||||
[{ offset: 0, type: LogsTokenTypes.Comment, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID }],
|
||||
] as monacoTypes.Token[][],
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
export const emptyQuery = {
|
||||
query: '',
|
||||
tokens: [],
|
||||
position: { lineNumber: 1, column: 1 },
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
export { emptyQuery } from './empty';
|
||||
export { whitespaceOnlyQuery } from './whitespaceQuery';
|
||||
export { commentOnlyQuery } from './commentOnlyQuery';
|
||||
export { singleLineFullQuery } from './singleLineFullQuery';
|
||||
export { multiLineFullQuery } from './multiLineFullQuery';
|
@ -0,0 +1,109 @@
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { LogsTokenTypes } from '../../language/logs/completion/types';
|
||||
import { CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID } from '../../language/logs/definition';
|
||||
|
||||
export const multiLineFullQuery = {
|
||||
query: `fields @timestamp, unmask(@message) as msg, @memorySize
|
||||
| filter (@message like /error/ and bytes > 1000)
|
||||
| parse @message /(?<NetworkInterface>eni-.*?)/
|
||||
| stats count(NetworkInterface), max(@memorySize / 1000 / 1000) as provisonedMemoryMB by bin(1m)
|
||||
# this is a comment with the next line left being intentionally blank
|
||||
|
||||
| limit 20`,
|
||||
tokens: [
|
||||
[
|
||||
{ offset: 0, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 6, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 7, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 17, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 18, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 19, type: LogsTokenTypes.Function, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 25, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 26, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 34, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 35, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 36, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 38, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 39, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 42, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 43, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 44, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
],
|
||||
[
|
||||
{ offset: 0, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 1, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 2, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 8, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 9, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 10, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 18, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 19, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 26, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 27, type: LogsTokenTypes.Regexp, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 31, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 32, type: LogsTokenTypes.Operator, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 35, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 36, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 41, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 42, type: LogsTokenTypes.Operator, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 43, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 44, type: LogsTokenTypes.Number, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 48, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
],
|
||||
[
|
||||
{ offset: 0, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 1, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 2, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 7, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 8, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 16, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 17, type: LogsTokenTypes.Regexp, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
],
|
||||
[
|
||||
{ offset: 0, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 1, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 2, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 7, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 8, type: LogsTokenTypes.Function, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 13, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 14, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 30, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 31, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 32, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 33, type: LogsTokenTypes.Function, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 36, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 37, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 48, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 49, type: LogsTokenTypes.Operator, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 50, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 51, type: LogsTokenTypes.Number, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 55, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 56, type: LogsTokenTypes.Operator, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 57, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 58, type: LogsTokenTypes.Number, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 62, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 63, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 64, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 66, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 67, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 85, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 86, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 88, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 89, type: LogsTokenTypes.Function, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 92, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 93, type: LogsTokenTypes.Number, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 94, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 95, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
],
|
||||
[{ offset: 0, type: LogsTokenTypes.Comment, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID }],
|
||||
[{ offset: 0, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID }],
|
||||
[
|
||||
{ offset: 0, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 1, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 2, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 7, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 8, type: LogsTokenTypes.Number, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
],
|
||||
] as monacoTypes.Token[][],
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { LogsTokenTypes } from '../../language/logs/completion/types';
|
||||
import { CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID } from '../../language/logs/definition';
|
||||
|
||||
export const singleLineFullQuery = {
|
||||
query: `fields @timestamp, @message | limit 20 # this is a comment`,
|
||||
tokens: [
|
||||
[
|
||||
{ offset: 0, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 6, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 7, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 17, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 18, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 19, type: LogsTokenTypes.Identifier, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 27, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 28, type: LogsTokenTypes.Delimiter, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 29, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 30, type: LogsTokenTypes.Keyword, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 35, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 36, type: LogsTokenTypes.Number, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 38, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
{ offset: 39, type: LogsTokenTypes.Comment, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID },
|
||||
],
|
||||
] as monacoTypes.Token[][],
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { LogsTokenTypes } from '../../language/logs/completion/types';
|
||||
import { CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID } from '../../language/logs/definition';
|
||||
|
||||
export const whitespaceOnlyQuery = {
|
||||
query: ` `,
|
||||
tokens: [
|
||||
[{ offset: 0, type: LogsTokenTypes.Whitespace, language: CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID }],
|
||||
] as monacoTypes.Token[][],
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { Monaco } from '../../language/monarch/types';
|
||||
import * as CloudwatchLogsTestData from '../cloudwatch-logs-test-data';
|
||||
import * as SQLTestData from '../cloudwatch-sql-test-data';
|
||||
import * as DynamicLabelTestData from '../dynamic-label-test-data';
|
||||
import * as MetricMathTestData from '../metric-math-test-data';
|
||||
@ -39,6 +40,16 @@ const MonacoMock: Monaco = {
|
||||
};
|
||||
return TestData[value];
|
||||
}
|
||||
if (languageId === 'cloudwatch-logs') {
|
||||
const TestData = {
|
||||
[CloudwatchLogsTestData.emptyQuery.query]: CloudwatchLogsTestData.emptyQuery.tokens,
|
||||
[CloudwatchLogsTestData.whitespaceOnlyQuery.query]: CloudwatchLogsTestData.whitespaceOnlyQuery.tokens,
|
||||
[CloudwatchLogsTestData.commentOnlyQuery.query]: CloudwatchLogsTestData.commentOnlyQuery.tokens,
|
||||
[CloudwatchLogsTestData.singleLineFullQuery.query]: CloudwatchLogsTestData.singleLineFullQuery.tokens,
|
||||
[CloudwatchLogsTestData.multiLineFullQuery.query]: CloudwatchLogsTestData.multiLineFullQuery.tokens,
|
||||
};
|
||||
return TestData[value];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
|
@ -0,0 +1,157 @@
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import {
|
||||
emptyQuery,
|
||||
whitespaceOnlyQuery,
|
||||
commentOnlyQuery,
|
||||
singleLineFullQuery,
|
||||
multiLineFullQuery,
|
||||
} from '../../../__mocks__/cloudwatch-logs-test-data';
|
||||
import MonacoMock from '../../../__mocks__/monarch/Monaco';
|
||||
import TextModel from '../../../__mocks__/monarch/TextModel';
|
||||
import { linkedTokenBuilder } from '../../monarch/linkedTokenBuilder';
|
||||
import { StatementPosition } from '../../monarch/types';
|
||||
import cloudWatchLogsLanguageDefinition from '../definition';
|
||||
|
||||
import { getStatementPosition } from './statementPosition';
|
||||
import { LogsTokenTypes } from './types';
|
||||
|
||||
function generateToken(query: string, position: monacoTypes.IPosition) {
|
||||
const testModel = TextModel(query);
|
||||
return linkedTokenBuilder(
|
||||
MonacoMock,
|
||||
cloudWatchLogsLanguageDefinition,
|
||||
testModel as monacoTypes.editor.ITextModel,
|
||||
position,
|
||||
LogsTokenTypes
|
||||
);
|
||||
}
|
||||
|
||||
describe('getStatementPosition', () => {
|
||||
it('should return StatementPosition.NewCommand the current token is null', () => {
|
||||
expect(getStatementPosition(null)).toEqual(StatementPosition.NewCommand);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.NewCommand for an empty query', () => {
|
||||
expect(getStatementPosition(generateToken(emptyQuery.query, { lineNumber: 1, column: 1 }))).toEqual(
|
||||
StatementPosition.NewCommand
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.NewCommand for a query that is only whitespace', () => {
|
||||
expect(getStatementPosition(generateToken(whitespaceOnlyQuery.query, { lineNumber: 1, column: 1 }))).toEqual(
|
||||
StatementPosition.NewCommand
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.Comment for a query with only a comment', () => {
|
||||
expect(getStatementPosition(generateToken(commentOnlyQuery.query, { lineNumber: 1, column: 1 }))).toEqual(
|
||||
StatementPosition.Comment
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.NewCommand after a `|`', () => {
|
||||
expect(getStatementPosition(generateToken(singleLineFullQuery.query, { lineNumber: 1, column: 30 }))).toEqual(
|
||||
StatementPosition.NewCommand
|
||||
);
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 2, column: 2 }))).toEqual(
|
||||
StatementPosition.NewCommand
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.FieldsKeyword inside the `fields` keyword', () => {
|
||||
expect(getStatementPosition(generateToken(singleLineFullQuery.query, { lineNumber: 1, column: 6 }))).toEqual(
|
||||
StatementPosition.FieldsKeyword
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.AfterFieldsKeyword after the `fields` keyword', () => {
|
||||
expect(getStatementPosition(generateToken(singleLineFullQuery.query, { lineNumber: 1, column: 7 }))).toEqual(
|
||||
StatementPosition.AfterFieldsKeyword
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.CommandArg after a keyword', () => {
|
||||
expect(getStatementPosition(generateToken(singleLineFullQuery.query, { lineNumber: 1, column: 8 }))).toEqual(
|
||||
StatementPosition.CommandArg
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.AfterCommand after a function', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 2, column: 49 }))).toEqual(
|
||||
StatementPosition.AfterCommand
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.Function within a function', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 9 }))).toEqual(
|
||||
StatementPosition.Function
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.FunctionArg when providing arguments to a function', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 16 }))).toEqual(
|
||||
StatementPosition.FunctionArg
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.AfterFunction after a function', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 64 }))).toEqual(
|
||||
StatementPosition.AfterFunction
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.ArithmeticOperatorArg after an arithmetic operator', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 51 }))).toEqual(
|
||||
StatementPosition.ArithmeticOperatorArg
|
||||
);
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 58 }))).toEqual(
|
||||
StatementPosition.ArithmeticOperatorArg
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.BooleanOperatorArg after a boolean operator', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 2, column: 37 }))).toEqual(
|
||||
StatementPosition.BooleanOperatorArg
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.ComparisonOperatorArg after a comparison operator', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 2, column: 44 }))).toEqual(
|
||||
StatementPosition.ComparisonOperatorArg
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.ArithmeticOperator after an arithmetic operator', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 50 }))).toEqual(
|
||||
StatementPosition.ArithmeticOperator
|
||||
);
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 4, column: 57 }))).toEqual(
|
||||
StatementPosition.ArithmeticOperator
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.BooleanOperator after a boolean operator', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 2, column: 35 }))).toEqual(
|
||||
StatementPosition.BooleanOperator
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.ComparisonOperator after a comparison operator', () => {
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 2, column: 43 }))).toEqual(
|
||||
StatementPosition.ComparisonOperator
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.Comment when token is a comment', () => {
|
||||
expect(getStatementPosition(generateToken(singleLineFullQuery.query, { lineNumber: 1, column: 40 }))).toEqual(
|
||||
StatementPosition.Comment
|
||||
);
|
||||
expect(getStatementPosition(generateToken(commentOnlyQuery.query, { lineNumber: 1, column: 35 }))).toEqual(
|
||||
StatementPosition.Comment
|
||||
);
|
||||
expect(getStatementPosition(generateToken(multiLineFullQuery.query, { lineNumber: 5, column: 3 }))).toEqual(
|
||||
StatementPosition.Comment
|
||||
);
|
||||
});
|
||||
});
|
@ -0,0 +1,203 @@
|
||||
import { LinkedToken } from '../../monarch/LinkedToken';
|
||||
import { StatementPosition } from '../../monarch/types';
|
||||
import {
|
||||
DISPLAY,
|
||||
FIELDS,
|
||||
FILTER,
|
||||
STATS,
|
||||
SORT,
|
||||
LIMIT,
|
||||
PARSE,
|
||||
DEDUP,
|
||||
LOGS_COMMANDS,
|
||||
LOGS_FUNCTION_OPERATORS,
|
||||
LOGS_LOGIC_OPERATORS,
|
||||
} from '../language';
|
||||
|
||||
import { LogsTokenTypes } from './types';
|
||||
|
||||
export const getStatementPosition = (currentToken: LinkedToken | null): StatementPosition => {
|
||||
const previousNonWhiteSpace = currentToken?.getPreviousNonWhiteSpaceToken();
|
||||
const nextNonWhiteSpace = currentToken?.getNextNonWhiteSpaceToken();
|
||||
|
||||
const normalizedCurrentToken = currentToken?.value?.toLowerCase();
|
||||
const normalizedPreviousNonWhiteSpace = previousNonWhiteSpace?.value?.toLowerCase();
|
||||
|
||||
if (currentToken?.is(LogsTokenTypes.Comment)) {
|
||||
return StatementPosition.Comment;
|
||||
}
|
||||
|
||||
if (currentToken?.isFunction()) {
|
||||
return StatementPosition.Function;
|
||||
}
|
||||
|
||||
if (
|
||||
currentToken === null ||
|
||||
(currentToken?.isWhiteSpace() && previousNonWhiteSpace === null && nextNonWhiteSpace === null) ||
|
||||
(previousNonWhiteSpace?.is(LogsTokenTypes.Delimiter, '|') && currentToken?.isWhiteSpace()) ||
|
||||
(currentToken?.isIdentifier() &&
|
||||
(previousNonWhiteSpace?.is(LogsTokenTypes.Delimiter, '|') || previousNonWhiteSpace === null))
|
||||
) {
|
||||
return StatementPosition.NewCommand;
|
||||
}
|
||||
|
||||
if (
|
||||
currentToken?.is(LogsTokenTypes.Delimiter, ')') ||
|
||||
(currentToken?.isWhiteSpace() && previousNonWhiteSpace?.is(LogsTokenTypes.Delimiter, ')'))
|
||||
) {
|
||||
const openingParenthesis = currentToken?.getPreviousOfType(LogsTokenTypes.Delimiter, '(');
|
||||
const normalizedNonWhitespacePreceedingOpeningParenthesis = openingParenthesis
|
||||
?.getPreviousNonWhiteSpaceToken()
|
||||
?.value?.toLowerCase();
|
||||
|
||||
if (normalizedNonWhitespacePreceedingOpeningParenthesis) {
|
||||
if (LOGS_COMMANDS.includes(normalizedNonWhitespacePreceedingOpeningParenthesis)) {
|
||||
return StatementPosition.AfterCommand;
|
||||
}
|
||||
if (LOGS_FUNCTION_OPERATORS.includes(normalizedNonWhitespacePreceedingOpeningParenthesis)) {
|
||||
return StatementPosition.AfterFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentToken?.isKeyword() && normalizedCurrentToken) {
|
||||
switch (normalizedCurrentToken) {
|
||||
case DEDUP:
|
||||
return StatementPosition.DedupKeyword;
|
||||
case DISPLAY:
|
||||
return StatementPosition.DisplayKeyword;
|
||||
case FIELDS:
|
||||
return StatementPosition.FieldsKeyword;
|
||||
case FILTER:
|
||||
return StatementPosition.FilterKeyword;
|
||||
case LIMIT:
|
||||
return StatementPosition.LimitKeyword;
|
||||
case PARSE:
|
||||
return StatementPosition.ParseKeyword;
|
||||
case STATS:
|
||||
return StatementPosition.StatsKeyword;
|
||||
case SORT:
|
||||
return StatementPosition.SortKeyword;
|
||||
case 'as':
|
||||
return StatementPosition.AsKeyword;
|
||||
case 'by':
|
||||
return StatementPosition.ByKeyword;
|
||||
case 'in':
|
||||
return StatementPosition.InKeyword;
|
||||
case 'like':
|
||||
return StatementPosition.LikeKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentToken?.isWhiteSpace() && previousNonWhiteSpace?.isKeyword && normalizedPreviousNonWhiteSpace) {
|
||||
switch (normalizedPreviousNonWhiteSpace) {
|
||||
case DEDUP:
|
||||
return StatementPosition.AfterDedupKeyword;
|
||||
case DISPLAY:
|
||||
return StatementPosition.AfterDisplayKeyword;
|
||||
case FIELDS:
|
||||
return StatementPosition.AfterFieldsKeyword;
|
||||
case FILTER:
|
||||
return StatementPosition.AfterFilterKeyword;
|
||||
case LIMIT:
|
||||
return StatementPosition.AfterLimitKeyword;
|
||||
case PARSE:
|
||||
return StatementPosition.AfterParseKeyword;
|
||||
case STATS:
|
||||
return StatementPosition.AfterStatsKeyword;
|
||||
case SORT:
|
||||
return StatementPosition.AfterSortKeyword;
|
||||
case 'as':
|
||||
return StatementPosition.AfterAsKeyword;
|
||||
case 'by':
|
||||
return StatementPosition.AfterByKeyword;
|
||||
case 'in':
|
||||
return StatementPosition.AfterInKeyword;
|
||||
case 'like':
|
||||
return StatementPosition.AfterLikeKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentToken?.is(LogsTokenTypes.Operator) && normalizedCurrentToken) {
|
||||
if (['+', '-', '*', '/', '^', '%'].includes(normalizedCurrentToken)) {
|
||||
return StatementPosition.ArithmeticOperator;
|
||||
}
|
||||
|
||||
if (['=', '!=', '<', '>', '<=', '>='].includes(normalizedCurrentToken)) {
|
||||
return StatementPosition.ComparisonOperator;
|
||||
}
|
||||
|
||||
if (LOGS_LOGIC_OPERATORS.includes(normalizedCurrentToken)) {
|
||||
return StatementPosition.BooleanOperator;
|
||||
}
|
||||
}
|
||||
|
||||
if (previousNonWhiteSpace?.is(LogsTokenTypes.Operator) && normalizedPreviousNonWhiteSpace) {
|
||||
if (['+', '-', '*', '/', '^', '%'].includes(normalizedPreviousNonWhiteSpace)) {
|
||||
return StatementPosition.ArithmeticOperatorArg;
|
||||
}
|
||||
|
||||
if (['=', '!=', '<', '>', '<=', '>='].includes(normalizedPreviousNonWhiteSpace)) {
|
||||
return StatementPosition.ComparisonOperatorArg;
|
||||
}
|
||||
|
||||
if (LOGS_LOGIC_OPERATORS.includes(normalizedPreviousNonWhiteSpace)) {
|
||||
return StatementPosition.BooleanOperatorArg;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
currentToken?.isIdentifier() ||
|
||||
currentToken?.isNumber() ||
|
||||
currentToken?.is(LogsTokenTypes.Parenthesis, '()') ||
|
||||
currentToken?.is(LogsTokenTypes.Delimiter, ',') ||
|
||||
currentToken?.is(LogsTokenTypes.Parenthesis, ')') ||
|
||||
(currentToken?.isWhiteSpace() && previousNonWhiteSpace?.is(LogsTokenTypes.Delimiter, ',')) ||
|
||||
(currentToken?.isWhiteSpace() && previousNonWhiteSpace?.isIdentifier()) ||
|
||||
(currentToken?.isWhiteSpace() &&
|
||||
previousNonWhiteSpace?.isKeyword() &&
|
||||
normalizedPreviousNonWhiteSpace &&
|
||||
LOGS_COMMANDS.includes(normalizedPreviousNonWhiteSpace))
|
||||
) {
|
||||
const nearestKeyword = currentToken?.getPreviousOfType(LogsTokenTypes.Keyword);
|
||||
const nearestFunction = currentToken?.getPreviousOfType(LogsTokenTypes.Function);
|
||||
|
||||
if (nearestKeyword !== null && nearestFunction === null) {
|
||||
if (nearestKeyword.value === SORT) {
|
||||
return StatementPosition.SortArg;
|
||||
}
|
||||
if (nearestKeyword.value === FILTER) {
|
||||
return StatementPosition.FilterArg;
|
||||
}
|
||||
return StatementPosition.CommandArg;
|
||||
}
|
||||
|
||||
if (nearestFunction !== null && nearestKeyword === null) {
|
||||
return StatementPosition.FunctionArg;
|
||||
}
|
||||
|
||||
if (nearestKeyword !== null && nearestFunction !== null) {
|
||||
if (
|
||||
nearestKeyword.range.startLineNumber > nearestFunction.range.startLineNumber ||
|
||||
nearestKeyword.range.endColumn > nearestFunction.range.endColumn
|
||||
) {
|
||||
if (nearestKeyword.value === SORT) {
|
||||
return StatementPosition.SortArg;
|
||||
}
|
||||
if (nearestKeyword.value === FILTER) {
|
||||
return StatementPosition.FilterArg;
|
||||
}
|
||||
return StatementPosition.CommandArg;
|
||||
}
|
||||
|
||||
if (
|
||||
nearestFunction.range.startLineNumber > nearestKeyword.range.startLineNumber ||
|
||||
nearestFunction.range.endColumn > nearestKeyword.range.endColumn
|
||||
) {
|
||||
return StatementPosition.FunctionArg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return StatementPosition.Unknown;
|
||||
};
|
@ -45,6 +45,49 @@ export enum StatementPosition {
|
||||
PredefinedFuncSecondArg,
|
||||
AfterFunction,
|
||||
WithinString,
|
||||
// logs
|
||||
NewCommand,
|
||||
Comment,
|
||||
|
||||
DedupKeyword,
|
||||
AfterDedupKeyword,
|
||||
DisplayKeyword,
|
||||
AfterDisplayKeyword,
|
||||
FieldsKeyword,
|
||||
AfterFieldsKeyword,
|
||||
FilterKeyword,
|
||||
AfterFilterKeyword,
|
||||
FilterArg,
|
||||
LimitKeyword,
|
||||
AfterLimitKeyword,
|
||||
ParseKeyword,
|
||||
AfterParseKeyword,
|
||||
SortKeyword,
|
||||
AfterSortKeyword,
|
||||
SortArg,
|
||||
StatsKeyword,
|
||||
AfterStatsKeyword,
|
||||
|
||||
AsKeyword,
|
||||
AfterAsKeyword,
|
||||
ByKeyword,
|
||||
AfterByKeyword,
|
||||
InKeyword,
|
||||
AfterInKeyword,
|
||||
LikeKeyword,
|
||||
AfterLikeKeyword,
|
||||
|
||||
Function,
|
||||
FunctionArg,
|
||||
CommandArg,
|
||||
AfterCommand,
|
||||
|
||||
ArithmeticOperator,
|
||||
ArithmeticOperatorArg,
|
||||
BooleanOperator,
|
||||
BooleanOperatorArg,
|
||||
ComparisonOperator,
|
||||
ComparisonOperatorArg,
|
||||
}
|
||||
|
||||
export enum SuggestionKind {
|
||||
|
Loading…
Reference in New Issue
Block a user