mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
fix: added fix for context breaking with spaces
This commit is contained in:
parent
e0582f6edb
commit
b0a2f64ebe
@ -17,37 +17,6 @@ import {
|
|||||||
} from './tokenUtils';
|
} from './tokenUtils';
|
||||||
import { NON_VALUE_OPERATORS } from 'constants/antlrQueryConstants';
|
import { NON_VALUE_OPERATORS } from 'constants/antlrQueryConstants';
|
||||||
|
|
||||||
// Function to normalize multiple spaces to single spaces when not in quotes
|
|
||||||
function normalizeSpaces(query: string): string {
|
|
||||||
let result = '';
|
|
||||||
let inQuotes = false;
|
|
||||||
let lastChar = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < query.length; i++) {
|
|
||||||
const char = query[i];
|
|
||||||
|
|
||||||
// Track quote state
|
|
||||||
if (char === "'" && (i === 0 || query[i - 1] !== '\\')) {
|
|
||||||
inQuotes = !inQuotes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're in quotes, always keep the original character
|
|
||||||
if (inQuotes) {
|
|
||||||
result += char;
|
|
||||||
}
|
|
||||||
// Otherwise, collapse multiple spaces to a single space
|
|
||||||
else if (char === ' ' && lastChar === ' ') {
|
|
||||||
// Skip this space (don't add it)
|
|
||||||
} else {
|
|
||||||
result += char;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastChar = char;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to create a context object
|
// Function to create a context object
|
||||||
export function createContext(
|
export function createContext(
|
||||||
token: Token,
|
token: Token,
|
||||||
@ -576,33 +545,8 @@ export function getQueryContextAtCursor(
|
|||||||
(isAtSpace && isAfterToken) ||
|
(isAtSpace && isAfterToken) ||
|
||||||
(cursorIndex === query.length && isAfterToken);
|
(cursorIndex === query.length && isAfterToken);
|
||||||
|
|
||||||
// First normalize the query to handle multiple spaces
|
|
||||||
// We need to adjust cursorIndex based on space normalization
|
|
||||||
let adjustedCursorIndex = cursorIndex;
|
|
||||||
let spaceCount = 0;
|
|
||||||
let inQuotes = false;
|
|
||||||
|
|
||||||
// Count consecutive spaces before the cursor to adjust the cursor position
|
|
||||||
for (let i = 0; i < cursorIndex; i++) {
|
|
||||||
// Track quote state
|
|
||||||
if (query[i] === "'" && (i === 0 || query[i - 1] !== '\\')) {
|
|
||||||
inQuotes = !inQuotes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only count spaces when not in quotes
|
|
||||||
if (!inQuotes && query[i] === ' ' && (i === 0 || query[i - 1] === ' ')) {
|
|
||||||
spaceCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust cursor position based on removed spaces
|
|
||||||
adjustedCursorIndex = cursorIndex - spaceCount;
|
|
||||||
|
|
||||||
// Normalize the query by removing extra spaces when not in quotes
|
|
||||||
const normalizedQuery = normalizeSpaces(query);
|
|
||||||
|
|
||||||
// Create input stream and lexer with normalized query
|
// Create input stream and lexer with normalized query
|
||||||
const input = normalizedQuery || '';
|
const input = query || '';
|
||||||
const chars = CharStreams.fromString(input);
|
const chars = CharStreams.fromString(input);
|
||||||
const lexer = new FilterQueryLexer(chars);
|
const lexer = new FilterQueryLexer(chars);
|
||||||
|
|
||||||
@ -626,15 +570,12 @@ export function getQueryContextAtCursor(
|
|||||||
|
|
||||||
// FIXED: Consider a token to be the lastTokenBeforeCursor if the cursor is
|
// FIXED: Consider a token to be the lastTokenBeforeCursor if the cursor is
|
||||||
// exactly at the end of the token (including the last character)
|
// exactly at the end of the token (including the last character)
|
||||||
if (
|
if (token.stop < cursorIndex || token.stop + 1 === cursorIndex) {
|
||||||
token.stop < adjustedCursorIndex ||
|
|
||||||
token.stop + 1 === adjustedCursorIndex
|
|
||||||
) {
|
|
||||||
lastTokenBeforeCursor = token;
|
lastTokenBeforeCursor = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we found a token that starts after the cursor, we're done searching
|
// If we found a token that starts after the cursor, we're done searching
|
||||||
if (token.start > adjustedCursorIndex) {
|
if (token.start > cursorIndex) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,13 +586,13 @@ export function getQueryContextAtCursor(
|
|||||||
// Find the current pair without causing a circular dependency
|
// Find the current pair without causing a circular dependency
|
||||||
let currentPair: IQueryPair | null = null;
|
let currentPair: IQueryPair | null = null;
|
||||||
if (queryPairs.length > 0) {
|
if (queryPairs.length > 0) {
|
||||||
currentPair = getCurrentQueryPair(queryPairs, query, adjustedCursorIndex);
|
currentPair = getCurrentQueryPair(queryPairs, query, cursorIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine precise context boundaries
|
// Determine precise context boundaries
|
||||||
const contextBoundaries = determineContextBoundaries(
|
const contextBoundaries = determineContextBoundaries(
|
||||||
query,
|
query,
|
||||||
adjustedCursorIndex,
|
cursorIndex,
|
||||||
allTokens,
|
allTokens,
|
||||||
queryPairs,
|
queryPairs,
|
||||||
);
|
);
|
||||||
@ -660,54 +601,54 @@ export function getQueryContextAtCursor(
|
|||||||
// FIXED: Include the case where the cursor is exactly at the end of a boundary
|
// FIXED: Include the case where the cursor is exactly at the end of a boundary
|
||||||
const isInKeyBoundary =
|
const isInKeyBoundary =
|
||||||
contextBoundaries.keyContext &&
|
contextBoundaries.keyContext &&
|
||||||
((adjustedCursorIndex >= contextBoundaries.keyContext.start &&
|
((cursorIndex >= contextBoundaries.keyContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.keyContext.end) ||
|
cursorIndex <= contextBoundaries.keyContext.end) ||
|
||||||
adjustedCursorIndex === contextBoundaries.keyContext.end + 1);
|
cursorIndex === contextBoundaries.keyContext.end + 1);
|
||||||
|
|
||||||
const isInNegationBoundary =
|
const isInNegationBoundary =
|
||||||
contextBoundaries.negationContext &&
|
contextBoundaries.negationContext &&
|
||||||
((adjustedCursorIndex >= contextBoundaries.negationContext.start &&
|
((cursorIndex >= contextBoundaries.negationContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.negationContext.end) ||
|
cursorIndex <= contextBoundaries.negationContext.end) ||
|
||||||
adjustedCursorIndex === contextBoundaries.negationContext.end + 1);
|
cursorIndex === contextBoundaries.negationContext.end + 1);
|
||||||
|
|
||||||
const isInOperatorBoundary =
|
const isInOperatorBoundary =
|
||||||
contextBoundaries.operatorContext &&
|
contextBoundaries.operatorContext &&
|
||||||
((adjustedCursorIndex >= contextBoundaries.operatorContext.start &&
|
((cursorIndex >= contextBoundaries.operatorContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.operatorContext.end) ||
|
cursorIndex <= contextBoundaries.operatorContext.end) ||
|
||||||
adjustedCursorIndex === contextBoundaries.operatorContext.end + 1);
|
cursorIndex === contextBoundaries.operatorContext.end + 1);
|
||||||
|
|
||||||
const isInValueBoundary =
|
const isInValueBoundary =
|
||||||
contextBoundaries.valueContext &&
|
contextBoundaries.valueContext &&
|
||||||
((adjustedCursorIndex >= contextBoundaries.valueContext.start &&
|
((cursorIndex >= contextBoundaries.valueContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.valueContext.end) ||
|
cursorIndex <= contextBoundaries.valueContext.end) ||
|
||||||
adjustedCursorIndex === contextBoundaries.valueContext.end + 1);
|
cursorIndex === contextBoundaries.valueContext.end + 1);
|
||||||
|
|
||||||
const isInConjunctionBoundary =
|
const isInConjunctionBoundary =
|
||||||
contextBoundaries.conjunctionContext &&
|
contextBoundaries.conjunctionContext &&
|
||||||
((adjustedCursorIndex >= contextBoundaries.conjunctionContext.start &&
|
((cursorIndex >= contextBoundaries.conjunctionContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.conjunctionContext.end) ||
|
cursorIndex <= contextBoundaries.conjunctionContext.end) ||
|
||||||
adjustedCursorIndex === contextBoundaries.conjunctionContext.end + 1);
|
cursorIndex === contextBoundaries.conjunctionContext.end + 1);
|
||||||
|
|
||||||
// Check for bracket list context (used for IN operator values)
|
// Check for bracket list context (used for IN operator values)
|
||||||
const isInBracketListBoundary =
|
const isInBracketListBoundary =
|
||||||
contextBoundaries.bracketContext &&
|
contextBoundaries.bracketContext &&
|
||||||
contextBoundaries.bracketContext.isForList &&
|
contextBoundaries.bracketContext.isForList &&
|
||||||
adjustedCursorIndex >= contextBoundaries.bracketContext.start &&
|
cursorIndex >= contextBoundaries.bracketContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.bracketContext.end + 1;
|
cursorIndex <= contextBoundaries.bracketContext.end + 1;
|
||||||
|
|
||||||
// Check for general parenthesis context (not for IN operator lists)
|
// Check for general parenthesis context (not for IN operator lists)
|
||||||
const isInParenthesisBoundary =
|
const isInParenthesisBoundary =
|
||||||
contextBoundaries.bracketContext &&
|
contextBoundaries.bracketContext &&
|
||||||
!contextBoundaries.bracketContext.isForList &&
|
!contextBoundaries.bracketContext.isForList &&
|
||||||
adjustedCursorIndex >= contextBoundaries.bracketContext.start &&
|
cursorIndex >= contextBoundaries.bracketContext.start &&
|
||||||
adjustedCursorIndex <= contextBoundaries.bracketContext.end + 1;
|
cursorIndex <= contextBoundaries.bracketContext.end + 1;
|
||||||
|
|
||||||
// Check if we're right after a closing bracket for a list (IN operator)
|
// Check if we're right after a closing bracket for a list (IN operator)
|
||||||
// This helps transition to conjunction context after a multi-value list
|
// This helps transition to conjunction context after a multi-value list
|
||||||
const isAfterClosingBracketList =
|
const isAfterClosingBracketList =
|
||||||
contextBoundaries.bracketContext &&
|
contextBoundaries.bracketContext &&
|
||||||
contextBoundaries.bracketContext.isForList &&
|
contextBoundaries.bracketContext.isForList &&
|
||||||
adjustedCursorIndex === contextBoundaries.bracketContext.end + 2 &&
|
cursorIndex === contextBoundaries.bracketContext.end + 2 &&
|
||||||
query[contextBoundaries.bracketContext.end + 1] === ' ';
|
query[contextBoundaries.bracketContext.end + 1] === ' ';
|
||||||
|
|
||||||
// If cursor is within a specific context boundary, this takes precedence
|
// If cursor is within a specific context boundary, this takes precedence
|
||||||
@ -741,8 +682,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: -1,
|
tokenType: -1,
|
||||||
text: '',
|
text: '',
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: '',
|
currentToken: '',
|
||||||
isInKey: isInKeyBoundary || false,
|
isInKey: isInKeyBoundary || false,
|
||||||
isInNegation: isInNegationBoundary || false,
|
isInNegation: isInNegationBoundary || false,
|
||||||
@ -770,7 +711,7 @@ export function getQueryContextAtCursor(
|
|||||||
|
|
||||||
// Continue with existing token-based logic for cases not covered by context boundaries
|
// Continue with existing token-based logic for cases not covered by context boundaries
|
||||||
// Handle cursor at the very end of input
|
// Handle cursor at the very end of input
|
||||||
if (adjustedCursorIndex >= input.length && allTokens.length > 0) {
|
if (cursorIndex >= input.length && allTokens.length > 0) {
|
||||||
const lastRealToken = allTokens
|
const lastRealToken = allTokens
|
||||||
.filter((t) => t.type !== FilterQueryLexer.EOF)
|
.filter((t) => t.type !== FilterQueryLexer.EOF)
|
||||||
.pop();
|
.pop();
|
||||||
@ -789,10 +730,7 @@ export function getQueryContextAtCursor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXED: Check if cursor is within token bounds (inclusive) or exactly at the end
|
// FIXED: Check if cursor is within token bounds (inclusive) or exactly at the end
|
||||||
if (
|
if (token.start <= cursorIndex && cursorIndex <= token.stop + 1) {
|
||||||
token.start <= adjustedCursorIndex &&
|
|
||||||
adjustedCursorIndex <= token.stop + 1
|
|
||||||
) {
|
|
||||||
exactToken = token;
|
exactToken = token;
|
||||||
previousToken = i > 0 ? allTokens[i - 1] : null;
|
previousToken = i > 0 ? allTokens[i - 1] : null;
|
||||||
nextToken = i < allTokens.length - 1 ? allTokens[i + 1] : null;
|
nextToken = i < allTokens.length - 1 ? allTokens[i + 1] : null;
|
||||||
@ -812,10 +750,7 @@ export function getQueryContextAtCursor(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (current.stop + 1 < cursorIndex && cursorIndex < next.start) {
|
||||||
current.stop + 1 < adjustedCursorIndex &&
|
|
||||||
adjustedCursorIndex < next.start
|
|
||||||
) {
|
|
||||||
previousToken = current;
|
previousToken = current;
|
||||||
nextToken = next;
|
nextToken = next;
|
||||||
break;
|
break;
|
||||||
@ -829,8 +764,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: -1,
|
tokenType: -1,
|
||||||
text: '',
|
text: '',
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: '',
|
currentToken: '',
|
||||||
isInKey: true, // Default to key context when input is empty
|
isInKey: true, // Default to key context when input is empty
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -859,8 +794,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: lastTokenBeforeCursor.type,
|
tokenType: lastTokenBeforeCursor.type,
|
||||||
text: lastTokenBeforeCursor.text,
|
text: lastTokenBeforeCursor.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: lastTokenBeforeCursor.text,
|
currentToken: lastTokenBeforeCursor.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -880,8 +815,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: lastTokenBeforeCursor.type,
|
tokenType: lastTokenBeforeCursor.type,
|
||||||
text: lastTokenBeforeCursor.text,
|
text: lastTokenBeforeCursor.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: lastTokenBeforeCursor.text,
|
currentToken: lastTokenBeforeCursor.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -904,8 +839,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: lastTokenBeforeCursor.type,
|
tokenType: lastTokenBeforeCursor.type,
|
||||||
text: lastTokenBeforeCursor.text,
|
text: lastTokenBeforeCursor.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: lastTokenBeforeCursor.text,
|
currentToken: lastTokenBeforeCursor.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -929,8 +864,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: lastTokenBeforeCursor.type,
|
tokenType: lastTokenBeforeCursor.type,
|
||||||
text: lastTokenBeforeCursor.text,
|
text: lastTokenBeforeCursor.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: lastTokenBeforeCursor.text,
|
currentToken: lastTokenBeforeCursor.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -953,8 +888,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: lastTokenBeforeCursor.type,
|
tokenType: lastTokenBeforeCursor.type,
|
||||||
text: lastTokenBeforeCursor.text,
|
text: lastTokenBeforeCursor.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: lastTokenBeforeCursor.text,
|
currentToken: lastTokenBeforeCursor.text,
|
||||||
isInKey: true, // After conjunction + space, should be key context
|
isInKey: true, // After conjunction + space, should be key context
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -972,7 +907,7 @@ export function getQueryContextAtCursor(
|
|||||||
|
|
||||||
// FIXED: Consider the case where the cursor is at the end of a token
|
// FIXED: Consider the case where the cursor is at the end of a token
|
||||||
// with no space yet (user is actively typing)
|
// with no space yet (user is actively typing)
|
||||||
if (exactToken && adjustedCursorIndex === exactToken.stop + 1) {
|
if (exactToken && cursorIndex === exactToken.stop + 1) {
|
||||||
const tokenContext = determineTokenContext(exactToken, input);
|
const tokenContext = determineTokenContext(exactToken, input);
|
||||||
|
|
||||||
// When the cursor is at the end of a token, return the current token context
|
// When the cursor is at the end of a token, return the current token context
|
||||||
@ -1047,8 +982,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: previousToken.type,
|
tokenType: previousToken.type,
|
||||||
text: previousToken.text,
|
text: previousToken.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: previousToken.text,
|
currentToken: previousToken.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -1070,8 +1005,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: previousToken.type,
|
tokenType: previousToken.type,
|
||||||
text: previousToken.text,
|
text: previousToken.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: previousToken.text,
|
currentToken: previousToken.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -1091,8 +1026,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: previousToken.type,
|
tokenType: previousToken.type,
|
||||||
text: previousToken.text,
|
text: previousToken.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: previousToken.text,
|
currentToken: previousToken.text,
|
||||||
isInKey: false,
|
isInKey: false,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -1114,8 +1049,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: previousToken.type,
|
tokenType: previousToken.type,
|
||||||
text: previousToken.text,
|
text: previousToken.text,
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: previousToken.text,
|
currentToken: previousToken.text,
|
||||||
isInKey: true, // After conjunction, progress back to key context
|
isInKey: true, // After conjunction, progress back to key context
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -1135,8 +1070,8 @@ export function getQueryContextAtCursor(
|
|||||||
return {
|
return {
|
||||||
tokenType: -1,
|
tokenType: -1,
|
||||||
text: '',
|
text: '',
|
||||||
start: adjustedCursorIndex,
|
start: cursorIndex,
|
||||||
stop: adjustedCursorIndex,
|
stop: cursorIndex,
|
||||||
currentToken: '',
|
currentToken: '',
|
||||||
isInKey: true,
|
isInKey: true,
|
||||||
isInNegation: false,
|
isInNegation: false,
|
||||||
@ -1188,11 +1123,8 @@ export function extractQueryPairs(query: string): IQueryPair[] {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize the query to handle multiple spaces
|
|
||||||
const normalizedQuery = normalizeSpaces(query);
|
|
||||||
|
|
||||||
// Create input stream and lexer with normalized query
|
// Create input stream and lexer with normalized query
|
||||||
const input = normalizedQuery || '';
|
const input = query || '';
|
||||||
const chars = CharStreams.fromString(input);
|
const chars = CharStreams.fromString(input);
|
||||||
const lexer = new FilterQueryLexer(chars);
|
const lexer = new FilterQueryLexer(chars);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user