Skip to content

Commit e2bf1d0

Browse files
authored
feat(csharp): Generate version constant file (#4424)
1 parent 04c4c53 commit e2bf1d0

File tree

209 files changed

+1045
-23
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

209 files changed

+1045
-23
lines changed

generators/csharp/codegen/src/ast/Field.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export declare namespace Field {
1212
name: string;
1313
/* The type of the field */
1414
type: Type;
15+
/* The access level of the method */
16+
access: Access;
17+
/* Whether the the field is a constant value */
18+
const_?: boolean;
1519
/* Whether the the field should use the new keyword */
1620
new_?: boolean;
1721
/* Whether the field has a getter method */
@@ -20,8 +24,6 @@ export declare namespace Field {
2024
init?: boolean;
2125
/* Whether the field has an set method. Cannot be used with an init method. */
2226
set?: boolean;
23-
/* The access level of the method */
24-
access: Access;
2527
/* Whether the field is static */
2628
static_?: boolean;
2729
/* Field annotations */
@@ -43,6 +45,7 @@ export class Field extends AstNode {
4345
public readonly name: string;
4446
public readonly access: Access;
4547
private type: Type;
48+
private const_: boolean;
4649
private new_: boolean;
4750
private get: boolean;
4851
private init: boolean;
@@ -58,11 +61,12 @@ export class Field extends AstNode {
5861
constructor({
5962
name,
6063
type,
64+
access,
65+
const_,
6166
new_,
6267
get,
6368
init,
6469
set,
65-
access,
6670
annotations,
6771
initializer,
6872
summary,
@@ -74,6 +78,7 @@ export class Field extends AstNode {
7478
super();
7579
this.name = name;
7680
this.type = type;
81+
this.const_ = const_ ?? false;
7782
this.new_ = new_ ?? false;
7883
this.get = get ?? false;
7984
this.init = init ?? false;
@@ -119,6 +124,9 @@ export class Field extends AstNode {
119124
}
120125

121126
writer.write(`${this.access} `);
127+
if (this.const_) {
128+
writer.write("const ");
129+
}
122130
if (this.new_) {
123131
writer.write("new ");
124132
}

generators/csharp/codegen/src/context/AbstractCsharpGeneratorContext.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export abstract class AbstractCsharpGeneratorContext<
7979
return `${this.namespace}.Core`;
8080
}
8181

82+
public getPublicCoreNamespace(): string {
83+
return this.getNamespace();
84+
}
85+
8286
public getTestNamespace(): string {
8387
return `${this.namespace}.Test`;
8488
}
@@ -91,6 +95,15 @@ export abstract class AbstractCsharpGeneratorContext<
9195
return `${this.getTestNamespace()}.Unit.MockServer`;
9296
}
9397

98+
public getVersion(): string | undefined {
99+
return this.config.output?.mode._visit({
100+
downloadFiles: () => undefined,
101+
github: (github) => github.version,
102+
publish: (publish) => publish.version,
103+
_other: () => undefined
104+
});
105+
}
106+
94107
public hasGrpcEndpoints(): boolean {
95108
// TODO: Replace this with the this.ir.sdkConfig.hasGrpcEndpoints property (when available).
96109
return Object.values(this.ir.services).some((service) => service.transport?.type === "grpc");
@@ -185,6 +198,25 @@ export abstract class AbstractCsharpGeneratorContext<
185198
});
186199
}
187200

201+
public getVersionClassReference(): csharp.ClassReference {
202+
return csharp.classReference({
203+
name: "Version",
204+
namespace: this.getPublicCoreNamespace()
205+
});
206+
}
207+
208+
public getCurrentVersionValueAccess(): csharp.CodeBlock {
209+
return csharp.codeblock((writer) => {
210+
writer.writeNode(this.getVersionClassReference());
211+
writer.write(".");
212+
writer.write(this.getCurrentVersionPropertyName());
213+
});
214+
}
215+
216+
public getCurrentVersionPropertyName(): string {
217+
return "Current";
218+
}
219+
188220
public getCollectionItemSerializerReference(
189221
itemType: csharp.ClassReference,
190222
serializer: csharp.ClassReference

generators/csharp/codegen/src/project/CsharpProject.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,7 @@ export class CsharpProject {
151151
const protobufSourceFilePaths = await this.sourceFetcher.copyProtobufSources(absolutePathToProtoDirectory);
152152

153153
const csproj = new CsProj({
154-
version: this.context.config.output?.mode._visit({
155-
downloadFiles: () => undefined,
156-
github: (github) => github.version,
157-
publish: (publish) => publish.version,
158-
_other: () => undefined
159-
}),
154+
version: this.context.getVersion(),
160155
license: this.context.config.license?._visit({
161156
custom: (val) => {
162157
return val.filename;

generators/csharp/model/src/ModelGeneratorCli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { FernGeneratorExec, GeneratorNotificationService } from "@fern-api/gener
33
import { IntermediateRepresentation } from "@fern-fern/ir-sdk/api";
44
import { generateModels } from "./generateModels";
55
import { generateWellKnownProtobufFiles } from "./generateWellKnownProtobufFiles";
6+
import { generateVersion } from "./generateVersion";
67
import { ModelCustomConfigSchema } from "./ModelCustomConfig";
78
import { ModelGeneratorContext } from "./ModelGeneratorContext";
89

@@ -51,12 +52,16 @@ export class ModelGeneratorCLI extends AbstractCsharpGeneratorCli<ModelCustomCon
5152
for (const file of generatedTypes) {
5253
context.project.addSourceFiles(file);
5354
}
55+
56+
context.project.addSourceFiles(generateVersion({ context }));
57+
5458
const protobufFiles = generateWellKnownProtobufFiles(context);
5559
if (protobufFiles != null) {
5660
for (const file of protobufFiles) {
5761
context.project.addSourceFiles(file);
5862
}
5963
}
64+
6065
await context.project.persist();
6166
}
6267
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { CSharpFile } from "@fern-api/csharp-codegen";
2+
import { ModelGeneratorContext } from "./ModelGeneratorContext";
3+
import { VersionGenerator } from "./version/VersionGenerator";
4+
5+
export function generateVersion({ context }: { context: ModelGeneratorContext }): CSharpFile {
6+
const versionGenerator = new VersionGenerator(context);
7+
return versionGenerator.generate();
8+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export { generateModels } from "./generateModels";
22
export { generateModelTests as generateTests } from "./generateTests";
33
export { generateWellKnownProtobufFiles } from "./generateWellKnownProtobufFiles";
4+
export { generateVersion } from "./generateVersion";
45
export * from "./ModelGeneratorCli";
56
export { ExampleGenerator } from "./snippets/ExampleGenerator";
67
export { getUndiscriminatedUnionSerializerAnnotation } from "./undiscriminated-union/getUndiscriminatedUnionSerializerAnnotation";
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { csharp, CSharpFile, FileGenerator } from "@fern-api/csharp-codegen";
2+
import { join, RelativeFilePath } from "@fern-api/fs-utils";
3+
import { ModelCustomConfigSchema } from "../ModelCustomConfig";
4+
import { ModelGeneratorContext } from "../ModelGeneratorContext";
5+
6+
const DEFAULT_VERSION = "0.0.0";
7+
8+
export class VersionGenerator extends FileGenerator<CSharpFile, ModelCustomConfigSchema, ModelGeneratorContext> {
9+
private classReference: csharp.ClassReference;
10+
11+
constructor(context: ModelGeneratorContext) {
12+
super(context);
13+
this.classReference = this.context.getVersionClassReference();
14+
}
15+
16+
public doGenerate(): CSharpFile {
17+
const class_ = csharp.class_({
18+
...this.classReference,
19+
partial: false,
20+
access: "internal"
21+
});
22+
23+
class_.addField(
24+
csharp.field({
25+
name: this.context.getCurrentVersionPropertyName(),
26+
type: csharp.Type.string(),
27+
access: "public",
28+
const_: true,
29+
initializer: csharp.codeblock(`"${this.context.getVersion() ?? DEFAULT_VERSION}"`)
30+
})
31+
);
32+
33+
return new CSharpFile({
34+
clazz: class_,
35+
directory: this.context.getPublicCoreDirectory(),
36+
allNamespaceSegments: this.context.getAllNamespaceSegments(),
37+
allTypeClassReferences: this.context.getAllTypeClassReferences(),
38+
namespace: this.context.getPublicCoreNamespace(),
39+
customConfig: this.context.customConfig
40+
});
41+
}
42+
43+
protected getFilepath(): RelativeFilePath {
44+
return join(
45+
this.context.project.filepaths.getPublicCoreFilesDirectory(),
46+
RelativeFilePath.of(this.classReference.name + ".cs")
47+
);
48+
}
49+
}

generators/csharp/sdk/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.4.0] - 2024-08-26
9+
10+
- Improvement: Generate an internal `Version` class that can be used to reference the current version.
11+
This is useful for users that wrap the generated base client so that it's easier to keep the version
12+
in-sync across releases. For example, consider the following custom `User-Agent` header:
13+
14+
```csharp
15+
var defaultHeaders = new Headers()
16+
{
17+
...
18+
["User-Agent"] = $"lang=C#; version={Version.Current}"
19+
};
20+
```
21+
822
## [1.3.0] - 2024-08-22
923

1024
- No changes.

generators/csharp/sdk/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.3.0
1+
1.4.0

generators/csharp/sdk/src/SdkGeneratorCli.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { AbstractCsharpGeneratorCli, TestFileGenerator, validateReadOnlyMemoryTy
22
import {
33
generateModels,
44
generateTests as generateModelTests,
5-
generateWellKnownProtobufFiles
5+
generateWellKnownProtobufFiles,
6+
generateVersion
67
} from "@fern-api/fern-csharp-model";
78
import { GeneratorNotificationService } from "@fern-api/generator-commons";
89
import { FernGeneratorExec } from "@fern-fern/generator-exec-sdk";
@@ -96,6 +97,9 @@ export class SdkGeneratorCLI extends AbstractCsharpGeneratorCli<SdkCustomConfigS
9697
for (const file of models) {
9798
context.project.addSourceFiles(file);
9899
}
100+
101+
context.project.addSourceFiles(generateVersion({ context }));
102+
99103
if (context.config.writeUnitTests) {
100104
const modelTests = generateModelTests({ context });
101105
for (const file of modelTests) {

0 commit comments

Comments
 (0)