Property descriptions
This commit is contained in:
Родитель
a839469367
Коммит
7fca47e143
|
@ -24,7 +24,14 @@ import { Sourcelike, sourcelikeToSource, serializeRenderResult } from "./Source"
|
|||
import { trimEnd } from "lodash";
|
||||
import { declarationsForGraph, DeclarationIR, cycleBreakerTypesForGraph, Declaration } from "./DeclarationIR";
|
||||
import { TypeAttributeStoreView } from "./TypeGraph";
|
||||
import { TypeAttributeKind, descriptionTypeAttributeKind } from "./TypeAttributes";
|
||||
import { TypeAttributeKind, descriptionTypeAttributeKind, propertyDescriptionsTypeAttributeKind } from "./TypeAttributes";
|
||||
|
||||
function splitDescription(description: string | undefined): string[] | undefined {
|
||||
if (description === undefined) return undefined;
|
||||
description = description.trim();
|
||||
if (description === "") return undefined;
|
||||
return description.split("\n").map(l => l.trim());
|
||||
}
|
||||
|
||||
export type ForbiddenWordsInfo = { names: (Name | string)[]; includeGlobalForbidden: boolean };
|
||||
|
||||
|
@ -136,10 +143,13 @@ export abstract class ConvenienceRenderer extends Renderer {
|
|||
|
||||
protected descriptionForType(t: Type): string[] | undefined {
|
||||
let description = this.typeGraph.attributeStore.tryGet(descriptionTypeAttributeKind, t);
|
||||
if (description === undefined) return undefined;
|
||||
description = description.trim();
|
||||
if (description === "") return undefined;
|
||||
return description.split("\n").map(l => l.trim());
|
||||
return splitDescription(description);
|
||||
}
|
||||
|
||||
protected descriptionForClassProperty(c: ClassType, name: string): string[] | undefined {
|
||||
const descriptions = this.typeGraph.attributeStore.tryGet(propertyDescriptionsTypeAttributeKind, c);
|
||||
if (descriptions === undefined) return undefined;
|
||||
return splitDescription(descriptions.get(name));
|
||||
}
|
||||
|
||||
protected setUpNaming(): OrderedSet<Namespace> {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { TypeGraphBuilder, TypeRef } from "./TypeBuilder";
|
|||
import { TypeNames } from "./TypeNames";
|
||||
import { unifyTypes } from "./UnifyClasses";
|
||||
import { makeNamesTypeAttributes, modifyTypeNames, singularizeTypeNames } from "./TypeNames";
|
||||
import { TypeAttributes, descriptionTypeAttributeKind } from "./TypeAttributes";
|
||||
import { TypeAttributes, descriptionTypeAttributeKind, propertyDescriptionsTypeAttributeKind } from "./TypeAttributes";
|
||||
|
||||
enum PathElementKind {
|
||||
Root,
|
||||
|
@ -170,12 +170,25 @@ export function schemaToType(
|
|||
|
||||
function makeClass(path: Ref, attributes: TypeAttributes, properties: StringMap, requiredArray: string[]): TypeRef {
|
||||
const required = Set(requiredArray);
|
||||
const propertiesMap = Map(properties);
|
||||
const propertyDescriptions = propertiesMap.map(propSchema => {
|
||||
if (typeof propSchema === "object") {
|
||||
const desc = propSchema.description;
|
||||
if (typeof desc === "string") {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}).filter(v => v !== undefined) as Map<string, string>;
|
||||
if (!propertyDescriptions.isEmpty()) {
|
||||
attributes = propertyDescriptionsTypeAttributeKind.setInAttributes(attributes, propertyDescriptions);
|
||||
}
|
||||
const result = typeBuilder.getUniqueClassType(attributes, true);
|
||||
setTypeForPath(path, result);
|
||||
// FIXME: We're using a Map instead of an OrderedMap here because we represent
|
||||
// the JSON Schema as a JavaScript object, which has no map ordering. Ideally
|
||||
// we would use a JSON parser that preserves order.
|
||||
const props = Map(properties).map((propSchema, propName) => {
|
||||
const props = propertiesMap.map((propSchema, propName) => {
|
||||
const t = toType(
|
||||
checkStringMap(propSchema),
|
||||
path.push({ kind: PathElementKind.Property, name: propName }),
|
||||
|
|
|
@ -83,6 +83,11 @@ function isValueType(t: Type): boolean {
|
|||
return primitiveValueTypeKinds.indexOf(kind) >= 0 || kind === "class" || kind === "enum";
|
||||
}
|
||||
|
||||
function singleDescriptionComment(description: string[] | undefined): string {
|
||||
if (description === undefined) return "";
|
||||
return "// " + description.join("; ");
|
||||
}
|
||||
|
||||
class GoRenderer extends ConvenienceRenderer {
|
||||
private _topLevelUnmarshalNames = Map<Name, Name>();
|
||||
|
||||
|
@ -201,7 +206,8 @@ class GoRenderer extends ConvenienceRenderer {
|
|||
let columns: Sourcelike[][] = [];
|
||||
this.forEachClassProperty(c, "none", (name, jsonName, p) => {
|
||||
const goType = this.goType(p.type, true);
|
||||
columns.push([[name, " "], [goType, " "], ['`json:"', stringEscape(jsonName), '"`']]);
|
||||
const comment = singleDescriptionComment(this.descriptionForClassProperty(c, jsonName));
|
||||
columns.push([[name, " "], [goType, " "], ['`json:"', stringEscape(jsonName), '"`'], comment]);
|
||||
});
|
||||
this.emitDescription(this.descriptionForType(c));
|
||||
this.emitStruct(className, columns);
|
||||
|
|
|
@ -65,4 +65,12 @@ export function combineTypeAttributes(attributeArray: TypeAttributes[]): TypeAtt
|
|||
return first.mergeWith((aa, ab, kind) => kind.combine(aa, ab), ...rest);
|
||||
}
|
||||
|
||||
export const descriptionTypeAttributeKind = new TypeAttributeKind<string>("description", undefined);
|
||||
function combineDescriptions(a: string, b: string): string {
|
||||
return a.trim() + "\n\n" + b.trim();
|
||||
}
|
||||
|
||||
export const descriptionTypeAttributeKind = new TypeAttributeKind<string>("description", combineDescriptions);
|
||||
export const propertyDescriptionsTypeAttributeKind = new TypeAttributeKind<Map<string, string>>(
|
||||
"propertyDescriptions",
|
||||
(a, b) => a.mergeWith(combineDescriptions, b)
|
||||
);
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
"type": "string",
|
||||
"enum": ["foo", "bar"],
|
||||
"description": "An enumeration"
|
||||
},
|
||||
"foo": {
|
||||
"type": "number"
|
||||
},
|
||||
"bar": {
|
||||
"type": "boolean",
|
||||
"description": "A pretty boolean"
|
||||
}
|
||||
},
|
||||
"required": ["union", "enum"],
|
||||
|
|
Загрузка…
Ссылка в новой задаче