JS IDL2K refactoring according to review discussion

This commit is contained in:
Sergey Mashkov
2015-05-06 15:01:57 +03:00
committed by Sergey Mashkov
parent 4ee780ef07
commit 6e09100877
22 changed files with 766 additions and 6859 deletions
+2
View File
@@ -30,5 +30,7 @@ public annotation class library(public val name: String = "")
native
public annotation class enumerable()
// TODO make it "internal" or "fake"
native
deprecated("Do not use this annotation: it is for internal use only")
public annotation class marker
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
package org.w3c.dom.views
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
native public trait AbstractView {
}
+70 -70
View File
@@ -3,22 +3,22 @@ package kotlin.js.dom.html
import org.w3c.dom.*
native
deprecated("Use kotlin.browser instead")
deprecated("Use declarations from kotlin.browser instead")
public val window: Window = noImpl
native
deprecated("Use kotlin.browser instead")
deprecated("Use declarations from kotlin.browser instead")
public var document: HTMLDocument = noImpl
deprecated("Use org.w3c.dom instead")
deprecated("Do not use it")
public native trait Object {
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Image : HTMLImageElement {
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Navigator {
public native var userAgent: String
public native var product: String
@@ -44,7 +44,7 @@ public native trait Screen {
public native var colorDepth: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Option {
public native var defaultSelected: Boolean
public native var selected: Boolean
@@ -52,7 +52,7 @@ public native trait Option {
public native var value: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Location {
public native var href: String
public native var hash: String
@@ -67,7 +67,7 @@ public native trait Location {
public native fun replace(url: String): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Event {
public native var data: Array<Any>
public native var height: Double
@@ -88,20 +88,20 @@ public native trait Event {
public native var button: Boolean
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Selection {
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait CSSRule {
public native var selectorText: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Stylesheet {
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait History {
public native fun back(): Unit
public native fun forward(): Unit
@@ -112,7 +112,7 @@ public native trait Console {
public native fun log(message: Any): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait Window {
public native val document: HTMLDocument
public native val event: Event
@@ -172,21 +172,21 @@ public native trait Global {
public native fun unescape(): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLCollection {
public native val length: Double
public native fun item(index: Number): Node?
public native fun namedItem(name: String): Node?
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLOptionsCollection {
public native val length: Double
public native fun item(index: Number): Node?
public native fun namedItem(name: String): Node?
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLDocument : Document {
public native fun open(): Unit
public native fun write(text: String): Unit
@@ -194,7 +194,7 @@ public native trait HTMLDocument : Document {
public native var onunload: () -> Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLElement : Element {
public native var title: String
public native var lang: String
@@ -228,7 +228,7 @@ public native trait HTMLElement : Element {
public native var onresize: () -> Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait CSSStyleDeclaration {
public native var cssText: String
public native var length: Double
@@ -240,17 +240,17 @@ public native trait CSSStyleDeclaration {
public native fun setProperty(propertyName: String, value: String, priority: String): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLHtmlElement : HTMLElement {
public native var version: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLHeadElement : HTMLElement {
public native var profile: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLLinkElement : HTMLElement {
public native var disabled: Boolean
public native var charset: String
@@ -263,12 +263,12 @@ public native trait HTMLLinkElement : HTMLElement {
public native var type: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTitleElement : HTMLElement {
public native var text: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLMetaElement : HTMLElement {
public native var content: String
public native var httpEquiv: String
@@ -276,26 +276,26 @@ public native trait HTMLMetaElement : HTMLElement {
public native var scheme: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLBaseElement : HTMLElement {
public native var href: String
public native var target: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLIsIndexElement : HTMLElement {
public native val form: HTMLFormElement
public native var prompt: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLStyleElement : HTMLElement {
public native var disabled: Boolean
public native var media: String
public native var type: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLBodyElement : HTMLElement {
public native var aLink: String
public native var background: String
@@ -307,7 +307,7 @@ public native trait HTMLBodyElement : HTMLElement {
public native var onunload: () -> Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLFormElement {
public native val elements: HTMLCollection
public native val length: Double
@@ -321,7 +321,7 @@ public native trait HTMLFormElement {
public native fun reset(): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLSelectElement : HTMLElement {
public native val type: String
public native var selectedIndex: Double
@@ -340,13 +340,13 @@ public native trait HTMLSelectElement : HTMLElement {
public native fun focus(): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLOptGroupElement : HTMLElement {
public native var disabled: Boolean
public native var label: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLOptionElement : HTMLElement {
public native val form: HTMLFormElement
public native var defaultSelected: Boolean
@@ -358,7 +358,7 @@ public native trait HTMLOptionElement : HTMLElement {
public native var value: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLInputElement : HTMLElement {
public native var defaultValue: String
public native var defaultChecked: Boolean
@@ -386,7 +386,7 @@ public native trait HTMLInputElement : HTMLElement {
public native var selectionEnd: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTextAreaElement : HTMLElement {
public native var defaultValue: String
public native val form: HTMLFormElement
@@ -404,7 +404,7 @@ public native trait HTMLTextAreaElement : HTMLElement {
public native fun select(): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLButtonElement : HTMLElement {
public native val form: HTMLFormElement
public native var accessKey: String
@@ -415,104 +415,104 @@ public native trait HTMLButtonElement : HTMLElement {
public native var value: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLLabelElement : HTMLElement {
public native val form: HTMLFormElement
public native var accessKey: String
public native var htmlFor: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLFieldSetElement : HTMLElement {
public native val form: HTMLFormElement
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLLegendElement : HTMLElement {
public native val form: HTMLFormElement
public native var accessKey: String
public native var align: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLUListElement : HTMLElement {
public native var compact: Boolean
public native var type: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLOListElement : HTMLElement {
public native var compact: Boolean
public native var start: Double
public native var type: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLDListElement : HTMLElement {
public native var compact: Boolean
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLDirectoryElement : HTMLElement {
public native var compact: Boolean
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLMenuElement : HTMLElement {
public native var compact: Boolean
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLLIElement : HTMLElement {
public native var type: String
public native var value: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLDivElement : HTMLElement {
public native var align: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLParagraphElement : HTMLElement {
public native var align: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLHeadingElement : HTMLElement {
public native var align: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLQuoteElement : HTMLElement {
public native var cite: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLPreElement : HTMLElement {
public native var width: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLBRElement : HTMLElement {
public native var clear: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLBaseFontElement : HTMLElement {
public native var color: String
public native var face: String
public native var size: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLFontElement : HTMLElement {
public native var color: String
public native var face: String
public native var size: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLHRElement : HTMLElement {
public native var align: String
public native var noShade: Boolean
@@ -520,13 +520,13 @@ public native trait HTMLHRElement : HTMLElement {
public native var width: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLModElement : HTMLElement {
public native var cite: String
public native var dateTime: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLAnchorElement : HTMLElement {
public native var accessKey: String
public native var charset: String
@@ -544,7 +544,7 @@ public native trait HTMLAnchorElement : HTMLElement {
public native fun focus(): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLImageElement : HTMLElement {
public native var name: String
public native var align: String
@@ -562,7 +562,7 @@ public native trait HTMLImageElement : HTMLElement {
public native var width: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLObjectElement : HTMLElement {
public native val form: HTMLFormElement
public native var code: String
@@ -585,7 +585,7 @@ public native trait HTMLObjectElement : HTMLElement {
public native val contentDocument: Document
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLParamElement : HTMLElement {
public native var name: String
public native var type: String
@@ -593,7 +593,7 @@ public native trait HTMLParamElement : HTMLElement {
public native var valueType: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLAppletElement : HTMLElement {
public native var align: String
public native var alt: String
@@ -608,13 +608,13 @@ public native trait HTMLAppletElement : HTMLElement {
public native var width: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLMapElement : HTMLElement {
public native val areas: HTMLCollection
public native var name: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLAreaElement : HTMLElement {
public native var accessKey: String
public native var alt: String
@@ -626,7 +626,7 @@ public native trait HTMLAreaElement : HTMLElement {
public native var target: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLScriptElement : HTMLElement {
public native var text: String
public native var htmlFor: String
@@ -637,7 +637,7 @@ public native trait HTMLScriptElement : HTMLElement {
public native var type: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTableElement : HTMLElement {
public native var caption: HTMLTableCaptionElement
public native var tHead: HTMLTableSectionElement
@@ -663,12 +663,12 @@ public native trait HTMLTableElement : HTMLElement {
public native fun deleteRow(index: Number): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTableCaptionElement : HTMLElement {
public native var align: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTableColElement : HTMLElement {
public native var align: String
public native var ch: String
@@ -678,7 +678,7 @@ public native trait HTMLTableColElement : HTMLElement {
public native var width: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTableSectionElement : HTMLElement {
public native var align: String
public native var ch: String
@@ -689,7 +689,7 @@ public native trait HTMLTableSectionElement : HTMLElement {
public native fun deleteRow(index: Number): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTableRowElement : HTMLElement {
public native val rowIndex: Double
public native val sectionRowIndex: Double
@@ -703,7 +703,7 @@ public native trait HTMLTableRowElement : HTMLElement {
public native fun deleteCell(index: Number): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLTableCellElement : HTMLElement {
public native val cellIndex: Double
public native var abbr: String
@@ -722,13 +722,13 @@ public native trait HTMLTableCellElement : HTMLElement {
public native var width: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLFrameSetElement : HTMLElement {
public native var cols: String
public native var rows: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLFrameElement : HTMLElement {
public native var frameBorder: String
public native var longDesc: String
@@ -740,7 +740,7 @@ public native trait HTMLFrameElement : HTMLElement {
public native var src: String
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLIFrameElement : HTMLElement {
public native var align: String
public native var frameBorder: String
+5 -5
View File
@@ -3,7 +3,7 @@ package kotlin.js.dom.html5
import kotlin.js.dom.html.HTMLElement
import org.w3c.dom.Element
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait HTMLCanvasElement : HTMLElement {
public var width: Double
public var height: Double
@@ -13,7 +13,7 @@ public native trait HTMLCanvasElement : HTMLElement {
public fun toDataURL(string: String): String
}
deprecated("USe org.w3c.dom instead. See CanvasRenderingContext2D")
deprecated("Use declarations from org.w3c.dom instead. See CanvasRenderingContext2D")
public native trait CanvasContext {
public var canvas: HTMLCanvasElement
public fun save(): Unit
@@ -78,12 +78,12 @@ public native trait CanvasContext {
public fun putImageData(image_data: ImageData, dx: Number, dy: Number, dirtyX: Number, dirtyY: Number, dirtyWidth: Number): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait CanvasGradient {
public fun addColorStop(offset: Number, color: String): Unit
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait ImageData {
public var data: CanvasPixelArray
public var width: Double
@@ -94,7 +94,7 @@ public native trait CanvasPixelArray {
public var length: Double
}
deprecated("Use org.w3c.dom instead")
deprecated("Use declarations from org.w3c.dom instead")
public native trait TextMetrics {
public var width: Double
}
-6
View File
@@ -1,6 +1,5 @@
package html5.files
native
native
deprecated("Use org.w3c.dom")
public class FileReader() {
@@ -9,14 +8,12 @@ public class FileReader() {
public val result : File = noImpl
}
native
native
deprecated("Use org.w3c.dom")
public class FileReaderEvent() {
public val target : FileReader = noImpl
}
native
native
deprecated("Use org.w3c.dom")
public class FileList() {
@@ -24,7 +21,6 @@ public class FileList() {
public val length : Int = noImpl
}
native
native
deprecated("Use org.w3c.dom")
public class File() : Blob() {
@@ -32,7 +28,6 @@ public class File() : Blob() {
// readonly attribute Date lastModifiedDate;
}
native
native
deprecated("Use org.w3c.dom")
public open class Blob(blobParts: Array<Any>? = undefined, options: BlobPropertyBag? = undefined) {
@@ -44,7 +39,6 @@ public open class Blob(blobParts: Array<Any>? = undefined, options: BlobProperty
//
}
native
native
deprecated("Use org.w3c.dom")
public trait BlobPropertyBag {
+2 -2
View File
@@ -3,10 +3,10 @@ package kotlin.dom
import org.w3c.dom.Document
import org.w3c.dom.Node
deprecated("use org.w3c.dom instead: create document directly via constructor Document() or use document.implementation.createDocument")
deprecated("use declarations from org.w3c.dom instead: create document directly via constructor Document() or use document.implementation.createDocument")
public fun createDocument(): Document = Document()
deprecated("use org.w3c.dom instead")
deprecated("use member property outerHTML of Element class instead")
native public val Node.outerHTML: String get() = noImpl
/** Converts the node to an XML String */
+6 -45
View File
@@ -202,45 +202,6 @@ public fun Element.removeClass(vararg cssClasses: String): Boolean {
return false
}
/**
* Adds [cssClasses] to element if []condition] is true or removes it otherwise.
* Has no effect if class attribute already has corresponding content
*/
public fun Element.addOrRemoveClassWhen(condition : Boolean, vararg cssClasses : String) {
if (condition) {
addClass(*cssClasses)
} else {
removeClass(*cssClasses)
}
}
/**
* Adds [trueClassName] class to element if [condition] is true and removes [falseClassName].
* If [condition] is false then [trueClassName] will be removed and [falseClassName] will be added.
* Has no effect if class attribute already has corresponding content
*/
public fun Element.swapClassWhen(condition: Boolean, trueClassName: String, falseClassName: String) {
if (condition) {
addClass(trueClassName)
removeClass(falseClassName)
} else {
removeClass(trueClassName)
addClass(falseClassName)
}
}
/**
* If [condition] is true then [attributeName] with value [attributeValue] will be added to the element, otherwise attribute with
* name [attributeName] will be removed
*/
public fun Element.addOrRemoveAttributeWhen(condition : Boolean, attributeName : String, attributeValue : String = attributeName) {
if (condition) {
setAttribute(attributeName, attributeValue)
} else {
removeAttribute(attributeName)
}
}
/** Removes all the children from this node */
public fun Node.clear() {
while (hasChildNodes()) {
@@ -258,9 +219,10 @@ public fun Node.removeFromParent() {
private class NodeListAsList(val delegate: NodeList) : AbstractList<Node>() {
override fun size(): Int = delegate.length
override fun get(index: Int): Node =
if (index in 0..size() - 1) delegate.item(index)!!
else throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size() - 1})")
override fun get(index: Int): Node = when {
index in 0..size() - 1 -> delegate.item(index)!!
else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size() - 1})")
}
}
private class ElementListAsList(private val nodeList: NodeList) : AbstractList<Element>() {
@@ -398,7 +360,6 @@ public fun Element.createElement(name: String, doc: Document? = null, init: Elem
}
/** Returns the owner document of the element or uses the provided document */
deprecated("")
public fun Node.ownerDocument(doc: Document? = null): Document {
val answer = if (this.nodeType == Node.DOCUMENT_NODE) this as Document
else if (doc == null) this.ownerDocument
@@ -443,13 +404,13 @@ public fun Element.addText(text: String?, doc: Document? = null): Element {
/**
* Creates text node and append it to the element
*/
public fun Element.appendText(text : String, doc : Document = this.ownerDocument!!) {
public fun Element.appendText(text: String, doc : Document = this.ownerDocument!!) {
appendChild(doc.createTextNode(text))
}
/**
* Appends the node to the specified parent element
*/
public fun Node.appendTo(parent : Element) {
public fun Node.appendTo(parent: Element) {
parent.appendChild(this)
}
+14 -2
View File
@@ -82,15 +82,27 @@
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>download-idl</id>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.jetbrains.idl2k.dl.DlPackage</mainClass>
</configuration>
</execution>
<execution>
<id>idl2k</id>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.jetbrains.idl2k.Idl2kPackage</mainClass>
</configuration>
</execution>
</executions>
<configuration>
<mainClass>org.jetbrains.idl2k.Idl2kPackage</mainClass>
<classpathScope>compile</classpathScope>
<workingDirectory>${project.basedir}</workingDirectory>
<classpathScope>compile</classpathScope>
</configuration>
</plugin>
@@ -42,9 +42,19 @@ grammar WebIDL;
// Note: Added "wrapper" rule webIDL with EOF token.
webIDL
: definitions EOF
: namespace? definitions EOF
;
namespaceScope
: '*' | 'cpp' | 'java' | 'py' | 'perl' | 'rb' | 'cocoa' | 'csharp'
;
namespaceRest
: IDENTIFIER_WEBIDL ( '.' IDENTIFIER_WEBIDL )*
;
namespace
: 'namespace' namespaceScope? namespaceRest ';';
definitions
: extendedAttributeList definition definitions
@@ -414,6 +424,7 @@ argumentNameKeyword
| 'stringifier'
| 'typedef'
| 'unrestricted'
| 'namespace'
;
type
@@ -427,7 +438,7 @@ singleType
;
unionType
: '(' unionMemberType 'or' unionMemberType unionMemberTypes ')'
: '(' unionMemberType ( 'or' unionMemberType )* ')'
;
unionMemberType
@@ -500,12 +511,7 @@ unsignedIntegerType
integerType
: 'short'
| 'long' optionalLong
;
optionalLong
: 'long'
| /* empty */
| 'long'+
;
promiseType
@@ -0,0 +1,25 @@
grammar test;
testme
: namespace? declarations EOF
;
declarations
: declaration*
;
namespace
: 'namespace' IDENTIFIER ';'
;
declaration
: 'interface' IDENTIFIER
;
IDENTIFIER
: [A-Za-z_][A-Za-z_0-9]*
;
WHITESPACE_WEBIDL
: [\t\n\r ]+ -> channel(HIDDEN)
;
@@ -0,0 +1,92 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idl2k.dl
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.parser.Tag
import java.io.File
import java.net.URL
val urls = listOf(
"https://raw.githubusercontent.com/whatwg/html-mirror/master/source" to "org.w3c.dom",
"https://html.spec.whatwg.org/" to "org.w3c.dom",
"https://raw.githubusercontent.com/whatwg/dom/master/dom.html" to "org.w3c.dom",
"http://www.w3.org/TR/uievents/" to "org.w3c.dom.events",
"https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html" to "org.w3c.dom",
"https://raw.githubusercontent.com/whatwg/xhr/master/Overview.src.html" to "org.w3c.xhr",
"https://raw.githubusercontent.com/w3c/FileAPI/gh-pages/index.html" to "org.w3c.files",
"https://raw.githubusercontent.com/whatwg/notifications/master/notifications.html" to "org.w3c.notifications",
"https://raw.githubusercontent.com/whatwg/fullscreen/master/Overview.src.html" to "org.w3c.fullscreen",
"http://www.w3.org/TR/DOM-Parsing/" to "org.w3c.dom.parsing",
"http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html" to "org.w3c.workers",
"https://raw.githubusercontent.com/whatwg/fetch/master/Overview.src.html" to "org.w3c.fetch",
"http://www.w3.org/TR/vibration/" to "org.w3c.vibration",
"http://dev.w3.org/csswg/cssom/" to "org.w3c.dom.css",
"https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl" to "org.khronos.webgl"
)
fun main(args: Array<String>) {
val dir = File("../../idl")
dir.mkdirs()
val urlsPerFiles = urls.groupBy { it.second + ".idl" }
urlsPerFiles.forEach { e ->
val fileName = e.key
val pkg = e.value.first().second
File(dir, fileName).bufferedWriter().use { w ->
w.appendln("namespace ${pkg};")
w.appendln()
w.appendln()
e.value.forEach { pair ->
val (url, _) = pair
println("Loading ${url}...")
if (url.endsWith(".idl")) {
w.appendln(URL(url).readText())
} else {
extractIDLText(url, w)
}
}
w.appendln()
}
}
}
private fun extractIDLText(url: String, out: Appendable) {
// val soup = Jsoup.connect(url).validateTLSCertificates(false).ignoreHttpErrors(true).get()
val soup = Jsoup.parse(URL(url).readText())
fun append(it : Element) {
if (!it.tag().preserveWhitespace()) {
return append(Element(Tag.valueOf("pre"), it.baseUri()).appendChild(it))
}
val text = it.text()
out.appendln(text)
if (!text.trimEnd().endsWith(";")) {
out.appendln(";")
}
}
soup.select("pre.idl").filter {!it.hasClass("extract")}.forEach(::append)
soup.select("code.idl-code").forEach(::append)
soup.select("spec-idl").forEach(::append)
}
+118 -78
View File
@@ -1,84 +1,124 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idl2k
import java.util.*
import java.util.HashSet
private val typeMapper = mapOf(
"unsignedlong" to "Int",
"unsignedlonglong" to "Long",
"longlong" to "Long",
"unsignedshort" to "Short",
"void" to "Unit",
"DOMString" to "String",
"boolean" to "Boolean",
"short" to "Short",
"long" to "Int",
"double" to "Double",
"any" to "Any",
"" to "dynamic",
"DOMTimeStamp" to "Number",
"EventHandler" to "() -> Unit",
"object" to "dynamic",
"WindowProxy" to "Window",
"Uint8ClampedArray" to "dynamic", // TODO think of native arrays,
"Function" to "() -> dynamic",
"USVString" to "String",
"ByteString" to "String",
"DOMError" to "dynamic",
"SVGMatrix" to "dynamic",
"ArrayBuffer" to "dynamic",
"Elements" to "dynamic"
)
private fun fixDynamic(type : String) = if (type == "dynamic?") "dynamic" else type
private fun mapType(repository: Repository, type: String) = fixDynamic(handleSpecialTypes(repository, typeMapper[type] ?: type))
private fun handleSpecialTypes(repository: Repository, type: String): String {
if (type.endsWith("?")) {
return mapType(repository, type.substring(0, type.length() - 1)) + "?"
} else if (type.endsWith("...")) {
return mapType(repository, type.substring(0, type.length() - 3))
} else if (type.endsWith("[]")) {
return "Array<${mapType(repository, type.substring(0, type.length() - 2))}>"
} else if (type.startsWith("unrestricted")) {
return mapType(repository, type.substring(12))
} else if (type.startsWith("sequence")) {
return "Any" // TODO how do we handle sequences?
} else if (type in repository.typeDefs) {
val typedef = repository.typeDefs[type]!!
return if (!typedef.types.startsWith("Union<")) mapType(repository, typedef.types)
else if (splitUnionType(typedef.types).size() == 1) mapType(repository, splitUnionType(typedef.types).first())
else typedef.name
} else if (type in repository.enums) {
return "String"
} else if (type.endsWith("Callback")) {
return "() -> Unit"
// } else if (type.startsWith("Union<")) {
// return "dynamic"
} else if (type.startsWith("Promise<")) {
return "dynamic"
} else if ("NoInterfaceObject" in repository.interfaces[type]?.extendedAttributes?.map {it.call} ?: emptyList()) {
return "dynamic"
private fun Operation.getterOrSetter() = this.attributes.map { it.call }.toSet().let { attributes ->
when {
"getter" in attributes -> NativeGetterOrSetter.GETTER
"setter" in attributes -> NativeGetterOrSetter.SETTER
else -> NativeGetterOrSetter.NONE
}
return type
}
private fun findConstructorAttribute(iface: InterfaceDefinition) = iface.extendedAttributes.firstOrNull { it.call == "Constructor" }
fun String.ensureNullable() = when {
endsWith("?") -> this
this == "dynamic" -> this
contains("->") -> "($this)?"
else -> "$this?"
}
fun generateFunction(repository: Repository, function: Operation, functionName: String, nativeGetterOrSetter: NativeGetterOrSetter = function.getterOrSetter()): GenerateFunction =
function.attributes.map { it.call }.toSet().let { attributes ->
GenerateFunction(
name = functionName,
returnType = mapType(repository, function.returnType).let { mapped -> if (nativeGetterOrSetter != NativeGetterOrSetter.NONE) mapped.ensureNullable() else mapped },
arguments = function.parameters.map {
GenerateAttribute(
name = it.name,
type = mapType(repository, it.type),
initializer = it.defaultValue,
getterSetterNoImpl = false,
override = false,
readOnly = true,
vararg = it.vararg
)
},
nativeGetterOrSetter = nativeGetterOrSetter
)
}
fun generateFunctions(repository: Repository, function: Operation): List<GenerateFunction> {
val realFunction = if (function.name == "") null else generateFunction(repository, function, function.name, NativeGetterOrSetter.NONE)
val getterOrSetterFunction = when (function.getterOrSetter()) {
NativeGetterOrSetter.NONE -> null
NativeGetterOrSetter.GETTER -> generateFunction(repository, function, "get")
NativeGetterOrSetter.SETTER -> generateFunction(repository, function, "set")
}
return listOf(realFunction, getterOrSetterFunction).filterNotNull()
}
fun generateAttribute(putNoImpl: Boolean, repository: Repository, attribute: Attribute): GenerateAttribute =
GenerateAttribute(attribute.name,
type = mapType(repository, attribute.type),
initializer = attribute.defaultValue,
getterSetterNoImpl = putNoImpl,
readOnly = attribute.readOnly,
override = false,
vararg = attribute.vararg
)
private fun InterfaceDefinition.superTypes(repository: Repository) = superTypes.map { repository.interfaces[it] }.filterNotNull()
private fun resolveDefinitionType(repository: Repository, iface: InterfaceDefinition, constructor: ExtendedAttribute? = iface.findConstructor()): GenerateDefinitionKind =
if (iface.dictionary || constructor != null || iface.superTypes(repository).any { resolveDefinitionType(repository, it) == GenerateDefinitionKind.CLASS }) {
GenerateDefinitionKind.CLASS
}
else {
GenerateDefinitionKind.TRAIT
}
private fun InterfaceDefinition.mapAttributes(repository: Repository) = attributes.map { generateAttribute(!dictionary, repository, it) }
private fun InterfaceDefinition.mapOperations(repository: Repository) = operations.flatMap { generateFunctions(repository, it) }
private fun Constant.mapConstant(repository : Repository) = GenerateAttribute(name, mapType(repository, type), value, false, true, false, false)
fun generateTrait(repository: Repository, iface: InterfaceDefinition): GenerateTraitOrClass {
val constructor = iface.findConstructor()
val constructorFunction = generateFunction(repository, Operation("", "Unit", constructor?.arguments ?: emptyList(), emptyList()), functionName = "", nativeGetterOrSetter = NativeGetterOrSetter.NONE)
val constructorArgumentNames = constructorFunction.arguments.map { it.name }.toSet()
val constructorSuperCalls = iface.superTypes
.map { repository.interfaces[it] }
.filterNotNull()
.filter { resolveDefinitionType(repository, it) == GenerateDefinitionKind.CLASS }
.map {
val superConstructor = it.findConstructor()
GenerateFunctionCall(
name = it.name,
arguments = if (superConstructor == null) {
emptyList()
} else {
superConstructor.arguments.map { arg ->
if (arg.name in constructorArgumentNames) arg.name else "noImpl"
}
}
)
}
val entityType = resolveDefinitionType(repository, iface, constructor)
val extensions = repository.externals[iface.name]?.map { repository.interfaces[it] }?.filterNotNull() ?: emptyList()
return GenerateTraitOrClass(iface.name, iface.namespace, entityType, iface.superTypes,
memberAttributes = (iface.mapAttributes(repository) + extensions.flatMap { it.mapAttributes(repository) }).distinct().toList(),
memberFunctions = (iface.mapOperations(repository) + extensions.flatMap { it.mapOperations(repository) }).distinct().toList(),
constants = (iface.constants.map {it.mapConstant(repository)} + extensions.flatMap { it.constants.map {it.mapConstant(repository)} }.distinct().toList()),
constructor = constructorFunction,
superConstructorCalls = constructorSuperCalls
)
}
fun mapUnionType(it : UnionType) = GenerateTraitOrClass(
name = it.name,
namespace = it.namespace,
kind = GenerateDefinitionKind.TRAIT,
superTypes = emptyList(),
memberAttributes = emptyList(),
memberFunctions = emptyList(),
constants = emptyList(),
constructor = null,
superConstructorCalls = emptyList()
)
fun generateUnionTypeTraits(allUnionTypes : Iterable<UnionType>): List<GenerateTraitOrClass> = allUnionTypes.map(::mapUnionType)
fun mapDefinitions(repository: Repository, definitions: Iterable<InterfaceDefinition>) =
definitions.filter { "NoInterfaceObject" !in it.extendedAttributes.map { it.call } }.map { generateTrait(repository, it) }
@@ -1,298 +0,0 @@
package org.jetbrains.idl2k
import java.math.BigInteger
import java.util.*
import kotlin.support.AbstractIterator
private fun Operation.getterOrSetter() = this.attributes.map { it.call }.toSet().let { attributes ->
when {
"getter" in attributes -> NativeGetterOrSetter.GETTER
"setter" in attributes -> NativeGetterOrSetter.SETTER
else -> NativeGetterOrSetter.NONE
}
}
private fun String.ensureNullable() = if (this.endsWith("?") || this == "dynamic") this else this + "?"
fun generateFunction1(repository: Repository, function: Operation, functionName: String, nativeGetterOrSetter: Boolean): GenerateFunction =
function.attributes.map { it.call }.toSet().let { attributes ->
GenerateFunction(
name = functionName,
returnType = mapType(repository, function.returnType).let { mapped -> if (nativeGetterOrSetter) mapped.ensureNullable() else mapped },
arguments = function.parameters.map {
GenerateAttribute(
name = it.name,
type = mapType(repository, it.type),
initializer = it.defaultValue,
getterSetterNoImpl = false,
override = false,
readOnly = true,
vararg = it.vararg
)
},
native = if (nativeGetterOrSetter) function.getterOrSetter() else NativeGetterOrSetter.NONE
)
}
fun generateFunction(repository: Repository, function: Operation): List<GenerateFunction> {
val realFunction = if (function.name == "") null else generateFunction1(repository, function, function.name, false)
val getterOrSetterFunction = when (function.getterOrSetter()) {
NativeGetterOrSetter.NONE -> null
NativeGetterOrSetter.GETTER -> generateFunction1(repository, function, "get", true)
NativeGetterOrSetter.SETTER -> generateFunction1(repository, function, "set", true)
}
return listOf(realFunction, getterOrSetterFunction).filterNotNull()
}
fun generateAttribute(putNoImpl: Boolean, repository: Repository, attribute: Attribute): GenerateAttribute =
GenerateAttribute(attribute.name,
type = mapType(repository, attribute.type),
initializer = attribute.defaultValue,
getterSetterNoImpl = putNoImpl,
readOnly = attribute.readOnly,
override = false,
vararg = attribute.vararg
)
private fun InterfaceDefinition.findConstructor() = extendedAttributes.firstOrNull { it.call == "Constructor" }
private fun InterfaceDefinition.superTypes(repository: Repository) = superTypes.map { repository.interfaces[it] }.filterNotNull()
private fun resolveDefinitionType(repository: Repository, iface: InterfaceDefinition, constructor: ExtendedAttribute? = findConstructorAttribute(iface)): GenerateDefinitionType =
if (iface.dictionary || constructor != null || iface.superTypes(repository).any { resolveDefinitionType(repository, it) == GenerateDefinitionType.CLASS }) GenerateDefinitionType.CLASS
else GenerateDefinitionType.TRAIT
private fun InterfaceDefinition.mapAttributes(repository: Repository) = attributes.map { generateAttribute(!dictionary, repository, it) }
private fun InterfaceDefinition.mapOperations(repository: Repository) = operations.flatMap { generateFunction(repository, it) }
private fun Constant.mapConstant(repository : Repository) = GenerateAttribute(name, mapType(repository, type), value, false, true, false, false)
fun generateTrait(repository: Repository, iface: InterfaceDefinition): GenerateTraitOrClass {
val constructor = iface.findConstructor()
val parentTypes = iface.superTypes.map { repository.interfaces[it] }.filterNotNull().map { it to resolveDefinitionType(repository, it) }
val constructorFunction = generateFunction1(repository, Operation("", "Unit", constructor?.arguments ?: emptyList(), emptyList()), "", false)
val constructorArgumentNames = constructorFunction.arguments.map { it.name }.toSet()
val constructorSuperCalls = parentTypes.filter { it.second == GenerateDefinitionType.CLASS }.map { it.first }.map {
val superConstructor = it.findConstructor()
GenerateFunctionCall(name = it.name,
arguments = if (superConstructor == null) emptyList() else
superConstructor.arguments.map { arg ->
if (arg.name in constructorArgumentNames) arg.name
else "noImpl"
}
)
}
val entityType = resolveDefinitionType(repository, iface, constructor)
val extensions = repository.externals[iface.name]?.map { repository.interfaces[it] }?.filterNotNull() ?: emptyList()
return GenerateTraitOrClass(iface.name, entityType, iface.superTypes,
memberAttributes = (iface.mapAttributes(repository) + extensions.flatMap { it.mapAttributes(repository) }).distinct().toList(),
memberFunctions = (iface.mapOperations(repository) + extensions.flatMap { it.mapOperations(repository) }).distinct().toList(),
constnats = (iface.constants.map {it.mapConstant(repository)} + extensions.flatMap { it.constants.map {it.mapConstant(repository)} }.distinct().toList()),
constructor = constructorFunction,
superConstructorCalls = constructorSuperCalls
)
}
private fun splitUnionType(unionType: String) =
unionType.split("[>]*,(Union<)*".toRegex()).toList().filter { it != "" }.map { it.removePrefix("Union<").replaceAll(">*$", "") }.distinct()
private fun GenerateFunction?.allTypes() = if (this != null) sequenceOf(returnType) + arguments.asSequence().map { it.type } else emptySequence()
class UnionType(types : Collection<String>) {
val types = HashSet(types)
val name = "Union${this.types.sort().joinToString("Or")}"
fun contains(type : String) = type in types
override fun equals(other: Any?): Boolean = other is UnionType && name == other.name
override fun hashCode(): Int = name.hashCode()
override fun toString(): String = name
}
private fun collectUnionTypes(allTypes: Map<String, GenerateTraitOrClass>) =
allTypes.values().asSequence()
.flatMap {
it.constructor.allTypes() +
it.memberAttributes.asSequence().map { it.type } +
it.memberFunctions.asSequence().flatMap { it.allTypes() }
}
.filter { it.startsWith("Union<") }
.map { splitUnionType(it) }
.filter { it.all { unionMember -> unionMember in allTypes } }
.toSet()
.map { UnionType(it) }
fun mapUnionType(it : UnionType) = GenerateTraitOrClass(
name = it.name,
type = GenerateDefinitionType.TRAIT,
superTypes = emptyList(),
memberAttributes = emptyList(),
memberFunctions = emptyList(),
constnats = emptyList(),
constructor = null,
superConstructorCalls = emptyList()
)
fun generateUnionTypeTraits(allUnionTypes : Iterable<UnionType>): List<GenerateTraitOrClass> = allUnionTypes.map(::mapUnionType)
fun mapDefinitions(repository: Repository, definitions: Iterable<InterfaceDefinition>) =
definitions.filter { "NoInterfaceObject" !in it.extendedAttributes.map { it.call } }.map { generateTrait(repository, it) }
private fun <O: Appendable> O.indent(level : Int) {
for (i in 1..level) {
append(" ")
}
}
private fun <O : Appendable> O.renderAttributeDeclaration(allTypes: Set<String>, arg: GenerateAttribute, override: Boolean, level : Int = 1) {
indent(level)
if (override) {
append("override ")
}
append(if (arg.readOnly) "val" else "var")
append(" ")
append(arg.name)
append(" : ")
append(arg.type.mapUnknownType(allTypes))
if (arg.initializer != null) {
append(" = ")
append(arg.initializer)
}
appendln()
if (arg.getterNoImpl) {
indent(level + 1)
appendln("get() = noImpl")
}
if (arg.setterNoImpl) {
indent(level + 1)
appendln("set(value) = noImpl")
}
}
fun GenerateTraitOrClass.allSuperTypes(all: Map<String, GenerateTraitOrClass>) = HashSet<GenerateTraitOrClass>().let { result -> allSuperTypesImpl(listOf(this), all, result); result.toList() }
tailRecursive
private fun allSuperTypesImpl(roots: List<GenerateTraitOrClass>, all: Map<String, GenerateTraitOrClass>, result: HashSet<GenerateTraitOrClass>) {
if (roots.isNotEmpty()) {
allSuperTypesImpl(roots.flatMap { it.superTypes }.map { all[it] }.filterNotNull().filter { result.add(it) }, all, result)
}
}
private fun String.mapUnknownType(allTypes: Set<String>, standardTypes: Set<String> = typeMapper.values().toSet()): String =
if (this.endsWith("?")) (this.substring(0, length() - 1).mapUnknownType(allTypes, standardTypes) + "?").replace("dynamic?", "dynamic")
else if (this.startsWith("Union<")) UnionType(splitUnionType(this)).name.mapUnknownType(allTypes, standardTypes)
else if (this in allTypes || this in standardTypes) this else "dynamic"
private fun String.parse() = if (this.startsWith("0x")) BigInteger(this.substring(2), 16) else BigInteger(this)
private fun String.replaceInitializer(type: String) = if (this == "noImpl" || type == "Int" && parse() > BigInteger.valueOf(Int.MAX_VALUE.toLong())) "noImpl" else this
private fun <O : Appendable> O.renderArgumentsDeclaration(allTypes: Set<String>, args: List<GenerateAttribute>, omitDefaults: Boolean) =
args.map { "${if (it.vararg) "vararg " else ""}${it.name} : ${it.type.mapUnknownType(allTypes)}${if (omitDefaults || it.initializer == null) "" else " = ${it.initializer.replaceInitializer(it.type)}"}" }.joinTo(this, ", ")
private fun renderCall(call: GenerateFunctionCall) = "${call.name}(${call.arguments.join(", ")})"
private fun <O : Appendable> O.renderFunction(allTypes: Set<String>, f: GenerateFunction, override: Boolean) {
indent(1)
when (f.native) {
NativeGetterOrSetter.GETTER -> append("nativeGetter ")
NativeGetterOrSetter.GETTER -> append("nativeSetter ")
}
if (override) {
append("override ")
}
append("fun ${f.name}(")
renderArgumentsDeclaration(allTypes, f.arguments, override)
appendln(") : ${f.returnType.mapUnknownType(allTypes)} = noImpl")
}
fun <O : Appendable> O.render(allTypes: Map<String, GenerateTraitOrClass>, classesToUnions : Map<String, List<String>>, iface: GenerateTraitOrClass, markerAnnotation : Boolean = false) {
val superTypes = iface.allSuperTypes(allTypes).filter { it.name != "" }
val superTypesNames = superTypes.map { it.name }.toSet()
append("native ")
if (markerAnnotation) {
append("marker ")
}
when (iface.type) {
GenerateDefinitionType.CLASS -> append("open class ")
GenerateDefinitionType.TRAIT -> append("trait ")
}
append(iface.name)
if (iface.constructor != null && iface.constructor.arguments.isNotEmpty()) {
append("(")
renderArgumentsDeclaration(allTypes.keySet(), iface.constructor.arguments, false)
append(")")
}
val superCalls = iface.superConstructorCalls.map { it.name }.toSet()
val superTypesWithCalls =
iface.superConstructorCalls.filter { it.name in superTypesNames }.map { renderCall(it) } +
iface.superTypes.filter { it !in superCalls && it in superTypesNames } +
(classesToUnions[iface.name] ?: emptyList())
if (superTypesWithCalls.isNotEmpty()) {
superTypesWithCalls.joinTo(this, ", ", " : ")
}
appendln (" {")
val superAttributes = superTypes.flatMap { it.memberAttributes }.distinct()
val superFunctions = superTypes.flatMap { it.memberFunctions }.distinct()
val superProtos = superAttributes.map { it.proto } merge superFunctions.map { it.proto }
iface.memberAttributes.filter { it !in superAttributes }.forEach { arg ->
renderAttributeDeclaration(allTypes.keySet(), arg, arg.proto in superProtos)
}
iface.memberFunctions.filter { it !in superFunctions }.forEach {
renderFunction(allTypes.keySet(), it, it.proto in superProtos)
}
if (iface.constnats.isNotEmpty()) {
indent(1)
appendln("companion object {")
iface.constnats.forEach {
renderAttributeDeclaration(allTypes.keySet(), it, override = false, level = 2)
}
indent(1)
appendln("}")
}
appendln("}")
}
fun <O : Appendable> O.render(ifaces: List<GenerateTraitOrClass>, typedefs : Iterable<TypedefDefinition>) {
val all = ifaces.groupBy { it.name }.mapValues { it.getValue().single() }
val unionTypes = collectUnionTypes(all)
val unionTypeTraits = generateUnionTypeTraits(unionTypes)
val allUnions = unionTypeTraits.groupBy { it.name }.mapValues { it.getValue().single() }
val typedefsToBeGenerated = typedefs.filter {it.types.startsWith("Union<")}
.map { UnionType(splitUnionType(it.types)) to it.name }
.filter { it.first.types.all { type -> type in all} }
val typedefsClasses = typedefsToBeGenerated.groupBy { it.second }.mapValues { mapUnionType(it.value.first().first).copy(name = it.key) }
val classesToUnions = unionTypes.flatMap { unionType -> unionType.types.map { it to unionType } }.groupBy { it.first }.mapValues { it.getValue().map { it.second.name} } +
typedefsToBeGenerated.flatMap { typedef -> typedef.first.types.map { it to typedef.second } }.groupBy { it.first }.mapValues { it.getValue().map {it.second} }
val allTypes = all + allUnions + typedefsClasses
ifaces.forEach {
render(allTypes, classesToUnions, it)
}
unionTypeTraits.forEach {
render(allTypes, emptyMap(), it, markerAnnotation = true)
}
typedefsClasses.values().forEach {
render(allTypes, emptyMap(), it, markerAnnotation = true)
}
}
@@ -1,56 +0,0 @@
package org.jetbrains.idl2k
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.parser.Tag
import java.net.URL
val urls = listOf(
"https://raw.githubusercontent.com/whatwg/html-mirror/master/source",
"https://html.spec.whatwg.org/",
"https://raw.githubusercontent.com/whatwg/dom/master/dom.html",
"http://www.w3.org/TR/uievents/",
"https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html",
"https://raw.githubusercontent.com/whatwg/xhr/master/Overview.src.html",
"https://raw.githubusercontent.com/w3c/FileAPI/gh-pages/index.html",
"https://raw.githubusercontent.com/whatwg/notifications/master/notifications.html",
"https://raw.githubusercontent.com/whatwg/fullscreen/master/Overview.src.html",
"http://www.w3.org/TR/DOM-Parsing/",
"http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html",
"https://raw.githubusercontent.com/whatwg/fetch/master/Overview.src.html",
"http://www.w3.org/TR/vibration/",
"http://dev.w3.org/csswg/cssom/",
"https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl"
)
private fun extractIDLText(url: String, out: StringBuilder) {
// val soup = Jsoup.connect(url).validateTLSCertificates(false).ignoreHttpErrors(true).get()
val soup = Jsoup.parse(URL(url).readText())
fun append(it : Element) {
if (!it.tag().preserveWhitespace()) {
return append(Element(Tag.valueOf("pre"), it.baseUri()).appendChild(it))
}
val text = it.text()
out.appendln(text)
if (!text.trimEnd().endsWith(";")) {
out.appendln(";")
}
}
soup.select("pre.idl").filter {!it.hasClass("extract")}.forEach(::append)
soup.select("code.idl-code").forEach(::append)
soup.select("spec-idl").forEach(::append)
}
fun getAllIDLs(): String =
StringBuilder {
urls.forEach {
if (it.endsWith(".idl")) {
appendln(URL(it).readText())
} else {
extractIDLText(it, this)
}
}
}.toString()
+26 -19
View File
@@ -16,14 +16,11 @@
package org.jetbrains.idl2k
import org.antlr.v4.runtime.*
import org.antlr.webidl.WebIDLBaseListener
import org.antlr.webidl.WebIDLLexer
import org.antlr.webidl.WebIDLParser
import org.antlr.webidl.WebIDLParser.*
import org.antlr.v4.runtime.ANTLRInputStream
import org.antlr.v4.runtime.BufferedTokenStream
import org.antlr.v4.runtime.CommonTokenStream
import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.tree.TerminalNode
import org.antlr.webidl.WebIDLBaseVisitor
import org.jsoup.Jsoup
@@ -46,10 +43,10 @@ enum class DefinitionType {
DICTIONARY
}
trait Definition
data class TypedefDefinition(val types: String, val name: String) : Definition
data class InterfaceDefinition(val name : String, val extendedAttributes: List<ExtendedAttribute>, val operations : List<Operation>, val attributes : List<Attribute>, val superTypes : List<String>, val constants : List<Constant>, val dictionary : Boolean = false) : Definition
data class ExtensionInterfaceDefinition(val name : String, val implements : String) : Definition
data class EnumDefinition(val name : String) : Definition
data class TypedefDefinition(val types: String, val namespace : String, val name: String) : Definition
data class InterfaceDefinition(val name : String, val namespace : String, val extendedAttributes: List<ExtendedAttribute>, val operations : List<Operation>, val attributes : List<Attribute>, val superTypes : List<String>, val constants : List<Constant>, val dictionary : Boolean = false) : Definition
data class ExtensionInterfaceDefinition(val namespace : String, val name : String, val implements : String) : Definition
data class EnumDefinition(val namespace : String, val name : String) : Definition
class ExtendedAttributeArgumentsParser : WebIDLBaseVisitor<List<Attribute>>() {
private val arguments = ArrayList<Attribute>()
@@ -132,6 +129,11 @@ class TypeVisitor : WebIDLBaseVisitor<String>() {
return type
}
override fun visitTypeSuffix(ctx: TypeSuffixContext): String {
type += ctx.getText()
return type
}
override fun visitTerminal(node: TerminalNode): String {
type = node.getText()
return type
@@ -248,7 +250,7 @@ class ConstantVisitor(val attributes : List<ExtendedAttribute>) : WebIDLBaseVisi
}
}
class DefinitionVisitor(val extendedAttributes: List<ExtendedAttribute>) : WebIDLBaseVisitor<Definition>() {
class DefinitionVisitor(val extendedAttributes: List<ExtendedAttribute>, val namespace : String) : WebIDLBaseVisitor<Definition>() {
private var type : DefinitionType = DefinitionType.INTERFACE
private var name = ""
private val memberAttributes = ArrayList<ExtendedAttribute>()
@@ -261,11 +263,11 @@ class DefinitionVisitor(val extendedAttributes: List<ExtendedAttribute>) : WebID
private val constants = ArrayList<Constant>()
override fun defaultResult(): Definition = when(type) {
DefinitionType.INTERFACE -> InterfaceDefinition(name, extendedAttributes, operations, attributes, inherited, constants)
DefinitionType.DICTIONARY -> InterfaceDefinition(name, extendedAttributes, operations, attributes, inherited, constants, true)
DefinitionType.EXTENSION_INTERFACE -> ExtensionInterfaceDefinition(name, implements ?: "")
DefinitionType.TYPEDEF -> TypedefDefinition(typedefType ?: "", name)
DefinitionType.ENUM -> EnumDefinition(name)
DefinitionType.INTERFACE -> InterfaceDefinition(name, namespace, extendedAttributes, operations, attributes, inherited, constants)
DefinitionType.DICTIONARY -> InterfaceDefinition(name, namespace, extendedAttributes, operations, attributes, inherited, constants, true)
DefinitionType.EXTENSION_INTERFACE -> ExtensionInterfaceDefinition(namespace, name, implements ?: "")
DefinitionType.TYPEDEF -> TypedefDefinition(typedefType ?: "", namespace, name)
DefinitionType.ENUM -> EnumDefinition(namespace, name)
}
override fun visitInterface_(ctx: Interface_Context) : Definition {
@@ -322,7 +324,7 @@ class DefinitionVisitor(val extendedAttributes: List<ExtendedAttribute>) : WebID
?.first { it.getText() != "" }
?.getText()
val type = TypeVisitor().visit(ctx)
val type = TypeVisitor().visit(ctx.children.first {it is TypeContext})
val defaultValue = object : WebIDLBaseVisitor<String?>() {
private var value : String? = null
@@ -404,8 +406,8 @@ class DefinitionVisitor(val extendedAttributes: List<ExtendedAttribute>) : WebID
private fun getName(ctx: ParserRuleContext) = ctx.children.first {it is TerminalNode && it.getSymbol().getType() == WebIDLLexer.IDENTIFIER_WEBIDL}.getText()
fun parseIDL(reader : Reader) : Repository {
val ll = WebIDLLexer(ANTLRInputStream(reader))
fun parseIDL(reader : CharStream) : Repository {
val ll = WebIDLLexer(reader)
val pp = WebIDLParser(CommonTokenStream(ll))
val idl = pp.webIDL()
@@ -414,9 +416,10 @@ fun parseIDL(reader : Reader) : Repository {
idl.accept(object : WebIDLBaseVisitor<Unit>() {
val extendedAttributes = ArrayList<ExtendedAttribute>()
var namespace = ""
override fun visitDefinition(ctx: WebIDLParser.DefinitionContext) {
val declaration = DefinitionVisitor(extendedAttributes.toList()).visitChildren(ctx)
val declaration = DefinitionVisitor(extendedAttributes.toList(), namespace).visitChildren(ctx)
extendedAttributes.clear()
declarations.add(declaration)
}
@@ -428,6 +431,10 @@ fun parseIDL(reader : Reader) : Repository {
extendedAttributes.add(att)
}
override fun visitNamespaceRest(ctx: NamespaceRestContext) {
this.namespace = ctx.getText()
}
})
return Repository(
@@ -441,7 +448,7 @@ fun parseIDL(reader : Reader) : Repository {
fun merge(i1 : InterfaceDefinition, i2 : InterfaceDefinition) : InterfaceDefinition {
require(i1.name == i2.name)
return InterfaceDefinition(i1.name,
return InterfaceDefinition(i1.name, i1.namespace,
extendedAttributes = i1.extendedAttributes merge i2.extendedAttributes,
operations = i1.operations merge i2.operations,
attributes = i1.attributes merge i2.attributes,
+56 -21
View File
@@ -1,36 +1,71 @@
package org.jetbrains.idl2k
import org.antlr.v4.runtime.ANTLRFileStream
import java.io.File
import java.io.StringReader
import java.util.*
fun main(args: Array<String>) {
val idl = getAllIDLs()
val defs = parseIDL(StringReader(idl))
val outDir = File("../../../js/js.libraries/src/generated")
val srcDir = File("../../idl")
if (!srcDir.exists()) {
System.err?.println("Directory ${srcDir.getAbsolutePath()} doesn't exist")
System.exit(1)
return
}
outDir.deleteRecursively()
outDir.mkdirs()
println("IDL dump:")
idl.lineSequence().forEachIndexed { i, line ->
println("${i.toString().padStart(4, ' ')}: ${line}")
val repository = srcDir.walkTopDown().filter { it.isDirectory() || it.extension == "idl" }.asSequence().filter {it.isFile()}.fold(Repository(emptyMap(), emptyMap(), emptyMap(), emptyMap())) { acc, e ->
val fileRepository = parseIDL(ANTLRFileStream(e.getAbsolutePath(), "UTF-8"))
Repository(
interfaces = acc.interfaces + fileRepository.interfaces,
typeDefs = acc.typeDefs + fileRepository.typeDefs,
externals = acc.externals merge fileRepository.externals,
enums = acc.enums + fileRepository.enums
)
}
println()
defs.typeDefs.values().forEach { typedef ->
println(typedef)
}
val definitions = mapDefinitions(repository, repository.interfaces.values())
val allPackages = definitions.map { it.namespace }.distinct().sort()
val definitions = mapDefinitions(defs, defs.interfaces.values())
allPackages.forEach { pkg ->
File(outDir, pkg + ".kt").bufferedWriter().use { w ->
w.appendln("/*")
w.appendln(" * Generated file")
w.appendln(" * DO NOT EDIT")
w.appendln(" * ")
w.appendln(" * See libraries/tools/idl2k for details")
w.appendln(" */")
File("../../../js/js.libraries/src/core/dom.kt").writer().use { w ->
w.appendln("/*")
w.appendln(" * Generated file")
w.appendln(" * DO NOT EDIT")
w.appendln(" * ")
w.appendln(" * See libraries/tools/idl2k for details")
w.appendln(" */")
w.appendln()
w.appendln("package ${pkg}")
w.appendln()
w.appendln()
w.appendln("package org.w3c.dom")
w.appendln()
allPackages.filter {it != pkg}.forEach { import ->
w.appendln("import ${import}.*")
}
w.appendln()
w.render(definitions, defs.typeDefs.values())
w.render(pkg, definitions, repository.typeDefs.values())
}
}
}
private fun <K, V> Map<K, List<V>>.merge(other : Map<K, List<V>>) : Map<K, List<V>> {
val result = LinkedHashMap<K, MutableList<V>>(size() + other.size())
this.forEach {
result[it.key] = ArrayList(it.value)
}
other.forEach {
val list = result[it.key]
if (list == null) {
result[it.key] = ArrayList(it.value)
} else {
list.addAll(it.value)
}
}
return result
}
+56 -19
View File
@@ -16,6 +16,10 @@
package org.jetbrains.idl2k
import java.util.HashSet
data class NamedValue<V>(val name: String, val value: V)
data class Repository(
val interfaces: Map<String, InterfaceDefinition>,
val typeDefs: Map<String, TypedefDefinition>,
@@ -23,14 +27,14 @@ data class Repository(
val enums: Map<String, EnumDefinition>
)
data class GenerateAttribute(val name: String, val type: String, val initializer: String?, val getterSetterNoImpl: Boolean, val readOnly: Boolean, val override: Boolean, var vararg : Boolean) {
val getterNoImpl: Boolean
get() = getterSetterNoImpl
val setterNoImpl: Boolean
get() = getterSetterNoImpl && !readOnly
}
data class GenerateAttribute(val name: String, val type: String, val initializer: String?, val getterSetterNoImpl: Boolean, val readOnly: Boolean, val override: Boolean, var vararg: Boolean)
val GenerateAttribute.proto : String
val GenerateAttribute.getterNoImpl: Boolean
get() = getterSetterNoImpl
val GenerateAttribute.setterNoImpl: Boolean
get() = getterSetterNoImpl && !readOnly
val GenerateAttribute.signature: String
get() = "$name:$type"
enum class NativeGetterOrSetter {
@@ -39,20 +43,53 @@ enum class NativeGetterOrSetter {
SETTER
}
enum class GenerateDefinitionType {
enum class GenerateDefinitionKind {
TRAIT
CLASS
}
data class GenerateFunction(val name: String, val returnType: String, val arguments: List<GenerateAttribute>, val native : NativeGetterOrSetter)
class UnionType(val namespace: String, types: Collection<String>) {
val memberTypes = HashSet(types)
val name = "Union${this.memberTypes.sort().joinToString("Or")}"
fun contains(type: String) = type in memberTypes
override fun equals(other: Any?): Boolean = other is UnionType && name == other.name
override fun hashCode(): Int = name.hashCode()
override fun toString(): String = name
}
data class GenerateFunctionCall(val name: String, val arguments: List<String>)
data class GenerateTraitOrClass(val name: String,
val type : GenerateDefinitionType,
val superTypes: List<String>,
val memberAttributes: List<GenerateAttribute>,
val memberFunctions: List<GenerateFunction>,
val constnats : List<GenerateAttribute>,
val constructor: GenerateFunction?,
val superConstructorCalls: List<GenerateFunctionCall>)
val GenerateFunction.proto : String
get() = arguments.map {it.type}.joinToString(", ", "$name(", ")")
data class GenerateFunction(
val name: String,
val returnType: String,
val arguments: List<GenerateAttribute>,
val nativeGetterOrSetter: NativeGetterOrSetter
)
data class GenerateTraitOrClass(
val name: String,
val namespace: String,
val kind: GenerateDefinitionKind,
val superTypes: List<String>,
val memberAttributes: List<GenerateAttribute>,
val memberFunctions: List<GenerateFunction>,
val constants: List<GenerateAttribute>,
val constructor: GenerateFunction?,
val superConstructorCalls: List<GenerateFunctionCall>
) {
init {
assert(superConstructorCalls.size() <= 1, "It shoould be zero or one super constructors")
}
}
val GenerateFunction.signature: String
get() = arguments.map { it.type }.joinToString(", ", "$name(", ")")
fun InterfaceDefinition.findExtendedAttribute(name: String) = extendedAttributes.firstOrNull { it.call == name }
fun InterfaceDefinition?.hasExtendedAttribute(name: String) = this?.findExtendedAttribute(name) ?: null != null
fun InterfaceDefinition.findConstructor() = findExtendedAttribute("Constructor")
@@ -0,0 +1,172 @@
package org.jetbrains.idl2k
import java.math.BigInteger
private fun <O: Appendable> O.indent(level : Int) {
for (i in 1..level) {
append(" ")
}
}
private fun Appendable.renderAttributeDeclaration(allTypes: Set<String>, arg: GenerateAttribute, override: Boolean, level : Int = 1) {
indent(level)
if (override) {
append("override ")
}
append(if (arg.readOnly) "val" else "var")
append(" ")
append(arg.name)
append(": ")
append(arg.type.dynamicIfUnknownType(allTypes))
if (arg.initializer != null) {
append(" = ")
append(arg.initializer.replaceWrongConstants(arg.type))
}
appendln()
if (arg.getterNoImpl) {
indent(level + 1)
appendln("get() = noImpl")
}
if (arg.setterNoImpl) {
indent(level + 1)
appendln("set(value) = noImpl")
}
}
private val keywords = setOf("interface")
private fun String.parse() = if (this.startsWith("0x")) BigInteger(this.substring(2), 16) else BigInteger(this)
private fun String.replaceWrongConstants(type: String) = if (this == "noImpl" || type == "Int" && parse() > BigInteger.valueOf(Int.MAX_VALUE.toLong())) "noImpl" else this
private fun String.replaceKeywords() = if (this in keywords) this + "_" else this
private fun Appendable.renderArgumentsDeclaration(allTypes: Set<String>, args: List<GenerateAttribute>, omitDefaults: Boolean) =
args.map {
StringBuilder {
if (it.vararg) {
append("vararg ")
}
append(it.name.replaceKeywords())
append(": ")
append(it.type.dynamicIfUnknownType(allTypes))
if (!omitDefaults && it.initializer != null && it.initializer != "") {
append(" = ")
append(it.initializer.replaceWrongConstants(it.type))
}
}
}.joinTo(this, ", ")
private fun renderCall(call: GenerateFunctionCall) = "${call.name.replaceKeywords()}(${call.arguments.map {it.replaceKeywords()}.join(", ")})"
private fun Appendable.renderFunctionDeclaration(allTypes: Set<String>, f: GenerateFunction, override: Boolean) {
indent(1)
when (f.nativeGetterOrSetter) {
NativeGetterOrSetter.GETTER -> append("nativeGetter ")
NativeGetterOrSetter.GETTER -> append("nativeSetter ")
}
if (override) {
append("override ")
}
if (f.name in keywords) {
append("native(\"${f.name}\") ")
}
append("fun ${f.name.replaceKeywords()}(")
renderArgumentsDeclaration(allTypes, f.arguments, override)
appendln("): ${f.returnType.dynamicIfUnknownType(allTypes)} = noImpl")
}
fun Appendable.render(allTypes: Map<String, GenerateTraitOrClass>, typeNamesToUnions: Map<String, List<String>>, iface: GenerateTraitOrClass, markerAnnotation : Boolean = false) {
append("native ")
if (markerAnnotation) {
append("marker ")
}
when (iface.kind) {
GenerateDefinitionKind.CLASS -> append("open class ")
GenerateDefinitionKind.TRAIT -> append("trait ")
}
append(iface.name)
if (iface.constructor != null && iface.constructor.arguments.isNotEmpty()) {
append("(")
renderArgumentsDeclaration(allTypes.keySet(), iface.constructor.arguments, false)
append(")")
}
val allSuperTypes = iface.allSuperTypes(allTypes)
val allSuperTypesNames = allSuperTypes.map { it.name }.toSet()
val superCalls = iface.superConstructorCalls.map { it.name }.toSet()
val superTypesWithCalls =
iface.superConstructorCalls.map { renderCall(it) } +
iface.superTypes.filter { it !in superCalls && it in allSuperTypesNames } +
(typeNamesToUnions[iface.name] ?: emptyList())
if (superTypesWithCalls.isNotEmpty()) {
superTypesWithCalls.joinTo(this, ", ", " : ")
}
appendln (" {")
val superAttributes = allSuperTypes.flatMap { it.memberAttributes }.distinct()
val superFunctions = allSuperTypes.flatMap { it.memberFunctions }.distinct()
val superSignatures = superAttributes.map { it.signature } merge superFunctions.map { it.signature }
iface.memberAttributes.filter { it !in superAttributes }.forEach { arg ->
renderAttributeDeclaration(allTypes.keySet(), arg, arg.signature in superSignatures)
}
iface.memberFunctions.filter { it !in superFunctions }.forEach {
renderFunctionDeclaration(allTypes.keySet(), it, it.signature in superSignatures)
}
if (iface.constants.isNotEmpty()) {
appendln()
indent(1)
appendln("companion object {")
iface.constants.forEach {
renderAttributeDeclaration(allTypes.keySet(), it, override = false, level = 2)
}
indent(1)
appendln("}")
}
appendln("}")
appendln()
}
fun <K, V> List<Pair<K, V>>.toMultiMap() : Map<K, List<V>> = groupBy { it.first }.mapValues { it.value.map { it.second } }
fun Appendable.render(namespace : String, ifaces: List<GenerateTraitOrClass>, typedefs : Iterable<TypedefDefinition>) {
val declaredTypes = ifaces.toMap { it.name }
val anonymousUnionTypes = collectUnionTypes(declaredTypes)
val anonymousUnionTypeTraits = generateUnionTypeTraits(anonymousUnionTypes)
val anonymousUnionsMap = anonymousUnionTypeTraits.toMap { it.name }
val typedefsToBeGenerated = typedefs.filter {it.types.startsWith("Union<")}
.filter {it.namespace == namespace}
.map { NamedValue(it.name, UnionType(namespace, splitUnionType(it.types))) }
.filter { it.value.memberTypes.all { type -> type in declaredTypes} }
val typedefsMarkerTraits = typedefsToBeGenerated.groupBy { it.name }.mapValues { mapUnionType(it.value.first().value).copy(name = it.key) }
// TODO better name, extract duplication
val typeNamesToUnions = anonymousUnionTypes.flatMap { unionType -> unionType.memberTypes.map { unionMember -> unionMember to unionType.name } }.toMultiMap()
typedefsToBeGenerated.flatMap { typedef -> typedef.value.memberTypes.map { unionMember -> unionMember to typedef.name } }.toMultiMap()
val allTypes = declaredTypes + anonymousUnionsMap + typedefsMarkerTraits
declaredTypes.values().filter {it.namespace == namespace}.forEach {
render(allTypes, typeNamesToUnions, it)
}
anonymousUnionTypeTraits.forEach {
render(allTypes, emptyMap(), it, markerAnnotation = true)
}
typedefsMarkerTraits.values().forEach {
render(allTypes, emptyMap(), it, markerAnnotation = true)
}
}
@@ -0,0 +1,107 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idl2k
import java.util.*
private val typeMapper = mapOf(
"unsignedlong" to "Int",
"unsignedlonglong" to "Long",
"longlong" to "Long",
"unsignedshort" to "Short",
"void" to "Unit",
"boolean" to "Boolean",
"short" to "Short",
"long" to "Int",
"double" to "Double",
"any" to "Any",
"DOMTimeStamp" to "Number",
"object" to "dynamic", // TODO map to Any?
"EventHandler" to "(Event) -> Unit",
"WindowProxy" to "Window",
"Function" to "() -> dynamic",
"USVString" to "String",
"DOMString" to "String",
"ByteString" to "String",
"DOMError" to "dynamic",
"Uint8ClampedArray" to "dynamic", // TODO think of native arrays,
"ArrayBuffer" to "dynamic",
"Elements" to "dynamic",
"Date" to "Date",
"" to "dynamic"
)
fun GenerateTraitOrClass.allSuperTypes(all: Map<String, GenerateTraitOrClass>) = HashSet<GenerateTraitOrClass>().let { result -> allSuperTypesImpl(listOf(this), all, result); result.toList() }
tailRecursive
fun allSuperTypesImpl(roots: List<GenerateTraitOrClass>, all: Map<String, GenerateTraitOrClass>, result: HashSet<GenerateTraitOrClass>) {
if (roots.isNotEmpty()) {
allSuperTypesImpl(roots.flatMap { it.superTypes }.map { all[it] }.filterNotNull().filter { result.add(it) }, all, result)
}
}
fun String.dynamicIfUnknownType(allTypes: Set<String>, standardTypes: Set<String> = typeMapper.values().toSet()): String =
if (this.endsWith("?")) this.substring(0, length() - 1).dynamicIfUnknownType(allTypes, standardTypes).ensureNullable()
else if (this.startsWith("Union<")) UnionType("", splitUnionType(this)).name.dynamicIfUnknownType(allTypes, standardTypes) // TODO check it is required here
else if (this in allTypes || this in standardTypes) this else "dynamic"
private fun mapType(repository: Repository, type: String): String =
when {
type in typeMapper -> typeMapper[type]!!
type.endsWith("?") -> mapType(repository, type.substring(0, type.length() - 1)).ensureNullable()
type.endsWith("...") -> mapType(repository, type.substring(0, type.length() - 3))
type.endsWith("[]") -> "Array<${mapType(repository, type.substring(0, type.length() - 2))}>"
type.startsWith("unrestricted") -> mapType(repository, type.substring(12))
type.startsWith("sequence") -> "Any" // TODO how do we handle sequences?
type in repository.typeDefs -> mapTypedef(repository, type)
type in repository.enums -> "String"
type.endsWith("Callback") -> "() -> Unit"
type.startsWith("Promise<") -> "dynamic"
repository.interfaces[type].hasExtendedAttribute("NoInterfaceObject") -> "dynamic"
else -> type
}
private fun mapTypedef(repository: Repository, type: String): String {
val typedef = repository.typeDefs[type]!!
return if (!typedef.types.startsWith("Union<")) mapType(repository, typedef.types)
else if (splitUnionType(typedef.types).size() == 1) mapType(repository, splitUnionType(typedef.types).first())
else typedef.name
}
// Union<A, B, C> -> [A, B, C]
// Union<A, Union<B>, C> -> [A, B, C]
// Union<Union<Union<A, B>>, C> -> [A, B, C]
private fun splitUnionType(unionType: String) =
unionType.replaceAll("Union<", "").replaceAll("[>]+", "").split("\\s*,\\s*".toRegex()).distinct().map {it.replaceAll("\\?$", "")}
private fun GenerateFunction?.allTypes() = if (this != null) sequenceOf(returnType) + arguments.asSequence().map { it.type } else emptySequence()
private fun collectUnionTypes(allTypes: Map<String, GenerateTraitOrClass>) =
allTypes.values().asSequence()
.flatMap {
it.constructor.allTypes() +
it.memberAttributes.asSequence().map { it.type } +
it.memberFunctions.asSequence().flatMap { it.allTypes() }
}
.filter { it.startsWith("Union<") }
.map { splitUnionType(it) }
.filter { it.all { unionMember -> unionMember in allTypes } }
.toSet()
.map { UnionType("", it) }
@@ -1,192 +0,0 @@
package generators
import java.io.File
import java.io.FileWriter
import java.io.PrintWriter
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.util.ArrayList
import java.util.TreeMap
import org.w3c.dom.*
import org.w3c.dom.events.*
/**
* This tool generates JavaScript stubs for classes available in the JDK which are already available in the browser environment
* such as the W3C DOM
*/
deprecated("You shouldn't use it anymore as there is idl2k tool and DOM3 specification")
fun generateDomAPI(file: File): Unit {
val packageName = "org.w3c.dom"
val imports = ""
val classes: List<Class<*>> = arrayListOf(javaClass<Attr>(), javaClass<CDATASection>(),
javaClass<CharacterData>(), javaClass<Comment>(),
javaClass<Document>(), javaClass<DocumentFragment>(), javaClass<DocumentType>(),
javaClass<DOMConfiguration>(),
javaClass<DOMError>(), javaClass<DOMErrorHandler>(),
javaClass<DOMImplementation>(), javaClass<DOMImplementationList>(),
javaClass<DOMLocator>(),
javaClass<DOMStringList>(),
javaClass<Element>(),
javaClass<Entity>(), javaClass<EntityReference>(),
javaClass<NameList>(), javaClass<NamedNodeMap>(), javaClass<Node>(), javaClass<NodeList>(),
javaClass<Notation>(), javaClass<ProcessingInstruction>(),
javaClass<Text>(), javaClass<TypeInfo>(),
javaClass<UserDataHandler>())
writeClassesFile(file, packageName, imports, classes)
}
fun generateDomEventsAPI(file: File): Unit {
val packageName = "org.w3c.dom.events"
val imports = "import org.w3c.dom.*\nimport org.w3c.dom.views.*\n"
val classes: List<Class<*>> = arrayList(javaClass<DocumentEvent>(), javaClass<Event>(),
// TODO see domEventsCode.kt we manually hand craft this for now
// to get the implementation in JS
//
// javaClass<EventListener>(),
javaClass<EventTarget>(),
javaClass<MouseEvent>(), javaClass<MutationEvent>(),
javaClass<UIEvent>())
writeClassesFile(file, packageName, imports, classes)
}
private fun writeClassesFile(file: File, packageName: String, imports: String, classes: List<Class<*>>): Unit {
write(file) {
println("""
package $packageName
$imports
//
// NOTE THIS FILE IS AUTO-GENERATED by the GenerateJavaScriptStubs.kt
// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib
//
// Contains stub APIs for the W3C DOM API so we can delegate to the platform DOM instead
""")
fun simpleTypeName(klass: Class<out Any?>?): String {
val answer = klass?.getSimpleName()?.capitalize() ?: "Unit"
return if (answer == "Void") "Unit" else if (answer == "Object") "Any" else answer
}
fun parameterTypeName(klass: Class<out Any?>?): String {
val answer = simpleTypeName(klass)
return if (answer == "String" || answer == "Event" || answer.endsWith("DocumentType")) {
answer + "?"
} else answer
}
for (klass in classes) {
val interfaces = klass.getInterfaces()
val extends = if (interfaces != null && interfaces.size == 1) ": ${interfaces[0]?.getSimpleName()}" else ""
println("deprecated(\"Use org.w3c.dom3 instead\")")
println("native public interface ${klass.getSimpleName()}$extends {")
val methods = klass.getDeclaredMethods().sortBy { it.getName()!! }
if (methods != null) {
// lets figure out the properties versus methods
val validMethods = ArrayList<Method>()
val properties = TreeMap<String, PropertyKind>()
for (method in methods) {
if (method != null) {
val name = method.getName() ?: ""
fun propertyName(): String {
val answer = name.substring(3).decapitalize()
return if (answer == "typealias") {
"`typealias`"
} else answer
}
fun propertyType() = simpleTypeName(method.getReturnType())
fun propertyKind(method: Method): PropertyKind {
val propName = propertyName()
return properties.getOrPut(propName) { PropertyKind(propName, "val", method) }
}
val params = method.getParameterTypes()!!
val paramSize = params.size
if (name.size > 3) {
if (name.startsWith("get") && paramSize == 0) {
propertyKind(method).typeName = propertyType()
} else if (name.startsWith("set") && paramSize == 1) {
propertyKind(method).kind = "var"
} else {
validMethods.add(method)
}
} else {
validMethods.add(method)
}
}
}
for (pk in properties.values()!!) {
// some properties might not have a getter defined
// so lets ignore those
val typeName = pk.typeName
if (typeName == null) {
validMethods.add(pk.method)
} else {
println(" deprecated(\"Use org.w3c.dom instead\")")
println(" public ${pk.kind} ${pk.name}: ${typeName}")
}
}
for (method in validMethods) {
val parameterTypes = method.getParameterTypes()!!
// TODO in java 7 its not easy with reflection to get the parameter argument name...
var counter = 0
val parameters = parameterTypes.map{ "arg${++counter}: ${parameterTypeName(it)}" }.makeString(", ")
val returnType = simpleTypeName(method.getReturnType())
println(" deprecated(\"Use org.w3c.dom instead\")")
println(" public fun ${method.getName()}($parameters): $returnType = noImpl")
}
}
val fields = klass.getDeclaredFields().sortBy { it.getName()!! }
if (fields != null) {
if (fields.isNotEmpty()) {
println("")
println(" public companion object {")
for (field in fields) {
if (field != null) {
val modifiers = field.getModifiers()
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
val fieldType = simpleTypeName(field.getType())
try {
val value = field.get(null)
if (value != null) {
val fieldType = simpleTypeName(field.getType())
println(" deprecated(\"Use org.w3c.dom instead\")")
println(" public val ${field.getName()}: $fieldType = $value")
}
} catch (e: Exception) {
println("Caught: $e")
e.printStackTrace()
}
}
}
}
println(" }")
}
}
println("}")
println("")
}
}
}
class PropertyKind(val name: String, var kind: String, val method: Method, var typeName: String? = null)
fun write(file: File, block: PrintWriter.() -> Unit): Unit {
println("Generating file: ${file.getCanonicalPath()}")
val writer = PrintWriter(FileWriter(file))
writer.use { writer.block() }
}