mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-29 06:32:28 +00:00
fix(php): resolve symbol-named PSR-4 imports
This commit is contained in:
parent
b65a5daa8e
commit
dd633d3cda
3 changed files with 201 additions and 43 deletions
|
|
@ -27,6 +27,60 @@ export interface PhpResolveContext {
|
|||
readonly allFilePaths: ReadonlySet<string>;
|
||||
}
|
||||
|
||||
function normalizePhpPath(value: string): string {
|
||||
return value.replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
function namespaceDirectories(
|
||||
targetRaw: string,
|
||||
composerConfig: ComposerConfig | null,
|
||||
resolved: string | null,
|
||||
): string[] {
|
||||
const directories = new Set<string>();
|
||||
if (resolved !== null) {
|
||||
const normalizedResolved = normalizePhpPath(resolved);
|
||||
const separator = normalizedResolved.lastIndexOf('/');
|
||||
if (separator >= 0) directories.add(normalizedResolved.slice(0, separator));
|
||||
}
|
||||
|
||||
if (composerConfig === null) return [...directories];
|
||||
|
||||
const normalizedTarget = normalizePhpPath(targetRaw);
|
||||
const mappings = [...composerConfig.psr4.entries()].sort((left, right) => {
|
||||
const lengthDifference = right[0].length - left[0].length;
|
||||
return lengthDifference !== 0 ? lengthDifference : left[0].localeCompare(right[0]);
|
||||
});
|
||||
for (const [namespacePrefix, directoryPrefix] of mappings) {
|
||||
const normalizedPrefix = normalizePhpPath(namespacePrefix);
|
||||
if (
|
||||
normalizedTarget !== normalizedPrefix &&
|
||||
!normalizedTarget.startsWith(`${normalizedPrefix}/`)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const remainder = normalizedTarget.slice(normalizedPrefix.length).replace(/^\//, '');
|
||||
const separator = remainder.lastIndexOf('/');
|
||||
const relativeNamespace = separator >= 0 ? remainder.slice(0, separator) : '';
|
||||
directories.add(
|
||||
normalizePhpPath(
|
||||
relativeNamespace === '' ? directoryPrefix : `${directoryPrefix}/${relativeNamespace}`,
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
return [...directories];
|
||||
}
|
||||
|
||||
function isDirectChild(filePath: string, directory: string): boolean {
|
||||
const normalizedPath = normalizePhpPath(filePath);
|
||||
const separator = normalizedPath.lastIndexOf('/');
|
||||
if (separator < 0) return directory === '';
|
||||
const parent = normalizedPath.slice(0, separator);
|
||||
const normalizedDirectory = normalizePhpPath(directory);
|
||||
return parent === normalizedDirectory || parent.endsWith(`/${normalizedDirectory}`);
|
||||
}
|
||||
|
||||
// ─── loadResolutionConfig ──────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
|
@ -145,26 +199,36 @@ export function resolvePhpImportTargetInternal(
|
|||
parsedImport?.kind === 'named' || parsedImport?.kind === 'alias'
|
||||
? parsedImport.importedSymbolKind
|
||||
: undefined;
|
||||
if (resolved === null || (symbolKind !== 'function' && symbolKind !== 'const')) return resolved;
|
||||
if (
|
||||
context === undefined ||
|
||||
parsedImport === undefined ||
|
||||
(symbolKind !== 'function' && symbolKind !== 'const')
|
||||
) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
const importedName = targetRaw.replace(/\\/g, '/').split('/').filter(Boolean).at(-1);
|
||||
if (importedName === undefined) return resolved;
|
||||
|
||||
const normalizedResolved = resolved.replace(/\\/g, '/');
|
||||
const resolvedDirectory = normalizedResolved.slice(0, normalizedResolved.lastIndexOf('/') + 1);
|
||||
const directories = namespaceDirectories(targetRaw, composerConfig, resolved);
|
||||
const candidateFiles = context.parsedFiles.filter((parsed) =>
|
||||
directories.some((directory) => isDirectChild(parsed.filePath, directory)),
|
||||
);
|
||||
const expectedType = symbolKind === 'function' ? 'Function' : 'Variable';
|
||||
const declaringFiles = context.parsedFiles.filter((parsed) => {
|
||||
const normalizedPath = parsed.filePath.replace(/\\/g, '/');
|
||||
if (!normalizedPath.startsWith(resolvedDirectory)) return false;
|
||||
if (normalizedPath.slice(resolvedDirectory.length).includes('/')) return false;
|
||||
|
||||
return parsed.localDefs.some((def) => {
|
||||
const declaringFiles = candidateFiles.filter((parsed) =>
|
||||
parsed.localDefs.some((def) => {
|
||||
if (def.type !== expectedType) return false;
|
||||
const simpleName = (def.qualifiedName ?? '').split(/[\\.]/).at(-1);
|
||||
return simpleName === importedName;
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
if (declaringFiles.length > 1) return null;
|
||||
return declaringFiles.length === 1 ? declaringFiles[0].filePath : resolved;
|
||||
if (declaringFiles.length === 1) return declaringFiles[0].filePath;
|
||||
|
||||
// PHP constants are not currently emitted as local definitions. A single
|
||||
// file in the namespace directory is still unambiguous; multiple files must
|
||||
// fail closed rather than inheriting Set iteration order.
|
||||
if (symbolKind === 'const' && candidateFiles.length === 1) return candidateFiles[0].filePath;
|
||||
return resolved;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
},
|
||||
"php-abstract-dispatch/src/Repositories/SqlRepository.php": {
|
||||
"captureGroups": 14,
|
||||
"digest": "5905bb450b29d4e186d74b50f70f07a54c8e0d4b8c3748c998c1579e72283215"
|
||||
"digest": "584da0b8d38ba3b2e45513e24ee17e0366bcfe48e353c274daed367250a0ccd9"
|
||||
},
|
||||
"php-abstract-dispatch/src/app.php": {
|
||||
"captureGroups": 10,
|
||||
"digest": "52ce761f1d53a56034124fa5e674863bce9092c1b523f6d71139c4f335e8b9f0"
|
||||
"digest": "af85999f2ddf2bf718cc419553efd09425919835460bd6739277cc570cb2d3c4"
|
||||
},
|
||||
"php-alias-imports/app/Models/Repo.php": {
|
||||
"captureGroups": 14,
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
},
|
||||
"php-alias-imports/app/Services/Main.php": {
|
||||
"captureGroups": 15,
|
||||
"digest": "bf8e1b8079956e7ef9ebfcb3ca38f547e9760da5c83856e93163efe6961067b9"
|
||||
"digest": "685798f8164a494d7dc794cf6076ff5ccade0e79fe570947a824be0099011739"
|
||||
},
|
||||
"php-ambiguous/app/Models/Dispatchable.php": {
|
||||
"captureGroups": 6,
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
},
|
||||
"php-ambiguous/app/Services/UserHandler.php": {
|
||||
"captureGroups": 12,
|
||||
"digest": "1c47e7020939a6cd6bb18f3732b51a16f4c75ded0fe9883a87d6706a2c624d1f"
|
||||
"digest": "87bbd866d8748b7cd4932aea209abc1e17f9eca518c0a5bb0dc9572cc5cd95be"
|
||||
},
|
||||
"php-anonymous-class/anon.php": {
|
||||
"captureGroups": 5,
|
||||
|
|
@ -61,15 +61,15 @@
|
|||
},
|
||||
"php-app/app/Models/BaseModel.php": {
|
||||
"captureGroups": 18,
|
||||
"digest": "be7ca5be7e28417afdef2e45c8cfed9e04594b341b0d676e7a00fdd84c94e42a"
|
||||
"digest": "7d5a013f34f909846e3a91cef4b3daa8638034e5c6939d90ccd7dae34c8f9272"
|
||||
},
|
||||
"php-app/app/Models/User.php": {
|
||||
"captureGroups": 27,
|
||||
"digest": "b6b08be1af66cbd757cfd715389725952c0e2a8e5e910ed715594c0b07570a37"
|
||||
"digest": "718b9ba0238e2139ff34027d68cb135c4698a2fc401a4f85200864b1e27a9a78"
|
||||
},
|
||||
"php-app/app/Services/UserService.php": {
|
||||
"captureGroups": 38,
|
||||
"digest": "80b8557e183052f25222cfda8879e08b1613752001f58670ce7b3dbf4b8bee28"
|
||||
"digest": "a911c5af5042738b1ca9aeb71dad06f4918d8c41e84b6a27ffaa0eadfe56ca22"
|
||||
},
|
||||
"php-app/app/Traits/HasTimestamps.php": {
|
||||
"captureGroups": 11,
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
},
|
||||
"php-assignment-chain/app/Services/AppService.php": {
|
||||
"captureGroups": 15,
|
||||
"digest": "36c5358d7f724cc0906e087828c86d9a29fe0629e2bad6105967fe8d671aa6fe"
|
||||
"digest": "0e9a9ef52a987dbd12c9478a75d5019c2a0059ab4b862924597d2ecd32f03aa7"
|
||||
},
|
||||
"php-call-result-binding/App.php": {
|
||||
"captureGroups": 23,
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
},
|
||||
"php-calls/app/Services/UserService.php": {
|
||||
"captureGroups": 7,
|
||||
"digest": "94f1cdfb0c444dc9e8116d1bbf824dc88584046539b2cbc48297729eb49e41a1"
|
||||
"digest": "84e2e65cbb4026ef9e67ac2710d1304c8dffe335f2b1b1cb70123157a04acf50"
|
||||
},
|
||||
"php-calls/app/Utils/OneArg/log.php": {
|
||||
"captureGroups": 5,
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
},
|
||||
"php-child-extends-parent/src/App.php": {
|
||||
"captureGroups": 11,
|
||||
"digest": "0c8a7c7edaa20009b71f22fef98230119a4738d2a21c8b88d64047c3c932fd36"
|
||||
"digest": "6e8b1d8f2e9c02eebcf8e2b6cacc15dfbd48c9fc03011c03d70afd265c38f3dc"
|
||||
},
|
||||
"php-child-extends-parent/src/Child.php": {
|
||||
"captureGroups": 5,
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
},
|
||||
"php-constructor-calls/app.php": {
|
||||
"captureGroups": 8,
|
||||
"digest": "23ef0f05446126892e598872a0b3c3d2f96e3b0dc50e301f1fa784a56ebc81d4"
|
||||
"digest": "0f3e6cf60248ae02ca0a744d3fa4f67b2d8421858c29243c4fcaf60763c7ac3d"
|
||||
},
|
||||
"php-constructor-promotion-fields/Models.php": {
|
||||
"captureGroups": 22,
|
||||
|
|
@ -145,7 +145,7 @@
|
|||
},
|
||||
"php-constructor-type-inference/app/Services/AppService.php": {
|
||||
"captureGroups": 15,
|
||||
"digest": "26181127fe9e9bf04431a7cc801624bde9dd284049627bb7ca0a4c9234141eec"
|
||||
"digest": "5aee8297c1f3e032523fe871571ee4410422b7ee932b259e9f36b0cab4d79c8f"
|
||||
},
|
||||
"php-coverage/enum-and-anon.php": {
|
||||
"captureGroups": 9,
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
},
|
||||
"php-coverage/multi-import.php": {
|
||||
"captureGroups": 7,
|
||||
"digest": "4d72fbfba40f2e083aa55d1c48bb500aeb7dd615de18b48b00eaca5b26a2001e"
|
||||
"digest": "e3746c5f7a68dc4dd9d658159077eb272573e27dfc29fedeadfbd6ab7ef35a10"
|
||||
},
|
||||
"php-deep-field-chain/Models.php": {
|
||||
"captureGroups": 26,
|
||||
|
|
@ -245,7 +245,7 @@
|
|||
},
|
||||
"php-fqn-cross-namespace/app/Services/Service.php": {
|
||||
"captureGroups": 15,
|
||||
"digest": "94a2bec57ccde7aa663ce2027c7f36151d18ee257830663365bc14f9d4d5f703"
|
||||
"digest": "e711548813d38a0db268d89a7edff1d31bbaa9ff0399898e09f8e93bdbc1c785"
|
||||
},
|
||||
"php-grandparent-resolution/app/Models/A.php": {
|
||||
"captureGroups": 9,
|
||||
|
|
@ -265,7 +265,7 @@
|
|||
},
|
||||
"php-grandparent-resolution/app/Services/App.php": {
|
||||
"captureGroups": 12,
|
||||
"digest": "5d0c3524e1ca41ee57bd05fd0a2831804598fca8079ea4ece38045d9c4bb1113"
|
||||
"digest": "7273ba524f587c01ca3ba9ededfdfef635c20fd9c6ade95225e81aff07ace6a6"
|
||||
},
|
||||
"php-grouped-imports/app/Models/Repo.php": {
|
||||
"captureGroups": 7,
|
||||
|
|
@ -277,11 +277,11 @@
|
|||
},
|
||||
"php-grouped-imports/app/Services/Main.php": {
|
||||
"captureGroups": 15,
|
||||
"digest": "b315d87f85f0899ed3883ec529b86a57f2d1a88d41b2b615e707307e2889c049"
|
||||
"digest": "aef9ddf30722a053664637b7fefdfcdd541baf09b24e65a3a0d80fe920189828"
|
||||
},
|
||||
"php-local-shadow/app/Services/Main.php": {
|
||||
"captureGroups": 9,
|
||||
"digest": "b4b3e35399501d98521dc9d9281a4e5c94449b580cc6cb9b3ed4187e79ee2c07"
|
||||
"digest": "52549cd82f7e2e69fb8bb81bca4e5e3487e216f4305023b77579de92374b9ee3"
|
||||
},
|
||||
"php-local-shadow/app/Utils/Logger.php": {
|
||||
"captureGroups": 5,
|
||||
|
|
@ -293,7 +293,7 @@
|
|||
},
|
||||
"php-member-calls/app/Services/UserService.php": {
|
||||
"captureGroups": 11,
|
||||
"digest": "6f6d5d34edd1cd4e32ea77db7e4b07b73de9ca09bb658123455820af8228d0cc"
|
||||
"digest": "dfe3ef69a8d6dbd95cf5a6bdc754914973b7208ad0c9575bf2595a0f84ac22cf"
|
||||
},
|
||||
"php-method-chain-binding/App.php": {
|
||||
"captureGroups": 48,
|
||||
|
|
@ -309,7 +309,7 @@
|
|||
},
|
||||
"php-method-enrichment/src/app.php": {
|
||||
"captureGroups": 11,
|
||||
"digest": "52791f6945c8c4ae083b816bd3af239bce44f0e97cbf80cdc119f4f366015138"
|
||||
"digest": "ebfa35aa3eb065977f922ae72f353d5bf31dd49956c3e9aaef349718e555b7a7"
|
||||
},
|
||||
"php-mro-arity-mismatch/app/Models/ChildModel.php": {
|
||||
"captureGroups": 16,
|
||||
|
|
@ -325,11 +325,11 @@
|
|||
},
|
||||
"php-mro-arity-mismatch/app/Services/Caller.php": {
|
||||
"captureGroups": 22,
|
||||
"digest": "d51fdbcf226f31f9220a506cceb9f538642ff99d238a1828b6b43fce6193f664"
|
||||
"digest": "20f76e10fc598152597ba8df71deccb698761938bfde8cf7c3437044c8fcdcf1"
|
||||
},
|
||||
"php-namespace-fallback-isolation/src/App/Caller.php": {
|
||||
"captureGroups": 13,
|
||||
"digest": "d5040d068fd8227388da7f25cc471f154adb37cd6bbfb78b5cac00f44bf45734"
|
||||
"digest": "48f132404e2d00efbf49302a69e5ab31540eb0eac71cd2fca43a8a0eb4533d98"
|
||||
},
|
||||
"php-namespace-fallback-isolation/src/App/Utils/Caller.php": {
|
||||
"captureGroups": 8,
|
||||
|
|
@ -353,7 +353,7 @@
|
|||
},
|
||||
"php-nullable-receiver/app/Services/AppService.php": {
|
||||
"captureGroups": 13,
|
||||
"digest": "cea6ae3f9e32a3e0448a279034bcf039b1d5af6334ab1b1ae43d9c55b6ca094d"
|
||||
"digest": "52e6db35e8fa4174ce698fec802b9b034dcda8f49fd7ab98cd9e884a6bd9777f"
|
||||
},
|
||||
"php-overload-dispatch/src/Services/Formatter.php": {
|
||||
"captureGroups": 7,
|
||||
|
|
@ -365,7 +365,7 @@
|
|||
},
|
||||
"php-overload-dispatch/src/app.php": {
|
||||
"captureGroups": 10,
|
||||
"digest": "d11621fbaec9f5015e61f35b5c2747b9f2da090a346adc5fcc10f191af61f048"
|
||||
"digest": "d29646b0c2d1e072ee0265acf641f99f3c443b57859c2582b782d5a485bfb089"
|
||||
},
|
||||
"php-parent-resolution/app/Models/BaseModel.php": {
|
||||
"captureGroups": 7,
|
||||
|
|
@ -421,7 +421,7 @@
|
|||
},
|
||||
"php-receiver-resolution/app/Services/AppService.php": {
|
||||
"captureGroups": 13,
|
||||
"digest": "59783c7af75e9075f00f425984ca1ba7a4c556bb0301e2eb2c3fdcaa94cd547f"
|
||||
"digest": "5e92226af09405c7fc4a02d3aeafcedc8462f3e525b8f67b8509f38091488505"
|
||||
},
|
||||
"php-response-shapes/api/items.php": {
|
||||
"captureGroups": 11,
|
||||
|
|
@ -445,7 +445,7 @@
|
|||
},
|
||||
"php-return-type/app/Services/UserService.php": {
|
||||
"captureGroups": 17,
|
||||
"digest": "fcc2d78ac4bdde1ac5179e6623a35299465bcbf9bb016375100bcb636624d043"
|
||||
"digest": "ac4851815d7a450ab92f7f68ccadabf219d2534b99ef1b65ced0a344188f2a69"
|
||||
},
|
||||
"php-self-this-resolution/app/Models/Repo.php": {
|
||||
"captureGroups": 7,
|
||||
|
|
@ -481,7 +481,7 @@
|
|||
},
|
||||
"php-transitive-traits/app/Models/Consumer.php": {
|
||||
"captureGroups": 18,
|
||||
"digest": "c4524f4fa18f6e7f0fd76a11920a6a65ab547ab4cf0fa5799b42b7678e14db08"
|
||||
"digest": "19b4d42452d84a4da0d1f05a03880561cee4d77ae0efd382351933875787ad96"
|
||||
},
|
||||
"php-transitive-traits/app/Traits/TraitA.php": {
|
||||
"captureGroups": 8,
|
||||
|
|
@ -501,7 +501,7 @@
|
|||
},
|
||||
"php-typed-properties/app/Services/UserService.php": {
|
||||
"captureGroups": 12,
|
||||
"digest": "2ec84482a3e2332f3f15ebb3f2d8d01d1d56e62da256127ece571a8c2e0c070c"
|
||||
"digest": "9f0540a4f7f322ee96dad4437c4e41e087f29a6993d2659fc48bd26e3277e963"
|
||||
},
|
||||
"php-typed-property-dedup/app/Models/UserRepo.php": {
|
||||
"captureGroups": 7,
|
||||
|
|
@ -509,7 +509,7 @@
|
|||
},
|
||||
"php-typed-property-dedup/app/Services/Mixed.php": {
|
||||
"captureGroups": 14,
|
||||
"digest": "9f4ba6bd183c20acaad547b6a713e80498eb70eaabaa7b416650bb64098bde0d"
|
||||
"digest": "97d09b46f6e66bef700f4686e5988c98372853203885b9a2d99dafce6fdc8343"
|
||||
},
|
||||
"php-unresolved-receiver-arity/app/Models/Handler.php": {
|
||||
"captureGroups": 21,
|
||||
|
|
@ -529,7 +529,7 @@
|
|||
},
|
||||
"php-use-function-const/app/Services/Calculator.php": {
|
||||
"captureGroups": 15,
|
||||
"digest": "d6996da68f917c3ae6b52b530d166e8266f5053ce6c9b76e1643cb61edcafa38"
|
||||
"digest": "b2206861c8550b6d2c7610ff167c42f4236c7249c87584b418e05f687233ad22"
|
||||
},
|
||||
"php-use-function-const/app/Utils/helpers.php": {
|
||||
"captureGroups": 6,
|
||||
|
|
@ -537,7 +537,7 @@
|
|||
},
|
||||
"php-variadic-arity-minimum/app/Services/Caller.php": {
|
||||
"captureGroups": 29,
|
||||
"digest": "d5669fe609abae6b7db19c15c0cb795859e0b4b0570ae83fbe80a392f3775ca8"
|
||||
"digest": "4ac7be9ff21c52b76630cdcfde0eb41af43e126c2de5db327e9f82c46c3aabbc"
|
||||
},
|
||||
"php-variadic-arity-minimum/app/Utils/Logger.php": {
|
||||
"captureGroups": 18,
|
||||
|
|
@ -545,7 +545,7 @@
|
|||
},
|
||||
"php-variadic-resolution/app/Services/AppService.php": {
|
||||
"captureGroups": 9,
|
||||
"digest": "8b5298358fba8f578b2470f9d93ffbc1089d1ef3208c1142185880b4dc174751"
|
||||
"digest": "6591007d2f4ba85b25a59c11c3ae200452fbad23cacb1ebc04291a074b534dd8"
|
||||
},
|
||||
"php-variadic-resolution/app/Utils/Logger.php": {
|
||||
"captureGroups": 7,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
import type { ParsedFile, ParsedImport, SymbolDefinition } from 'gitnexus-shared';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { ComposerConfig } from '../../../../src/core/ingestion/language-config.js';
|
||||
import { resolvePhpImportTargetInternal } from '../../../../src/core/ingestion/languages/php/import-target.js';
|
||||
|
||||
const composerConfig: ComposerConfig = { psr4: new Map([['App', 'app']]) };
|
||||
|
||||
function parsedFile(filePath: string, definitions: readonly SymbolDefinition[]): ParsedFile {
|
||||
return { filePath, localDefs: definitions } as ParsedFile;
|
||||
}
|
||||
|
||||
function definition(
|
||||
filePath: string,
|
||||
type: SymbolDefinition['type'],
|
||||
name: string,
|
||||
): SymbolDefinition {
|
||||
return {
|
||||
nodeId: `def:${filePath}:${type}:${name}`,
|
||||
filePath,
|
||||
type,
|
||||
qualifiedName: name,
|
||||
};
|
||||
}
|
||||
|
||||
const functionImport: ParsedImport = {
|
||||
kind: 'named',
|
||||
localName: 'getUser',
|
||||
importedName: 'getUser',
|
||||
targetRaw: 'App\\Models\\getUser',
|
||||
importedSymbolKind: 'function',
|
||||
};
|
||||
|
||||
describe('resolvePhpImportTargetInternal declaration selection', () => {
|
||||
it('finds a unique function declaration when the symbol name is not a filename', () => {
|
||||
const user = '/repo/app/Models/User.php';
|
||||
const factory = '/repo/app/Models/UserFactory.php';
|
||||
const parsedFiles = [
|
||||
parsedFile(user, [definition(user, 'Class', 'User')]),
|
||||
parsedFile(factory, [definition(factory, 'Function', 'getUser')]),
|
||||
];
|
||||
|
||||
expect(
|
||||
resolvePhpImportTargetInternal(
|
||||
functionImport.targetRaw,
|
||||
'/repo/app/Main.php',
|
||||
new Set(parsedFiles.map((parsed) => parsed.filePath)),
|
||||
composerConfig,
|
||||
{ parsedFiles, parsedImport: functionImport },
|
||||
),
|
||||
).toBe(factory);
|
||||
});
|
||||
|
||||
it('fails closed when the namespace has duplicate function declarations', () => {
|
||||
const first = '/repo/app/Models/First.php';
|
||||
const second = '/repo/app/Models/Second.php';
|
||||
const parsedFiles = [
|
||||
parsedFile(first, [definition(first, 'Function', 'getUser')]),
|
||||
parsedFile(second, [definition(second, 'Function', 'getUser')]),
|
||||
];
|
||||
|
||||
expect(
|
||||
resolvePhpImportTargetInternal(
|
||||
functionImport.targetRaw,
|
||||
'/repo/app/Main.php',
|
||||
new Set(parsedFiles.map((parsed) => parsed.filePath)),
|
||||
composerConfig,
|
||||
{ parsedFiles, parsedImport: functionImport },
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('resolves a constant only when its namespace directory has one candidate file', () => {
|
||||
const constants = '/repo/app/Config/constants.php';
|
||||
const parsedFiles = [parsedFile(constants, [])];
|
||||
const parsedImport: ParsedImport = {
|
||||
kind: 'named',
|
||||
localName: 'MAX_RETRIES',
|
||||
importedName: 'MAX_RETRIES',
|
||||
targetRaw: 'App\\Config\\MAX_RETRIES',
|
||||
importedSymbolKind: 'const',
|
||||
};
|
||||
|
||||
expect(
|
||||
resolvePhpImportTargetInternal(
|
||||
parsedImport.targetRaw,
|
||||
'/repo/app/Main.php',
|
||||
new Set([constants]),
|
||||
composerConfig,
|
||||
{ parsedFiles, parsedImport },
|
||||
),
|
||||
).toBe(constants);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue