diff --git a/eng/packages/http-client-csharp-mgmt/emitter/src/resource-detection.ts b/eng/packages/http-client-csharp-mgmt/emitter/src/resource-detection.ts index e49597312fae..565266a46766 100644 --- a/eng/packages/http-client-csharp-mgmt/emitter/src/resource-detection.ts +++ b/eng/packages/http-client-csharp-mgmt/emitter/src/resource-detection.ts @@ -55,7 +55,7 @@ import { getOperationScopeFromPath } from "./resolve-arm-resources-converter.js"; import { AzureMgmtEmitterOptions } from "./options.js"; -import { getSharedSegmentCount, isPrefix } from "./utils.js"; +import { getSegmentCount, getSharedSegmentCount } from "./utils.js"; import { getAllSdkClients, traverseClient } from "./sdk-client-utils.js"; export async function updateClients( @@ -187,12 +187,20 @@ export function buildArmProviderSchema( 0, existingPath.lastIndexOf("/") ); - if (isPrefix(existingParentPath, operationPath)) { + const parentSegmentCount = getSegmentCount(existingParentPath); + const sharedCount = getSharedSegmentCount( + existingParentPath, + operationPath + ); + if ( + sharedCount === parentSegmentCount && + sharedCount <= getSegmentCount(operationPath) + ) { // Score based on how many segments match (longer prefix = better match) - const score = existingParentPath - .split("/") - .filter((s) => s.length > 0).length; - prefixMatchCandidates.push({ existingPath, matchScore: score }); + prefixMatchCandidates.push({ + existingPath, + matchScore: parentSegmentCount + }); } } } @@ -390,17 +398,20 @@ export function buildArmProviderSchema( const potentialParentPath = otherMetadata.resourceIdPattern; // The child path should start with the parent path followed by a "/" + const parentSegmentCount = getSegmentCount(potentialParentPath); + const childSegmentCount = getSegmentCount(thisPath); + const sharedCount = getSharedSegmentCount( + potentialParentPath, + thisPath + ); + // potentialParentPath is a strict prefix of thisPath when all parent segments match + // and the child has more segments if ( - isPrefix(potentialParentPath, thisPath) && - !isPrefix(thisPath, potentialParentPath) + sharedCount === parentSegmentCount && + parentSegmentCount < childSegmentCount ) { - // Use getSharedSegmentCount to get the segment count without redundant splitting - const segmentCount = getSharedSegmentCount( - potentialParentPath, - thisPath - ); - if (segmentCount > longestParentSegmentCount) { - longestParentSegmentCount = segmentCount; + if (sharedCount > longestParentSegmentCount) { + longestParentSegmentCount = sharedCount; longestParentPath = potentialParentPath; } } diff --git a/eng/packages/http-client-csharp-mgmt/emitter/src/utils.ts b/eng/packages/http-client-csharp-mgmt/emitter/src/utils.ts index 64c2b126cb3e..ff04ad8cf432 100644 --- a/eng/packages/http-client-csharp-mgmt/emitter/src/utils.ts +++ b/eng/packages/http-client-csharp-mgmt/emitter/src/utils.ts @@ -10,6 +10,15 @@ export function isVariableSegment(segment: string): boolean { return segment.startsWith("{") && segment.endsWith("}"); } +/** + * Returns the number of non-empty segments in a path + * @param path the path + * @returns + */ +export function getSegmentCount(path: string): number { + return path.split("/").filter((s) => s.length > 0).length; +} + /** * Returns true if left path is a prefix of right path * @param left the first path @@ -17,12 +26,10 @@ export function isVariableSegment(segment: string): boolean { * @returns */ export function isPrefix(left: string, right: string): boolean { - const leftSegments = left.split("/").filter((s) => s.length > 0); - const rightSegments = right.split("/").filter((s) => s.length > 0); + const leftCount = getSegmentCount(left); + const rightCount = getSegmentCount(right); const sharedCount = getSharedSegmentCount(left, right); - return ( - sharedCount === leftSegments.length && sharedCount <= rightSegments.length - ); + return sharedCount === leftCount && sharedCount <= rightCount; } /**