Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: recursive search of direct type references #591

Merged
merged 2 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions packages/sdk-codegen/src/sdkModels.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,15 +291,14 @@ describe('sdkModels', () => {
}
})

// TODO create a mock spec that has a recursive type, since this no longer does
// it ('detects recursive types', () => {
// const type = apiTestModel.types['LookmlModelExploreField']
// const actual = type.isRecursive()
// expect(actual).toEqual(true)
// type = apiTestModel.types['CredentialsApi3']
// actual = type.isRecursive()
// expect(actual).toEqual(false)
// })
it('detects recursive types', () => {
let type = apiTestModel.types.LookmlModelExploreField
let actual = type.isRecursive()
expect(actual).toEqual(true)
type = apiTestModel.types.CredentialsApi3
actual = type.isRecursive()
expect(actual).toEqual(false)
})
})

describe('response modes', () => {
Expand Down
40 changes: 32 additions & 8 deletions packages/sdk-codegen/src/sdkModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,9 @@ export class Type implements IType {
Object.entries(this.schema.properties || {}).forEach(
([propName, propSchema]) => {
const propType = api.resolveType(propSchema, undefined, propName)
if (!propType) {
throw new Error(propName)
}
jkaster marked this conversation as resolved.
Show resolved Hide resolved
// Using class name instead of instanceof check because Typescript
// linting complains about declaration order
if (propType.instanceOf('EnumType')) {
Expand Down Expand Up @@ -1608,10 +1611,13 @@ export class Type implements IType {
return false
let result = rx.test(this.searchString(criteria))
if (!result && Type.isPropSearch(criteria)) {
for (const [, p] of Object.entries(this.properties)) {
if (p.search(rx, criteria)) {
result = true
break
for (const [, prop] of Object.entries(this.properties)) {
if (this.name !== prop.type.name) {
/** Avoiding recursion */
if (prop.search(rx, criteria)) {
result = true
break
}
}
}
}
Expand All @@ -1630,7 +1636,10 @@ export class Type implements IType {
}
if (criteria.has(SearchCriterion.property)) {
Object.entries(this.properties).forEach(([, prop]) => {
result += prop.searchString(criteria)
if (this.name !== prop.type.name) {
/** Avoiding recursion */
result += prop.searchString(criteria)
}
})
}
return result
Expand Down Expand Up @@ -1915,7 +1924,7 @@ export class ApiModel implements ISymbolTable, IApiModel {
return new ApiModel(spec)
}

private static isModelSearch(criteria: SearchCriteria): boolean {
private static isMethodSearch(criteria: SearchCriteria): boolean {
return (
criteria.has(SearchCriterion.method) ||
criteria.has(SearchCriterion.argument) ||
Expand Down Expand Up @@ -1979,7 +1988,7 @@ export class ApiModel implements ISymbolTable, IApiModel {
return result
}

if (ApiModel.isModelSearch(criteria)) {
if (ApiModel.isMethodSearch(criteria)) {
Object.entries(this.methods).forEach(([, method]) => {
if (method.search(rx, criteria)) {
methodCount++
Expand Down Expand Up @@ -2029,6 +2038,21 @@ export class ApiModel implements ISymbolTable, IApiModel {
typeName?: string,
methodName?: string
): IType {
const getRef = (schema: OAS.SchemaObject | OAS.ReferenceObject) => {
const ref = schema.$ref
let result = this.refs[ref]

if (!result) {
/** This must be recursive */
const parts: string[] = ref.split('/')
const name = parts[parts.length - 1]
const t = new Type(schema, name)
this.refs[ref] = t
result = t
}
return result
}

if (typeof schema === 'string') {
if (schema.indexOf('/requestBodies/') < 0)
return this.types[schema.substr(schema.lastIndexOf('/') + 1)]
Expand All @@ -2042,7 +2066,7 @@ export class ApiModel implements ISymbolTable, IApiModel {
if (ref) return this.resolveType(ref, style, typeName, methodName)
}
} else if (OAS.isReferenceObject(schema)) {
return this.refs[schema.$ref]
return getRef(schema)
} else if (schema.type) {
if (schema.type === 'integer' && schema.format === 'int64') {
return this.types.int64
Expand Down
Loading