From cc5ee919e42a9d99039407de39085e70c0a4c840 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 9 Mar 2018 13:21:46 +0900 Subject: [PATCH 1/5] add webidl2.js types --- types/webidl2/index.d.ts | 278 +++++++++++++++++++++++++++++++++ types/webidl2/tsconfig.json | 25 +++ types/webidl2/tslint.json | 1 + types/webidl2/webidl2-tests.ts | 138 ++++++++++++++++ 4 files changed, 442 insertions(+) create mode 100644 types/webidl2/index.d.ts create mode 100644 types/webidl2/tsconfig.json create mode 100644 types/webidl2/tslint.json create mode 100644 types/webidl2/webidl2-tests.ts diff --git a/types/webidl2/index.d.ts b/types/webidl2/index.d.ts new file mode 100644 index 0000000000..e9805357e1 --- /dev/null +++ b/types/webidl2/index.d.ts @@ -0,0 +1,278 @@ +// Type definitions for webidl2.js +// Project: https://github.com/w3c/webidl2.js/ +// Definitions by: Kagama Sascha Rosylight +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +export declare function parse(str: string, options?: ParseOptions): IDLRootType[]; + +export type IDLRootType = InterfaceType | InterfaceMixinType | NamespaceType | CallbackType | DictionaryType | EnumType | TypedefType | ImplementsType | IncludesType; + +export type IDLInterfaceMemberType = OperationMemberType | AttributeMemberType | ConstantMemberType | DeclarationMemberType; + +export type IDLNamespaceMemberType = OperationMemberType | AttributeMemberType; + +export interface ParseOptions { + /** Boolean indicating whether the parser should accept typedefs as valid members of interfaces. */ + allowNestedTypedefs?: boolean; +} + +export interface WebIDLParseError { + /** the error message */ + message: string; + /** the line at which the error occurred. */ + line: number; + /** a short peek at the text at the point where the error happened */ + input: string; + /** the five tokens at the point of error, as understood by the tokeniser */ + tokens: ValueDescription[]; + + toString(): string; +} + +export interface IDLTypeDescription { + type: string; + /** Boolean indicating if it is a sequence. Same as generic === "sequence" */ + sequence: boolean; + /** String indicating the generic type (e.g. "Promise", "sequence"). null otherwise. */ + generic: string | null; + /** Boolean indicating whether this is nullable or not. */ + nullable: boolean; + /** Boolean indicating whether this is a union type or not. */ + union: boolean; + /** In most cases, this will just be a string with the type name. + If the type is a union, then this contains an array of the types it unites. + If it is a generic type, it contains the IDL type description for the type in the sequence, + the eventual value of the promise, etc. */ + idlType: string | IDLTypeDescription | IDLTypeDescription[]; +} + +export interface InterfaceType { + type: "interface" | "callback interface"; + /** The name of the interface */ + name: string; + /** A boolean indicating whether it's a partial interface. */ + partial: boolean; + /** An array of interface members (attributes, operations, etc.). Empty if there are none. */ + members: IDLInterfaceMemberType[]; + /** A string giving the name of an interface this one inherits from, null otherwise. */ + inheritance: string | null; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface InterfaceMixinType { + type: "interface mixin"; + /** The name of the interface mixin */ + name: string; + /** A boolean indicating whether it's a partial interface mixin. */ + partial: boolean; + /** An array of interface members (attributes, operations, etc.). Empty if there are none. */ + members: IDLInterfaceMemberType[]; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface NamespaceType { + type: "namespace"; + /** A boolean indicating whether it's a partial namespace. */ + partial: boolean; + /** The enum's name. */ + name: string; + /** An array of namespace members (attributes, operations). Empty if there are none. */ + members: IDLNamespaceMemberType[]; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface CallbackType { + type: "callback"; + /** The name of the callback. */ + name: string; + /** An IDL Type describing what the callback returns. */ + idlType: IDLTypeDescription; + /** A list of arguments, as in function paramters. */ + arguments: Argument[]; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface DictionaryType { + type: "dictionary"; + /** The dictionary name. */ + name: string; + /** Boolean indicating whether it's a partial dictionary. */ + partial: boolean; + /** An array of members (see below). */ + members: DictionaryMemberType[]; + /** A string indicating which dictionary is being inherited from, null otherwise. */ + inheritance: string | null; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface DictionaryMemberType extends FieldType { + /** Boolean indicating whether this is a required field. */ + required: boolean; + /** A default value, absent if there is none. */ + default: ValueDescription | null; +} + +export interface FieldType { + type: "field"; + /** The name of the field. */ + name: string; + /** An IDL Type describing what field's type. */ + idlType: IDLTypeDescription; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; + /** A default value, absent if there is none. */ + default: ValueDescription | null; +} + +export interface EnumType { + type: "enum"; + /** The enum's name. */ + name: string; + /** An array of values (strings). */ + values: { type: "string", value: string }[]; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface TypedefType { + type: "typedef"; + /** The typedef's name. */ + name: string; + /** An IDL Type describing what typedef's type. */ + idlType: IDLTypeDescription; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface ImplementsType { + type: "implements"; + /** The interface that implements another. */ + target: string; + /** The interface that is being implemented by the target. */ + implements: string; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface IncludesType { + type: "includes"; + /** The interface that includes an interface mixin. */ + target: string; + /** The interface mixin that is being included by the target. */ + includes: string; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface OperationMemberType { + type: "operation"; + /** True if a getter operation. */ + getter: boolean; + /** True if a setter operation. */ + setter: boolean; + /** True if a deleter operation. */ + deleter: boolean; + /** True if a static operation. */ + static: boolean; + /** True if a stringifier operation. */ + stringifier: boolean; + /** An IDL Type of what the operation returns. If a stringifier, may be absent. */ + idlType: IDLTypeDescription | null; + /** The name of the operation. If a stringifier, may be null. */ + name: string | null; + /** An array of arguments for the operation. */ + arguments: Argument[] | null; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface AttributeMemberType { + type: "attribute"; + /** The attribute's name. */ + name: string; + /** True if it's a static attribute. */ + static: boolean; + /** True if it's a stringifier attribute. */ + stringifier: boolean; + /** True if it's an inherit attribute. */ + inherit: boolean; + /** True if it's a read-only attribute. */ + readonly: boolean; + /** An IDL Type for the attribute. */ + idlType: IDLTypeDescription; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface ConstantMemberType { + type: "const"; + /** Whether its type is nullable. */ + nullable: boolean; + /** The type of the constant (a simple type, the type name). */ + idlType: string; + /** The name of the constant. */ + name: string; + /** The constant value */ + value: ValueDescription; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface Argument { + default: ValueDescription; + /** True if the argument is optional. */ + optional: boolean; + /** True if the argument is variadic. */ + variadic: boolean; + /** An IDL Type describing the type of the argument. */ + idlType: IDLTypeDescription; + /** The argument's name. */ + name: string; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} + +export interface ExtendedAttributes { + /** The extended attribute's name. */ + name: string; + /** If the extended attribute takes arguments or if its right-hand side does they are listed here. */ + arguments: Argument[]; + /** If there is a right-hand side, this will capture its type ("identifier" or "identifier-list") and its value. */ + rhs: ExtendedAttributeRightHandSideIdentifier | ExtendedAttributeRightHandSideIdentifierList; +} + +export interface Token { + type: "float" | "integer" | "identifier" | "string" | "whitespace" | "other"; + value: string; +} + +export interface ExtendedAttributeRightHandSideIdentifier { + type: "identifier"; + value: string; +} + +export interface ExtendedAttributeRightHandSideIdentifierList { + type: "identifier-list" + value: string[]; +} + +export interface ValueDescription { + type: "string" | "number" | "boolean" | "null" | "Infinity" | "NaN" | "sequence"; + value: string | any[] | null; + negative: boolean | null; +} + +export interface DeclarationMemberType { + type: "iterable" | "legacyiterable" | "setlike" | "maplike"; + /** An array with one or more IDL Types representing the declared type arguments. */ + idlType: IDLTypeDescription[]; + /** Whether the maplike or setlike is declared as read only. */ + readonly: boolean; + /** A list of extended attributes. */ + extAttrs: ExtendedAttributes[]; +} diff --git a/types/webidl2/tsconfig.json b/types/webidl2/tsconfig.json new file mode 100644 index 0000000000..3d3ff31d07 --- /dev/null +++ b/types/webidl2/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": false, + "strictNullChecks": false, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "webidl2-tests.ts" + ] +} diff --git a/types/webidl2/tslint.json b/types/webidl2/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/webidl2/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/webidl2/webidl2-tests.ts b/types/webidl2/webidl2-tests.ts new file mode 100644 index 0000000000..b008b4d11a --- /dev/null +++ b/types/webidl2/webidl2-tests.ts @@ -0,0 +1,138 @@ +import * as webidl2 from "webidl2"; + +const parsed = webidl2.parse(""); + +for (const rootType of parsed) { + if (rootType.type !== "implements" && rootType.type !== "includes") { + console.log(rootType.name); + } + if (rootType.type === "interface") { + console.log(rootType.inheritance); + logMembers(rootType.members); + console.log(rootType.partial); + } + else if (rootType.type === "interface mixin") { + logMembers(rootType.members); + console.log(rootType.partial); + } + else if (rootType.type === "namespace") { + console.log(rootType.partial); + logNamespaceMembers(rootType.members); + } + else if (rootType.type === "callback interface") { + logMembers(rootType.members); + console.log(rootType.partial); + } + else if (rootType.type === "callback") { + logArguments(rootType.arguments); + } + else if (rootType.type === "dictionary") { + console.log(rootType.inheritance); + for (const member of rootType.members) { + console.log(member.required, member.default); + } + } + else if (rootType.type === "enum") { + for (const v of rootType.values) { + console.log(v.type); + console.log(v.value); + } + } + else if (rootType.type === "typedef") { + logIdlType(rootType.idlType); + } + else if (rootType.type === "implements") { + console.log(rootType.target); + console.log(rootType.implements); + } + else if (rootType.type === "includes") { + console.log(rootType.target); + console.log(rootType.includes); + } + + logExtAttrs(rootType.extAttrs); +} + +function logMembers(members: webidl2.IDLInterfaceMemberType[]) { + for (const member of members) { + if (member.type === "operation" || member.type === "attribute") { + logNamespaceMembers([member]); + } + else if (member.type === "const") { + console.log(member.name); + console.log(member.value); + console.log(member.nullable); + } + else if (member.type === "iterable") { + console.log(member.readonly); + } + else if (member.type === "legacyiterable") { + console.log(member.readonly); + } + else if (member.type === "setlike") { + console.log(member.readonly); + } + else if (member.type === "maplike") { + console.log(member.readonly); + } + + logIdlType(member.idlType); + logExtAttrs(member.extAttrs); + } +} + +function logNamespaceMembers(members: webidl2.IDLNamespaceMemberType[]) { + for (const member of members) { + if (member.type === "operation") { + console.log(member.name); + console.log(member.getter, member.setter, member.deleter); + console.log(member.static, member.stringifier); + } + else if (member.type === "attribute") { + console.log(member.name); + console.log(member.static, member.stringifier, member.readonly, member.inherit); + } + } +} + +function logExtAttrs(extAttrs: webidl2.ExtendedAttributes[]) { + console.log(extAttrs[0].name); + logArguments(extAttrs[0].arguments); + const { rhs } = extAttrs[0]; + if (rhs.type === "identifier") { + console.log(rhs); + } + else { + for (const v of rhs.value) { + console.log(v); + } + } +} + +function logArguments(args: webidl2.Argument[]) { + for (const arg of args) { + console.log(arg.name); + console.log(arg.default, arg.optional, arg.variadic); + logIdlType(arg.idlType); + logExtAttrs(arg.extAttrs); + } +} + +function logIdlType(idlType: string | webidl2.IDLTypeDescription | webidl2.IDLTypeDescription[]) { + if (typeof idlType === "string") { + return; + } + if (Array.isArray(idlType)) { + for (const t of idlType) { + logEachType(t); + } + return; + } + logEachType(idlType); + + function logEachType(t: webidl2.IDLTypeDescription) { + console.log(t.type); + console.log(t.generic, t.nullable, t.sequence, t.union); + logIdlType(t.idlType); + } +} From 3246586fee8a43f4e075229fe2282d4ad7d38dc5 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 9 Mar 2018 13:47:33 +0900 Subject: [PATCH 2/5] linting --- types/webidl2/index.d.ts | 19 +++-- types/webidl2/webidl2-tests.ts | 134 +++++++++++++++++---------------- 2 files changed, 79 insertions(+), 74 deletions(-) diff --git a/types/webidl2/index.d.ts b/types/webidl2/index.d.ts index e9805357e1..a1999c1c2e 100644 --- a/types/webidl2/index.d.ts +++ b/types/webidl2/index.d.ts @@ -1,9 +1,9 @@ -// Type definitions for webidl2.js +// Type definitions for webidl2.js 10.2 // Project: https://github.com/w3c/webidl2.js/ // Definitions by: Kagama Sascha Rosylight // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -export declare function parse(str: string, options?: ParseOptions): IDLRootType[]; +export function parse(str: string, options?: ParseOptions): IDLRootType[]; export type IDLRootType = InterfaceType | InterfaceMixinType | NamespaceType | CallbackType | DictionaryType | EnumType | TypedefType | ImplementsType | IncludesType; @@ -29,6 +29,7 @@ export interface WebIDLParseError { toString(): string; } +// tslint:disable-next-line interface-name export interface IDLTypeDescription { type: string; /** Boolean indicating if it is a sequence. Same as generic === "sequence" */ @@ -39,10 +40,12 @@ export interface IDLTypeDescription { nullable: boolean; /** Boolean indicating whether this is a union type or not. */ union: boolean; - /** In most cases, this will just be a string with the type name. - If the type is a union, then this contains an array of the types it unites. - If it is a generic type, it contains the IDL type description for the type in the sequence, - the eventual value of the promise, etc. */ + /** + * In most cases, this will just be a string with the type name. + * If the type is a union, then this contains an array of the types it unites. + * If it is a generic type, it contains the IDL type description for the type in the sequence, + * the eventual value of the promise, etc. + */ idlType: string | IDLTypeDescription | IDLTypeDescription[]; } @@ -134,7 +137,7 @@ export interface EnumType { /** The enum's name. */ name: string; /** An array of values (strings). */ - values: { type: "string", value: string }[]; + values: Array<{ type: "string", value: string }>; /** A list of extended attributes. */ extAttrs: ExtendedAttributes[]; } @@ -257,7 +260,7 @@ export interface ExtendedAttributeRightHandSideIdentifier { } export interface ExtendedAttributeRightHandSideIdentifierList { - type: "identifier-list" + type: "identifier-list"; value: string[]; } diff --git a/types/webidl2/webidl2-tests.ts b/types/webidl2/webidl2-tests.ts index b008b4d11a..e7b1168a68 100644 --- a/types/webidl2/webidl2-tests.ts +++ b/types/webidl2/webidl2-tests.ts @@ -6,48 +6,50 @@ for (const rootType of parsed) { if (rootType.type !== "implements" && rootType.type !== "includes") { console.log(rootType.name); } - if (rootType.type === "interface") { - console.log(rootType.inheritance); - logMembers(rootType.members); - console.log(rootType.partial); - } - else if (rootType.type === "interface mixin") { - logMembers(rootType.members); - console.log(rootType.partial); - } - else if (rootType.type === "namespace") { - console.log(rootType.partial); - logNamespaceMembers(rootType.members); - } - else if (rootType.type === "callback interface") { - logMembers(rootType.members); - console.log(rootType.partial); - } - else if (rootType.type === "callback") { - logArguments(rootType.arguments); - } - else if (rootType.type === "dictionary") { - console.log(rootType.inheritance); - for (const member of rootType.members) { - console.log(member.required, member.default); - } - } - else if (rootType.type === "enum") { - for (const v of rootType.values) { - console.log(v.type); - console.log(v.value); - } - } - else if (rootType.type === "typedef") { - logIdlType(rootType.idlType); - } - else if (rootType.type === "implements") { - console.log(rootType.target); - console.log(rootType.implements); - } - else if (rootType.type === "includes") { - console.log(rootType.target); - console.log(rootType.includes); + switch (rootType.type) { + case "interface": + console.log(rootType.inheritance); + logMembers(rootType.members); + console.log(rootType.partial); + break; + case "interface mixin": + logMembers(rootType.members); + console.log(rootType.partial); + break; + case "namespace": + console.log(rootType.partial); + logNamespaceMembers(rootType.members); + break; + case "callback interface": + logMembers(rootType.members); + console.log(rootType.partial); + break; + case "callback": + logArguments(rootType.arguments); + break; + case "dictionary": + console.log(rootType.inheritance); + for (const member of rootType.members) { + console.log(member.required, member.default); + } + break; + case "enum": + for (const v of rootType.values) { + console.log(v.type); + console.log(v.value); + } + break; + case "typedef": + logIdlType(rootType.idlType); + break; + case "implements": + console.log(rootType.target); + console.log(rootType.implements); + break; + case "includes": + console.log(rootType.target); + console.log(rootType.includes); + break; } logExtAttrs(rootType.extAttrs); @@ -55,27 +57,29 @@ for (const rootType of parsed) { function logMembers(members: webidl2.IDLInterfaceMemberType[]) { for (const member of members) { - if (member.type === "operation" || member.type === "attribute") { - logNamespaceMembers([member]); + switch (member.type) { + case "operation": + case "attribute": + logNamespaceMembers([member]); + break; + case "const": + console.log(member.name); + console.log(member.value); + console.log(member.nullable); + break; + case "iterable": + console.log(member.readonly); + break; + case "legacyiterable": + console.log(member.readonly); + break; + case "setlike": + console.log(member.readonly); + break; + case "maplike": + console.log(member.readonly); + break; } - else if (member.type === "const") { - console.log(member.name); - console.log(member.value); - console.log(member.nullable); - } - else if (member.type === "iterable") { - console.log(member.readonly); - } - else if (member.type === "legacyiterable") { - console.log(member.readonly); - } - else if (member.type === "setlike") { - console.log(member.readonly); - } - else if (member.type === "maplike") { - console.log(member.readonly); - } - logIdlType(member.idlType); logExtAttrs(member.extAttrs); } @@ -87,8 +91,7 @@ function logNamespaceMembers(members: webidl2.IDLNamespaceMemberType[]) { console.log(member.name); console.log(member.getter, member.setter, member.deleter); console.log(member.static, member.stringifier); - } - else if (member.type === "attribute") { + } else if (member.type === "attribute") { console.log(member.name); console.log(member.static, member.stringifier, member.readonly, member.inherit); } @@ -101,8 +104,7 @@ function logExtAttrs(extAttrs: webidl2.ExtendedAttributes[]) { const { rhs } = extAttrs[0]; if (rhs.type === "identifier") { console.log(rhs); - } - else { + } else { for (const v of rhs.value) { console.log(v); } From 5305f69e77728b820b396378837e277cf6ee98e0 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 9 Mar 2018 14:01:58 +0900 Subject: [PATCH 3/5] use dts-gen --- types/webidl2/index.d.ts | 6 ++++-- types/webidl2/tsconfig.json | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/types/webidl2/index.d.ts b/types/webidl2/index.d.ts index a1999c1c2e..0dd0cc7f10 100644 --- a/types/webidl2/index.d.ts +++ b/types/webidl2/index.d.ts @@ -1,8 +1,10 @@ -// Type definitions for webidl2.js 10.2 -// Project: https://github.com/w3c/webidl2.js/ +// Type definitions for webidl2 10.2 +// Project: https://github.com/w3c/webidl2.js#readme // Definitions by: Kagama Sascha Rosylight // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +export as namespace WebIDL2; + export function parse(str: string, options?: ParseOptions): IDLRootType[]; export type IDLRootType = InterfaceType | InterfaceMixinType | NamespaceType | CallbackType | DictionaryType | EnumType | TypedefType | ImplementsType | IncludesType; diff --git a/types/webidl2/tsconfig.json b/types/webidl2/tsconfig.json index 3d3ff31d07..acd7383a13 100644 --- a/types/webidl2/tsconfig.json +++ b/types/webidl2/tsconfig.json @@ -1,15 +1,13 @@ { "compilerOptions": { "module": "commonjs", - "target": "es6", "lib": [ "es6", "dom" ], "noImplicitAny": true, - "noImplicitThis": false, - "strictNullChecks": false, - "strictFunctionTypes": true, + "noImplicitThis": true, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" From 4149e524b72f5354e0a894bd55c4b68f36704f98 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 9 Mar 2018 14:03:48 +0900 Subject: [PATCH 4/5] re-add strictFunctionTypes --- types/webidl2/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/types/webidl2/tsconfig.json b/types/webidl2/tsconfig.json index acd7383a13..04827a6268 100644 --- a/types/webidl2/tsconfig.json +++ b/types/webidl2/tsconfig.json @@ -8,6 +8,7 @@ "noImplicitAny": true, "noImplicitThis": true, "strictNullChecks": true, + "strictFunctionTypes": true, "baseUrl": "../", "typeRoots": [ "../" From 0d3a8038e277e86a43d71fe158629d14b428223b Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 9 Mar 2018 14:17:47 +0900 Subject: [PATCH 5/5] fix null error --- types/webidl2/webidl2-tests.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/types/webidl2/webidl2-tests.ts b/types/webidl2/webidl2-tests.ts index e7b1168a68..61b437f563 100644 --- a/types/webidl2/webidl2-tests.ts +++ b/types/webidl2/webidl2-tests.ts @@ -120,8 +120,12 @@ function logArguments(args: webidl2.Argument[]) { } } -function logIdlType(idlType: string | webidl2.IDLTypeDescription | webidl2.IDLTypeDescription[]) { +function logIdlType(idlType: string | webidl2.IDLTypeDescription | webidl2.IDLTypeDescription[] | null) { + if (!idlType) { + return; + } if (typeof idlType === "string") { + console.log(idlType); return; } if (Array.isArray(idlType)) {