Родитель
e6098a7280
Коммит
fb328a75b4
|
@ -1,15 +1,20 @@
|
|||
steps:
|
||||
- command: "FIXTURE=cplusplus,schema-cplusplus,kotlin,schema-kotlin,graphql .buildkite/build-pr.sh"
|
||||
- command:
|
||||
"FIXTURE=cplusplus,schema-cplusplus,kotlin,schema-kotlin,graphql .buildkite/build-pr.sh"
|
||||
label: "C++ Kotlin GraphQL"
|
||||
|
||||
- command: "FIXTURE=java,schema-java,schema-json-csharp .buildkite/build-pr.sh"
|
||||
- command:
|
||||
"FIXTURE=java,schema-java,schema-json-csharp .buildkite/build-pr.sh"
|
||||
label: "java schema-json-c#"
|
||||
|
||||
- command: "FIXTURE=typescript,schema-typescript,javascript,schema-javascript,flow,schema-flow,json-ts-csharp,python,schema-python .buildkite/build-pr.sh"
|
||||
- command:
|
||||
"FIXTURE=typescript,schema-typescript,javascript,schema-javascript,flow,schema-flow,json-ts-csharp,python,schema-python .buildkite/build-pr.sh"
|
||||
label: "typescript javascript flow python"
|
||||
|
||||
- command: "FIXTURE=swift,schema-swift,rust,schema-rust,elm,schema-elm .buildkite/build-pr.sh"
|
||||
label: "swift rust elm"
|
||||
- command:
|
||||
"FIXTURE=swift,schema-swift,rust,schema-rust,elm,schema-elm,dart,schema-dart .buildkite/build-pr.sh"
|
||||
label: "swift rust elm dart"
|
||||
|
||||
- command: "FIXTURE=csharp,schema-csharp,ruby,schema-ruby,golang,schema-golang .buildkite/build-pr.sh"
|
||||
label: "csharp ruby golang"
|
||||
- command:
|
||||
"FIXTURE=csharp,schema-csharp,ruby,schema-ruby,golang,schema-golang .buildkite/build-pr.sh"
|
||||
label: "csharp ruby golang"
|
||||
|
|
|
@ -58,6 +58,13 @@ RUN apt-get install python3.6 --assume-yes
|
|||
RUN curl https://bootstrap.pypa.io/get-pip.py | python3.6
|
||||
RUN pip3.6 install mypy python-dateutil
|
||||
|
||||
# Dart
|
||||
RUN apt-get install apt-transport-https
|
||||
RUN sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
|
||||
RUN sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
|
||||
RUN apt-get update
|
||||
RUN apt-get install dart
|
||||
|
||||
ENV PATH="${workdir}/node_modules/.bin:${PATH}"
|
||||
|
||||
COPY . .
|
||||
|
|
|
@ -15,6 +15,7 @@ import { ElmTargetLanguage } from "./Elm";
|
|||
import { JSONSchemaTargetLanguage } from "./JSONSchema";
|
||||
import { RustTargetLanguage } from "./Rust";
|
||||
import { RubyTargetLanguage } from "./ruby";
|
||||
import { DartTargetLanguage } from "./Dart";
|
||||
import { PythonTargetLanguage } from "./Python";
|
||||
|
||||
export const all: TargetLanguage[] = [
|
||||
|
@ -32,6 +33,7 @@ export const all: TargetLanguage[] = [
|
|||
new ElmTargetLanguage(),
|
||||
new JSONSchemaTargetLanguage(),
|
||||
new RubyTargetLanguage(),
|
||||
new DartTargetLanguage(),
|
||||
new PythonTargetLanguage("Python", ["python", "py"], "py")
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,487 @@
|
|||
import { Type, EnumType, UnionType, ClassType, ClassProperty } from "../Type";
|
||||
import { matchType, nullableFromUnion, directlyReachableSingleNamedType } from "../TypeUtils";
|
||||
import { Sourcelike, maybeAnnotated, modifySource } from "../Source";
|
||||
import {
|
||||
utf16LegalizeCharacters,
|
||||
escapeNonPrintableMapper,
|
||||
utf16ConcatMap,
|
||||
standardUnicodeHexEscape,
|
||||
isAscii,
|
||||
isLetter,
|
||||
isDigit,
|
||||
splitIntoWords,
|
||||
combineWords,
|
||||
allUpperWordStyle,
|
||||
firstUpperWordStyle,
|
||||
allLowerWordStyle,
|
||||
isPrintable,
|
||||
decapitalize
|
||||
} from "../support/Strings";
|
||||
import { Name, Namer, funPrefixNamer, DependencyName } from "../Naming";
|
||||
import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer";
|
||||
import { TargetLanguage } from "../TargetLanguage";
|
||||
import { Option, BooleanOption, getOptionValues, OptionValues } from "../RendererOptions";
|
||||
import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation";
|
||||
import { defined } from "../support/Support";
|
||||
import { RenderContext } from "../Renderer";
|
||||
import { arrayIntercalate } from "../../../node_modules/collection-utils";
|
||||
import { pythonOptions } from "./Python";
|
||||
|
||||
export const dartOptions = {
|
||||
justTypes: new BooleanOption("just-types", "Types only", false)
|
||||
};
|
||||
|
||||
export class DartTargetLanguage extends TargetLanguage {
|
||||
constructor() {
|
||||
super("Dart", ["dart"], "dart");
|
||||
}
|
||||
|
||||
protected getOptions(): Option<any>[] {
|
||||
return [pythonOptions.justTypes];
|
||||
}
|
||||
|
||||
get supportsUnionsWithBothNumberTypes(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): DartRenderer {
|
||||
const options = getOptionValues(dartOptions, untypedOptionValues);
|
||||
return new DartRenderer(this, renderContext, options);
|
||||
}
|
||||
}
|
||||
|
||||
const keywords = [
|
||||
"abstract",
|
||||
"do",
|
||||
"import",
|
||||
"super",
|
||||
"as",
|
||||
"dynamic",
|
||||
"in",
|
||||
"switch",
|
||||
"assert",
|
||||
"else",
|
||||
"interface",
|
||||
"sync*",
|
||||
"async",
|
||||
"enum",
|
||||
"is",
|
||||
"this",
|
||||
"async*",
|
||||
"export",
|
||||
"library",
|
||||
"throw",
|
||||
"await",
|
||||
"external",
|
||||
"mixin",
|
||||
"true",
|
||||
"break",
|
||||
"extends",
|
||||
"new",
|
||||
"try",
|
||||
"case",
|
||||
"factory",
|
||||
"null",
|
||||
"typedef",
|
||||
"catch",
|
||||
"false",
|
||||
"operator",
|
||||
"var",
|
||||
"class",
|
||||
"final",
|
||||
"part",
|
||||
"void",
|
||||
"const",
|
||||
"finally",
|
||||
"rethrow",
|
||||
"while",
|
||||
"continue",
|
||||
"for",
|
||||
"return",
|
||||
"with",
|
||||
"covariant",
|
||||
"get",
|
||||
"set",
|
||||
"yield",
|
||||
"default",
|
||||
"if",
|
||||
"static",
|
||||
"yield*",
|
||||
"deferred",
|
||||
"implements",
|
||||
"int",
|
||||
"double",
|
||||
"bool",
|
||||
"Map",
|
||||
"List",
|
||||
"String",
|
||||
"File",
|
||||
"fromJson",
|
||||
"toJson"
|
||||
];
|
||||
|
||||
const typeNamingFunction = funPrefixNamer("types", n => dartNameStyle(true, false, n));
|
||||
const propertyNamingFunction = funPrefixNamer("properties", n => dartNameStyle(false, false, n));
|
||||
const enumCaseNamingFunction = funPrefixNamer("enum-cases", n => dartNameStyle(true, true, n));
|
||||
|
||||
// Escape the dollar sign, which is used in string interpolation
|
||||
const stringEscape = utf16ConcatMap(
|
||||
escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape)
|
||||
);
|
||||
|
||||
function isStartCharacter(codePoint: number): boolean {
|
||||
if (codePoint === 0x5f) return false; // underscore
|
||||
return isAscii(codePoint) && isLetter(codePoint);
|
||||
}
|
||||
|
||||
function isPartCharacter(codePoint: number): boolean {
|
||||
return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint));
|
||||
}
|
||||
|
||||
const legalizeName = utf16LegalizeCharacters(isPartCharacter);
|
||||
|
||||
// FIXME: Handle acronyms consistently. In particular, that means that
|
||||
// we have to use namers to produce the getter and setter names - we can't
|
||||
// just capitalize and concatenate.
|
||||
// https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations
|
||||
function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, original: string): string {
|
||||
const words = splitIntoWords(original);
|
||||
const firstWordStyle = upperUnderscore
|
||||
? allUpperWordStyle
|
||||
: startWithUpper
|
||||
? firstUpperWordStyle
|
||||
: allLowerWordStyle;
|
||||
const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle;
|
||||
return combineWords(
|
||||
words,
|
||||
legalizeName,
|
||||
firstWordStyle,
|
||||
restWordStyle,
|
||||
firstWordStyle,
|
||||
restWordStyle,
|
||||
upperUnderscore ? "_" : "",
|
||||
isStartCharacter
|
||||
);
|
||||
}
|
||||
|
||||
type TopLevelDependents = {
|
||||
encoder: Name;
|
||||
decoder: Name;
|
||||
};
|
||||
|
||||
export class DartRenderer extends ConvenienceRenderer {
|
||||
private readonly _gettersAndSettersForPropertyName = new Map<Name, [Name, Name]>();
|
||||
private _needEnumValues = false;
|
||||
private readonly _topLevelDependents = new Map<Name, TopLevelDependents>();
|
||||
private readonly _enumValues = new Map<EnumType, Name>();
|
||||
|
||||
constructor(
|
||||
targetLanguage: TargetLanguage,
|
||||
renderContext: RenderContext,
|
||||
private readonly _options: OptionValues<typeof dartOptions>
|
||||
) {
|
||||
super(targetLanguage, renderContext);
|
||||
}
|
||||
|
||||
protected forbiddenNamesForGlobalNamespace(): string[] {
|
||||
return keywords;
|
||||
}
|
||||
|
||||
protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo {
|
||||
return { names: [], includeGlobalForbidden: true };
|
||||
}
|
||||
|
||||
protected makeNamedTypeNamer(): Namer {
|
||||
return typeNamingFunction;
|
||||
}
|
||||
|
||||
protected namerForObjectProperty(): Namer {
|
||||
return propertyNamingFunction;
|
||||
}
|
||||
|
||||
protected makeUnionMemberNamer(): Namer {
|
||||
return propertyNamingFunction;
|
||||
}
|
||||
|
||||
protected makeEnumCaseNamer(): Namer {
|
||||
return enumCaseNamingFunction;
|
||||
}
|
||||
|
||||
protected unionNeedsName(u: UnionType): boolean {
|
||||
return nullableFromUnion(u) === null;
|
||||
}
|
||||
|
||||
protected namedTypeToNameForTopLevel(type: Type): Type | undefined {
|
||||
// If the top-level type doesn't contain any classes or unions
|
||||
// we have to define a class just for the `FromJson` method, in
|
||||
// emitFromJsonForTopLevel.
|
||||
return directlyReachableSingleNamedType(type);
|
||||
}
|
||||
|
||||
protected makeTopLevelDependencyNames(_t: Type, name: Name): DependencyName[] {
|
||||
const encoder = new DependencyName(propertyNamingFunction, name.order, lookup => `${lookup(name)}_to_json`);
|
||||
const decoder = new DependencyName(propertyNamingFunction, name.order, lookup => `${lookup(name)}_from_json`);
|
||||
this._topLevelDependents.set(name, { encoder, decoder });
|
||||
return [encoder, decoder];
|
||||
}
|
||||
|
||||
protected makeNamesForPropertyGetterAndSetter(
|
||||
_c: ClassType,
|
||||
_className: Name,
|
||||
_p: ClassProperty,
|
||||
_jsonName: string,
|
||||
name: Name
|
||||
): [Name, Name] {
|
||||
const getterName = new DependencyName(propertyNamingFunction, name.order, lookup => `get_${lookup(name)}`);
|
||||
const setterName = new DependencyName(propertyNamingFunction, name.order, lookup => `set_${lookup(name)}`);
|
||||
return [getterName, setterName];
|
||||
}
|
||||
|
||||
protected makePropertyDependencyNames(
|
||||
c: ClassType,
|
||||
className: Name,
|
||||
p: ClassProperty,
|
||||
jsonName: string,
|
||||
name: Name
|
||||
): Name[] {
|
||||
const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name);
|
||||
this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames);
|
||||
return getterAndSetterNames;
|
||||
}
|
||||
|
||||
protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] {
|
||||
if (!(t instanceof EnumType)) return [];
|
||||
const enumValue = new DependencyName(propertyNamingFunction, name.order, lookup => `${lookup(name)}_values`);
|
||||
this._enumValues.set(t, enumValue);
|
||||
return [enumValue];
|
||||
}
|
||||
|
||||
protected emitFileHeader(): void {
|
||||
if (this.leadingComments !== undefined) {
|
||||
this.emitCommentLines(this.leadingComments);
|
||||
}
|
||||
|
||||
if (this._options.justTypes) return;
|
||||
|
||||
this.emitLine("// To parse this JSON data, do");
|
||||
this.emitLine("//");
|
||||
this.forEachTopLevel("none", (_t, name) => {
|
||||
const { decoder } = defined(this._topLevelDependents.get(name));
|
||||
this.emitLine("// final ", modifySource(decapitalize, name), " = ", decoder, "(jsonString);");
|
||||
});
|
||||
|
||||
this.ensureBlankLine();
|
||||
this.emitLine("import 'dart:convert';");
|
||||
}
|
||||
|
||||
protected emitDescriptionBlock(lines: string[]): void {
|
||||
this.emitCommentLines(lines, " * ", "/**", " */");
|
||||
}
|
||||
|
||||
protected emitBlock(line: Sourcelike, f: () => void): void {
|
||||
this.emitLine(line, " {");
|
||||
this.indent(f);
|
||||
this.emitLine("}");
|
||||
}
|
||||
|
||||
protected dartType(t: Type, withIssues: boolean = false): Sourcelike {
|
||||
return matchType<Sourcelike>(
|
||||
t,
|
||||
_anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "dynamic"),
|
||||
_nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "dynamic"),
|
||||
_boolType => "bool",
|
||||
_integerType => "int",
|
||||
_doubleType => "double",
|
||||
_stringType => "String",
|
||||
arrayType => ["List<", this.dartType(arrayType.items, withIssues), ">"],
|
||||
classType => this.nameForNamedType(classType),
|
||||
mapType => ["Map<String, ", this.dartType(mapType.values, withIssues), ">"],
|
||||
enumType => this.nameForNamedType(enumType),
|
||||
unionType => {
|
||||
const maybeNullable = nullableFromUnion(unionType);
|
||||
if (maybeNullable === null) {
|
||||
return "dynamic";
|
||||
}
|
||||
return this.dartType(maybeNullable, withIssues);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected mapList(itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike {
|
||||
return ["new List<", itemType, ">.from(", list, ".map((x) => ", mapper, "))"];
|
||||
}
|
||||
|
||||
protected mapMap(valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike {
|
||||
return ["new Map.from(", map, ").map((k, v) => new MapEntry<String, ", valueType, ">(k, ", valueMapper, "))"];
|
||||
}
|
||||
|
||||
protected fromDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike {
|
||||
return matchType<Sourcelike>(
|
||||
t,
|
||||
_anyType => dynamic,
|
||||
_nullType => dynamic, // FIXME: check null
|
||||
_boolType => dynamic,
|
||||
_integerType => dynamic,
|
||||
_doubleType => [dynamic, ".toDouble()"],
|
||||
_stringType => dynamic,
|
||||
arrayType =>
|
||||
this.mapList(this.dartType(arrayType.items), dynamic, this.fromDynamicExpression(arrayType.items, "x")),
|
||||
classType => [this.nameForNamedType(classType), ".fromJson(", dynamic, ")"],
|
||||
mapType =>
|
||||
this.mapMap(this.dartType(mapType.values), dynamic, this.fromDynamicExpression(mapType.values, "v")),
|
||||
enumType => [defined(this._enumValues.get(enumType)), ".map[", dynamic, "]"],
|
||||
unionType => {
|
||||
const maybeNullable = nullableFromUnion(unionType);
|
||||
if (maybeNullable === null) {
|
||||
return dynamic;
|
||||
}
|
||||
return [dynamic, " == null ? null : ", this.fromDynamicExpression(maybeNullable, dynamic)];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected toDynamicExpression = (t: Type, ...dynamic: Sourcelike[]): Sourcelike => {
|
||||
return matchType<Sourcelike>(
|
||||
t,
|
||||
_anyType => dynamic,
|
||||
_nullType => dynamic,
|
||||
_boolType => dynamic,
|
||||
_integerType => dynamic,
|
||||
_doubleType => dynamic,
|
||||
_stringType => dynamic,
|
||||
arrayType => this.mapList("dynamic", dynamic, this.toDynamicExpression(arrayType.items, "x")),
|
||||
_classType => [dynamic, ".toJson()"],
|
||||
mapType => this.mapMap("dynamic", dynamic, this.toDynamicExpression(mapType.values, "v")),
|
||||
enumType => [defined(this._enumValues.get(enumType)), ".reverse[", dynamic, "]"],
|
||||
unionType => {
|
||||
const maybeNullable = nullableFromUnion(unionType);
|
||||
if (maybeNullable === null) {
|
||||
return dynamic;
|
||||
}
|
||||
return [dynamic, " == null ? null : ", this.toDynamicExpression(maybeNullable, dynamic)];
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
protected emitClassDefinition(c: ClassType, className: Name): void {
|
||||
this.emitDescription(this.descriptionForType(c));
|
||||
this.emitBlock(["class ", className], () => {
|
||||
if (c.getProperties().size === 0) {
|
||||
this.emitLine(className, "();");
|
||||
} else {
|
||||
this.forEachClassProperty(c, "none", (name, _, p) => {
|
||||
this.emitLine(this.dartType(p.type, true), " ", name, ";");
|
||||
});
|
||||
this.ensureBlankLine();
|
||||
|
||||
this.emitLine(className, "({");
|
||||
this.indent(() => {
|
||||
this.forEachClassProperty(c, "none", (name, _, _p) => {
|
||||
this.emitLine("this.", name, ",");
|
||||
});
|
||||
});
|
||||
this.emitLine("});");
|
||||
}
|
||||
|
||||
if (this._options.justTypes) return;
|
||||
|
||||
this.ensureBlankLine();
|
||||
this.emitLine("factory ", className, ".fromJson(Map<String, dynamic> json) => new ", className, "(");
|
||||
this.indent(() => {
|
||||
this.forEachClassProperty(c, "none", (name, jsonName, property) => {
|
||||
this.emitLine(
|
||||
name,
|
||||
": ",
|
||||
this.fromDynamicExpression(property.type, 'json["', stringEscape(jsonName), '"]'),
|
||||
","
|
||||
);
|
||||
});
|
||||
});
|
||||
this.emitLine(");");
|
||||
this.ensureBlankLine();
|
||||
|
||||
this.emitLine("Map<String, dynamic> toJson() => {");
|
||||
this.indent(() => {
|
||||
this.forEachClassProperty(c, "none", (name, jsonName, property) => {
|
||||
this.emitLine(
|
||||
'"',
|
||||
stringEscape(jsonName),
|
||||
'": ',
|
||||
this.toDynamicExpression(property.type, name),
|
||||
","
|
||||
);
|
||||
});
|
||||
});
|
||||
this.emitLine("};");
|
||||
});
|
||||
}
|
||||
|
||||
protected emitEnumDefinition(e: EnumType, enumName: Name): void {
|
||||
const caseNames: Sourcelike[] = Array.from(e.cases).map(c => this.nameForEnumCase(e, c));
|
||||
this.emitDescription(this.descriptionForType(e));
|
||||
this.emitLine("enum ", enumName, " { ", arrayIntercalate(", ", caseNames), " }");
|
||||
|
||||
if (this._options.justTypes) return;
|
||||
|
||||
this.ensureBlankLine();
|
||||
this.emitLine("final ", defined(this._enumValues.get(e)), " = new EnumValues({");
|
||||
this.indent(() => {
|
||||
this.forEachEnumCase(e, "none", (name, jsonName, pos) => {
|
||||
const comma = pos === "first" || pos === "middle" ? "," : [];
|
||||
this.emitLine('"', stringEscape(jsonName), '": ', enumName, ".", name, comma);
|
||||
});
|
||||
});
|
||||
this.emitLine("});");
|
||||
|
||||
this._needEnumValues = true;
|
||||
}
|
||||
|
||||
protected emitEnumValues(): void {
|
||||
this.ensureBlankLine();
|
||||
this.emitMultiline(`class EnumValues<T> {
|
||||
Map<String, T> map;
|
||||
Map<T, String> reverseMap;
|
||||
|
||||
EnumValues(this.map);
|
||||
|
||||
Map<T, String> get reverse {
|
||||
if (reverseMap == null) {
|
||||
reverseMap = map.map((k, v) => new MapEntry(v, k));
|
||||
}
|
||||
return reverseMap;
|
||||
}
|
||||
}`);
|
||||
}
|
||||
|
||||
protected emitSourceStructure(): void {
|
||||
this.emitFileHeader();
|
||||
|
||||
if (!this._options.justTypes) {
|
||||
this.forEachTopLevel("leading-and-interposing", (t, name) => {
|
||||
const { encoder, decoder } = defined(this._topLevelDependents.get(name));
|
||||
this.emitBlock([this.dartType(t), " ", decoder, "(String str)"], () => {
|
||||
this.emitLine("final jsonData = json.decode(str);");
|
||||
this.emitLine("return ", this.fromDynamicExpression(t, "jsonData"), ";");
|
||||
});
|
||||
this.ensureBlankLine();
|
||||
this.emitBlock(["String ", encoder, "(", this.dartType(t), " data)"], () => {
|
||||
this.emitLine("final dyn = ", this.toDynamicExpression(t, "data"), ";");
|
||||
this.emitLine("return json.encode(dyn);");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.forEachNamedType(
|
||||
"leading-and-interposing",
|
||||
(c: ClassType, n: Name) => this.emitClassDefinition(c, n),
|
||||
(e, n) => this.emitEnumDefinition(e, n),
|
||||
(_e, _n) => {
|
||||
// We don't support this yet.
|
||||
}
|
||||
);
|
||||
|
||||
if (this._needEnumValues) {
|
||||
this.emitEnumValues();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -677,6 +677,7 @@ export const allFixtures: Fixture[] = [
|
|||
new JSONFixture(languages.FlowLanguage),
|
||||
new JSONFixture(languages.JavaScriptLanguage),
|
||||
new JSONFixture(languages.KotlinLanguage),
|
||||
new JSONFixture(languages.DartLanguage),
|
||||
new JSONSchemaJSONFixture(languages.CSharpLanguage),
|
||||
new JSONTypeScriptFixture(languages.CSharpLanguage),
|
||||
new JSONSchemaFixture(languages.CSharpLanguage),
|
||||
|
@ -692,6 +693,7 @@ export const allFixtures: Fixture[] = [
|
|||
new JSONSchemaFixture(languages.FlowLanguage),
|
||||
new JSONSchemaFixture(languages.JavaScriptLanguage),
|
||||
new JSONSchemaFixture(languages.KotlinLanguage),
|
||||
new JSONSchemaFixture(languages.DartLanguage),
|
||||
// FIXME: Why are we missing so many language with GraphQL?
|
||||
new GraphQLFixture(languages.CSharpLanguage),
|
||||
new GraphQLFixture(languages.JavaLanguage),
|
||||
|
@ -702,5 +704,6 @@ export const allFixtures: Fixture[] = [
|
|||
new GraphQLFixture(languages.ObjectiveCLanguage, true),
|
||||
new GraphQLFixture(languages.TypeScriptLanguage),
|
||||
new GraphQLFixture(languages.FlowLanguage),
|
||||
new GraphQLFixture(languages.JavaScriptLanguage)
|
||||
new GraphQLFixture(languages.JavaScriptLanguage),
|
||||
new GraphQLFixture(languages.DartLanguage)
|
||||
];
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import 'dart:io';
|
||||
import 'TopLevel.dart';
|
||||
|
||||
void main(List<String> arguments) async {
|
||||
final path = arguments[0];
|
||||
new File(path).readAsString().then((String contents) async {
|
||||
final topLevel = topLevelFromJson(contents);
|
||||
final result = topLevelToJson(topLevel);
|
||||
stdout.write(result);
|
||||
});
|
||||
}
|
|
@ -659,3 +659,23 @@ export const KotlinLanguage: Language = {
|
|||
quickTestRendererOptions: [],
|
||||
sourceFiles: ["src/Language/Kotlin.ts"]
|
||||
};
|
||||
|
||||
export const DartLanguage: Language = {
|
||||
name: "dart",
|
||||
base: "test/fixtures/dart",
|
||||
runCommand(sample: string) {
|
||||
return `dart parser.dart \"${sample}\"`;
|
||||
},
|
||||
diffViaSchema: false,
|
||||
skipDiffViaSchema: [],
|
||||
allowMissingNull: true,
|
||||
features: [],
|
||||
output: "TopLevel.dart",
|
||||
topLevel: "TopLevel",
|
||||
skipJSON: [],
|
||||
skipSchema: [],
|
||||
skipMiscJSON: false,
|
||||
rendererOptions: {},
|
||||
quickTestRendererOptions: [],
|
||||
sourceFiles: ["src/Language/Dart.ts"]
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче