@typespec/http-server-csharp 0.58.0-alpha.10-dev.0 → 0.58.0-alpha.10-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/lib/attributes.js +4 -4
- package/dist/src/lib/attributes.js.map +1 -1
- package/dist/src/lib/boilerplate.d.ts.map +1 -1
- package/dist/src/lib/boilerplate.js +5 -5
- package/dist/src/lib/boilerplate.js.map +1 -1
- package/dist/src/lib/interfaces.d.ts +17 -0
- package/dist/src/lib/interfaces.d.ts.map +1 -1
- package/dist/src/lib/interfaces.js +4 -0
- package/dist/src/lib/interfaces.js.map +1 -1
- package/dist/src/lib/lib.d.ts +10 -1
- package/dist/src/lib/lib.d.ts.map +1 -1
- package/dist/src/lib/lib.js +6 -0
- package/dist/src/lib/lib.js.map +1 -1
- package/dist/src/lib/scaffolding.d.ts +5 -4
- package/dist/src/lib/scaffolding.d.ts.map +1 -1
- package/dist/src/lib/scaffolding.js +70 -26
- package/dist/src/lib/scaffolding.js.map +1 -1
- package/dist/src/lib/service.d.ts.map +1 -1
- package/dist/src/lib/service.js +64 -421
- package/dist/src/lib/service.js.map +1 -1
- package/dist/src/lib/utils.d.ts +43 -3
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +545 -4
- package/dist/src/lib/utils.js.map +1 -1
- package/package.json +3 -3
package/dist/src/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NoTarget, getFriendlyName, isNullType, isNumericType, isTemplateInstance, isUnknownType, isVoidType, } from "@typespec/compiler";
|
|
2
|
-
import { StringBuilder } from "@typespec/compiler/emitter-framework";
|
|
3
|
-
import { Visibility, createMetadataInfo, isBody, isBodyRoot, isMetadata, isStatusCode, } from "@typespec/http";
|
|
2
|
+
import { StringBuilder, code, } from "@typespec/compiler/emitter-framework";
|
|
3
|
+
import { Visibility, createMetadataInfo, getHeaderFieldName, isBody, isBodyRoot, isHeader, isMetadata, isPathParam, isQueryParam, isStatusCode, } from "@typespec/http";
|
|
4
4
|
import { camelCase, pascalCase } from "change-case";
|
|
5
5
|
import { getAttributes } from "./attributes.js";
|
|
6
6
|
import { BooleanValue, CSharpType, NameCasingType, NullValue, NumericValue, StringValue, } from "./interfaces.js";
|
|
@@ -21,7 +21,7 @@ export function getCSharpTypeForScalar(program, scalar) {
|
|
|
21
21
|
target: scalar,
|
|
22
22
|
});
|
|
23
23
|
const result = new CSharpType({
|
|
24
|
-
name: "
|
|
24
|
+
name: "object",
|
|
25
25
|
namespace: "System",
|
|
26
26
|
isBuiltIn: true,
|
|
27
27
|
isValueType: false,
|
|
@@ -82,6 +82,7 @@ export function getCSharpType(program, type, namespace) {
|
|
|
82
82
|
namespace: namespace || "Models",
|
|
83
83
|
isBuiltIn: false,
|
|
84
84
|
isValueType: false,
|
|
85
|
+
isClass: true,
|
|
85
86
|
}),
|
|
86
87
|
};
|
|
87
88
|
case "Enum":
|
|
@@ -90,7 +91,7 @@ export function getCSharpType(program, type, namespace) {
|
|
|
90
91
|
name: ensureCSharpIdentifier(program, type, type.name, NameCasingType.Class),
|
|
91
92
|
namespace: `${namespace}.Models`,
|
|
92
93
|
isBuiltIn: false,
|
|
93
|
-
isValueType:
|
|
94
|
+
isValueType: true,
|
|
94
95
|
}),
|
|
95
96
|
};
|
|
96
97
|
case "Model":
|
|
@@ -105,6 +106,8 @@ export function getCSharpType(program, type, namespace) {
|
|
|
105
106
|
namespace: itemType.namespace,
|
|
106
107
|
isBuiltIn: itemType.isBuiltIn,
|
|
107
108
|
isValueType: false,
|
|
109
|
+
isClass: itemType.isClass,
|
|
110
|
+
isCollection: true,
|
|
108
111
|
}),
|
|
109
112
|
};
|
|
110
113
|
}
|
|
@@ -118,6 +121,7 @@ export function getCSharpType(program, type, namespace) {
|
|
|
118
121
|
namespace: `${namespace}.Models`,
|
|
119
122
|
isBuiltIn: false,
|
|
120
123
|
isValueType: false,
|
|
124
|
+
isClass: true,
|
|
121
125
|
}),
|
|
122
126
|
};
|
|
123
127
|
default:
|
|
@@ -474,6 +478,23 @@ export function ensureCSharpIdentifier(program, target, name, context = NameCasi
|
|
|
474
478
|
export function getModelAttributes(program, entity, cSharpName) {
|
|
475
479
|
return getAttributes(program, entity, cSharpName);
|
|
476
480
|
}
|
|
481
|
+
export function getModelDeclarationName(program, model, defaultSuffix) {
|
|
482
|
+
if (model.name !== null && model.name.length > 0) {
|
|
483
|
+
return ensureCSharpIdentifier(program, model, model.name, NameCasingType.Class);
|
|
484
|
+
}
|
|
485
|
+
if (model.sourceModel && model.sourceModel.name && model.sourceModel.name.length > 0) {
|
|
486
|
+
return ensureCSharpIdentifier(program, model, `${model.sourceModel.name}${defaultSuffix}`, NameCasingType.Class);
|
|
487
|
+
}
|
|
488
|
+
if (model.sourceModels.length > 0) {
|
|
489
|
+
const sourceNames = model.sourceModels
|
|
490
|
+
.filter((m) => m.model.name !== undefined && m.model.name.length > 0)
|
|
491
|
+
.flatMap((m) => ensureCSharpIdentifier(program, model, m.model.name, NameCasingType.Class));
|
|
492
|
+
if (sourceNames.length > 0) {
|
|
493
|
+
return `${sourceNames.join()}${defaultSuffix}`;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return `Model${defaultSuffix}`;
|
|
497
|
+
}
|
|
477
498
|
export function getModelInstantiationName(program, model, name) {
|
|
478
499
|
const friendlyName = getFriendlyName(program, model);
|
|
479
500
|
if (friendlyName && friendlyName.length > 0)
|
|
@@ -563,6 +584,8 @@ export class HttpMetadata {
|
|
|
563
584
|
});
|
|
564
585
|
switch (responseType.kind) {
|
|
565
586
|
case "Model":
|
|
587
|
+
if (responseType.indexer && responseType.indexer.key.name !== "string")
|
|
588
|
+
return responseType;
|
|
566
589
|
const bodyProp = new ModelInfo().filterAllProperties(program, responseType, (p) => isBody(program, p) || isBodyRoot(program, p));
|
|
567
590
|
if (bodyProp !== undefined)
|
|
568
591
|
return metaInfo.getEffectivePayloadType(bodyProp.type, Visibility.Read);
|
|
@@ -642,4 +665,522 @@ export function getCSharpStatusCode(entry) {
|
|
|
642
665
|
return undefined;
|
|
643
666
|
}
|
|
644
667
|
}
|
|
668
|
+
export function isEmptyResponseModel(program, model) {
|
|
669
|
+
if (model.kind !== "Model")
|
|
670
|
+
return false;
|
|
671
|
+
if (model.properties.size === 0)
|
|
672
|
+
return true;
|
|
673
|
+
return model.properties.size === 1 && isStatusCode(program, [...model.properties.values()][0]);
|
|
674
|
+
}
|
|
675
|
+
export function isContentTypeHeader(program, parameter) {
|
|
676
|
+
return (isHeader(program, parameter) &&
|
|
677
|
+
(parameter.name === "contentType" || getHeaderFieldName(program, parameter) === "Content-type"));
|
|
678
|
+
}
|
|
679
|
+
export function isValidParameter(program, parameter) {
|
|
680
|
+
return (!isContentTypeHeader(program, parameter) &&
|
|
681
|
+
(parameter.type.kind !== "Intrinsic" || parameter.type.name !== "never") &&
|
|
682
|
+
parameter.model?.name === "");
|
|
683
|
+
}
|
|
684
|
+
/** Determine whether the given parameter is http metadata */
|
|
685
|
+
export function isHttpMetadata(program, property) {
|
|
686
|
+
return (isPathParam(program, property) || isHeader(program, property) || isQueryParam(program, property));
|
|
687
|
+
}
|
|
688
|
+
export function getBusinessLogicCallParameters(parameters) {
|
|
689
|
+
const builder = new StringBuilder();
|
|
690
|
+
const blParameters = parameters.filter((p) => p.operationKind === "BusinessLogic" || p.operationKind === "All");
|
|
691
|
+
let i = 0;
|
|
692
|
+
for (const param of blParameters) {
|
|
693
|
+
builder.push(code `${getBusinessLogicCallParameter(param)}${++i < blParameters.length ? ", " : ""}`);
|
|
694
|
+
}
|
|
695
|
+
return builder.reduce();
|
|
696
|
+
}
|
|
697
|
+
export function getBusinessLogicDeclParameters(parameters) {
|
|
698
|
+
const builder = new StringBuilder();
|
|
699
|
+
const blParameters = parameters.filter((p) => p.operationKind === "BusinessLogic" || p.operationKind === "All");
|
|
700
|
+
let i = 0;
|
|
701
|
+
for (const param of blParameters) {
|
|
702
|
+
builder.push(code `${getBusinessLogicSignatureParameter(param)}${++i < blParameters.length ? ", " : ""}`);
|
|
703
|
+
}
|
|
704
|
+
return builder.reduce();
|
|
705
|
+
}
|
|
706
|
+
export function getHttpDeclParameters(parameters) {
|
|
707
|
+
const builder = new StringBuilder();
|
|
708
|
+
const blParameters = parameters.filter((p) => p.operationKind === "Http" || p.operationKind === "All");
|
|
709
|
+
let i = 0;
|
|
710
|
+
for (const param of blParameters) {
|
|
711
|
+
builder.push(code `${getHttpSignatureParameter(param)}${++i < blParameters.length ? ", " : ""}`);
|
|
712
|
+
}
|
|
713
|
+
return builder.reduce();
|
|
714
|
+
}
|
|
715
|
+
export function getBusinessLogicCallParameter(param) {
|
|
716
|
+
const builder = new StringBuilder();
|
|
717
|
+
builder.push(code `${param.callName}`);
|
|
718
|
+
return builder.reduce();
|
|
719
|
+
}
|
|
720
|
+
export function getBusinessLogicSignatureParameter(param) {
|
|
721
|
+
const builder = new StringBuilder();
|
|
722
|
+
builder.push(code `${param.typeName}${param.optional || param.nullable ? "? " : " "}${param.name}`);
|
|
723
|
+
return builder.reduce();
|
|
724
|
+
}
|
|
725
|
+
export function getHttpSignatureParameter(param) {
|
|
726
|
+
const builder = new StringBuilder();
|
|
727
|
+
builder.push(code `${getHttpParameterDecorator(param)}${getBusinessLogicSignatureParameter(param)}${param.defaultValue === undefined ? "" : code ` = ${typeof param.defaultValue === "boolean" ? code `${param.defaultValue.toString()}` : code `${param.defaultValue}`}`}`);
|
|
728
|
+
return builder.reduce();
|
|
729
|
+
}
|
|
730
|
+
export function getHttpParameterDecorator(parameter) {
|
|
731
|
+
switch (parameter.httpParameterKind) {
|
|
732
|
+
case "query":
|
|
733
|
+
return code `[FromQuery${parameter.httpParameterName ? code `(Name="${parameter.httpParameterName}")` : ""}] `;
|
|
734
|
+
case "header":
|
|
735
|
+
return code `[FromHeader${parameter.httpParameterName ? code `(Name="${parameter.httpParameterName}")` : ""}] `;
|
|
736
|
+
default:
|
|
737
|
+
return "";
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
export function getParameterKind(parameter) {
|
|
741
|
+
switch (parameter.type) {
|
|
742
|
+
case "path":
|
|
743
|
+
return "path";
|
|
744
|
+
case "cookie":
|
|
745
|
+
case "header":
|
|
746
|
+
return "header";
|
|
747
|
+
case "query":
|
|
748
|
+
return "query";
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
export function canHaveDefault(program, type) {
|
|
752
|
+
switch (type.kind) {
|
|
753
|
+
case "Boolean":
|
|
754
|
+
case "EnumMember":
|
|
755
|
+
case "Enum":
|
|
756
|
+
case "Number":
|
|
757
|
+
case "String":
|
|
758
|
+
case "Scalar":
|
|
759
|
+
case "StringTemplate":
|
|
760
|
+
return true;
|
|
761
|
+
case "ModelProperty":
|
|
762
|
+
return canHaveDefault(program, type.type);
|
|
763
|
+
default:
|
|
764
|
+
return false;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
export class CSharpOperationHelpers {
|
|
768
|
+
constructor(inEmitter) {
|
|
769
|
+
this.emitter = inEmitter;
|
|
770
|
+
this.#anonymousModels = new Map();
|
|
771
|
+
this.#opCache = new Map();
|
|
772
|
+
}
|
|
773
|
+
emitter;
|
|
774
|
+
#anonymousModels;
|
|
775
|
+
#opCache;
|
|
776
|
+
getParameters(program, operation) {
|
|
777
|
+
function safeConcat(...names) {
|
|
778
|
+
return names
|
|
779
|
+
.filter((n) => n !== undefined && n !== null && n.length > 0)
|
|
780
|
+
.flatMap((s) => getCSharpIdentifier(s, NameCasingType.Class))
|
|
781
|
+
.join();
|
|
782
|
+
}
|
|
783
|
+
const cached = this.#opCache.get(operation.operation);
|
|
784
|
+
if (cached)
|
|
785
|
+
return cached;
|
|
786
|
+
const bodyParam = operation.parameters.body;
|
|
787
|
+
const isExplicitBodyParam = bodyParam?.property !== undefined;
|
|
788
|
+
const result = [];
|
|
789
|
+
if (operation.verb === "get" && operation.parameters.body !== undefined) {
|
|
790
|
+
reportDiagnostic(program, {
|
|
791
|
+
code: "get-request-body",
|
|
792
|
+
target: operation.operation,
|
|
793
|
+
format: {},
|
|
794
|
+
});
|
|
795
|
+
this.#opCache.set(operation.operation, result);
|
|
796
|
+
return result;
|
|
797
|
+
}
|
|
798
|
+
const validParams = operation.parameters.parameters.filter((p) => isValidParameter(program, p.param));
|
|
799
|
+
const requiredParams = validParams.filter((p) => p.type === "path" || (!p.param.optional && p.param.defaultValue === undefined));
|
|
800
|
+
const optionalParams = validParams.filter((p) => p.type !== "path" && (p.param.optional || p.param.defaultValue !== undefined));
|
|
801
|
+
for (const parameter of requiredParams) {
|
|
802
|
+
let { typeReference: paramType, defaultValue: paramValue } = this.getTypeInfo(program, parameter.param.type);
|
|
803
|
+
// cSharp does not allow array defaults in operation parameters
|
|
804
|
+
if (!canHaveDefault(program, parameter.param)) {
|
|
805
|
+
paramValue = undefined;
|
|
806
|
+
}
|
|
807
|
+
const paramName = ensureCSharpIdentifier(program, parameter.param, parameter.param.name, NameCasingType.Parameter);
|
|
808
|
+
result.push({
|
|
809
|
+
isExplicitBody: false,
|
|
810
|
+
name: paramName,
|
|
811
|
+
callName: paramName,
|
|
812
|
+
optional: false,
|
|
813
|
+
typeName: paramType,
|
|
814
|
+
defaultValue: paramValue,
|
|
815
|
+
httpParameterKind: getParameterKind(parameter),
|
|
816
|
+
httpParameterName: parameter.name,
|
|
817
|
+
nullable: false,
|
|
818
|
+
operationKind: "All",
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
const overrideParameters = getExplicitBodyParameters(program, operation);
|
|
822
|
+
if (overrideParameters !== undefined) {
|
|
823
|
+
for (const overrideParam of overrideParameters) {
|
|
824
|
+
result.push(overrideParam);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
else if (bodyParam !== undefined && isExplicitBodyParam) {
|
|
828
|
+
let { typeReference: bodyType, defaultValue: bodyValue, nullableType: isNullable, } = this.getTypeInfo(program, bodyParam.type);
|
|
829
|
+
if (!canHaveDefault(program, bodyParam.type)) {
|
|
830
|
+
bodyValue = undefined;
|
|
831
|
+
}
|
|
832
|
+
result.push({
|
|
833
|
+
isExplicitBody: true,
|
|
834
|
+
httpParameterKind: "body",
|
|
835
|
+
name: "body",
|
|
836
|
+
callName: "body",
|
|
837
|
+
typeName: bodyType,
|
|
838
|
+
nullable: isNullable,
|
|
839
|
+
defaultValue: bodyValue,
|
|
840
|
+
optional: bodyParam.property?.optional ?? false,
|
|
841
|
+
operationKind: "All",
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
else if (bodyParam !== undefined) {
|
|
845
|
+
switch (bodyParam.type.kind) {
|
|
846
|
+
case "Model":
|
|
847
|
+
let tsBody = bodyParam.type;
|
|
848
|
+
if (!bodyParam.type.name) {
|
|
849
|
+
tsBody = program.checker.cloneType(bodyParam.type, {
|
|
850
|
+
name: safeConcat(operation.operation.interface?.name, operation.operation.name, "Request"),
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
const { typeReference: bodyType } = this.getTypeInfo(program, tsBody);
|
|
854
|
+
const bodyName = ensureCSharpIdentifier(program, bodyParam.type, "body", NameCasingType.Parameter);
|
|
855
|
+
result.push({
|
|
856
|
+
isExplicitBody: false,
|
|
857
|
+
httpParameterKind: "body",
|
|
858
|
+
name: bodyName,
|
|
859
|
+
callName: bodyName,
|
|
860
|
+
typeName: bodyType,
|
|
861
|
+
nullable: false,
|
|
862
|
+
defaultValue: undefined,
|
|
863
|
+
optional: false,
|
|
864
|
+
operationKind: "Http",
|
|
865
|
+
});
|
|
866
|
+
for (const [propName, propDef] of bodyParam.type.properties) {
|
|
867
|
+
let { typeReference: csType, defaultValue: csValue, nullableType: isNullable, } = this.getTypeInfo(program, propDef.type);
|
|
868
|
+
// cSharp does not allow array defaults in operation parameters
|
|
869
|
+
if (!canHaveDefault(program, propDef)) {
|
|
870
|
+
csValue = undefined;
|
|
871
|
+
}
|
|
872
|
+
const paramName = ensureCSharpIdentifier(program, propDef, propName, NameCasingType.Parameter);
|
|
873
|
+
const refName = ensureCSharpIdentifier(program, propDef, propName, NameCasingType.Property);
|
|
874
|
+
result.push({
|
|
875
|
+
isExplicitBody: false,
|
|
876
|
+
httpParameterKind: "body",
|
|
877
|
+
name: paramName,
|
|
878
|
+
callName: `body.${refName}`,
|
|
879
|
+
typeName: csType,
|
|
880
|
+
nullable: isNullable,
|
|
881
|
+
defaultValue: csValue,
|
|
882
|
+
optional: propDef.optional,
|
|
883
|
+
operationKind: "BusinessLogic",
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
break;
|
|
887
|
+
case "ModelProperty":
|
|
888
|
+
{
|
|
889
|
+
let { typeReference: csType, defaultValue: csValue, nullableType: isNullable, } = this.getTypeInfo(program, bodyParam.type.type);
|
|
890
|
+
if (!canHaveDefault(program, bodyParam.type)) {
|
|
891
|
+
csValue = undefined;
|
|
892
|
+
}
|
|
893
|
+
const optName = ensureCSharpIdentifier(program, bodyParam.type.type, bodyParam.type.name, NameCasingType.Parameter);
|
|
894
|
+
result.push({
|
|
895
|
+
isExplicitBody: true,
|
|
896
|
+
httpParameterKind: "body",
|
|
897
|
+
name: optName,
|
|
898
|
+
callName: optName,
|
|
899
|
+
typeName: csType,
|
|
900
|
+
nullable: isNullable,
|
|
901
|
+
defaultValue: csValue,
|
|
902
|
+
optional: bodyParam.type.optional,
|
|
903
|
+
operationKind: "All",
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
break;
|
|
907
|
+
default: {
|
|
908
|
+
let { typeReference: csType, defaultValue: csValue, nullableType: isNullable, } = this.getTypeInfo(program, bodyParam.type);
|
|
909
|
+
if (!canHaveDefault(program, bodyParam.type)) {
|
|
910
|
+
csValue = undefined;
|
|
911
|
+
}
|
|
912
|
+
result.push({
|
|
913
|
+
isExplicitBody: true,
|
|
914
|
+
httpParameterKind: "body",
|
|
915
|
+
name: "body",
|
|
916
|
+
callName: "body",
|
|
917
|
+
typeName: csType,
|
|
918
|
+
nullable: isNullable,
|
|
919
|
+
defaultValue: csValue,
|
|
920
|
+
optional: false,
|
|
921
|
+
operationKind: "All",
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
for (const parameter of optionalParams) {
|
|
927
|
+
const { typeReference: paramType, defaultValue: paramValue, nullableType: isNullable, } = this.getTypeInfo(program, parameter.param.type);
|
|
928
|
+
const optName = ensureCSharpIdentifier(program, parameter.param, parameter.param.name, NameCasingType.Parameter);
|
|
929
|
+
result.push({
|
|
930
|
+
isExplicitBody: false,
|
|
931
|
+
name: optName,
|
|
932
|
+
callName: optName,
|
|
933
|
+
optional: true,
|
|
934
|
+
typeName: paramType,
|
|
935
|
+
defaultValue: paramValue,
|
|
936
|
+
httpParameterKind: getParameterKind(parameter),
|
|
937
|
+
httpParameterName: parameter.name,
|
|
938
|
+
nullable: isNullable,
|
|
939
|
+
operationKind: "All",
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
this.#opCache.set(operation.operation, result);
|
|
943
|
+
return result;
|
|
944
|
+
}
|
|
945
|
+
getTypeInfo(program, tsType) {
|
|
946
|
+
const myEmitter = this.emitter;
|
|
947
|
+
function extractStringValue(type, span) {
|
|
948
|
+
switch (type.kind) {
|
|
949
|
+
case "String":
|
|
950
|
+
return type.value;
|
|
951
|
+
case "Boolean":
|
|
952
|
+
return `${type.value}`;
|
|
953
|
+
case "Number":
|
|
954
|
+
return type.valueAsString;
|
|
955
|
+
case "StringTemplateSpan":
|
|
956
|
+
if (type.isInterpolated) {
|
|
957
|
+
return extractStringValue(type.type, span);
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
return type.type.value;
|
|
961
|
+
}
|
|
962
|
+
case "ModelProperty":
|
|
963
|
+
return extractStringValue(type.type, span);
|
|
964
|
+
case "EnumMember":
|
|
965
|
+
if (type.value === undefined)
|
|
966
|
+
return type.name;
|
|
967
|
+
if (typeof type.value === "string")
|
|
968
|
+
return type.value;
|
|
969
|
+
if (typeof type.value === "number")
|
|
970
|
+
return `${type.value}`;
|
|
971
|
+
}
|
|
972
|
+
reportDiagnostic(myEmitter.getProgram(), {
|
|
973
|
+
code: "invalid-interpolation",
|
|
974
|
+
target: span,
|
|
975
|
+
format: {},
|
|
976
|
+
});
|
|
977
|
+
return "";
|
|
978
|
+
}
|
|
979
|
+
switch (tsType.kind) {
|
|
980
|
+
case "String":
|
|
981
|
+
return {
|
|
982
|
+
typeReference: code `string`,
|
|
983
|
+
defaultValue: `"${tsType.value}"`,
|
|
984
|
+
nullableType: false,
|
|
985
|
+
};
|
|
986
|
+
case "StringTemplate":
|
|
987
|
+
const template = tsType;
|
|
988
|
+
if (template.stringValue !== undefined)
|
|
989
|
+
return {
|
|
990
|
+
typeReference: code `string`,
|
|
991
|
+
defaultValue: `"${template.stringValue}"`,
|
|
992
|
+
nullableType: false,
|
|
993
|
+
};
|
|
994
|
+
const spanResults = [];
|
|
995
|
+
for (const span of template.spans) {
|
|
996
|
+
spanResults.push(extractStringValue(span, span));
|
|
997
|
+
}
|
|
998
|
+
return {
|
|
999
|
+
typeReference: code `string`,
|
|
1000
|
+
defaultValue: `"${spanResults.join("")}"`,
|
|
1001
|
+
nullableType: false,
|
|
1002
|
+
};
|
|
1003
|
+
case "Boolean":
|
|
1004
|
+
return {
|
|
1005
|
+
typeReference: code `bool`,
|
|
1006
|
+
defaultValue: `${tsType.value === true ? true : false}`,
|
|
1007
|
+
nullableType: false,
|
|
1008
|
+
};
|
|
1009
|
+
case "Number":
|
|
1010
|
+
const [type, value] = findNumericType(tsType);
|
|
1011
|
+
return { typeReference: code `${type}`, defaultValue: `${value}`, nullableType: false };
|
|
1012
|
+
case "Tuple":
|
|
1013
|
+
const defaults = [];
|
|
1014
|
+
const [csharpType, isObject] = coalesceTsTypes(program, tsType.values);
|
|
1015
|
+
if (isObject)
|
|
1016
|
+
return { typeReference: "object[]", defaultValue: undefined, nullableType: false };
|
|
1017
|
+
for (const value of tsType.values) {
|
|
1018
|
+
const { defaultValue: itemDefault } = this.getTypeInfo(program, value);
|
|
1019
|
+
defaults.push(itemDefault);
|
|
1020
|
+
}
|
|
1021
|
+
return {
|
|
1022
|
+
typeReference: code `${csharpType.getTypeReference()}[]`,
|
|
1023
|
+
defaultValue: `[${defaults.join(", ")}]`,
|
|
1024
|
+
nullableType: csharpType.isNullable,
|
|
1025
|
+
};
|
|
1026
|
+
case "Object":
|
|
1027
|
+
return { typeReference: code `object`, defaultValue: undefined, nullableType: false };
|
|
1028
|
+
case "Model":
|
|
1029
|
+
let modelResult;
|
|
1030
|
+
const cachedResult = this.#anonymousModels.get(tsType);
|
|
1031
|
+
if (cachedResult) {
|
|
1032
|
+
return cachedResult;
|
|
1033
|
+
}
|
|
1034
|
+
if (isRecord(tsType)) {
|
|
1035
|
+
modelResult = { typeReference: code `JsonObject`, nullableType: false };
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
modelResult = {
|
|
1039
|
+
typeReference: code `${this.emitter.emitTypeReference(tsType)}`,
|
|
1040
|
+
nullableType: false,
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
this.#anonymousModels.set(tsType, modelResult);
|
|
1044
|
+
return modelResult;
|
|
1045
|
+
case "ModelProperty":
|
|
1046
|
+
return this.getTypeInfo(program, tsType.type);
|
|
1047
|
+
case "Enum":
|
|
1048
|
+
return {
|
|
1049
|
+
typeReference: code `${this.emitter.emitTypeReference(tsType)}`,
|
|
1050
|
+
nullableType: false,
|
|
1051
|
+
};
|
|
1052
|
+
case "EnumMember":
|
|
1053
|
+
if (typeof tsType.value === "number") {
|
|
1054
|
+
const stringValue = tsType.value.toString();
|
|
1055
|
+
if (stringValue.includes(".") || stringValue.includes("e"))
|
|
1056
|
+
return { typeReference: "double", defaultValue: stringValue, nullableType: false };
|
|
1057
|
+
return { typeReference: "int", defaultValue: stringValue, nullableType: false };
|
|
1058
|
+
}
|
|
1059
|
+
if (typeof tsType.value === "string") {
|
|
1060
|
+
return { typeReference: "string", defaultValue: tsType.value, nullableType: false };
|
|
1061
|
+
}
|
|
1062
|
+
return { typeReference: code `object`, nullableType: false };
|
|
1063
|
+
case "Union":
|
|
1064
|
+
return this.getUnionInfo(program, tsType);
|
|
1065
|
+
case "UnionVariant":
|
|
1066
|
+
return this.getTypeInfo(program, tsType.type);
|
|
1067
|
+
default:
|
|
1068
|
+
return {
|
|
1069
|
+
typeReference: code `${this.emitter.emitTypeReference(tsType)}`,
|
|
1070
|
+
nullableType: false,
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
getUnionInfo(program, union) {
|
|
1075
|
+
const propResult = getNonNullableTsType(union);
|
|
1076
|
+
if (propResult === undefined) {
|
|
1077
|
+
return {
|
|
1078
|
+
typeReference: code `${this.emitter.emitTypeReference(union)}`,
|
|
1079
|
+
nullableType: [...union.variants.values()].some((v) => isNullType(v.type)),
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
const candidate = this.getTypeInfo(program, propResult.type);
|
|
1083
|
+
candidate.nullableType = propResult.nullable;
|
|
1084
|
+
return candidate;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
export function getExplicitBodyParameters(program, httpOperation) {
|
|
1088
|
+
if (httpOperation.parameters.body && httpOperation.parameters.body.bodyKind === "multipart") {
|
|
1089
|
+
return [
|
|
1090
|
+
{
|
|
1091
|
+
name: "reader",
|
|
1092
|
+
callName: "reader",
|
|
1093
|
+
nullable: false,
|
|
1094
|
+
optional: false,
|
|
1095
|
+
typeName: "MultipartReader",
|
|
1096
|
+
isExplicitBody: false,
|
|
1097
|
+
httpParameterKind: "body",
|
|
1098
|
+
operationKind: "BusinessLogic",
|
|
1099
|
+
},
|
|
1100
|
+
];
|
|
1101
|
+
}
|
|
1102
|
+
return undefined;
|
|
1103
|
+
}
|
|
1104
|
+
export function findNumericType(type) {
|
|
1105
|
+
const stringValue = type.valueAsString;
|
|
1106
|
+
if (stringValue.includes(".") || stringValue.includes("e"))
|
|
1107
|
+
return ["double", stringValue];
|
|
1108
|
+
return ["int", stringValue];
|
|
1109
|
+
}
|
|
1110
|
+
export function coalesceUnionTypes(program, union) {
|
|
1111
|
+
const [result, _] = coalesceTsTypes(program, [...union.variants.values()].flatMap((v) => v.type));
|
|
1112
|
+
return result;
|
|
1113
|
+
}
|
|
1114
|
+
export function getNonNullableTsType(union) {
|
|
1115
|
+
const types = [...union.variants.values()];
|
|
1116
|
+
const nulls = types.flatMap((v) => v.type).filter((t) => isNullType(t));
|
|
1117
|
+
const nonNulls = types.flatMap((v) => v.type).filter((t) => !isNullType(t));
|
|
1118
|
+
if (nonNulls.length === 1)
|
|
1119
|
+
return { type: nonNulls[0], nullable: nulls.length > 0 };
|
|
1120
|
+
return undefined;
|
|
1121
|
+
}
|
|
1122
|
+
export function coalesceTsTypes(program, types) {
|
|
1123
|
+
const defaultValue = [
|
|
1124
|
+
new CSharpType({
|
|
1125
|
+
name: "object",
|
|
1126
|
+
namespace: "System",
|
|
1127
|
+
isBuiltIn: true,
|
|
1128
|
+
isValueType: false,
|
|
1129
|
+
}),
|
|
1130
|
+
true,
|
|
1131
|
+
];
|
|
1132
|
+
let current = undefined;
|
|
1133
|
+
let nullable = false;
|
|
1134
|
+
for (const type of types) {
|
|
1135
|
+
let candidate = undefined;
|
|
1136
|
+
switch (type.kind) {
|
|
1137
|
+
case "Boolean":
|
|
1138
|
+
candidate = new CSharpType({ name: "bool", namespace: "System", isValueType: true });
|
|
1139
|
+
break;
|
|
1140
|
+
case "StringTemplate":
|
|
1141
|
+
case "String":
|
|
1142
|
+
candidate = new CSharpType({ name: "string", namespace: "System", isValueType: false });
|
|
1143
|
+
break;
|
|
1144
|
+
case "Number":
|
|
1145
|
+
const stringValue = type.valueAsString;
|
|
1146
|
+
if (stringValue.includes(".") || stringValue.includes("e")) {
|
|
1147
|
+
candidate = new CSharpType({
|
|
1148
|
+
name: "double",
|
|
1149
|
+
namespace: "System",
|
|
1150
|
+
isValueType: true,
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
else {
|
|
1154
|
+
candidate = new CSharpType({ name: "int", namespace: "System", isValueType: true });
|
|
1155
|
+
}
|
|
1156
|
+
break;
|
|
1157
|
+
case "Union":
|
|
1158
|
+
candidate = coalesceUnionTypes(program, type);
|
|
1159
|
+
break;
|
|
1160
|
+
case "Scalar":
|
|
1161
|
+
candidate = getCSharpTypeForScalar(program, type);
|
|
1162
|
+
break;
|
|
1163
|
+
case "Intrinsic":
|
|
1164
|
+
if (isNullType(type)) {
|
|
1165
|
+
nullable = true;
|
|
1166
|
+
candidate = current;
|
|
1167
|
+
}
|
|
1168
|
+
else {
|
|
1169
|
+
return defaultValue;
|
|
1170
|
+
}
|
|
1171
|
+
break;
|
|
1172
|
+
default:
|
|
1173
|
+
return defaultValue;
|
|
1174
|
+
}
|
|
1175
|
+
current = current ?? candidate;
|
|
1176
|
+
if (current === undefined || (candidate !== undefined && !candidate.equals(current)))
|
|
1177
|
+
return defaultValue;
|
|
1178
|
+
}
|
|
1179
|
+
if (current !== undefined && nullable === true)
|
|
1180
|
+
current.isNullable = true;
|
|
1181
|
+
return current === undefined ? defaultValue : [current, false];
|
|
1182
|
+
}
|
|
1183
|
+
export function isRecord(type) {
|
|
1184
|
+
return type.kind === "Model" && type.name === "Record" && type.indexer !== undefined;
|
|
1185
|
+
}
|
|
645
1186
|
//# sourceMappingURL=utils.js.map
|