fix: satisfy CI quality checks

Remove the unused parsing import and format the updated Spring route files so the quality lint and prettier checks pass cleanly.

Made-with: Cursor
This commit is contained in:
许恩宁 2026-04-02 22:48:56 +08:00
parent 71735cf9b6
commit 59db54f284
3 changed files with 74 additions and 50 deletions

View file

@ -6,7 +6,7 @@ import { getProvider } from './languages/index.js';
import { generateId } from '../../lib/utils.js';
import { SymbolTable } from './symbol-table.js';
import { ASTCache } from './ast-cache.js';
import { SupportedLanguages, getLanguageFromFilename } from 'gitnexus-shared';
import { getLanguageFromFilename } from 'gitnexus-shared';
import { yieldToEventLoop } from './utils/event-loop.js';
import {
getDefinitionNodeFromCaptures,
@ -504,7 +504,9 @@ const processParsingSequential = async (
});
if (provider.isRouteFile?.(file.path) && provider.deferredRouteExtractor) {
extractedData.deferredRouteCandidates.push(...(provider.deferredRouteExtractor(tree, file.path)));
extractedData.deferredRouteCandidates.push(
...provider.deferredRouteExtractor(tree, file.path),
);
}
}
@ -557,13 +559,7 @@ export const processParsing = async (
}
}
const data = await processParsingSequential(
graph,
files,
symbolTable,
astCache,
onFileProgress,
);
const data = await processParsingSequential(graph, files, symbolTable, astCache, onFileProgress);
return {
data,
usedWorkers: false,

View file

@ -31,7 +31,10 @@ function getAnnotationName(node: SyntaxNode): string | null {
return nameNode?.text ?? null;
}
function getElementValuePairParts(node: SyntaxNode): { key: string | null; value: SyntaxNode | null } {
function getElementValuePairParts(node: SyntaxNode): {
key: string | null;
value: SyntaxNode | null;
} {
const keyNode = node.childForFieldName('key') ?? node.namedChild(0);
const valueNode = node.childForFieldName('value') ?? node.namedChild(1);
return {
@ -52,7 +55,9 @@ function extractOwnerPath(node: SyntaxNode | null | undefined): string[] | null
return [...objectPath, fieldNode.text];
}
function extractRoutePathExpression(node: SyntaxNode | null | undefined): SpringRoutePathExpression | null {
function extractRoutePathExpression(
node: SyntaxNode | null | undefined,
): SpringRoutePathExpression | null {
if (!node) return null;
const literal = extractJavaStringLiteral(node);
@ -92,7 +97,11 @@ function extractRequestMappingPath(annotation: SyntaxNode): {
const direct = extractRoutePathExpression(child);
if (direct) return { expression: direct, hasExplicitPath: true };
if (child.type === 'string_literal' || child.type === 'identifier' || child.type === 'field_access') {
if (
child.type === 'string_literal' ||
child.type === 'identifier' ||
child.type === 'field_access'
) {
return { expression: null, hasExplicitPath: true };
}
@ -160,7 +169,10 @@ function joinRoutePaths(prefix: string | null, routePath: string | null): string
return '/';
}
function findAnnotation(modifiersNode: SyntaxNode | null, names: ReadonlySet<string>): SyntaxNode | null {
function findAnnotation(
modifiersNode: SyntaxNode | null,
names: ReadonlySet<string>,
): SyntaxNode | null {
if (!modifiersNode) return null;
for (let i = 0; i < modifiersNode.namedChildCount; i++) {
@ -197,7 +209,9 @@ function resolveUniqueClassLike(
): SymbolDefinition | null {
const resolved = ctx.resolve(name, filePath);
if (!resolved) return null;
const classLikes = resolved.candidates.filter((candidate) => CLASS_LIKE_TYPES.has(candidate.type));
const classLikes = resolved.candidates.filter((candidate) =>
CLASS_LIKE_TYPES.has(candidate.type),
);
return classLikes.length === 1 ? classLikes[0] : null;
}
@ -240,7 +254,10 @@ function resolvePathExpression(
case 'identifier': {
const sameClass = resolveUniqueClassLike(className, filePath, ctx);
if (sameClass) {
const local = ctx.symbols.lookupFieldByOwner(sameClass.nodeId, expression.name)?.constantValue;
const local = ctx.symbols.lookupFieldByOwner(
sameClass.nodeId,
expression.name,
)?.constantValue;
if (local) return local;
}
@ -248,7 +265,9 @@ function resolvePathExpression(
if (imported) return imported;
const sameFile = firstConstantValue(
ctx.symbols.lookupExactAll(filePath, expression.name).filter((def) => def.type === 'Property'),
ctx.symbols
.lookupExactAll(filePath, expression.name)
.filter((def) => def.type === 'Property'),
);
if (sameFile) return sameFile;

View file

@ -9,6 +9,11 @@ import {
type PipelineResult,
} from './helpers.js';
function expectDefined<T>(value: T | undefined): T {
expect(value).toBeDefined();
return value as T;
}
describe('Spring route mapping', () => {
let result: PipelineResult;
@ -41,31 +46,36 @@ describe('Spring route mapping', () => {
const health = routes.find((r) => r.name === '/health');
const status = routes.find((r) => r.name === '/status');
expect(users).toBeDefined();
expect(users!.properties.httpMethod).toBe('GET');
expect(users!.properties.controllerName).toBe('UserController');
expect(users!.properties.methodName).toBe('listUsers');
expect(users!.properties.prefix).toBe('/api');
const usersRoute = expectDefined(users);
const createRoute = expectDefined(create);
const profileRoute = expectDefined(profile);
const searchRouteNode = expectDefined(search);
const fqcnRouteNode = expectDefined(fqcn);
const healthRouteNode = expectDefined(health);
const statusRouteNode = expectDefined(status);
expect(create!.properties.httpMethod).toBe('POST');
expect(create!.properties.methodName).toBe('createUser');
expect(profile!.properties.httpMethod).toBe('PATCH');
expect(profile!.properties.methodName).toBe('updateProfile');
expect(search!.properties.httpMethod).toBe('POST');
expect(search!.properties.methodName).toBe('searchUsers');
expect(fqcn!.properties.httpMethod).toBe('PUT');
expect(fqcn!.properties.methodName).toBe('fullyQualifiedUsers');
expect(usersRoute.properties.httpMethod).toBe('GET');
expect(usersRoute.properties.controllerName).toBe('UserController');
expect(usersRoute.properties.methodName).toBe('listUsers');
expect(usersRoute.properties.prefix).toBe('/api');
expect(health).toBeDefined();
expect(health!.properties.httpMethod).toBe('GET');
expect(health!.properties.controllerName).toBe('HealthController');
expect(health!.properties.methodName).toBe('health');
expect(health!.properties.prefix).toBeUndefined();
expect(createRoute.properties.httpMethod).toBe('POST');
expect(createRoute.properties.methodName).toBe('createUser');
expect(profileRoute.properties.httpMethod).toBe('PATCH');
expect(profileRoute.properties.methodName).toBe('updateProfile');
expect(searchRouteNode.properties.httpMethod).toBe('POST');
expect(searchRouteNode.properties.methodName).toBe('searchUsers');
expect(fqcnRouteNode.properties.httpMethod).toBe('PUT');
expect(fqcnRouteNode.properties.methodName).toBe('fullyQualifiedUsers');
expect(status).toBeDefined();
expect(status!.properties.httpMethod).toBe('GET');
expect(status!.properties.controllerName).toBe('HealthController');
expect(status!.properties.methodName).toBe('status');
expect(healthRouteNode.properties.httpMethod).toBe('GET');
expect(healthRouteNode.properties.controllerName).toBe('HealthController');
expect(healthRouteNode.properties.methodName).toBe('health');
expect(healthRouteNode.properties.prefix).toBeUndefined();
expect(statusRouteNode.properties.httpMethod).toBe('GET');
expect(statusRouteNode.properties.controllerName).toBe('HealthController');
expect(statusRouteNode.properties.methodName).toBe('status');
});
it('creates HANDLES_ROUTE edges from controller files', () => {
@ -76,16 +86,11 @@ describe('Spring route mapping', () => {
const healthRoute = edges.find((edge) => edge.target === '/health');
const statusRoute = edges.find((edge) => edge.target === '/status');
expect(usersRoute).toBeDefined();
expect(usersRoute!.sourceFilePath).toContain('UserController.java');
expect(searchRoute).toBeDefined();
expect(searchRoute!.sourceFilePath).toContain('UserController.java');
expect(fqcnRoute).toBeDefined();
expect(fqcnRoute!.sourceFilePath).toContain('UserController.java');
expect(healthRoute).toBeDefined();
expect(healthRoute!.sourceFilePath).toContain('HealthController.java');
expect(statusRoute).toBeDefined();
expect(statusRoute!.sourceFilePath).toContain('HealthController.java');
expect(expectDefined(usersRoute).sourceFilePath).toContain('UserController.java');
expect(expectDefined(searchRoute).sourceFilePath).toContain('UserController.java');
expect(expectDefined(fqcnRoute).sourceFilePath).toContain('UserController.java');
expect(expectDefined(healthRoute).sourceFilePath).toContain('HealthController.java');
expect(expectDefined(statusRoute).sourceFilePath).toContain('HealthController.java');
});
it('creates framework CALLS edges from controller files to handler methods', () => {
@ -97,13 +102,17 @@ describe('Spring route mapping', () => {
edges.some((edge) => edge.source === 'UserController.java' && edge.target === 'createUser'),
).toBe(true);
expect(
edges.some((edge) => edge.source === 'UserController.java' && edge.target === 'updateProfile'),
edges.some(
(edge) => edge.source === 'UserController.java' && edge.target === 'updateProfile',
),
).toBe(true);
expect(
edges.some((edge) => edge.source === 'UserController.java' && edge.target === 'searchUsers'),
).toBe(true);
expect(
edges.some((edge) => edge.source === 'UserController.java' && edge.target === 'fullyQualifiedUsers'),
edges.some(
(edge) => edge.source === 'UserController.java' && edge.target === 'fullyQualifiedUsers',
),
).toBe(true);
expect(
edges.some((edge) => edge.source === 'HealthController.java' && edge.target === 'health'),