Skip to content

Commit

Permalink
feat: add noComment toggle to code generators (#627)
Browse files Browse the repository at this point in the history
Closes #626
  • Loading branch information
jkaster authored Apr 23, 2021
1 parent c7b5bf8 commit 90bbecb
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 24 deletions.
6 changes: 6 additions & 0 deletions packages/sdk-codegen/src/codeGen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ export interface ICodeGen {
*/
commentStr: string

/** Generate comments in source code? */
noComment: boolean

/**
* string representation of null value
* e.g. Python None, C# null, Delphi nil
Expand Down Expand Up @@ -735,6 +738,7 @@ export abstract class CodeGen implements ICodeGen {

indentStr = ' '
commentStr = '// '
noComment = false
nullStr = 'null'
endTypeStr = ''
transport = 'rtl'
Expand Down Expand Up @@ -1106,6 +1110,7 @@ export abstract class CodeGen implements ICodeGen {
}

comment(indent: string, description: string) {
if (this.noComment) return ''
return commentBlock(description, indent, this.commentStr)
}

Expand All @@ -1114,6 +1119,7 @@ export abstract class CodeGen implements ICodeGen {
text: string | undefined,
_commentStr?: string
) {
if (this.noComment) return ''
return text ? `${this.comment(indent, text)}\n` : ''
}

Expand Down
33 changes: 33 additions & 0 deletions packages/sdk-codegen/src/csharp.gen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ describe('c# generator', () => {
expect(actual).toEqual(expected)
})

it('noComment type', () => {
const type = apiTestModel.types.AccessToken
const expected = `public class AccessToken : SdkModel
{
public string? access_token { get; set; } = null;
public string? token_type { get; set; } = null;
public long? expires_in { get; set; } = null;
public string? refresh_token { get; set; } = null;
}`
gen.noComment = true
const actual = gen.declareType(indent, type)
gen.noComment = false
expect(actual).toEqual(expected)
})

it('with special names', () => {
const type = apiTestModel.types.HyphenType
const actual = gen.declareType(indent, type)
Expand Down Expand Up @@ -204,6 +219,24 @@ public async Task<SdkResponse<TSuccess, Exception>> run_sql_query<TSuccess>(
const actual = gen.declareMethod(indent, method)
expect(actual).toEqual(expected)
})
it('noComment method with multiple return types', () => {
const method = apiTestModel.methods.run_sql_query
const expected = `public async Task<SdkResponse<TSuccess, Exception>> run_sql_query<TSuccess>(
string slug,
string result_format,
string? download = null,
ITransportSettings? options = null) where TSuccess : class
{
slug = SdkUtils.EncodeParam(slug);
result_format = SdkUtils.EncodeParam(result_format);
return await AuthRequest<TSuccess, Exception>(HttpMethod.Post, $"/sql_queries/{slug}/run/{result_format}", new Values {
{ "download", download }},null,options);
}`
gen.noComment = true
const actual = gen.declareMethod(indent, method)
gen.noComment = false
expect(actual).toEqual(expected)
})
it('generates a method with a single return type', () => {
const method = apiTestModel.methods.query_task_multi_results
const expected = `/// ### Fetch results of multiple async queries
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk-codegen/src/csharp.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export class CSharpGen extends CodeGen {
codeQuote = '"'

commentHeader(indent: string, text: string | undefined) {
if (this.noComment) return ''
return text ? `${commentBlock(text, indent, '/// ')}\n` : ''
}

Expand Down Expand Up @@ -381,7 +382,7 @@ namespace Looker.SDK.API${this.apiRef}
}

summary(indent: string, summary: string) {
if (!summary) return ''
if (this.noComment || !summary) return ''
const nl = summary.indexOf('\n') >= 0 ? '\n' : ''
return this.commentHeader(indent, `<summary>${nl}${summary}${nl}</summary>`)
}
Expand Down
92 changes: 92 additions & 0 deletions packages/sdk-codegen/src/go.gen.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
MIT License
Copyright (c) 2021 Looker Data Sciences, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

import { TestConfig } from './testUtils'
import { IEnumType } from './sdkModels'
import { GoGen } from './go.gen'

const config = TestConfig()
const apiTestModel = config.apiTestModel
const gen = new GoGen(apiTestModel)
const indent = ''

describe('Go generator', () => {
describe('comment header', () => {
it('is empty with no comment', () => {
expect(gen.commentHeader(indent, '')).toEqual('')
})

it('is multiple lines with a two line comment', () => {
const expected = `/*
foo
bar
*/
`
expect(gen.commentHeader(indent, 'foo\nbar')).toEqual(expected)
})
})

describe('types', () => {
it('enum type', () => {
const type = apiTestModel.types.PermissionType as IEnumType
expect(type).toBeDefined()
expect(type.values).toEqual(['view', 'edit'])
const expected = `type PermissionType string
const PermissionType_View PermissionType = "view"
const PermissionType_Edit PermissionType = "edit"
`
const actual = gen.declareType('', type)
expect(actual).toEqual(expected)
})

it('special needs', () => {
const type = apiTestModel.types.HyphenType
const expected = `
type HyphenType struct {
ProjectName *string \`json:"project_name,omitempty"\` // A normal variable name
ProjectDigest *string \`json:"project_digest,omitempty"\` // A hyphenated property name
ComputationTime *float32 \`json:"computation_time,omitempty"\` // A spaced out property name
}`
const actual = gen.declareType('', type)
expect(actual).toEqual(expected)
})
it('noComment special needs', () => {
const type = apiTestModel.types.HyphenType
const expected = `
type HyphenType struct {
ProjectName *string \`json:"project_name,omitempty"\`
ProjectDigest *string \`json:"project_digest,omitempty"\`
ComputationTime *float32 \`json:"computation_time,omitempty"\`
}`
gen.noComment = true
const actual = gen.declareType('', type)
gen.noComment = false
expect(actual).toEqual(expected)
})
})
})
6 changes: 4 additions & 2 deletions packages/sdk-codegen/src/go.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class AlignColumnWriter {
result +=
rowSize - 1 === colIndex ? col : align(col, this.sizes[colIndex])
})
result += '\n'
result = result.trimRight() + '\n'
})
return result
}
Expand Down Expand Up @@ -133,12 +133,14 @@ export class GoGen extends CodeGen {
}

commentHeader(indent: string, text: string | undefined) {
if (this.noComment) return ''
return text
? `${indent}/*\n\n${commentBlock(text, indent, '')}\n\n${indent}*/\n`
: ''
}

comment(indent: string, description: string) {
if (this.noComment) return ''
return commentBlock(description, indent, this.commentStr)
}

Expand Down Expand Up @@ -481,7 +483,7 @@ import (
let propertyValues = ''
const num = type as EnumType
const typeName = this.capitalize(type.name)
props.push(`type ${typeName} string`) // todo: handle other types then string
props.push(`type ${typeName} string`) // todo: handle other types than string
num.values.forEach((value) => {
// props.push(this.declareEnumValue(bump, value, typeName))
this.declareEnumValue(bump, value, typeName, writer)
Expand Down
15 changes: 14 additions & 1 deletion packages/sdk-codegen/src/kotlin.gen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,30 @@ describe('Kotlin generator', () => {
const type = apiTestModel.types.PermissionType as IEnumType
expect(type).toBeDefined()
expect(type.values).toEqual(['view', 'edit'])
const actual = gen.declareType('', type)
const expected = `/**
* Type of permission: "view" or "edit" Valid values are: "view", "edit".
*/
enum class PermissionType : Serializable {
view,
edit
}`
const actual = gen.declareType('', type)
expect(actual).toEqual(expected)
})

it('noComment enum type', () => {
const type = apiTestModel.types.PermissionType as IEnumType
expect(type).toBeDefined()
expect(type.values).toEqual(['view', 'edit'])
const expected = `enum class PermissionType : Serializable {
view,
edit
}`
gen.noComment = true
const actual = gen.declareType('', type)
gen.noComment = false
expect(actual).toEqual(expected)
})
it('special needs', () => {
const type = apiTestModel.types.HyphenType
const actual = gen.declareType('', type)
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk-codegen/src/kotlin.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ import java.util.*

// TODO create methodHeader(IMethod) and typeHeader(IType) https://kotlinlang.org/docs/reference/kotlin-doc.html
commentHeader(indent: string, text: string | undefined, commentStr = ' * ') {
if (!text) return ''
if (this.noComment || !text) return ''
if (commentStr === ' ') {
return `${indent}/**\n\n${commentBlock(
text,
Expand Down
54 changes: 48 additions & 6 deletions packages/sdk-codegen/src/pseudo.gen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,63 @@ const gen = new PseudoGen(apiTestModel)

describe('pseudocode', () => {
describe('method signature', () => {
it('optional body and additional param', () => {
it('noComment optional body and additional param', () => {
const method = apiTestModel.methods.create_user_credentials_email
expect(method).toBeDefined()
const expected = `create_user_credentials_email(
user_id: int64,
body: CredentialsEmail,
[fields: string]
): CredentialsEmail`
gen.noComment = true
const actual = gen.methodSignature('', method)
gen.noComment = false
expect(actual).toEqual(expected)
})
it('optional body and additional param', () => {
const method = apiTestModel.methods.create_user_credentials_email
expect(method).toBeDefined()
const expected = `"### Email/password login information for the specified user."
create_user_credentials_email(
"id of user"
user_id: int64,
body: CredentialsEmail,
"Requested fields."
[fields: string]
): CredentialsEmail`
const actual = gen.methodSignature('', method)
expect(actual).toEqual(expected)
})
it('no params', () => {
const method = apiTestModel.methods.all_datagroups
expect(method).toBeDefined()
const expected = `all_datagroups(): Datagroup[]`
const expected = `"### Get information about all datagroups."
all_datagroups(): Datagroup[]`
const actual = gen.methodSignature('', method)
expect(actual).toEqual(expected)
})
test('import_lookml_dashboard', () => {
const method = apiTestModel.methods.import_lookml_dashboard
const expected = `import_lookml_dashboard(
lookml_dashboard_id: string,
space_id: string,
const expected = `"### Import a LookML dashboard to a space as a UDD
"Creates a UDD (a dashboard which exists in the Looker database rather than as a LookML file) from the LookML dashboard
"and puts it in the space specified. The created UDD will have a lookml_link_id which links to the original LookML dashboard.
"
"To give the imported dashboard specify a (e.g. title: "my title") in the body of your request, otherwise the imported
"dashboard will have the same title as the original LookML dashboard.
"
"For this operation to succeed the user must have permission to see the LookML dashboard in question, and have permission to
"create content in the space the dashboard is being imported to.
"
"**Sync** a linked UDD with [sync_lookml_dashboard()](#!/Dashboard/sync_lookml_dashboard)
"**Unlink** a linked UDD by setting lookml_link_id to null with [update_dashboard()](#!/Dashboard/update_dashboard)"
import_lookml_dashboard(
"Id of LookML dashboard"
lookml_dashboard_id: string,
"Id of space to import the dashboard to"
space_id: string,
[body: Dashboard],
[raw_locale: boolean]
"If true, and this dashboard is localized, export it with the raw keys, not localized."
[raw_locale: boolean]
): Dashboard`
const actual = gen.methodSignature('', method)
expect(actual).toEqual(expected)
Expand All @@ -69,15 +101,25 @@ describe('pseudocode', () => {
const type = apiTestModel.types.Datagroup
expect(type).toBeDefined()
const expected = `Datagroup {
"Operations the current user is able to perform on this object"
[can: Hash[boolean]]
"UNIX timestamp at which this entry was created."
[created_at: int64]
"Unique ID of the datagroup"
[id: int64]
"Name of the model containing the datagroup. Unique when combined with name."
[model_name: string]
"Name of the datagroup. Unique when combined with model_name."
[name: string]
"UNIX timestamp before which cache entries are considered stale. Cannot be in the future."
[stale_before: int64]
"UNIX timestamp at which this entry trigger was last checked."
[trigger_check_at: int64]
"The message returned with the error of the last trigger check."
[trigger_error: string]
"The value of the trigger when last checked."
[trigger_value: string]
"UNIX timestamp at which this entry became triggered. Cannot be in the future."
[triggered_at: int64]}`
const actual = gen.declareType('', type)
expect(actual).toEqual(expected)
Expand Down
Loading

0 comments on commit 90bbecb

Please sign in to comment.