mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-23 00:35:51 +00:00
style: 完成所有文件的lint
This commit is contained in:
@@ -1,19 +1,16 @@
|
||||
import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'
|
||||
import React from 'react'
|
||||
import { CtrlOToExpand } from 'src/components/CtrlOToExpand.js'
|
||||
import { FallbackToolUseErrorMessage } from 'src/components/FallbackToolUseErrorMessage.js'
|
||||
import { MessageResponse } from 'src/components/MessageResponse.js'
|
||||
import { Box, Text } from '@anthropic/ink'
|
||||
import { getDisplayPath } from 'src/utils/file.js'
|
||||
import { extractTag } from 'src/utils/messages.js'
|
||||
import type { Input, Output } from './LSPTool.js'
|
||||
import { getSymbolAtPosition } from './symbolContext.js'
|
||||
import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs';
|
||||
import React from 'react';
|
||||
import { CtrlOToExpand } from 'src/components/CtrlOToExpand.js';
|
||||
import { FallbackToolUseErrorMessage } from 'src/components/FallbackToolUseErrorMessage.js';
|
||||
import { MessageResponse } from 'src/components/MessageResponse.js';
|
||||
import { Box, Text } from '@anthropic/ink';
|
||||
import { getDisplayPath } from 'src/utils/file.js';
|
||||
import { extractTag } from 'src/utils/messages.js';
|
||||
import type { Input, Output } from './LSPTool.js';
|
||||
import { getSymbolAtPosition } from './symbolContext.js';
|
||||
|
||||
// Lookup map for operation-specific labels
|
||||
const OPERATION_LABELS: Record<
|
||||
Input['operation'],
|
||||
{ singular: string; plural: string; special?: string }
|
||||
> = {
|
||||
const OPERATION_LABELS: Record<Input['operation'], { singular: string; plural: string; special?: string }> = {
|
||||
goToDefinition: { singular: 'definition', plural: 'definitions' },
|
||||
findReferences: { singular: 'reference', plural: 'references' },
|
||||
documentSymbol: { singular: 'symbol', plural: 'symbols' },
|
||||
@@ -23,7 +20,7 @@ const OPERATION_LABELS: Record<
|
||||
prepareCallHierarchy: { singular: 'call item', plural: 'call items' },
|
||||
incomingCalls: { singular: 'caller', plural: 'callers' },
|
||||
outgoingCalls: { singular: 'callee', plural: 'callees' },
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reusable component for LSP result summaries with collapsed/expanded views
|
||||
@@ -35,19 +32,18 @@ function LSPResultSummary({
|
||||
content,
|
||||
verbose,
|
||||
}: {
|
||||
operation: Input['operation']
|
||||
resultCount: number
|
||||
fileCount: number
|
||||
content: string
|
||||
verbose: boolean
|
||||
operation: Input['operation'];
|
||||
resultCount: number;
|
||||
fileCount: number;
|
||||
content: string;
|
||||
verbose: boolean;
|
||||
}): React.ReactNode {
|
||||
// Get label configuration for this operation
|
||||
const labelConfig = OPERATION_LABELS[operation] || {
|
||||
singular: 'result',
|
||||
plural: 'results',
|
||||
}
|
||||
const countLabel =
|
||||
resultCount === 1 ? labelConfig.singular : labelConfig.plural
|
||||
};
|
||||
const countLabel = resultCount === 1 ? labelConfig.singular : labelConfig.plural;
|
||||
|
||||
const primaryText =
|
||||
operation === 'hover' && resultCount > 0 && labelConfig.special ? (
|
||||
@@ -57,7 +53,7 @@ function LSPResultSummary({
|
||||
Found <Text bold>{resultCount} </Text>
|
||||
{countLabel}
|
||||
</Text>
|
||||
)
|
||||
);
|
||||
|
||||
const secondaryText =
|
||||
fileCount > 1 ? (
|
||||
@@ -66,7 +62,7 @@ function LSPResultSummary({
|
||||
across <Text bold>{fileCount} </Text>
|
||||
files
|
||||
</Text>
|
||||
) : null
|
||||
) : null;
|
||||
|
||||
if (verbose) {
|
||||
return (
|
||||
@@ -82,7 +78,7 @@ function LSPResultSummary({
|
||||
<Text>{content}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -92,22 +88,19 @@ function LSPResultSummary({
|
||||
{secondaryText} {resultCount > 0 && <CtrlOToExpand />}
|
||||
</Text>
|
||||
</MessageResponse>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function userFacingName(): string {
|
||||
return 'LSP'
|
||||
return 'LSP';
|
||||
}
|
||||
|
||||
export function renderToolUseMessage(
|
||||
input: Partial<Input>,
|
||||
{ verbose }: { verbose: boolean },
|
||||
): React.ReactNode {
|
||||
export function renderToolUseMessage(input: Partial<Input>, { verbose }: { verbose: boolean }): React.ReactNode {
|
||||
if (!input.operation) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts: string[] = []
|
||||
const parts: string[] = [];
|
||||
|
||||
// For position-based operations (goToDefinition, findReferences, hover, goToImplementation),
|
||||
// show the symbol at the position for better context
|
||||
@@ -121,58 +114,46 @@ export function renderToolUseMessage(
|
||||
input.character !== undefined
|
||||
) {
|
||||
// Convert from 1-based (user input) to 0-based (internal file reading)
|
||||
const symbol = getSymbolAtPosition(
|
||||
input.filePath,
|
||||
input.line - 1,
|
||||
input.character - 1,
|
||||
)
|
||||
const displayPath = verbose
|
||||
? input.filePath
|
||||
: getDisplayPath(input.filePath)
|
||||
const symbol = getSymbolAtPosition(input.filePath, input.line - 1, input.character - 1);
|
||||
const displayPath = verbose ? input.filePath : getDisplayPath(input.filePath);
|
||||
|
||||
if (symbol) {
|
||||
parts.push(`operation: "${input.operation}"`)
|
||||
parts.push(`symbol: "${symbol}"`)
|
||||
parts.push(`in: "${displayPath}"`)
|
||||
parts.push(`operation: "${input.operation}"`);
|
||||
parts.push(`symbol: "${symbol}"`);
|
||||
parts.push(`in: "${displayPath}"`);
|
||||
} else {
|
||||
parts.push(`operation: "${input.operation}"`)
|
||||
parts.push(`file: "${displayPath}"`)
|
||||
parts.push(`position: ${input.line}:${input.character}`)
|
||||
parts.push(`operation: "${input.operation}"`);
|
||||
parts.push(`file: "${displayPath}"`);
|
||||
parts.push(`position: ${input.line}:${input.character}`);
|
||||
}
|
||||
|
||||
return parts.join(', ')
|
||||
return parts.join(', ');
|
||||
}
|
||||
|
||||
// For other operations (documentSymbol, workspaceSymbol),
|
||||
// show operation and file without position details
|
||||
parts.push(`operation: "${input.operation}"`)
|
||||
parts.push(`operation: "${input.operation}"`);
|
||||
|
||||
if (input.filePath) {
|
||||
const displayPath = verbose
|
||||
? input.filePath
|
||||
: getDisplayPath(input.filePath)
|
||||
parts.push(`file: "${displayPath}"`)
|
||||
const displayPath = verbose ? input.filePath : getDisplayPath(input.filePath);
|
||||
parts.push(`file: "${displayPath}"`);
|
||||
}
|
||||
|
||||
return parts.join(', ')
|
||||
return parts.join(', ');
|
||||
}
|
||||
|
||||
export function renderToolUseErrorMessage(
|
||||
result: ToolResultBlockParam['content'],
|
||||
{ verbose }: { verbose: boolean },
|
||||
): React.ReactNode {
|
||||
if (
|
||||
!verbose &&
|
||||
typeof result === 'string' &&
|
||||
extractTag(result, 'tool_use_error')
|
||||
) {
|
||||
if (!verbose && typeof result === 'string' && extractTag(result, 'tool_use_error')) {
|
||||
return (
|
||||
<MessageResponse>
|
||||
<Text color="error">LSP operation failed</Text>
|
||||
</MessageResponse>
|
||||
)
|
||||
);
|
||||
}
|
||||
return <FallbackToolUseErrorMessage result={result} verbose={verbose} />
|
||||
return <FallbackToolUseErrorMessage result={result} verbose={verbose} />;
|
||||
}
|
||||
|
||||
export function renderToolResultMessage(
|
||||
@@ -190,7 +171,7 @@ export function renderToolResultMessage(
|
||||
content={output.result}
|
||||
verbose={verbose}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback for error cases where counts aren't available
|
||||
@@ -199,5 +180,5 @@ export function renderToolResultMessage(
|
||||
<MessageResponse>
|
||||
<Text>{output.result}</Text>
|
||||
</MessageResponse>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { mock, describe, expect, test } from "bun:test";
|
||||
import { debugMock } from "../../../../../../tests/mocks/debug";
|
||||
import { mock, describe, expect, test } from 'bun:test'
|
||||
import { debugMock } from '../../../../../../tests/mocks/debug'
|
||||
|
||||
mock.module("src/utils/debug.ts", debugMock);
|
||||
mock.module('src/utils/debug.ts', debugMock)
|
||||
|
||||
const {
|
||||
formatGoToDefinitionResult,
|
||||
@@ -12,23 +12,36 @@ const {
|
||||
formatPrepareCallHierarchyResult,
|
||||
formatIncomingCallsResult,
|
||||
formatOutgoingCallsResult,
|
||||
} = await import("../formatters");
|
||||
} = await import('../formatters')
|
||||
|
||||
// Minimal LSP type stubs for testing
|
||||
const makeLocation = (uri: string, startLine: number, startChar: number, endLine: number, endChar: number) => ({
|
||||
const makeLocation = (
|
||||
uri: string,
|
||||
startLine: number,
|
||||
startChar: number,
|
||||
endLine: number,
|
||||
endChar: number,
|
||||
) => ({
|
||||
uri,
|
||||
range: {
|
||||
start: { line: startLine, character: startChar },
|
||||
end: { line: endLine, character: endChar },
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const makeSymbol = (name: string, kind: number, range: { start: { line: number; character: number }; end: { line: number; character: number } }) => ({
|
||||
const makeSymbol = (
|
||||
name: string,
|
||||
kind: number,
|
||||
range: {
|
||||
start: { line: number; character: number }
|
||||
end: { line: number; character: number }
|
||||
},
|
||||
) => ({
|
||||
name,
|
||||
kind,
|
||||
range,
|
||||
children: undefined,
|
||||
});
|
||||
})
|
||||
|
||||
const makeCallItem = (name: string, uri: string, line: number) => ({
|
||||
name,
|
||||
@@ -42,145 +55,153 @@ const makeCallItem = (name: string, uri: string, line: number) => ({
|
||||
start: { line: line, character: 0 },
|
||||
end: { line: line, character: name.length },
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
describe("formatGoToDefinitionResult", () => {
|
||||
test("returns no definitions message for null", () => {
|
||||
const result = formatGoToDefinitionResult(null);
|
||||
expect(result).toContain("No definition found");
|
||||
});
|
||||
describe('formatGoToDefinitionResult', () => {
|
||||
test('returns no definitions message for null', () => {
|
||||
const result = formatGoToDefinitionResult(null)
|
||||
expect(result).toContain('No definition found')
|
||||
})
|
||||
|
||||
test("formats single location", () => {
|
||||
const loc = makeLocation("file:///src/foo.ts", 10, 5, 10, 15);
|
||||
const result = formatGoToDefinitionResult(loc);
|
||||
expect(result).toContain("foo.ts");
|
||||
test('formats single location', () => {
|
||||
const loc = makeLocation('file:///src/foo.ts', 10, 5, 10, 15)
|
||||
const result = formatGoToDefinitionResult(loc)
|
||||
expect(result).toContain('foo.ts')
|
||||
// LSP lines are 0-based, display is 1-based → line 10 = display line 11
|
||||
expect(result).toContain("11");
|
||||
});
|
||||
expect(result).toContain('11')
|
||||
})
|
||||
|
||||
test("formats array of locations", () => {
|
||||
test('formats array of locations', () => {
|
||||
const locs = [
|
||||
makeLocation("file:///src/a.ts", 1, 0, 1, 5),
|
||||
makeLocation("file:///src/b.ts", 5, 0, 5, 5),
|
||||
];
|
||||
const result = formatGoToDefinitionResult(locs);
|
||||
expect(result).toContain("a.ts");
|
||||
expect(result).toContain("b.ts");
|
||||
});
|
||||
});
|
||||
makeLocation('file:///src/a.ts', 1, 0, 1, 5),
|
||||
makeLocation('file:///src/b.ts', 5, 0, 5, 5),
|
||||
]
|
||||
const result = formatGoToDefinitionResult(locs)
|
||||
expect(result).toContain('a.ts')
|
||||
expect(result).toContain('b.ts')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatFindReferencesResult", () => {
|
||||
test("returns no references message for null", () => {
|
||||
expect(formatFindReferencesResult(null)).toContain("No references found");
|
||||
});
|
||||
describe('formatFindReferencesResult', () => {
|
||||
test('returns no references message for null', () => {
|
||||
expect(formatFindReferencesResult(null)).toContain('No references found')
|
||||
})
|
||||
|
||||
test("formats references", () => {
|
||||
test('formats references', () => {
|
||||
const refs = [
|
||||
makeLocation("file:///src/a.ts", 1, 0, 1, 5),
|
||||
makeLocation("file:///src/b.ts", 3, 0, 3, 5),
|
||||
];
|
||||
const result = formatFindReferencesResult(refs);
|
||||
expect(result).toContain("a.ts");
|
||||
expect(result).toContain("b.ts");
|
||||
});
|
||||
});
|
||||
makeLocation('file:///src/a.ts', 1, 0, 1, 5),
|
||||
makeLocation('file:///src/b.ts', 3, 0, 3, 5),
|
||||
]
|
||||
const result = formatFindReferencesResult(refs)
|
||||
expect(result).toContain('a.ts')
|
||||
expect(result).toContain('b.ts')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatHoverResult", () => {
|
||||
test("returns no hover message for null", () => {
|
||||
expect(formatHoverResult(null)).toContain("No hover information");
|
||||
});
|
||||
describe('formatHoverResult', () => {
|
||||
test('returns no hover message for null', () => {
|
||||
expect(formatHoverResult(null)).toContain('No hover information')
|
||||
})
|
||||
|
||||
test("formats hover with string contents", () => {
|
||||
test('formats hover with string contents', () => {
|
||||
const hover = {
|
||||
contents: { kind: "plaintext", value: "string" },
|
||||
range: makeLocation("file:///a.ts", 0, 0, 0, 5).range,
|
||||
};
|
||||
const result = formatHoverResult(hover as any);
|
||||
expect(result).toContain("string");
|
||||
});
|
||||
});
|
||||
contents: { kind: 'plaintext', value: 'string' },
|
||||
range: makeLocation('file:///a.ts', 0, 0, 0, 5).range,
|
||||
}
|
||||
const result = formatHoverResult(hover as any)
|
||||
expect(result).toContain('string')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatDocumentSymbolResult", () => {
|
||||
test("returns no symbols message for null", () => {
|
||||
expect(formatDocumentSymbolResult(null)).toContain("No symbols found");
|
||||
});
|
||||
describe('formatDocumentSymbolResult', () => {
|
||||
test('returns no symbols message for null', () => {
|
||||
expect(formatDocumentSymbolResult(null)).toContain('No symbols found')
|
||||
})
|
||||
|
||||
test("returns no symbols for empty array", () => {
|
||||
expect(formatDocumentSymbolResult([])).toContain("No symbols found");
|
||||
});
|
||||
test('returns no symbols for empty array', () => {
|
||||
expect(formatDocumentSymbolResult([])).toContain('No symbols found')
|
||||
})
|
||||
|
||||
test("formats document symbols", () => {
|
||||
test('formats document symbols', () => {
|
||||
const symbols = [
|
||||
makeSymbol("MyClass", 5, { start: { line: 0, character: 0 }, end: { line: 10, character: 0 } }),
|
||||
makeSymbol("myMethod", 6, { start: { line: 2, character: 0 }, end: { line: 5, character: 0 } }),
|
||||
];
|
||||
const result = formatDocumentSymbolResult(symbols as any);
|
||||
expect(result).toContain("MyClass");
|
||||
expect(result).toContain("myMethod");
|
||||
});
|
||||
});
|
||||
makeSymbol('MyClass', 5, {
|
||||
start: { line: 0, character: 0 },
|
||||
end: { line: 10, character: 0 },
|
||||
}),
|
||||
makeSymbol('myMethod', 6, {
|
||||
start: { line: 2, character: 0 },
|
||||
end: { line: 5, character: 0 },
|
||||
}),
|
||||
]
|
||||
const result = formatDocumentSymbolResult(symbols as any)
|
||||
expect(result).toContain('MyClass')
|
||||
expect(result).toContain('myMethod')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatWorkspaceSymbolResult", () => {
|
||||
test("returns no symbols for null", () => {
|
||||
expect(formatWorkspaceSymbolResult(null)).toContain("No symbols found");
|
||||
});
|
||||
describe('formatWorkspaceSymbolResult', () => {
|
||||
test('returns no symbols for null', () => {
|
||||
expect(formatWorkspaceSymbolResult(null)).toContain('No symbols found')
|
||||
})
|
||||
|
||||
test("formats workspace symbols", () => {
|
||||
test('formats workspace symbols', () => {
|
||||
const symbols = [
|
||||
{
|
||||
name: "SearchResult",
|
||||
name: 'SearchResult',
|
||||
kind: 12,
|
||||
location: makeLocation("file:///src/a.ts", 0, 0, 0, 5),
|
||||
location: makeLocation('file:///src/a.ts', 0, 0, 0, 5),
|
||||
},
|
||||
];
|
||||
const result = formatWorkspaceSymbolResult(symbols as any);
|
||||
expect(result).toContain("SearchResult");
|
||||
});
|
||||
});
|
||||
]
|
||||
const result = formatWorkspaceSymbolResult(symbols as any)
|
||||
expect(result).toContain('SearchResult')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatPrepareCallHierarchyResult", () => {
|
||||
test("returns no items for null", () => {
|
||||
expect(formatPrepareCallHierarchyResult(null)).toContain("No call hierarchy");
|
||||
});
|
||||
describe('formatPrepareCallHierarchyResult', () => {
|
||||
test('returns no items for null', () => {
|
||||
expect(formatPrepareCallHierarchyResult(null)).toContain(
|
||||
'No call hierarchy',
|
||||
)
|
||||
})
|
||||
|
||||
test("formats call hierarchy items", () => {
|
||||
const items = [makeCallItem("main", "file:///src/main.ts", 5)];
|
||||
const result = formatPrepareCallHierarchyResult(items as any);
|
||||
expect(result).toContain("main");
|
||||
expect(result).toContain("main.ts");
|
||||
});
|
||||
});
|
||||
test('formats call hierarchy items', () => {
|
||||
const items = [makeCallItem('main', 'file:///src/main.ts', 5)]
|
||||
const result = formatPrepareCallHierarchyResult(items as any)
|
||||
expect(result).toContain('main')
|
||||
expect(result).toContain('main.ts')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatIncomingCallsResult", () => {
|
||||
test("returns no calls for null", () => {
|
||||
expect(formatIncomingCallsResult(null)).toContain("No incoming calls");
|
||||
});
|
||||
describe('formatIncomingCallsResult', () => {
|
||||
test('returns no calls for null', () => {
|
||||
expect(formatIncomingCallsResult(null)).toContain('No incoming calls')
|
||||
})
|
||||
|
||||
test("formats incoming calls", () => {
|
||||
test('formats incoming calls', () => {
|
||||
const calls = [
|
||||
{
|
||||
from: makeCallItem("caller", "file:///src/a.ts", 3),
|
||||
fromRanges: [makeLocation("file:///src/a.ts", 3, 0, 3, 5).range],
|
||||
from: makeCallItem('caller', 'file:///src/a.ts', 3),
|
||||
fromRanges: [makeLocation('file:///src/a.ts', 3, 0, 3, 5).range],
|
||||
},
|
||||
];
|
||||
const result = formatIncomingCallsResult(calls as any);
|
||||
expect(result).toContain("caller");
|
||||
});
|
||||
});
|
||||
]
|
||||
const result = formatIncomingCallsResult(calls as any)
|
||||
expect(result).toContain('caller')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatOutgoingCallsResult", () => {
|
||||
test("returns no calls for null", () => {
|
||||
expect(formatOutgoingCallsResult(null)).toContain("No outgoing calls");
|
||||
});
|
||||
describe('formatOutgoingCallsResult', () => {
|
||||
test('returns no calls for null', () => {
|
||||
expect(formatOutgoingCallsResult(null)).toContain('No outgoing calls')
|
||||
})
|
||||
|
||||
test("formats outgoing calls", () => {
|
||||
test('formats outgoing calls', () => {
|
||||
const calls = [
|
||||
{
|
||||
to: makeCallItem("callee", "file:///src/b.ts", 10),
|
||||
fromRanges: [makeLocation("file:///src/main.ts", 5, 0, 5, 5).range],
|
||||
to: makeCallItem('callee', 'file:///src/b.ts', 10),
|
||||
fromRanges: [makeLocation('file:///src/main.ts', 5, 0, 5, 5).range],
|
||||
},
|
||||
];
|
||||
const result = formatOutgoingCallsResult(calls as any);
|
||||
expect(result).toContain("callee");
|
||||
});
|
||||
});
|
||||
]
|
||||
const result = formatOutgoingCallsResult(calls as any)
|
||||
expect(result).toContain('callee')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { isValidLSPOperation } from "../schemas";
|
||||
import { describe, expect, test } from 'bun:test'
|
||||
import { isValidLSPOperation } from '../schemas'
|
||||
|
||||
describe("isValidLSPOperation", () => {
|
||||
describe('isValidLSPOperation', () => {
|
||||
const validOps = [
|
||||
"goToDefinition",
|
||||
"findReferences",
|
||||
"hover",
|
||||
"documentSymbol",
|
||||
"workspaceSymbol",
|
||||
"goToImplementation",
|
||||
"prepareCallHierarchy",
|
||||
"incomingCalls",
|
||||
"outgoingCalls",
|
||||
];
|
||||
'goToDefinition',
|
||||
'findReferences',
|
||||
'hover',
|
||||
'documentSymbol',
|
||||
'workspaceSymbol',
|
||||
'goToImplementation',
|
||||
'prepareCallHierarchy',
|
||||
'incomingCalls',
|
||||
'outgoingCalls',
|
||||
]
|
||||
|
||||
test.each(validOps)("returns true for valid operation: %s", (op) => {
|
||||
expect(isValidLSPOperation(op)).toBe(true);
|
||||
});
|
||||
test.each(validOps)('returns true for valid operation: %s', op => {
|
||||
expect(isValidLSPOperation(op)).toBe(true)
|
||||
})
|
||||
|
||||
test("returns false for invalid operation", () => {
|
||||
expect(isValidLSPOperation("invalidOp")).toBe(false);
|
||||
});
|
||||
test('returns false for invalid operation', () => {
|
||||
expect(isValidLSPOperation('invalidOp')).toBe(false)
|
||||
})
|
||||
|
||||
test("returns false for empty string", () => {
|
||||
expect(isValidLSPOperation("")).toBe(false);
|
||||
});
|
||||
test('returns false for empty string', () => {
|
||||
expect(isValidLSPOperation('')).toBe(false)
|
||||
})
|
||||
|
||||
test("returns false for undefined", () => {
|
||||
expect(isValidLSPOperation(undefined as any)).toBe(false);
|
||||
});
|
||||
test('returns false for undefined', () => {
|
||||
expect(isValidLSPOperation(undefined as any)).toBe(false)
|
||||
})
|
||||
|
||||
test("is case sensitive", () => {
|
||||
expect(isValidLSPOperation("GoToDefinition")).toBe(false);
|
||||
expect(isValidLSPOperation("HOVER")).toBe(false);
|
||||
});
|
||||
});
|
||||
test('is case sensitive', () => {
|
||||
expect(isValidLSPOperation('GoToDefinition')).toBe(false)
|
||||
expect(isValidLSPOperation('HOVER')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user