jsweet中英文文檔,java代碼轉js代碼

這個工具能夠將java代碼轉爲js代碼,從而可使用java編寫前端代碼

若是排版看着費勁能夠下載下方html,打開html後使用google翻譯

JSweet語言規範
版本:2.x(快照)javascript

做者:Renaud Pawlakhtml

做者助理:Louis Grignon前端

JSweet JavaDoc API:http://www.jsweet.org/core-api-javadoc/java

注意:此降價是從Latex源文件自動生成的。不要直接修改。node

內容
基本概念
核心類型和對象

接口
無類型對象(地圖)
枚舉
全局
可選參數和重載
橋接外部JavaScript元素
例子
寫定義規則(又名橋樑)
沒法訪問
混入
從現有的TypeScript定義生成JSweet糖果
輔助類型
功能類型
對象類型
字符串類型
元組類型
聯盟類型
交叉類型
語義
主要方法
初始化器
數組初始化和分配
異步編程
姓名衝突
測試對象的類型
lambda表達式中的變量做用域
這個範圍
打包
使用您的文件,無需任何包裝
爲瀏覽器建立捆綁包
包裝模塊
根包
包裝JSweet jar(糖果)
擴輾轉換器
核心註釋
集中註釋 jsweetconfig.json
使用適配器進行編程調整
擴展現例
附錄1:JSweet轉換器選項
附錄2:包裝和靜態行爲
調用main方法時
靜態和繼承依賴項
基本概念
本節介紹JSweet語言的基本概念。必須記住,JSweet做爲Java-to-JavaScript轉換器,是編譯時Java的擴展,並在運行時做爲JavaScript執行。JSweet旨在經過儘量多地尊重Java語義來實現Java和JavaScript之間的權衡,但不會失去與JavaScript的互操做性。所以,在某種程度上,JSweet能夠看做是Java和JavaScript之間的融合,試圖用一種獨特且一致的語言來充分利用這兩個世界。在某些狀況下,很難充分利用這兩個世界,JSweet能夠提供方便實用的選擇。jquery

由於JSweet是一個開放的JavaScript轉換器,因此用戶能夠絕不費力地調整JavaScript生成,從而作出除默認選擇以外的其餘選擇來將Java映射到JavaScript。例如,若是JSweet實現Java映射的方式不適合您的上下文或用例,則能夠編寫JSweet擴展以覆蓋默認策略。第6節詳細介紹了編程和激活JSweet擴展 。ios

核心類型和對象
JSweet容許使用原始Java類型,核心Java對象(在java.lang許多JDK類中定義(特別是java.util但不只僅是),以及在def.js包中定義的核心JavaScript對象 。接下來,咱們描述了這些核心類型的使用和對象。git

原始Java類型
JSweet容許使用Java原始類型(和相關的文字)。程序員

int,byte,short,double,float被所有轉換成JavaScript數字(打字稿number類型)。精密一般不會在JSweet無所謂,可是,鑄造int,byte或 short強制四捨五入到合適的長度整數數量。es6

char遵循Java類型規則,但由轉換器轉換爲JavaScript string。

boolean對應於JavaScript boolean。

java.lang.String對應於JavaScript string。(不是說原始類型,可是是不可變的而且在Java中用做字符串文字的類)

轉換的直接後果是,JSweet中並不老是可使用數字或字符/字符串安全地重載方法。例如,方法pow(int, int)以及 pow(double, double)可能引發過載的問題。使用JSweet上下文,轉換器將可以選擇正確的方法,但JavaScript互操做性多是一個問題。總之,因爲沒有區別n instanceof Integer和n instanceof Double (它既裝置typeof n === ’number’)調用pow(number, number) 從JavaScript將隨機選擇一個實現或其餘。這不該該老是一個問題,但在某些特殊狀況下,它可能會產生微妙的錯誤。請注意,在這些狀況下,程序員將可以調整JavaScript生成,如第6節中的完整解釋 。

有效聲明的示例:

// warning '==' behaves like JavaScript '===' at runtime
int i = 2;
assert i == 2;
double d = i + 4;
assert d == 6;
String s = "string" + '0' + i;
assert s == "string02";
boolean b = false;
assert !b;
該==運營商的行爲相似於JavaScript的嚴格等於運算符 ===,使其接近Java語義。一樣,!=映射到!==。在將對象與null文字進行比較時,該行爲有一個例外。在這種狀況下,JSweet轉換爲鬆散的相等運算符,以便程序員看不到null和之間的區別undefined(這在JavaScript中是不一樣的,但它可能會讓Java程序員感到困惑)。要控制JSweet是否生成嚴格或鬆散的運算符,可使用如下輔助方法:jsweet.util.Lang.$strict和 jsweet.util.Lang.$loose。在這樣的宏中包裝比較運算符將強制JSweet生成嚴格或鬆散的運算符。例如:

import static jsweet.util.Lang.$loose;
[...]
int i = 2;
assert i == 2; // generates i === 2
assert !((Object)"2" == i);
assert $loose((Object)"2" == i); // generates "2" == i
容許的Java對象
默認狀況下,JSweet經過使用內置宏將核心Java對象和方法映射到JavaScript。這意味着Java代碼直接替換爲實現相似行爲的有效JavaScript代碼。爲大多數有用的核心Java類(java.lang,java.util)實現了默認映射。在可能的狀況下(當它有意義時),爲其餘JDK類實現一些部分映射,例如輸入和輸出流,區域設置,日曆,反射等。

使用默認行爲,咱們能夠指出如下限制:

除了某些特定的上下文以外,一般不可能擴展JDK類。若是須要擴展JDK類,應該考慮重構您的程序,或者使用容許它的JavaScript運行時(例如J4TS)。

Java反射API(java.lang.reflect)僅限於很是基本的操做。能夠訪問類和成員,但沒法訪問類型。可使用更完整的Java反射支持,但須要JSweet擴展。

目前還不支持Java 8流,但部分支持它們很簡單(歡迎貢獻)。

有效聲明的示例:

Integer i = 2;
assert i == 2;
Double d = i + 4d;
assert d.toString() == "6";
assert !((Object) d == "6");
BiFunction<String, Integer, String> f = (s, i) -> { return s.substring(i); };
assert "bc" == f.apply("abc", 1);
得到更多Java API
使用JSweet,能夠添加在JavaScript中實現Java API的運行時,以便程序員能夠訪問更多Java API,從而在Java和JavaScript之間共享相同的代碼。爲JSweet實現Java API的核心項目是J4TS(https://github.com/cincheo/j4ts),它包含一個很是完整的java.util.*類和其餘核心包的實現。J4TS基於GWT的JRE仿真的一個分支,但它適合用JSweet編譯。程序員能夠將J4TS用做Maven存儲庫中的常規JavaScript庫。

雖然J4TS不能直接執行Java核心類型的使用JavaScript的人發生衝突(Boolean,Byte,Short,Integer, Long,Float,Double,Character,String),J4TS有助於經過爲每一個類提供傭工(支持他們的靜態部分javaemul.internal.BooleanHelper,javaemul.internal.ByteHelper...)。當JSweet轉換器在java.lang.T不支持做爲內置宏的類型上遇到靜態Java方法時 ,它會委託給 javaemul.internal.THelper,它能夠爲給定的靜態方法提供JavaScript實現。這樣,經過使用J4TS,程序員可使用更多的核心JRE API。

Java數組
數組能夠在JSweet中使用,並轉換爲JavaScript數組。數組初始化,訪問和迭代都是有效的語句。

int[] arrayOfInts = { 1, 2, 3, 4};
assert arrayOfInts.length == 4;
assert arrayOfInts[0] == 1;
int i = 0;
for (int intItem : arrayOfInts) {

assert arrayOfInts[i++] == intItem;

}
核心JavaScript API
核心JavaScript API已定義def.js(完整文檔可在http://www.jsweet.org/core-ap...)。主要的JavaScript類是:

def.js.Object:JavaScript Object類。JavaScript對象函數和屬性的共同祖先。

def.js.Boolean:JavaScript布爾類。布爾值的包裝器。

def.js.Number:JavaScript Number類。數值的包裝器。

def.js.String:JavaScript String類。字符串的包裝器和構造函數。

def.js.Function:JavaScript函數類。函數的構造函數。

def.js.Date:JavaScript Date類,它支持基本存儲和檢索日期和時間。

def.js.Array<T>:JavaScript Array類。它用於構造數組,它是高級的,相似列表的對象。

def.js.Error:JavaScript錯誤類。這個類實現 java.lang.RuntimeException而且能夠被拋出並被try ... catch語句捕獲。

使用JavaScript框架時,程序員應該在大多數時間使用此API,這與HTML5兼容並遵循JavaScript最新支持的版本。可是,對於須要與Java文字(數字,布爾值和字符串)一塊兒使用的對象,java.lang 建議使用包類。例如,jQuery API聲明 $(java.lang.String)而不是$(def.js.String)。這容許程序員使用文字來編寫表達式,例如$("a")(用於選擇文檔中的全部連接)。

使用JSweet,程序員能夠根據須要輕鬆地從Java切換到JavaScript API(反之亦然)。在jsweet.util.Lang 類定義方便的靜態方法投來回核心Java對象到其相應的JavaScript對象。例如,該 string(...)方法將容許程序員從Java切換到JavaScript字符串,反之亦然。

import static jsweet.util.Lang.string;
// str is a Java string, but is actually a JavaScript string at runtime
String str = "This is a test string";
// str is exactly the same string object, but shown through the JS API
def.js.String str2 = string(str);
// valid: toLowerCase it defined both in Java and JavaScript
str.toLowerCase();
// this method is not JS-compatible, so a macro generates the JS code
str.equalsIgnoreCase("abc");
// direct call to the JS substr method on the JavaScript string
string(str).substr(1);
// or
str2.substr(1);
注意:例如,對於JavaScript客戶端和Java服務器之間的代碼共享,最好只使用Java API並避免使用JavaScript API。JavaScript API將編譯有效的Java字節碼,但嘗試在JVM上執行它們會引發不滿意的連接錯誤。

這是另外一個示例,顯示了使用該array方法訪問pushJavaScript數組中可用的方法。

import static jsweet.util.Lang.array;
String[] strings = { "a", "b", "c" };
array(strings).push("d");
assert strings[3] == "d";

JSweet中的類徹底支持全部類型的Java類聲明。例如:

public class BankAccount {

public double balance = 0;
public double deposit(double credit) {
    balance += credit;
    return this.balance;
}

}
這被轉換爲如下JavaScript代碼:

var BankAccount = (function () {

function BankAccount() {
    this.balance = 0;
}
BankAccount.prototype.deposit = function(credit) {
    this.balance += credit;
    return this.balance;
};
return BankAccount;

})();
類能夠定義構造函數,具備超類,而且能夠像在Java中同樣實例化。與Java相似,JSweet中容許使用內部類和匿名類(從1.1.0版開始)。JSweet支持靜態和常規內部/匿名類,它們能夠與封閉類共享狀態。仍然像在Java中同樣,匿名類能夠訪問其做用域中聲明的最終變量。例如,如下聲明在JSweet中有效,而且將在運行時模仿Java語義,以便Java程序員能夠受益於Java語言的全部功能。

abstract class C {

public abstract int m();

}
public class ContainerClass {

// inner class
public class InnerClass {
    public I aMethod(final int i) {
        // anonymous class
        return new C() {
            @Override
            public int m() {
                // access to final variable i
                return i;
            }
        }
    }
}

}
接口
在JSweet中,能夠像在Java中同樣使用接口。可是,與Java相反,沒有關聯的類可用做運行時。使用接口時,JSweet會生成代碼來模擬特定的Java行爲(例如instanceof在接口上)。

JSweet支持Java 8靜態和默認方法。可是,默認方法到目前爲止都是實驗性的,你應該自擔風險使用它們。

在JSweet中,接口更相似於TypeScript中的接口而不是Java中的接口。這意味着它們必須被視爲對象簽名,它能夠指定函數,還能夠指定屬性。爲了在定義接口時容許使用字段做爲屬性,JSweet容許使用帶註釋的常規類@jsweet.lang.Interface。例如,如下接口鍵入Point具備2個屬性的對象。

@Interface
public class Point {

public double x;
public double y;

}
對於Java程序員來講,這可能看起來像是一種很是奇怪的方法來定義一個對象,可是你必須記住它不是一個類,而是一個JavaScript對象的類型。所以,它不違反OOP原則。咱們能夠建立一個在界面後鍵入的JavaScript對象。請注意,如下代碼實際上並未建立Point 接口的實例,而是建立符合接口的對象。

Point p1 = new Point() {{ x=1; y=1; }};
此對象建立機制是TypeScript / JavaScript機制,不該與匿名類混淆,匿名類是相似Java的構造。由於Point有註釋@Interface,轉換後的JavaScript代碼相似於:

var p1 = Object.defineProperty({ x:1, y:1 }, "_interfaces", ["Point"]);
請注意,對於每一個對象,JSweet會跟蹤其建立的接口以及其類實現的全部可能接口。此接口跟蹤系統實現爲一個名爲的特殊對象屬性__interfaces。使用該屬性,JSweet容許instanceof在Java之類的接口上使用運算符。

接口中的可選字段
接口能夠定義可選字段,用於在程序員忘記初始化對象中的必填字段時報告錯誤。在JSweet中支持可選字段是經過使用 @jsweet.lang.Optional註釋完成的。例如:

@Interface
public class Point {

public double x;
public double y;
@Optional
public double z = 0;

}
在從接口構造對象時,JSweet編譯器將檢查字段是否已正確初始化。

// no errors (z is optional)
Point p1 = new Point() {{ x=1; y=1; }};
// JSweet reports a compile error since y is not optional
Point p2 = new Point() {{ x=1; z=1; }};
接口中的特殊JavaScript函數
在JavaScript中,對象能夠具備屬性和函數,但也能夠(非排他地)用做構造函數和函數自己。這在Java中是不可能的,所以JSweet定義了用於處理這些狀況的特殊函數。

$apply 用於表示該對象能夠用做函數。

$new 用於聲明該對象能夠用做構造函數。

例如,若是一個對象o是O定義 的接口$apply(),則寫:

o.$apply();
將轉變爲:

o();
一樣,若是O定義$new():

o.$new();
將轉變爲:

new o();
是的,它在Java中沒有意義,但在JavaScript中確實如此!

無類型對象(地圖)
在JavaScript中,對象能夠看做包含鍵值對的映射(鍵一般稱爲索引,尤爲是當它是數字時)。所以,在JSweet中,全部對象都定義了特殊函數(定義於 def.js.Object):

$get(key) 使用給定鍵訪問值。

$set(key,value) 設置或替換給定鍵的值。

$delete(key) 刪除給定鍵的值。

反射/無類型訪問
的功能$get(key),$set(key,value)而且$delete(key)能夠被看做是一個簡單的反射API來訪問對象字段和狀態。還要注意靜態方法def.js.Object.keys(object),它返回給定對象上定義的全部鍵。

如下代碼使用此API來內省對象的狀態 o。

for(String key : def.js.Object.keys(o)) {
console.log("key=" + key + " value=" + o.$get(key));
});
當沒有給定對象的類型化API時,此API可用於以無類型方式操做對象(固然應儘量避免使用)。

無類型對象初始化
可使用該$set(key,value)函數建立新的無類型對象。例如:

Object point = new def.js.Object() {{ $set("x", 1); $set("y", 1); }};
它也轉化爲:

var point = { "x": 1, "y": 1};
做爲一種快捷方式,可使用該jsweet.util.Lang.$map函數,該函數轉換爲徹底相同的JavaScript代碼:

import static jsweet.util.Lang.$map;
[...]
Object point = $map("x", 1, "y", 1);
索引對象
能夠爲每一個對象重載鍵和值的類型。例如,Array<T>類將鍵做爲數字和值定義爲符合類型的對象T。

對於使用數字鍵索引的對象,容許實現java.lang.Iterable接口,以即可以在foreach循環中使用它們。例如,NodeList類型(來自DOM)定義了一個索引函數:

@Interface
class NodeList implements java.lang.Iterable {

public double length;
public Node item(double index);
public Node $get(double index);

}
在JSweet中,您可使用該$get 函數訪問節點列表元素,也可使用foreach語法進行迭代。如下代碼生成徹底有效的JavaScript代碼。

NodeList nodes = ...
for (int i = 0; i < nodes.length; i++) {

HTMLElement element = (HTMLElement) nodes.$get(i);
[...]

}
// same as:
NodeList nodes = ...
for (Node node : nodes) {

HTMLElement element = (HTMLElement) node;
[...]

}
枚舉
JSweet容許相似於Java定義枚舉。下面的代碼聲明與樹可能值的枚舉(A,B,和C)。

enum MyEnum {

A, B, C

}
如下語句是JSweet中的有效語句。

MyEnum e = MyEnum.A;
assert MyEnum.A == e;
assert e.name() == "A";
assert e.ordinal() == 0;
assert MyEnum.valueOf("A") == e;
assert array(MyEnum.values()).indexOf(MyEnum.valueOf("C")) == 2;
與Java枚舉同樣,能夠在枚舉中添加其餘方法,構造函數和字段。

enum ScreenRatio {

FREE_RATIO(null),
RATIO_4_3(4f / 3),
RATIO_3_2(1.5f),
RATIO_16_9(16f / 9),
RATIO_2_1(2f / 1f),
SQUARE_RATIO(1f);

private final Float value;

private MyComplexEnum(Float value) {
    this.value = value;
}

public Float getValue() {
    return value;
}

}
枚舉便攜性說明
簡單的枚舉被轉換爲常規的TypeScript枚舉,即數字。在JavaScript中,在運行時,枚舉實例是簡單編碼的序數。所以,JSweet枚舉很容易與TypeScript枚舉共享,即便使用枚舉,JSweet程序也能夠與TypeScript程序進行互操做。

具備其餘成員的枚舉也會映射到TypeScript枚舉,但會生成另外一個類來存儲其餘信息。與TypeScript互操做時,序號將保留,但附加信息將丟失。想要與TypeScript共享枚舉的程序員應該知道這種行爲。

全局
在Java中,與JavaScript相反,沒有全局變量或函數(只有靜態成員,但即便那些必須屬於一個類)。所以,JSweet引入了保留的Globals 類和globals包。這有兩個目的:

生成具備全局變量和函數的代碼(在Java中不鼓勵這樣作)

綁定到定義全局變量和函數的現有JavaScript代碼(儘量多的JavaScript框架)

在Globals類中,只容許使用靜態字段(全局變量)和靜態方法(全局函數)。如下是適用於Globals類的主要約束:

沒有非靜態成員

沒有超級課程

不能延長

不能用做常規類的類型

沒有公共構造函數(空私有構造函數能夠)

不能在方法中使用$ get,$ set和$ delete

例如,如下代碼片斷將引起轉換錯誤。

class Globals {

public int a;
// error: public constructors are not allowed
public Globals() {
    this.a = 3;
}
public static void test() {
    // error: no instance is available
    $delete("key");
}

}
// error: Globals classes cannot be used as types
Globals myVariable = null;
必須記住,Globals類和global包在運行時被擦除,以即可以直接訪問它們的成員。例如mypackage.Globals.m(),在JSweet程序中,對應mypackage.m()於生成的代碼中的函數以及運行時的JavaScript VM中的 函數。此外,mypackage.globals.Globals.m()對應於m()。

爲了擦除生成代碼中的包,程序員也可使用@Root註釋,這將在第5節中解釋 。

可選參數和重載
In JavaScript, parameters can be optional, in the sense that a parameter value does not need to be provided when calling a function. Except for varargs, which are fully supported in JSweet, the general concept of an optional parameter does not exist in Java. To simulate optional parameters, JSweet programmers can use method overloading, which is supported in Java. Here are some examples of supported overloads in JSweet:

String m(String s, double n) { return s + n; }
// simple overloading (JSweet transpiles to optional parameter)
String m(String s) { return m(s, 0); }
// complex overloading (JSweet generates more complex code to mimic the Java behavior)
String m(String s) { return s; }
Bridging to external JavaScript elements
It can be the case that programmers need to use existing libraries from JSweet. In most cases, one should look up in the available candies, a.k.a. bridges at http://www.jsweet.org/jsweet-... When the candy does not exist, or does not entirely cover what is needed, one can create new definitions in the program just by placing them in the def.libname package. Definitions only specify the types of external libraries, but no implementations. Definitions are similar to TypeScript’s .d.ts definition files (actually JSweet generates intermediate TypeScript definition files for compilation purposes). Definitions can also be seen as similar to .h C/C++ header files.

Examples
如下示例顯示了使用簡單定義可供JSweet程序員訪問的主幹存儲類。此類僅用於鍵入,將做爲TypeScript定義生成,並在JavaScript生成期間擦除。

package def.backbone;
class Store {

public Store(String dbName) {}

}
請注意,定義類構造函數必須具備空體。此外,定義類方法必須是native。例如:

package def.mylib;
class MyExternalJavaScriptClass {

public native myExternalJavaScriptMethod();

}
能夠在定義中定義屬性,可是,沒法初始化這些屬性。

寫定義規則(又名橋樑)
按照慣例,將類放在def.libname包中定義了一組libname名爲的外部JavaScript庫 的定義libname。請注意,此機制相似於TypeScript d.ts 定義文件。

Candies(外部JavaScript庫的橋樑)使用定義。例如,jQuery candy定義了def.jquery包中的全部jQuery API 。

如下是編寫定義時須要遵循的規則和約束的列表。

接口比類更受歡迎,由於接口能夠合併,類能夠實例化。僅當API定義顯式構造函數(可使用其建立對象new)時,才應使用類。要在JSweet中定義接口,只需使用註釋類@jsweet.lang.Interface。

必須將頂級函數和變量定義爲類中的public static 成員Globals。

全部類,接口和包都應記錄在Javadoc標準以後的註釋。

當函數參數有多種類型時,方法重載應優先於使用union類型。當沒法進行方法重載時,簡單地使用Object類型會更方便。鍵入的強度較低,但更容易使用。

可使用字符串類型來提供函數重載,具體取決於字符串參數值。

在方法簽名中,可使用@jsweet.lang.Optional註釋定義可選參數 。

在界面中,可使用@jsweet.lang.Optional註釋定義可選字段 。

定義能夠直接嵌入到JSweet項目中,以便以類型化的方式訪問外部庫。

定義也能夠打包成糖果(Maven工件),以便它們能夠被其餘項目共享。有關如何建立糖果的完整詳細信息,請參閱「 包裝」部分。請注意,在使用JSweet編寫庫時不須要編寫定義,由於Java API能夠直接訪問,而且可使用該declaration選項由JSweet自動生成TypeScript定義。

沒法訪問
有時,定義不可用或不正確,只須要一個小補丁便可訪問功能。程序員必須記住,JSweet只是一個語法層,而且老是能夠繞過鍵入以訪問未在API中明確指定的字段或函數。

雖然具備良好類型的API是首選和建議的方式,可是當這樣的API不可用時,使用def.js.Object.$get容許反射訪問方法和屬性,而後能夠將其轉換爲正確的類型。爲了以無類型方式訪問函數,能夠強制轉換 def.js.Function並調用泛型和非類型化方法$apply。例如,如下是$在jQuery API不可用時如何調用jQuery 方法:

import def.dom.Globals.window;
[...]
Function $ = (Function)window.$get("$");
$.$apply("aCssSelector"):
該$get函數可用於def.js.Object(或子類)的實例。對於a def.js.Object,您可使用jsweet.util.Lang.object輔助方法強制轉換它 。例如:

import static jsweet.dom.Lang.object;
[...]
object(anyObject).$get("$");
最後,jsweet.util.Lang.$inserthelper方法容許用戶在程序中插入任何TypeScript表達式。無效的表達式將引起TypeScript編譯錯誤,但不建議使用此技術。

import static jsweet.dom.Lang.$get;
import static jsweet.dom.Lang.$apply;
[...]
// generate anyObject"prop";
$apply($get(anyObject, "prop"), "param");
最後,還要注意使用jsweet.util.Lang.any輔助方法,這對於擦除鍵入很是有用。因爲該any方法any在TypeScript中生成類型的強制轉換,所以它比例如強制轉換更激進Object。如下示例說明如何使用該any方法將Int32ArrayJava轉換爲Java int[](而後容許對其進行直接索引訪問)。

ArrayBuffer arb = new ArrayBuffer(2 2 4);
int[] array = any(new Int32Array(arb));
int whatever = array[0];
混入
在JavaScript中,一般的作法是使用新聞元素(字段和方法)來加強現有類。它是框架定義插件時使用的擴展機制。一般,jQuery插件會向JQuery類中添加新元素。例如,jQuery計時器插件timer向JQuery該類添加一個字段。所以,JQuery若是您單獨使用jQuery,或者使用其計時器插件加強jQuery ,則 該類沒有相同的原型。

在Java中,此擴展機制存在問題,由於Java語言默認狀況下不支持mixins或任何類型的擴展。

沒法訪問mixins
程序員可使用訪問$get器和/或強力轉換來訪問添加的元素。

如下是$get用於計時器插件的示例:

((Timer)$("#myId").$get("timer")).pause();
這是另外一種經過使用jQuery UI插件來實現它的方法(請注意,此解決方案強制使用def.jqueryui.JQuery 而不是def.jquery.JQuery爲了訪問menu()由UI插件添加的功能):

import def.jqueryui.JQuery;
[...]
Object obj = $("#myMenu");
JQuery jq = (JQuery) obj;
jq.menu();
然而,這些解決方案並不徹底使人滿意,由於在打字方面明顯不安全。

使用mixins鍵入訪問
當須要交叉糖果動態擴展時,JSweet定義了mixin的概念。mixin是一個定義成員的類,最終能夠在目標類(mixin-ed類)中直接訪問。Mixins使用@Mixin註釋定義。這是def.jqueryui.JQuerymixin 的摘錄 :

package def.jqueryui;
import def.dom.MouseEvent;
import def.js.Function;
import def.js.Date;
import def.js.Array;
import def.js.RegExp;
import def.dom.Element;
import def.jquery.JQueryEventObject;
@jsweet.lang.Interface
@jsweet.lang.Mixin(target=def.jquery.JQuery.class)
public abstract class JQuery extends def.jquery.JQuery {

native public JQuery accordion();
native public void accordion(jsweet.util.StringTypes.destroy methodName);
native public void accordion(jsweet.util.StringTypes.disable methodName);
native public void accordion(jsweet.util.StringTypes.enable methodName);
native public void accordion(jsweet.util.StringTypes.refresh methodName);
...
native public def.jqueryui.JQuery menu();
...

人們能夠注意到@jsweet.lang.Mixin(target=def.jquery.JQuery.class) ,這個mixin將被合併到一塊兒,def.jquery.JQuery以便用戶可以直接以一種良好的方式使用全部UI插件成員。

如何使用
TBD。

從現有的TypeScript定義生成JSweet糖果
TBD。

輔助類型
JSweet使用大多數Java輸入功能(包括功能類型),但也使用所謂的輔助類型擴展Java類型系統。輔助類型背後的想法是建立能夠經過使用類型參數(也稱爲泛型)來保存鍵入信息的類或接口 ,以便JSweet轉換器能夠涵蓋更多的鍵入方案。這些類型已經從TypeScript類型系統映射,它比Java更豐富(主要是由於JavaScript是一種動態語言,須要比Java更多的打字場景)。

功能類型
用於功能類型,JSweet重用java.Runnable和 java.util.function爪哇8的功能接口,這些接口是通用的,但只支持高達2參數的功能。所以,JSweet爲更多參數添加了一些支持jsweet.util.function,由於它是JavaScript API中的常見狀況。

如下是使用Function通用功能類型的示例:

import java.util.function.Function;

public class C {

String test(Function<String, String> f) {
    f.apply("a");
}

public static void main(String[] args) {
    String s = new C().test(p -> p);
    assert s == "a";
}

}
咱們鼓勵程序員使用jsweet.util.function和java.util.function(以及 java.lang.Runnable)中定義的通用功能接口。當須要具備更多參數的函數時,程序員能夠jsweet.util.function經過遵循與現有函數相同的模板來定義他們本身的通用函數類型 。

在某些狀況下,程序員更願意定義本身的特定功能接口。這獲得了JSweet的支持。例如:

@FunctionalInterface
interface MyFunction {

void run(int i, String s);

}

public class C {

void m(MyFunction f) {
    f.run(1, "test");
}
public static void main(String[] args) {
    new C().m((i, s) -> {
        // do something with i and s
    });
}

}
重要警告:這裏要注意的是,與Java相反,@FunctionInterface註釋的使用是強制性的。

還要注意apply函數的可能用途,按照慣例,該函數始終是目標對象的功能定義(除非使用apply註釋進行@Name註釋)。定義/調用 apply能夠在任何類/對象上完成(由於在JavaScript中任何對象均可以成爲一個功能對象)。

對象類型
對象類型與接口相似:它們定義了一組適用於對象的字段和方法(但請記住它是一個編譯時合同)。在TypeScript中,對象類型是內聯的和匿名的。例如,在TypeScript中,如下方法m接受一個參數,該參數是包含index字段的對象:

// TypeScript:
public class C {

public m(param : { index : number }) { ... }

}
對象類型是編寫較短代碼的便捷方式。能夠經過動態構建對象來傳遞正確鍵入的對象:

// TypeScript:
var c : C = ...;
c.m({ index : 2 });
顯然,對象類型是一種使程序員很容易輸入JavaScript程序的方法,這是TypeScript的主要目標之一。它使得JavaScript程序員的輸入簡潔,直觀,直觀。在Java / JSweet中,不存在相似的內聯類型,Java程序員用於爲這種狀況定義類或接口。所以,在JSweet中,程序員必須定義用@ObjectType對象類型註釋的輔助類。這可能看起來更復雜,但它有利於強制程序員命名全部類型,最終能夠根據上下文致使更易讀和可維護的代碼。請注意,與接口相似,對象類型在運行時被擦除。另外@ObjectType 註解的類能夠內部類,使他們在本地使用。

這是之前的TypeScript程序的JSweet版本。

public class C {

@ObjectType
public static class Indexed {
    int index;
}
public void m(Indexed param) { ... }

}
使用對象類型與使用接口相似:

C c = ...;
c.m(new Indexed() {{ index = 2; }});
當對象類型是共享對象並表示能夠在多個上下文中使用的鍵入實體時,建議使用 @Interface註釋而不是@ObjectType。這是基於界面的版本。

@Interface
public class Indexed {

int index;

}

public class C {

public m(Indexed param) { ... }

}

C c = ...;
c.m(new Indexed {{ index = 2; }});
字符串類型
在TypeScript中,字符串類型是一種根據字符串參數的值來模擬函數重載的方法。例如,這是DOM TypeScript定義文件的簡化摘錄:

// TypeScript:
interface Document {

[...]
getElementsByTagName(tagname: "a"): NodeListOf<HTMLAnchorElement>;
getElementsByTagName(tagname: "b"): NodeListOf<HTMLPhraseElement>;
getElementsByTagName(tagname: "body"): NodeListOf<HTMLBodyElement>;
getElementsByTagName(tagname: "button"): NodeListOf<HTMLButtonElement>;
[...]

}
在此代碼中,getElementsByTagName函數都是依賴於傳遞給tagname參數的字符串的重載。不只字符串類型容許函數重載(一般在TypeScript / JavaScript中不容許),但它們也約束字符串值(相似於枚舉),所以編譯器能夠自動檢測字符串值中的拼寫錯誤並引起錯誤。

此功能對代碼質量頗有用,JSweet提供了一種機制來模擬具備相同級別類型安全性的字符串類型。字符串類型是使用註釋的公共靜態字段@StringType。必須使用在同一容器類型中聲明的同名接口鍵入它。

對於JSweet翻譯庫(糖果),全部字符串類型都在類中聲明jsweet.util.StringTypes,所以程序員很容易找到它們。舉例來講,若是一個"body"字符串類型須要定義,一個名爲Java接口body和一個靜態的最終場被稱爲body在一個定義jsweet.util.StringTypes。

請注意,每一個糖果可能在jsweet.util.StringTypes類中定義了本身的字符串類型 。JSweet轉換器在字節碼級別合併全部這些類,以便全部糖果的全部字符串類型在同一個jsweet.util.StringTypes實用程序類中可用。所以,JSweet DOM API將以下所示:

@Interface
public class Document {

[...]
public native NodeListOf<HTMLAnchorElement> getElementsByTagName(a tagname);
public native NodeListOf<HTMLPhraseElement> getElementsByTagName(b tagname);
public native NodeListOf<HTMLBodyElement> getElementsByTagName(body tagname);
public native NodeListOf<HTMLButtonElement> getElementsByTagName(button tagname);
[...]

}
在此API中a,b,body和button是在定義的接口 jsweet.util.StringTypes類。當使用一種方法時 Document,程序員只須要使用相應的類型實例(同名)。例如:

Document doc = ...;
NodeListOf<HTMLAnchorElement> elts = doc.getElementsByTagName(StringTypes.a);
注意:若是字符串值不是有效的Java標識符(例如 "2d"或者"string-with-dashes"),則將其轉換爲有效的標識符並使​​用註釋@Name("originalName"),以便JSweet轉換器知道必須在生成的代碼中使用什麼實際字符串值。例如,默認狀況下,"2d"和"string-with-dashes"將對應於接口StringTypes._2d和 StringTypes.string_with_dashes與@Name註解。

程序員能夠根據本身的須要定義字符串類型,以下所示:

import jsweet.lang.Erased;
import jsweet.lang.StringType;

public class CustomStringTypes {

@Erased
public interface abc {}

@StringType
public static final abc abc = null;

// This method takes a string type parameter
void m2(abc arg) {
}

public static void main(String[] args) {
    new CustomStringTypes().m2(abc);
}

}
注意使用@Erased註釋,它容許聲明abc內部接口。此接口用於鍵入字符串類型字段abc。一般,咱們建議程序員將程序的全部字符串類型分組到同一個實用程序類中,以便於查找它們。

元組類型
元組類型表示具備單獨跟蹤的元素類型的JavaScript數組。對於的元組類型,JSweet定義參數化輔助類TupleN<T0, ... TN-1>,它定義$0,$1... $N-1 公共字段來模擬訪問類型數組(字段$i中鍵入與 Ti)。

例如,給定如下大小爲2的元組:

Tuple2<String, Integer> tuple = new Tuple2<String, Integer>("test", 10);
咱們能夠期待如下(良好類型)行爲:

assert tuple.$0 == "test";
assert tuple.$1 == 10;
tuple.$0 = "ok";
tuple.$1--;
assert tuple.$0 == "ok";
assert tuple.$1 == 9;
元組類型都在jsweet.util.tuple包中定義(而且必須定義) 。默認狀況下Tuple[2..6],定義了類。當在糖果API中遇到時,會自動生成其餘元組(> 6)。固然,當須要在jsweet.util.tuple包中找不到更大的元組時,程序員能夠根據須要在該包中添加本身的元組,只需遵循與現有元組相同的模板便可。

聯盟類型
聯合類型表示可能具備多個不一樣表示之一的值。當這種狀況發生在方法簽名中時(例如,容許給定參數的幾種類型的方法),JSweet利用了Java中可用的方法重載機制。例如,如下m方法接受參數p,該參數能夠是a String或a Integer。

public void m(String p) {...}
public void m(Integer p) {...}
在前一種狀況下,不須要使用顯式聯合類型。對於更通常的狀況,JSweet 在 包中定義了一個輔助接口 Union<T1, T2>(和UnionN<T1, ... TN>)jsweet.util.union。經過使用此輔助類型和union實用程序方法,程序員能夠在union類型和union-ed類型之間來回轉換,以便JSweet能夠確保與TypeScript聯合類型相似的屬性。

如下代碼顯示了JSweet中union類型的典型用法。它只是將一個變量聲明爲一個字符串和一個數字之間的聯合,這意味着該變量實際上能夠是其中一種類型(但沒有其餘類型)。從聯合類型到常規類型的切換是經過jsweet.util.Lang.union輔助方法完成的。這個輔助方法是徹底無類型的,容許從Java角度將任何聯合轉換爲另外一種類型。它其實是JSweet轉換器,它檢查是否一直使用了union類型。

import static jsweet.util.Lang.union;
import jsweet.util.union.Union;
[...]
Union<String, Number> u = ...;
// u can be used as a String
String s = union(u);
// or a number
Number n = union(u);
// but nothing else
Date d = union(u); // JSweet error
若是union須要,也可使用其餘方式將助手從常規類型切換回聯合類型。

import static jsweet.util.Lang.union;
import jsweet.util.union.Union3;
[...]
public void m(Union3<String, Number, Date>> u) { ... }
[...]
// u can be a String, a Number or a Date
m(union("a string"));
// but nothing else
m(union(new RegExp(".*"))); // compile error
注意:在鍵入函數參數時,優先使用Java函數重載而不是union類型。例如:

// with union types (discouraged)
native public void m(Union3<String, Number, Date>> u);
// with overloading (preferred way)
native public void m(String s);
native public void m(Number n);
native public void m(Date d);
交叉類型
TypeScript定義了類型交集的概念。當類型相交時,意味着結果類型是更大的類型,它是全部相交類型的總和。例如,在TypeScript中, A & B對應於定義二者A和B成員的類型。

因爲許多緣由,Java中的交集類型沒法輕鬆實現。所以,這裏作出的實際選擇是使用聯合類型代替交集類型。A & B所以,在JSweet中定義爲 Union<A, B>,這意味着程序員可使用輔助方法訪問這二者A和 B成員jsweet.util.Lang.union。它固然不如TypeScript版本方便,但它仍然是類型安全的。

語義
語義指定給定程序在執行時的行爲方式。雖然JSweet依賴於Java語法,但程序被轉換爲JavaScript而且不在JRE中運行。所以,與Java程序相比,JavaScript語義將影響JSweet程序的最終語義。在本節中,咱們將經過關注Java / JavaSript和JSweet之間的差別或共性來討論語義。

主要方法
主要方法是程序執行入口點,而且在main評估包含方法的類時將全局調用。例如:

public class C {

private int n;
public static C instance;
public static void main(String[] args) {
    instance = new C();
    instance.n = 4;
}
public int getN() {
    return n;
}

}
// when the source file containing C has been evaluated:
assert C.instance != null;
assert C.instance.getN() == 4;
全局調用main方法的方式取決於程序的打包方式。有關詳細信息,請參閱附錄。

初始化器
初始化器的行爲與Java相似。

例如:

public class C1 {

int n;
{
    n = 4;
}

}
assert new C1().n == 4;
與靜態初始化器相似:

public class C2 {

static int n;
static {
    n = 4;
}

}
assert C2.n == 4;
雖然在實例化類時會評估常規初始值設定項,可是爲了不前向依賴性問題而懶惰地評估靜態初始化程序,並模擬初始化程序的Java行爲。使用JSweet,程序員能夠定義靜態字段或靜態初始化程序,它依賴於還沒有初始化的靜態字段。

有關此行爲的更多詳細信息,請參閱附錄。

數組初始化和分配
數組能夠像Java同樣使用。

String[] strings = { "a", "b", "c" };
assert strings[1] == "b";
指定維度時,數組是預先分配的(如Java中所示),所以它們使用正確的長度進行初始化,並在多維數組的狀況下使用正確的子數組進行初始化。

String[][] strings = new String2;
assert strings.length == 2;
assert strings[0].length == 2;
strings0 = "a";
assert strings0 == "a";
經過強制轉換爲def.js.Arraywith,能夠在數組上使用JavaScript API jsweet.util.Lang.array。

import static jsweet.util.Lang.array;
[...]
String[] strings = { "a", "b", "c" };
assert strings.length == 3;
array(strings).push("d");
assert strings.length == 4;
assert strings[3] == "d";
在某些狀況下,最好def.js.Array直接使用該類。

Array<String> strings = new Array<String>("a", "b", "c");
// same as: Array<String> strings = array(new String[] { "a", "b", "c" });
// same as: Array<String> strings = new Array<String>(); strings.push("a", "b", "c");
assert strings.length == 3;
strings.push("d");
assert strings.length == 4;
assert strings.$get(3) == "d";
異步編程
在ES2015 + Promise API的幫助下,JSweet支持基本回調概念以外的高級異步編程。

承諾
經過聲明Promise返回類型來定義異步方法很是簡單 。當毫秒毫秒過去時,Promise將 知足如下方法。

Promise<Void> delay(int millis) {
return new Promise<Void>((Consumer<Void> resolve, Consumer<Object> reject) -> {

setTimeout(resolve, millis);

});
}
而後,您能夠在履行承諾後連接同步和異步操做。

delay(1000)
// chain with a synchronous action with "then". Here we just return a constant.
.then(() -> {

System.out.println("wait complete");
return 42;

})
// chain with an asynchronous action with "thenAsync". Here it is implied that anotherAsyncAction(String) returns a Promise<...>
.thenAsync((Integer result) -> {

System.out.println("previous task result: " + result); // will print "previous task result: 42"

return anotherAsyncAction("param");

})
// this chained action will be executed once anotherAsyncAction finishes its execution.
.then((String result) -> {

System.out.println("anotherAsyncAction returned " + result);

})
// catch errors during process using this method
.Catch(error -> {

System.out.println("error is " + error);

});
這容許徹底類型安全和流暢的異步編程模型。

異步/ AWAIT
Promises很是有趣,以免回調,但編寫它仍然須要大量的樣板代碼。它比純回調更好,但比線性編程更不易讀和直接。這就是async/await幫助的地方 。

使用await關鍵字,您能夠告訴運行時等待 Promise實現,而無需編寫then方法。await「是」 then部分以後的代碼。結果是您可使用線性編程編寫異步代碼。

import static jsweet.util.Lang.await;

// wait for the Promise returned by the delay method to be fulfilled
await(delay(1000));

System.out.println("wait complete");
錯誤處理也是如此。您可使用普通的 try / catch習語來處理異常。

import static jsweet.util.Lang.await;
import def.js.Error;

try {
Integer promiseResult = await(getANumber());
assert promiseResult == 42;
} catch(Error e) {
System.err.println("something unexpected happened: " + e);
}
你必須聲明爲async每一個異步方法/ lambda(即每一個等待某事的方法)。

import static jsweet.util.Lang.await;
import static jsweet.util.Lang.async;
import static jsweet.util.Lang.function;

import jsweet.lang.Async;
import def.js.Function;

@Async
Promise<Integer> findAnswer() {
await(delay(1000)); // won't compile if the enclosing method isn't @Async
return asyncReturn(42); // converts to Promise
}

@Async
void askAnswerThenVerifyAndPrintIt() {

try {

Integer answer = await(findAnswer());

// lambda expressions can be async
Function verifyAnswerAsync = async(function(() -> {
  return await(answerService.verifyAnswer(answer));
}))

Boolean verified = await(verifyAnswerAsync.$apply());

if (!verified) {
  throw new Error("cannot verify this answer");
}

console.log("answer found: " + answer);

} catch (Error e) {

console.error(e, "asynchronous process failed");

}
}
甜,不是嗎?;)

姓名衝突
與TypeScript / JavaScript相反,Java在方法,字段和包之間存在根本區別。Java還支持方法重載(具備相同名稱的不一樣簽名的方法)。在JavaScript中,對象變量和函數存儲在同一個對象映射中,這基本上意味着您不能爲多個對象成員使用相同的密鑰(這也解釋了Java中沒法實現Java語義中的方法重載)。所以,在TypeScript中生成時,某些Java代碼可能包含名稱衝突。JSweet將盡量自動避免名稱衝突,並在其餘狀況下報告聲音錯誤。

方法和字段名稱衝突
JSweet執行轉換以自動容許方法和私有字段具備相同的名稱。另外一方面,同一個類或具備子類連接的類中不容許使用相同名稱的方法和公共字段。

爲了不因爲這種JavaScript行爲致使編程錯誤,JSweet添加了一個語義檢查來檢測類中的重複名稱(這也考慮了在父類中定義的成員)。舉個例子:

public class NameClashes {

// error: field name clashes with existing method name
public String a;

// error: method name clashes with existing field name
public void a() {
    return a;
}

}
方法重載
與TypeScript和JavaScript相反(但與Java相似),JSweet中可能有多個具備相同名稱但具備不一樣參數的方法(所謂的重載)。咱們區分了簡單的重載和複雜的重載。簡單重載是使用方法重載來定義可選參數。JSweet容許這個習慣用語,它對應於如下模板:

String m(String s, double n) { return s + n; }
// valid overloading (JSweet transpiles to optional parameter)
String m(String s) { return m(s, 0); }
在這種狀況下,JSweet將生成JavaScript代碼,只有一個方法具備可選參數的默認值,所以生成的程序的行爲對應於原始程序。在這種狀況下:

function m(s, n = 0) { return s + n; }
若是程序員嘗試以不一樣方式使用重載,例如經過爲同一方法名定義兩個不一樣的實現,JSweet將回退複雜的重載,包括生成根實現(包含更多參數的方法)和一個輔助實現per overloading方法(用表示方法簽名的後綴命名)。根實現是通用的,並經過測試給定參數的值和類型調度到其餘實現。例如:

String m(String s, double n) { return s + n; }
String m(String s) { return s; }
生成如下(略微簡化的)JavaScript代碼:

function m(s, n) {

if(typeof s === 'string' && typeof n === 'number') {
    return s + n;
} else if(typeof s === 'string' && n === undefined) {
    return this.m$java_lang_String(s);
} else {
    throw new Error("invalid overload");
}

}

function m$java_lang_String(s) { return s; }
局部變量名稱
在TypeScript / JavaScript中,局部變量可能與使用全局方法衝突。例如,使用alertDOM(jsweet.dom.Globals.alert)中的全局方法要求沒有局部變量隱藏它:

import static jsweet.dom.Globals.alert;

[...]

public void m1(boolean alert) {

// JSweet compile error: name clash between parameter and method call
alert("test");

}

public void m2() {

// JSweet compile error: name clash between local variable and method call
String alert = "test";
alert(alert);

}
請注意,在調用全局方法時使用徹底限定名稱時也會發生此問題(這是由於限定條件在TypeScript / JavaScript中被刪除)。在任何狀況下,JSweet都會在發生此類問題時報告聲音錯誤,以便程序員能夠調整局部變量名稱以免與全局變量發生衝突。

測試對象的類型
要在運行時測試給定對象的類型,可使用instanceofJava運算符,也可使用 Object.getClass()函數。

instanceof
這instanceof是在運行時測試類型的建議和首選方法。JSweet將transpile到常規instanceof或一個 typeof取決於所測試的類型的操做(這將在回退 typeof對number,string和boolean核心類型)。

儘管不是必需的,但也可使用實用方法直接使用typeof JSweet中的運算符jsweet.util.Lang.typeof。如下是有效類型測試的一些示例:

import static jsweet.util.Lang.typeof;
import static jsweet.util.Lang.equalsStrict;
[...]
Number n1 = 2;
Object n2 = 2;
int n3 = 2;
Object s = "test";
MyClass c = new MyClass();

assert n1 instanceof Number; // transpiles to a typeof
assert n2 instanceof Number; // transpiles to a typeof
assert n2 instanceof Integer; // transpiles to a typeof
assert !(n2 instanceof String); // transpiles to a typeof
assert s instanceof String; // transpiles to a typeof
assert !(s instanceof Integer); // transpiles to a typeof
assert c instanceof MyClass;
assert typeof(n3) == "number";
從JSweet版本1.1.0開始,instanceof接口上也容許運算符,由於JSweet會跟蹤全部對象的全部實現接口。經過調用的對象中的附加隱藏屬性來確保此接口跟蹤,__interfaces而且包含對象實現的全部接口的名稱(直接或經過在編譯時肯定的類繼承樹)。所以,若是instanceof 運算符的類型參數是接口,JSweet只是檢查對象的 __interfaces字段是否存在幷包含給定的接口。例如,當Point接口是這個代碼在JSweet中徹底有效:

Point p1 = new Point() {{ x=1; y=1; }};
[...]
assert p1 instanceof Point
Object.getClass() 和 X.class
在JSweet中,可使用Object.getClass()on any實例。它實際上將返回類的構造函數。X.class若是X是類,using 也將返回構造函數。所以,如下斷言將在JSweet中保留:

String s = "abc";
assert String.class == s.getClass()
在課堂上,您能夠調用getSimpleName()或getName()函數。

String s = "abc";
assert "String" == s.getClass().getSimpleName()
assert String.class.getSimpleName() == s.getClass().getSimpleName()
請注意,getSimpleName()或者getName()函數也適用於接口。可是,您必須知道,X.class若是X是接口,將以字符串形式編碼(保存接口的名稱)。

限制和約束
因爲全部數字都映射到JavaScript數字,所以JSweet不區分整數和浮點數。所以, 不管實際類型是什麼n instanceof Integer,n instanceof Float都會給出相同的結果n。對於字符串和字符存在相同的限制,這些字符串和字符在運行時沒法區分,但也適用於具備相同參數數量的函數。例如,一個實例IntFunction<R>將沒法在運行時與a區分開Function<String,R>。

這些限制對函數重載有直接影響,由於重載使用instanceof運算符來決定調用哪一個重載。

就像在JavaScript中工做時同樣,序列化對象必須與其實際類正確「復活」,以便 instanceof操做員能夠再次工做。例如,經過建立的點對象Point p = (Point)JSON.parse("{x:1,y:1}")不會對instanceof運算符起做用。若是您遇到這樣的用例,您能夠聯繫咱們獲取一些有用的JSweet代碼以正確恢復對象類型。

lambda表達式中的變量做用域
已知JavaScript變量做用域給程序員帶來了一些問題,由於能夠從使用此變量的lambda外部更改對變量的引用。所以,JavaScript程序員不能依賴於在lambda範圍以外聲明的變量,由於當執行lambda時,該變量可能已在程序中的其餘位置被修改。例如,如下程序顯示了一個典型案例:

NodeList nodes = document.querySelectorAll(".control");
for (int i = 0; i < nodes.length; i++) {

HTMLElement element = (HTMLElement) nodes.$get(i); // final
element.addEventListener("keyup", (evt) -> {
    // this element variable will not change here
    element.classList.add("hit");
});

}
在JavaScript中(注意EcmaScript 6修復了這個問題),這樣的程序將沒法實現其目的,由於element事件監聽器中使用的變量被for循環修改而且不保持指望值。在JSweet中,這些問題與最終的Java變量相似。在咱們的示例中,element變量在lambda表達式中從新定義,以便封閉循環不會更改其值,所以程序的行爲與Java相似(正如大多數程序員所預期的那樣)。

這個範圍
與JavaScript相反,與Java相似,將方法用做lambda將防止丟失對引用的引用this。例如,在action如下程序的方法中this,即便在方法中action被稱爲lambda 時,也保持正確的值main。雖然這對Java程序員來講彷佛是合乎邏輯的,但JavaScript語義並不能確保這種行爲。

package example;
import static jsweet.dom.Globals.console;

public class Example {

private int i = 8;
public Runnable getAction() {
    return this::action;
}
public void action() {
    console.log(this.i); // this.i is 8
}
public static void main(String[] args) {
    Example instance = new Example();
    instance.getAction().run();
}

}
重要的是要強調this經過與ES5 bind功能相似的機制確保正確的值。結果是函數引用被包裝在函數中,這意味着函數指針(例如this::action)動態地建立包裝函數。它在操做函數指針時有反作用,這個問題在本期https://github.com/cincheo/js...

打包
打包是JavaScript的複雜點之一,尤爲是來自Java時。JavaScript包裝的複雜性歸結爲JavaScript自己沒有定義任何包裝這一事實。所以,多年來出現了許多事實上的解決方案和指南,使得對常規Java程序員的包裝理解不安。JSweet提供了有用的選項並生成代碼,以便經過使包裝問題更加透明和大多數狀況下的Java「簡單」來簡化Java程序員的生活。在本節中,咱們將描述和解釋典型的包裝方案。

使用您的文件,無需任何包裝
運行程序最多見和最簡單的狀況就是將每一個生成的文件包含在HTML頁面中。這不是任何包裝選項的默認模式。例如,當您的程序定義兩個類x.y.z.A並x.y.z.B在兩個單獨的文件中時,您能夠按以下方式使用它們:

<script type="text/javascript" src="target/js/x/y/z/A.js"></script>
<script type="text/javascript" src="target/js/x/y/z/B.js"></script>
[...]
<!-- access a method later in the file -->
<script type="text/javascript">x.y.z.B.myMethod()</script>
這樣作時,程序員須要很是謹慎,以免文件之間的正向靜態依賴關係。換句話說,A 類不能B在靜態字段,靜態初始化程序或靜態導入中使用任何內容,不然在嘗試加載頁面時會致使運行時錯誤。此外,A該類不能擴展B該類。這些約束來自JavaScript / TypeScript,與JSweet無關。

能夠想象,使用這種手動技術運行簡單的程序很好,可是對於開發複雜的應用程序會變得很是不舒服。複雜的應用程序大多數時候使用適當的工具捆綁和/或打包程序,以免必須手動處理JavaScript文件之間的依賴關係。

爲瀏覽器建立捆綁包
爲了不必須手動處理依賴項,程序員使用捆綁工具將其類捆綁到一個文件中。這樣的包使用如下內容包含在任何網頁中:

<script type="text/javascript" src="target/js/bundle.js"></script>
[...]
<!-- access a method later in the file -->
<script type="text/javascript">x.y.z.B.myMethod()</script>
JSweet帶有這樣的捆綁設施。要建立一個包文件,只需設定true的bundleJSweet的選項。請注意,您還能夠設置true的declaration,詢問JSweet生成打字稿定義文件(可選bundle.d.ts)。此文件容許您以類型合適的方式使用/編譯來自TypeScript的JSweet程序。

JSweet捆綁選項的「神奇之處」在於它分析源代碼中的依賴關係,並在構建捆綁時負責解決前向引用。特別是,JSweet爲靜態字段和初始化器實現了一個惰性初始化機制,以便分解跨類的靜態前向引用。程序員沒有具體的附加聲明使其工做(與TypeScript相反)。

請注意,它仍然存在一些小的限制(例如,在使用內部和匿名類時),但不多遇到這些限制,而且將在之後的版本中刪除。

另請注意,若是您隨module 選項一塊兒指定選項,JSweet將引起錯誤bundle。

包裝模塊
首先,讓咱們從解釋模塊開始,重點關注Java 包(或TypeScript 命名空間)和模塊之間的區別。若是您對差別感到滿意,請跳過此部分。

包和模塊是兩個類似的概念,但適用於不一樣的上下文。必須將Java包理解爲編譯時命名空間。它們容許經過名稱路徑對程序進行編譯時結構化,具備隱式或顯式可見性規則。軟件包一般對程序實際捆綁和部署的方式影響不大。

必須將模塊理解爲部署/運行時「捆綁」,這能夠required由其餘模塊實現。與Java世界中最接近模塊的概念多是OSGi包。模塊定義導入和導出的元素,以便它們建立強大的運行時結構,可用於獨立部署軟件組件,從而避免名稱衝突。例如,對於模塊,兩個不一樣的庫能夠定義一個util.List類,而且實際上在同一個VM上運行和使用,沒有命名問題(只要庫被捆綁在不一樣的模塊中)。

現在,許多庫都是經過模塊打包和訪問的。在瀏覽器中使用模塊的標準方法是AMD,但在Node.js中它是commonjs模塊系統。

JSweet中的模塊
JSweet支持用於打包的AMD,commonjs和UMD模塊系統。JSweet定義了一個module選項(值:amd,commonjs或umd)。指定此選項時,JSweet會根據簡單規則自動建立默認模塊組織:一個文件=一個模塊。

例如,當將module選項設置爲打包時commonjs,能夠編寫:

node target/js/x/y/z/MyMainClass.js
哪裏MyMainClass包含main方法。

模塊系統將自動處理參考,並在須要時須要其餘模塊。在引擎蓋下,JSweet分析了Java import語句並將它們轉換爲require指令。

注意:一旦使用該module選項編譯程序,就可使用適當的工具(如Browserify)將其打包爲捆綁包,這樣能夠提供與使用bundleJSweet選項相似的輸出。還要注意,同時指定時JSweet會引起錯誤module和bundle,這是排斥的選項。

外部模塊
使用module選項編譯JSweet程序時,必須將全部外部庫和組件做爲外部模塊。只需使用@Module(name) 註釋,JSweet就能夠自動須要模塊。在JSweet中,導入或使用帶有註釋的類或成員@Module(name)將在運行時自動須要相應的模塊。請注意,只有使用該module選項生成代碼時纔會出現這種狀況。若是該module選項處於禁用狀態,@Module 則會忽略註釋。

package def.jquery;
public final class Globals extends def.js.Object {

...
@jsweet.lang.Module("jquery")
native public static def.jquery.JQuery $(java.lang.String selector);
...

}
上面的代碼顯示了JSweet jQuery API的摘錄。咱們能夠注意到,該$函數帶有註釋@Module("jquery")。所以,對此函數的任何調用都將觸發jquery模塊的要求 。

注意:將來版本中可能會提供模塊的手動要求概念。可是,自動需求對於大多數程序員來講已經足夠,而且隱藏了必須明確要求模塊的複雜性。不管是否使用模塊,它還具備使用相同代碼的優勢。

故障排除:當糖果沒有正肯定義@Module 註釋時,能夠在一個名爲的特殊文件的註釋中強制聲明module_defs.java。例如,要強制將BABYLONBabylonjs candy 的 名稱空間導出爲 babylonjs模塊,能夠編寫如下文件:

package myprogram;
// declare module "babylonjs" {
// export = BABYLON;
// }
請注意,JSweet項目只能定義一個module_defs.java文件,該文件應包含註釋中的全部模塊聲明。另請注意,這是一個黑客攻擊,首選方法是爲糖果作出貢獻來解決問題。

根包
Root包是一種調整生成的代碼的方法,以便在生成的代碼中擦除JSweet包,從而在運行時刪除。要設置根包,只需定義一個package-info.java文件並使用@Root 包上的註釋,以下所示:

@Root
package a.b.c;
上述聲明意味着該c包是一個根包,即它將在生成的代碼及其全部父包中被刪除。所以,若是c包含一個包d和一個類C,它們將是運行時的頂級對象。換句話說,a.b.c.d成爲 d,a.b.c.C變成C。

請注意,因爲在封裝以前放置的@Root封裝被擦除,所以在封裝以前不能定義任何類型@Root。在前面的示例中,a和b包必須是空包。

不使用模塊時的行爲(默認)
默認狀況下,root包不會更改生成的文件的文件夾層次結構。例如,a.b.c.C該類仍將在<jsout>/a/b/c/C.js文件中生成(相對於<jsout> 輸出目錄)。可是,打開該noRootDirectories選項將刪除根目錄,以便爲該文件a.b.c.C生成類<jsout>/C.js。

不使用模塊時(默認),能夠有多個@Root 包(但@Root包不能包含另外一個@Root 包)。

使用模塊時的行爲
使用模塊時(請參閱模塊選項),只@Root容許一個@Root包,當有一個包時,其餘包或類型不能超出該@Root包的範圍。而後,生成的文件夾/文件層次結構從根包開始,以便實際擦除以前的全部文件夾。

包裝JSweet jar(糖果)
糖果是一種Maven工件,包含從JSweet客戶端程序輕鬆訪問JavaScript庫所需的全部內容。該庫能夠是外部JavaScript庫,TypeScript程序或其餘JSweet程序。

糖果的解剖學
與任何Maven工件同樣,糖果具備組ID,工件ID(名稱)和版本。此外,典型的糖果應包含如下元素:

編譯的Java文件(* .class),以便您使用candy的客戶端程序能夠編譯。

一個META-INF/candy-metadata.json包含transpiler的預期目標版本的文件(必須適應你的目標transpiler版)。

程序在d.ts文件中的聲明,放在src/typingsjar 的 目錄中。請注意,若是您打算使用JSweet生成TypeScript源代碼(tsOnly選項),則這些定義不是必需的。在這種狀況下,您能夠將JavaScript生成委派給外部tsc編譯器,並從另外一個源訪問TypeScript定義。

(可選)庫的JavaScript包,它能夠由JSweet客戶端程序自動提取和使用。JSweet但願JavaScript遵循Webjars約定打包:http://www.webjars.org/。以這種方式打包時,使用糖果的JSweet轉換器將自動在該candiesJsOut選項給出的目錄中提取捆綁的JavaScript (默認值:) js/candies。

如下是該META-INF/candy-metadata.json文件的示例:

{
"transpilerVersion": "2.0.0"
}
如何從JSweet程序建立糖果
使用JSweet構建應用程序時的典型用例是在多個其餘JSweet模塊/應用程序之間共享公共庫或模塊。請注意,因爲JSweet糖果是常規的Maven工件,只要它不使用任何JavaScript API,它也能夠由常規Java程序使用。

所以,項目中的典型示例是擁有包含DTO和公共實用程序函數的公共庫,這些庫能夠在用JSweet編寫的Web客戶端(例如使用angular或knockout庫)和在JSweet中編寫的移動客戶端之間共享。 (例如使用離子庫)。好消息是這個公地 庫也能夠由Java服務器(JEE,Spring,...)使用,由於DTO不使用任何JavaScript,而且包裝在糖果中的已編譯Java代碼能夠在Java VM上運行。這很是有用,由於這意味着當您在本身喜歡的IDE中開發此項目時,您將可以重構某些DTO和通用API,它將直接影響您的Java服務器代碼,Web客戶端代碼和移動客戶端碼!

咱們提供了一個快速入門項目來幫助您從這樣的用例開始:https://github.com/cincheo/jsweet-candy-quickstart

如何爲現有的JavaScript或TypeScript庫建立糖果
咱們提供了一個快速入門項目來幫助您從這樣的用例開始:https://github.com/cincheo/jsweet-candy-js-quickstart

擴輾轉換器
JSweet是一個從Java到TypeScript的Open Transpiler。這意味着它爲程序員提供了調整/擴展JSweet如何生成中間TypeScript代碼的方法。調整轉換器是一種避免重複性任務並使其自動化的解決方案。

例如,假設您有一個遺留Java代碼,它使用Java API來序列化對象(writeObject/ readObject)。使用JSweet,您能夠輕鬆地從程序中刪除這些方法,以便生成的JavaScript代碼不受任何特定於Java的序列化習慣用法的影響。

做爲另外一個例子,假設您有一個使用Java API的Java遺留代碼庫,它接近(但不徹底)您但願在最終JavaScript代碼中使用的JavaScript API。使用JSweet,您能夠編寫一個適配器,它將自動將全部Java調用映射到相應的JavaScript調用。

最後但並不是最不重要的是,您能夠根據上下文調整JSweet以利用某些特定的API。例如,若是您知道目標瀏覽器支持ES6映射,則可使用ES6映射,或者在其餘狀況下僅使用仿真或更簡單的實現。您能夠調整代碼以免在知道給定移動瀏覽器不能很好地支持時使用某些畫布或WebGL基元。依此類推......使用像JSweet這樣的Open Transpiler有許多實際的應用程序,您可能須要或沒必要使用它們,但不管如何最好知道什麼是可能的。

可使用註釋以聲明方式(而不是以編程方式)完成調整。註釋能夠添加到Java程序(硬編碼),也能夠集中在一個惟一的配置文件中,這樣它們甚至不會出如今Java代碼中(咱們稱之爲軟註釋)。使用註釋很是簡單直觀。可是,當須要對轉換器進行復雜的定製時,極可能註釋再也不足夠。在這種狀況下,程序員應該使用JSweet擴展API,這須要全部能夠經過註釋完成的調優等等。擴展API容許在所謂的打印機適配器的上下文中訪問Java AST(抽象語法樹) 。打印機適配器遵循裝飾器模式,以便它們能夠連接以擴展和/或覆蓋JSweet打印出中間TypeScript代碼的方式。

核心註釋
該包jsweet.lang定義了各類註釋,可用於調整JSweet生成中間TypeScript代碼的方式。在這裏,咱們解釋這些註釋,並舉例說明如何使用它們。

@Erased:此註釋類型用於應在生成時擦除的元素。它能夠應用於任何程序元素。若是應用於類型,則會自動刪除強制轉換和構造函數調用,從而可能致使程序不一致。若是應用於方法,則將刪除調用,可能致使程序不一致,尤爲是在表達式中使用調用的結果時。因爲潛在的不一致性,程序員應仔細使用此註釋,並應用於未使用的元素(也使用元素擦除)。

@Root:此包註釋用於爲已轉換的TypeScript / JavaScript指定根包,這意味着此包和子包中的全部已轉換引用將與此根包相關。做爲示例,給定 org.mycompany.mylibrary根包(帶註釋@Root),該類org.mycompany.mylibrary.MyClass實際上將對應 MyClass於JavaScript運行時。一樣, org.mycompany.mylibrary.mypackage.MyClass將會轉變爲 mypackage.MyClass。

@Name(String value):此批註容許定義將用於最終生成的代碼(而不是Java名稱)的名稱。當元素的名稱不是有效的Java標識符時,可使用它。按照慣例,JSweet實現了一個內置的約定,以節省使用@Name註解:Keyword在Java中transpiles到keyword,當keyword是一個Java的關鍵字(如 catch,finally,int,long,等等)。

@Replace(String value):此註釋容許程序員經過TypeScript實現替換方法體實現。註釋的值包含由JSweet轉換器生成的TypeScript。代碼將由TypeScript轉換器檢查。替換代碼能夠包含使用相似鬍鬚的約定({{variableName}} 替換的變量。如下是支持的變量列表:

{{className}}:當前的課程。

{{methodName}}:當前方法名稱。

{{body}}:當前方法的主體。此變量的典型用法是將原始行爲包裝在lambda中。例如: / before code / let _result = () => { {{body}} }(); / after code / return _result;。

{{baseIndent}}:替換方法的縮進。可用於生成格式良好的代碼。

{{indent}}:用縮進代替。可用於生成格式良好的代碼。


如下示例說明了@Erased和 @Replace註釋的使用。這裏,@Erased註釋用於readObject從生成的代碼中刪除方法,由於它在JavaScript中沒有意義(它是一種特定於Java序列化的方法)。該@Replace註釋容許定義直接打字稿/ JavaScript實現的searchAddress方法。

class Person {

List<String> addresses = new ArrayList<String>();

@Erased
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {

[...]

}

@Replace("return this.addresses.filter(address => address.match(regex))[0]")
public String searchAddress(String regex) {

Optional<String> match = addresses.stream().filter(address -> address.matches(regex)).findFirst();
      return match.isPresent()?match.get():null;

}
}
使用JSweet註釋能夠靈活地在Java和JavaScript之間共享類。JavaScript中的無用方法被擦除,而且一些方法能夠具備針對Java和JavaScript的不一樣實現。

集中註釋 jsweetconfig.json
JSweet支持在惟一配置文件(jsweetconfig.json)中定義註釋。程序員想要在該文件中定義註釋而不是在Java源代碼中定義註釋的緣由有不少。

註釋或註釋內容可能因上下文而異。根據上下文,具備不一樣的配置文件多是方便的。使用其餘配置文件切換配置文件比更改程序中的全部註釋更容易。

向Java程序添加註釋能夠方便地在本地調整程序(在給定元素上)。可是,在某些狀況下,相似的註釋應該適用於一組程序元素,以便自動化程序的全局調整。在這種狀況下,經過使用表達式來安裝註釋會更方便,該表達式將當即匹配一組程序元素。這種機制相似於面向方面的軟件設計中能夠找到的切入點機制。它容許以聲明方式捕獲全局修改。

在Java源代碼中使用註釋須要引用JSweet API(jsweet.lang包),對於但願Java代碼儘量保持「純」的程序員來講,這可能被視爲沒必要要的依賴。

JSweet配置文件(jsweetconf.json)是一個包含配置條目列表的JSON文件。在配置條目中,可使用如下結構定義所謂的全局過濾器:

<annotation>: {

"include": <match_expressions>,
  "exclude": <match_expressions>

}
<annotation>要添加的註釋在哪裏,具備潛在參數,include以及exclude是匹配表達式的列表。若是程序中的元素的簽名與include列表中的任何表達式匹配,而且與列表中的任何表達式都不匹配,則程序中的元素將使用批註進行批註exclude。

匹配表達式是一種簡化的正則表達式,支持如下通配符:

*匹配在程序元素的簽名任何令牌或令牌的子部分(令牌是簽名的識別符的一部分,例如A.m(java.lang.String)包含標記A,m和 java.lang.String)。

** 匹配程序元素簽名中的任何令牌列表。

..匹配程序元素簽名中的任何令牌列表。(同**)

! 否認表達式(僅限第一個字符)。

例如:

// all the elements and subelements (fields, methods, ...) in the x.y.z package
x.y.z.**

// all the methods in the x.y.z.A class
x.y.z.A.*(..)

// all the methods taking 2 arguments in the texttt{x.y.z.A} class
x.y.z.A.(,*)

// all fields called aField in all the classes of the program
**.aField
這是一個包含完整jsweetconfig.json 配置文件的更完整示例。

{
// all classes and packages in x.y.z will become top level
"@Root": {

"include": [ "x.y.z" ]

},
// do not generate any TypeScript code for Java-specific methods
"@Erased": {

"include": [ "**.writeObject(..)", "**.readObject(..)", "**.hashCode(..)" ]

},
// inject logging in all setters and getters of the x.y.z.A class
"@Replace('console.info('entering {{methodName}}'); let _result = () => { {{body}} }(); console.info('returning '+_result); return _result;')": {

"include": [ "x.y.z.A.set*(*)", "x.y.z.A.get*()", "x.y.z.A.is*()" ]

}
}
請注意,註釋僅使用簡單名稱定義。那是由於它們是核心JSweet註釋(定義於jsweet.lang)。非核心註釋能夠以相同的方式添加,但程序員必須使用徹底限定的名稱。

使用適配器進行編程調整
在爲特定目的調整生成時(一般在支持其餘Java庫時),經過註釋進行聲明性調整會快速達到限制。所以,JSweet提供了一個API,以便程序員能夠擴展JSweet生成中間TypeScript代碼的方式。編寫這樣的適應程序相似於編寫常規Java程序,除了它將應用於您的程序來轉換它們。所以,它屬於所謂的元程序類別(即程序使用其餘程序做爲數據)。因爲程序員可能會編寫致使無效代碼的擴展,所以擁有中間編譯層變得很是方便。若是生成的代碼無效,則TypeScript到JavaScript編譯將引起錯誤,從而容許程序員修復擴展代碼。

介紹擴展API
org.jsweet.transpiler.extension 包中提供了擴展API 。它基於工廠模式(org.jsweet.transpiler.JSweetFactory),容許程序員經過子類化來調整轉換器的全部主要組件。實際上,大多數調整均可以經過建立新的打印機適配器來完成,做爲子類org.jsweet.transpiler.extension.PrinterAdapter。適配器是核心擴展機制,由於它們是可連接的而且能夠組合(它是一種裝飾模式)。JSweet在默認適配鏈中使用默認適配器,而後調整JSweet將包括向鏈添加新適配器。

適配器一般會執行三種操做來調整生成的代碼:

將Java類型映射到TypeScript類型。

以聲明方式(使用全局過濾器)或以編程方式(使用註釋管理器)向程序添加註釋。

覆蓋定義的打印方法,PrinterAdapter以覆蓋默認生成的TypeScript核心。打印方法採用基於標準javax.lang.model.elementAPI的程序元素 。它爲表達式和語句(org.jsweet.transpiler.extension.model)的程序元素提供了該API的擴展。

如下模板顯示了編程適配器時的典型部分。首先,適配器必須擴展PrinterAdapter或任何其餘適配器。它必須定義一個構造函數來獲取父適配器,當在鏈中插入適配器時,它將由JSweet設置。

public class MyAdapter extends PrinterAdapter {

public MyAdapter(PrinterAdapter parent) {
    super(parent);
    ...

在構造函數中,適配器一般將Java類型映射到TypeScript類型。

// will change the type in variable/parameters declarations
    addTypeMapping("AJavaType", "ATypeScriptType");
    // you may want to erase type checking by mapping to 'any'
    addTypeMapping("AJavaType2", "any");
    [...]

在構造函數中,適配器還能夠比使用jsweetconfig.json語法時更靈活的方式添加註釋。

// add annotations dynamically to the AST, with global filters
    addAnnotation("jsweet.lang.Erased", //
            "**.readObject(..)", //
            "**.writeObject(..)", //
            "**.hashCode(..)");
    // or with annotation managers (see the Javadoc and the example below)
    addAnnotationManager(new AnnotationManager() { ... });
}

最重要的是,適配器能夠覆蓋最重要的AST元素的替換方法。經過重寫這些方法,適配器將改變JSweet生成中間TypeScript代碼的方式。要打印代碼,可使用print在根PrinterAdapter類中定義的方法。例如,下面的代碼將取代全部new AJavaType(...)帶new ATypeScriptType(...)。

@Override
public boolean substituteNewClass(NewClassElement newClass) {
    // check if the 'new' applies to the right class
    if ("AJavaType".equals(newClass.getTypeAsElement().toString())) {
        // the 'print' method will generate intermediate TypeScript code
        print("new ATypeScriptType(")
                .printArgList(newClass.getArguments()).print(")");
        // once some code has been printed, you should return true to break
        // the adapter chain, so your code will replace the default one
        return true;
    }
    // if not substituted, delegate to the adapter chain
    return super.substituteNewClass(newClass);
}

最有用的替換方法仍然是調用替換,它一般用於將Java API映射到相似的JavaScript API。

@Override
public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
    // substitute potential method invocation here
    [...]
    // delegate to the adapter chain
    return super.substituteMethodInvocation(invocation);
}

}
還要注意在打印Java類型後插入代碼的特殊方法:

@Override
public void afterType(TypeElement type) {
    super.afterType(type);
    // insert whatever TypeScript you need here
    [...]
}

適配器有許多應用(參見下面的示例)。除了在編譯時調整代碼生成和支持Java API以外,根據目標上下文,當編譯的代碼不符合預期標準時,適配器也可用於引起錯誤。另外一個很是有用的用例,它容許生成代理。例如,能夠編寫一個適配器來生成JavaScript存根,以調用使用JAX-RS部署的Java服務。

安裝和激活適配器
編寫適配器後,須要編譯它並將其添加到適配器鏈中。使用JSweet執行此操做的最簡單方法是將其放在jsweet_extension須要在項目JSweet的根目錄中建立的目錄中。在該目錄中,您能夠直接爲適配器添加Java源文件,這些文件將由JSweet動態編譯。例如,您能夠添加兩個自定義的適配器CustomAdapter1.java和 CustomAdapter2.java在jsweet_extension/com/mycompany/。

而後,爲了激活該適配器,您只須要jsweetconfig.json在項目的根目錄中添加該 文件並定義 adapters配置選項,以下所示:

{
// JSweet will add the declared adapters at the beginning of the default
// chain... you can add as many adapters as you need
adapters: [ "com.mycompany.CustomAdapter1", "com.mycompany.CustomAdapter2" ]
}
Hello世界適配器
在這裏,咱們將逐步介紹如何java.util.Date在Java程序中查找類型時調整JSweet生成以生成字符串來代替日期。

首先,HelloWorldAdapter.java在jsweet_extension項目根目錄的目錄中建立文件 。將如下代碼複製並粘貼到該文件中:

import org.jsweet.transpiler.extension.PrinterAdapter;
public class HelloWorldAdapter extends PrinterAdapter {

public HelloWorldAdapter(PrinterAdapter parent) {
    super(parent);
    addTypeMapping(java.util.Date.class.getName(), "string");
}

}
其次,在項目的根目錄中,jsweetconfig.json 使用如下配置建立文件:

{
adapters: [ "HelloWorldAdapter" ]
}
完成。如今,您能夠在如下簡單的Java DTO上嘗試此擴展:

package source.extension;
import java.util.Date;
/**

  • A Hello World DTO.

*

  • @author Renaud Pawlak

*/
public class HelloWorldDto {

private Date date;
/**
 * Gets the date.
 */
public Date getDate() {
    return date;
}
/**
 * Sets the date.
 */
public void setDate(Date date) {
    this.date = date;
}

}
生成的代碼應以下所示:

/ Generated from Java with JSweet 2.XXX - http://www.jsweet.org /
namespace source.extension {

/**
 * A Hello World DTO.
 *
 * @author Renaud Pawlak
 * @class
 */
export class HelloWorldDto {
    /*private*/ date : string;
    public constructor() {
        this.date = null;
    }
    /**
     * Gets the date.
     * @return {string}
     */
    public getDate() : string {
        return this.date;
    }
    /**
     * Sets the date.
     * @param {string} date
     */
    public setDate(date : string) {
        this.date = date;
    }
}
HelloWorldDto["__class"] = "source.extension.HelloWorldDto";

}
請注意,全部日期類型都已按預期轉換爲字符串。順便說一下,還要注意JSDoc支持,這使得JSweet成爲一個強大的工具,能夠從Java建立記錄良好的JavaScript API(文檔註釋也能夠在適配器中調整!)。

擴展現例
如下部分說明了使用JSweet適配器和5個實際示例。大多數這些適配器都內置了JSweet(在org.jsweet.transpiler.extension包中),能夠經過將它們添加到適配器鏈來激活,如上所述。若是要修改適配器,只需將代碼複製粘貼到jsweet_extension 目錄中並更更名稱便可。

示例1:用於重命名私有字段的適配器
這個簡單的適配器經過添加兩個下劃線做爲前綴來重命名非公共成員。請注意,若是但願從其餘JSweet項目中聲明的子類訪問受保護的字段,則這多是危險的。所以,您可能須要謹慎使用或根據本身的須要修改代碼。

此適配器是演示如何使用註釋管理器的一個很好的示例。註釋管理器用於將(軟)註釋添加到由某些Java代碼(以編程方式)驅動的程序元素。註釋管理器將添加到上下文中,並將連接到其餘現有註釋管理器(可能由其餘適配器添加)。註釋管理器必須實現該manageAnnotation方法,該方法將告知是否應在給定元素上添加,移除或保持給定註釋不變。若是註釋具備參數,則註釋管理器應實現該註釋getAnnotationValue以指定值。

在此示例中,註釋管理器將註釋添加@jsweet.lang.Name 到全部非公共元素,以便重命名它們並將下劃線添加到初始名稱。

package org.jsweet.transpiler.extension;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import org.jsweet.transpiler.util.Util;

public class AddPrefixToNonPublicMembersAdapter extends PrinterAdapter {

public AddPrefixToNonPublicMembersAdapter(PrinterAdapter parentAdapter) {
    super(parentAdapter);
    // add a custom annotation manager to the chain
    addAnnotationManager(new AnnotationManager() {

        @Override
        public Action manageAnnotation(Element element, String annotationType) {
            // add the @Name annotation to non-public elements
            return "jsweet.lang.Name".equals(annotationType)
                    && isNonPublicMember(element) ? Action.ADD : Action.VOID;
        }

        @Override
        public <T> T getAnnotationValue(Element element,
                String annotationType, String propertyName,
                Class<T> propertyClass, T defaultValue) {
            // set the name of the added @Name annotation (value)
            if ("jsweet.lang.Name".equals(annotationType) && isNonPublicMember(element)) {
                return propertyClass.cast("__" + element.getSimpleName());
            } else {
                return null;
            }
        }

        private boolean isNonPublicMember(Element element) {
            return (element instanceof VariableElement || element instanceof ExecutableElement)
                    && element.getEnclosingElement() instanceof TypeElement
                    && !element.getModifiers().contains(Modifier.PUBLIC)
                    && Util.isSourceElement(element);
        }
    });
}

}
示例2:使用ES6 Maps的適配器
JSweet映射的默認實現以下:

若是鍵類型是字符串,則映射將轉換爲常規JavaScript對象,其中屬性名稱將是鍵。

若是鍵類型是對象(除字符串之外的任何對象),則映射將轉換爲條目列表。實現效率很是低,由於查找密鑰須要遍歷條目以找到正確的條目密鑰。

在某些狀況下,您可能但願得到更有效的地圖實現。若是你瞄準現代瀏覽器(或指望有適當的polyfill),你能夠簡單地使用Map經過ES6標準化的對象。這樣作須要適配器執行如下操做:

擦除Java Map類型並將其替換爲JavaScript Map 類型或實際any類型,由於您可能但願Object在鍵是字符串時保留 實現。

用相應的JavaScript構造替換地圖的構造。

用相應的JavaScript調用替換Java映射上的調用。

請注意,如下適配器是部分實現,應擴展爲支持更多案例並根據您本身的要求進行調整。此外,此實現生成非類型化JavaScript,以免在編譯路徑中使用ES6 API。

package org.jsweet.transpiler.extension;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.TreeMap;
import javax.lang.model.element.Element;
import org.jsweet.transpiler.model.MethodInvocationElement;
import org.jsweet.transpiler.model.NewClassElement;

public class MapAdapter extends PrinterAdapter {

// all the Java types that will be translated to ES6 maps
static String[] mapTypes = {
    Map.class.getName(), HashMap.class.getName(),
    TreeMap.class.getName(), Hashtable.class.getName() };

public MapAdapter(PrinterAdapter parent) {
    super(parent);
    // rewrite all Java map and compatible map implementations types
    // note that we rewrite to 'any' because we don't want to require the
    // ES6 API to compile (all subsequent accesses will be untyped)
    for (String mapType : mapTypes) {
        addTypeMapping(mapType, "any");
    }
}

@Override
public boolean substituteNewClass(NewClassElement newClass) {
    String className = newClass.getTypeAsElement().toString();
    // map the map constructor to the global 'Map' variable (untyped access)
    if (Arrays.binarySearch(mapTypes, className) >= 0) {
        // this access is browser/node-compatible
        print("new (typeof window == 'undefined'?global:window)['Map'](")
                .printArgList(newClass.getArguments()).print(")");
        return true;
    }
    // delegate to the adapter chain
    return super.substituteNewClass(newClass);
}

@Override
public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
    if (invocation.getTargetExpression() != null) {
        Element targetType = invocation.getTargetExpression().getTypeAsElement();
        if (Arrays.binarySearch(mapTypes, targetType.toString()) >= 0) {
            // Java Map methods are mapped to their JavaScript equivalent
            switch (invocation.getMethodName()) {
            case "put":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression()).print(".set(")
                        .printArgList(invocation.getArguments())
                        .print(")");
                return true;
            // although 'get' has the same name, we still rewrite it in case
            // another extension would provide it's own implementation
            case "get":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression()).print(".get(")
                        .printArgList(invocation.getArguments())
                        .print(")");
                return true;
            case "containsKey":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression()).print(".has(")
                        .printArgList(invocation.getArguments())
                        .print(")");
                return true;
            // we use the ES6 'Array.from' method in an untyped way to
            // transform the iterator in an array
            case "keySet":
                printMacroName(invocation.getMethodName());
                print("(<any>Array).from(")
                        .print(invocation.getTargetExpression()).print(".keys())");
                return true;
            case "values":
                printMacroName(invocation.getMethodName());
                print("(<any>Array).from(")
                        .print(invocation.getTargetExpression()).print(".values())");
                return true;
            // in ES6 maps, 'size' is a property, not a method
            case "size":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression()).print(".size");
                return true;
            }
        }

    }
    // delegate to the adapter chain
    return super.substituteMethodInvocation(invocation);
}

}
示例3:支持Java BigDecimal的適配器
Java的BigDecimal API是一個很是好的API,能夠避免典型的浮點精度問題,尤爲是在處理貨幣時。默認狀況下,此API在JavaScript中不可用,而且很難模擬。GWT提供了使用Java實現的BigDecimal API的仿真,但JSweet提出了另外一種方法,包括將BigDecimal API映射到名爲Big.js的現有JavaScript API。與模擬API相比,映射到現有JS庫有幾個優勢:

該實現已經在JavaScript中提供,所以模擬Java庫的工做量較少。

該實現是純JavaScript,專爲JavaScript而設計。所以咱們能夠假設仿真效率更高,甚至更便攜。

生成的代碼不受任何Java API的影響,這使得JavaScript更加友好,而且能夠與現有的JavaScript程序更加互操做(遺留的JavaScript顯然使用Big.js對象,若是沒有,咱們能夠決定調整適配器)。

如下代碼顯示了調整JavaScript生成以將Java的BigDecimal API映射到Big JavaScript庫的適配器。此擴展須要在JSweet類路徑中提供big.js糖果:https://github.com/jsweet-candies/candy-bigjs。

package org.jsweet.transpiler.extension;

import java.math.BigDecimal;
import javax.lang.model.element.Element;
import org.jsweet.transpiler.extension.PrinterAdapter;
import org.jsweet.transpiler.model.MethodInvocationElement;
import org.jsweet.transpiler.model.NewClassElement;

public class BigDecimalAdapter extends PrinterAdapter {

public BigDecimalAdapter(PrinterAdapter parent) {
    super(parent);
    // all BigDecimal types are mapped to Big
    addTypeMapping(BigDecimal.class.getName(), "Big");
}

@Override
public boolean substituteNewClass(NewClassElement newClass) {
    String className = newClass.getTypeAsElement().toString();
    // map the BigDecimal constructors
    if (BigDecimal.class.getName().equals(className)) {
        print("new Big(").printArgList(newClass.getArguments()).print(")");
        return true;
    }
    // delegate to the adapter chain
    return super.substituteNewClass(newClass);
}

@Override
public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
    if (invocation.getTargetExpression() != null) {
        Element targetType = invocation.getTargetExpression().getTypeAsElement();
        if (BigDecimal.class.getName().equals(targetType.toString())) {
            // BigDecimal methods are mapped to their Big.js equivalent
            switch (invocation.getMethodName()) {
            case "multiply":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression())
                        .print(".times(").printArgList(invocation.getArguments())
                        .print(")");
                return true;
            case "add":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression())
                        .print(".plus(").printArgList(invocation.getArguments())
                        .print(")");
                return true;
            case "scale":
                printMacroName(invocation.getMethodName());
                // we assume that we always have a scale of 2, which is a
                // good default if we deal with currencies...
                // to be changed/implemented further
                print("2");
                return true;
            case "setScale":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression())
                        .print(".round(").print(invocation.getArguments().get(0))
                        .print(")");
                return true;
            case "compareTo":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression()).print(".cmp(")
                        .print(invocation.getArguments().get(0))
                        .print(")");
                return true;
            case "equals":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression()).print(".eq(")
                        .print(invocation.getArguments().get(0))
                        .print(")");
                return true;
            }
        }

    }
    // delegate to the adapter chain
    return super.substituteMethodInvocation(invocation);
}

}
示例4:將枚舉映射到字符串的適配器
此示例調整JavaScript生成以刪除枚舉並將其替換爲字符串。它僅適用於使用@註釋的枚舉jsweet.lang.StringType。

例如:@StringType enum MyEnum { A, B, C }將被擦除,而且對枚舉常量的全部後續訪問將映射到簡單的字符串(MyEnum.A => "A", MyEnum.B => "B", MyEnum.C => "C")。一般,方法聲明如void m(MyEnum e) {...}將打印爲void m(e : string) {...}。固然,調用 xxx.m(MyEnum.A)將打印爲xxx.m("A")。

package org.jsweet.transpiler.extension;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import org.jsweet.JSweetConfig;
import org.jsweet.transpiler.model.CaseElement;
import org.jsweet.transpiler.model.ExtendedElement;
import org.jsweet.transpiler.model.MethodInvocationElement;
import org.jsweet.transpiler.model.VariableAccessElement;

public class StringEnumAdapter extends PrinterAdapter {

private boolean isStringEnum(Element element) {
    // note: this function could be improved to exclude enums that have
    // fields or methods other than the enum constants
    return element.getKind() == ElementKind.ENUM
            && hasAnnotationType(element, JSweetConfig.ANNOTATION_STRING_TYPE);
}

public StringEnumAdapter(PrinterAdapter parent) {
    super(parent);
    // eligible enums will be translated to string in JS
    addTypeMapping((typeTree, name) ->
            isStringEnum(typeTree.getTypeAsElement()) ? "string" : null);

    // ignore enum declarations with a programmatic annotation manager
    addAnnotationManager(new AnnotationManager() {
        @Override
        public Action manageAnnotation(Element element, String annotationType) {
            // add the @Erased annotation to string enums
            return JSweetConfig.ANNOTATION_ERASED.equals(annotationType)
                    && isStringEnum(element) ? Action.ADD : Action.VOID;
        }
    });

}

@Override
public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
    if (invocation.getTargetExpression() != null) {
        Element targetType = invocation.getTargetExpression().getTypeAsElement();
        // enum API must be erased and use plain strings instead
        if (isStringEnum(targetType)) {
            switch (invocation.getMethodName()) {
            case "name":
                printMacroName(invocation.getMethodName());
                print(invocation.getTargetExpression());
                return true;
            case "valueOf":
                printMacroName(invocation.getMethodName());
                print(invocation.getArgument(0));
                return true;
            case "equals":
                printMacroName(invocation.getMethodName());
                print("(").print(invocation.getTargetExpression()).print(" == ")
                        .print(invocation.getArguments().get(0)).print(")");
                return true;
            }
        }
    }
    return super.substituteMethodInvocation(invocation);
}

@Override
public boolean substituteVariableAccess(VariableAccessElement variableAccess) {
    // accessing an enum field is replaced by a simple string value
    // (MyEnum.A => "A")
    if (isStringEnum(variableAccess.getTargetElement())) {
        print("\"" + variableAccess.getVariableName() + "\"");
        return true;
    }
    return super.substituteVariableAccess(variableAccess);
}

@Override
public boolean substituteCaseStatementPattern(CaseElement caseStatement,
        ExtendedElement pattern) {
    // map enums to strings in case statements
    if (isStringEnum(pattern.getTypeAsElement())) {
        print("\"" + pattern + "\"");
        return true;
    }
    return super.substituteCaseStatementPattern(caseStatement, pattern);
}

}
示例5:用於生成JavaScript JAX-RS代理/存根的適配器
在服務器上使用Java和在客戶端上使用JavaScript實現WEB或移動應用程序是一種常見的用例。一般,JEE / Jackson服務器將經過JAX-RS規範公開REST API,HTML5客戶端必須使用XMLHttpRequest或更高級別的庫(如jQuery)調用此API 。可是,手動編寫HTTP調用編碼有許多缺點:

它須要使用特定的API(XHR,jQuery),這對全部程序員來講都不容易,而且可能意味着不一樣的編程風格會使代碼更難以閱讀和維護。

它要求程序員手動處理序列化/反序列化,同時能夠經過使用註釋驅動的生成編程自動完成。

它致使未經檢查的調用,這意味着程序員很容易在服務/路徑/參數的名稱和預期的DTO中產生錯誤。沒有重構和內容輔助。

使用JSweet適配器,使用 afterType方法能夠輕鬆自動生成類型良好的TypeScript存根,並經過使用服務API和JAX-RS註釋執行調用REST服務所需的操做。這種類型的工具屬於所謂的生成編程。

如下代碼僅是適配器的部分實現,它將內省程序的模型並在TypeScript中生成相應的存根。它並不意味着可操做,所以您須要修改以適合您本身的用例。

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;

class JaxRSStubAdapter extends PrinterAdapter {

public JaxRSStubAdapter(PrinterAdapter parent) {
    super(parent);
    // erase service classes (server-side only)
    addAnnotationManager(new AnnotationManager() {
        @Override
        public Action manageAnnotation(Element element, String annotationType) {
            return JSweetConfig.ANNOTATION_ERASED.equals(annotationType)
                    && hasAnnotationType(element, Path.class.getName()) ?
                    Action.ADD : Action.VOID;
        }
    });
}

@Override
public void afterType(TypeElement type) {
    super.afterType(type);
    if (hasAnnotationType(type, Path.class.getName())) {
        // actually generates the JAX-RS stub
        println().printIndent();
        print("class ").print(type.getSimpleName()).print(" {");
        startIndent();
        String typePathAnnotationValue = getAnnotationValue(type,
                Path.class.getName(), String.class, null);
        String typePath = typePathAnnotationValue != null ? typePathAnnotationValue : "";
        for (Element e : type.getEnclosedElements()) {
            if (e instanceof ExecutableElement
                    && hasAnnotationType(e, GET.class.getName(),
                            PUT.class.getName(), Path.class.getName())) {
                ExecutableElement method = (ExecutableElement) e;
                println().printIndent().print(method.getSimpleName().toString())
                        .print("(");
                for (VariableElement parameter : method.getParameters()) {
                    print(parameter.getSimpleName())
                            .print(" : ").print(getMappedType(parameter.asType()))
                            .print(", ");
                }
                print("successHandler : (");
                if (method.getReturnType().getKind() != TypeKind.VOID) {
                    print("result : ").print(getMappedType(method.getReturnType()));
                }
                print(") => void, errorHandler?: () => void").print(") : void");
                print(" {").println().startIndent().printIndent();
                String pathAnnotationValue = getAnnotationValue(e, Path.class.getName(),
                        String.class, null);
                String path = pathAnnotationValue != null ? pathAnnotationValue : "";
                String httpMethod = "POST";
                if(hasAnnotationType(e, GET.class.getName())) {
                    httpMethod = "GET";
                }
                if(hasAnnotationType(e, POST.class.getName())) {
                    httpMethod = "POST";
                }
                String[] consumes = getAnnotationValue(e, "javax.ws.rs.Consumes",
                        String[].class, null);
                if (consumes == null) {
                    consumes = new String[] { "application/json" };
                }
                // actual code to be done
                print("// modify JaxRSStubAdapter to generate an HTTP invocation here")
                        .println().printIndent();
                print("//   - httpMethod: " + httpMethod).println().printIndent();
                print("//   - path: " + typePath + path).println().printIndent();
                print("//   - consumes: " + consumes[0]);
                println().endIndent().printIndent().print("}");
            }
        }
        println().endIndent().printIndent().print("}");
    }
}

}
注意:對於編譯,您須要在類路徑中使用JAX-RS API。

<dependency>

<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1-m07</version>

</dependency>
做爲示例,讓咱們考慮如下JAX-RS服務。

@Path("/hello")
public class HelloWorldService {

@GET
@Path("/{param}")
@Produces(MediaType.APPLICATION_JSON)
public HelloWorldDto getMsg(@PathParam("param") String msg) {
    String output = "service says : " + msg;
    return new HelloWorldDto(output);
}

}
使用如下DTO:

public class HelloWorldDto {

private String msg;
public HelloWorldDto(String msg) {
    super();
    this.msg = msg;
}
public String getMsg() {
    return msg;
}
public void setMsg(String msg) {
    this.msg = msg;
}

}
若是您應用JSweet加強版JaxRSStubAdapter,您將得到如下TypeScript代碼(和相應的JavaScript):

export class HelloWorldDto {

/*private*/ msg : string;
public constructor(msg : string) {
    this.msg = msg;
}
public getMsg() : string {
    return this.msg;
}
public setMsg(msg : string) {
    this.msg = msg;
}

}
HelloWorldDto["__class"] = "HelloWorldDto";

class HelloWorldService {

getMsg(msg : string,
        successHandler : (result : HelloWorldDto) => void,
        errorHandler?: () => void) : void {
    // modify JaxRSStubAdapter to generate an HTTP invocation here
    //   - httpMethod: GET
    //   - path: /hello/{param}
    //   - consumes: application/json
}

}
所以,您須要作的就是修改適配器的代碼以生成實際的調用代碼來代替註釋。完成後,您可使用生成的JavaScript代碼做爲捆綁包以良好的方式訪問您的服務。此外,您可使用JSweet生成服務和DTO的TypeScript定義,以便您的TypeScript客戶端輸入良好(請參閱JSweet的declaration 選項)。

示例6:禁用全局變量的適配器
這是一個很是特殊的適配器,由於它不會真正生成任何代碼,但它會在源代碼不符合某些編碼標準時報告錯誤。在這裏,咱們實現了一個簡單的約束,當用戶嘗試聲明全局變量時(即在Globals類中聲明的JSweet非最終靜態字段中)報告錯誤。

package org.jsweet.transpiler.extension;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;

import org.jsweet.transpiler.JSweetProblem;

public class DisallowGlobalVariablesAdapter extends PrinterAdapter {

public DisallowGlobalVariablesAdapter(PrinterAdapter parentAdapter) {
    super(parentAdapter);
}

@Override
public void afterType(TypeElement type) {
    // we only check for static variables that are in a Globals class but
    // this could be generalized to any static variable
    if (!type.getQualifiedName().toString().startsWith("def.")
            && type.getSimpleName().toString().equals("Globals")) {
        for (Element member : type.getEnclosedElements()) {
            if (member.getKind() == ElementKind.FIELD) {
                VariableElement field = (VariableElement) member;
                // only non-final static variable have side effect
                if (field.getModifiers().contains(Modifier.STATIC)
                        && !field.getModifiers().contains(Modifier.FINAL)) {
                    report(field, JSweetProblem.USER_ERROR, "global variables are not allowed");
                }
            }
        }
    }
    super.afterType(type);
}

}
此適配器屬於靜態分析類別,可用於(與代碼生成一塊兒)檢查輸入是否符合預期的編碼指南。加強此適配器以添加對任何靜態字段的檢查將很容易。一個很好的功能是在使用特定註釋(例如@AllowSideEffect)註釋字段時禁用檢查。

附錄1:JSweet轉換器選項
[-h|--help]

[-w|--watch]

Start a process that watches the input directories for changes and
    re-run transpilation on-the-fly.

[-v|--verbose]

Turn on all levels of logging.

[--encoding <encoding>]

Force the Java compiler to use a specific encoding (UTF-8, UTF-16, ...).
    (default: UTF-8)

[--jdkHome <jdkHome>]

Set the JDK home directory to be used to find the Java compiler. If not
    set, the transpiler will try to use the JAVA_HOME environment variable.
    Note that the expected JDK version is greater or equals to version 8.

(-i|--input) input1:input2:...:inputN

An input directory (or column-separated input directories) containing
    Java files to be transpiled. Java files will be recursively looked up in
    sub-directories. Inclusion and exclusion patterns can be defined with
    the 'includes' and 'excludes' options.

[--includes includes1:includes2:...:includesN ]

A column-separated list of expressions matching files to be included
    (relatively to the input directory).

[--excludes excludes1:excludes2:...:excludesN ]

A column-separated list of expressions matching files to be excluded
    (relatively to the input directory).

[(-d|--defInput) defInput1:defInput2:...:defInputN ]

An input directory (or column-separated input directories) containing
    TypeScript definition files (*.d.ts) to be used for transpilation.
    Definition files will be recursively looked up in sub-diredctories.

[--noRootDirectories]

Skip the root directories (i.e. packages annotated with
    @jsweet.lang.Root) so that the generated file hierarchy starts at the
    root directories rather than including the entire directory structure.

[--tsout <tsout>]

Specify where to place generated TypeScript files. (default: .ts)

[(-o|--jsout) <jsout>]

Specify where to place generated JavaScript files (ignored if jsFile is
    specified). (default: js)

[--disableSinglePrecisionFloats]

By default, for a target version >=ES5, JSweet will force Java floats to
    be mapped to JavaScript numbers that will be constrained with ES5
    Math.fround function. If this option is true, then the calls to
    Math.fround are erased and the generated program will use the JavaScript
    default precision (double precision).

[--tsOnly]

Do not compile the TypeScript output (let an external TypeScript
    compiler do so).

[--ignoreDefinitions]

Ignore definitions from def.* packages, so that they are not generated
    in d.ts definition files. If this option is not set, the transpiler
    generates d.ts definition files in the directory given by the tsout
    option.

[--declaration]

Generate the d.ts files along with the js files, so that other programs
    can use them to compile.

[--dtsout <dtsout>]

Specify where to place generated d.ts files when the declaration option
    is set (by default, d.ts files are generated in the JavaScript output
    directory - next to the corresponding js files).

[--candiesJsOut <candiesJsOut>]

Specify where to place extracted JavaScript files from candies.
    (default: js/candies)

[--sourceRoot <sourceRoot>]

Specify the location where debugger should locate Java files instead of
    source locations. Use this flag if the sources will be located at
    run-time in a different location than that at design-time. The location
    specified will be embedded in the sourceMap to direct the debugger where
    the source files will be located.

[--classpath <classpath>]

The JSweet transpilation classpath (candy jars). This classpath should
    at least contain the core candy.

[(-m|--module) <module>]

The module kind (none, commonjs, amd, system or umd). (default: none)

[-b|--bundle]

Bundle up all the generated code in a single file, which can be used in
    the browser. The bundle files are called 'bundle.ts', 'bundle.d.ts', or
    'bundle.js' depending on the kind of generated code. NOTE: bundles are
    not compatible with any module kind other than 'none'.

[(-f|--factoryClassName) <factoryClassName>]

Use the given factory to tune the default transpiler behavior.

[--sourceMap]

Generate source map files for the Java files, so that it is possible to
    debug Java files directly with a debugger that supports source maps
    (most JavaScript debuggers).

[--enableAssertions]

Java 'assert' statements are transpiled as runtime JavaScript checks.

[--header <header>]

A file that contains a header to be written at the beginning of each
    generated file. If left unspecified, JSweet will generate a default
    header.

[--workingDir <workingDir>]

The directory JSweet uses to store temporary files such as extracted
    candies. JSweet uses '.jsweet' if left unspecified.

[--targetVersion <targetVersion>]

The EcmaScript target (JavaScript) version. Possible values: [ES3, ES5,
    ES6] (default: ES3)

附錄2:包裝和靜態行爲
本附錄解釋了有關包裝的一些靜態行爲。

調用main方法時
調用main方法時,取決於程序的打包方式。

module:關閉,bundle:關閉。使用默認打包時,一個Java源文件對應於一個生成的JavaScript文件。在這種狀況下,在瀏覽器中加載文件時,將在文件末尾調用全部主要方法。

module:關閉,bundle開啓。當bundle選項打開和 module選項關閉,主要方法稱爲在束的端部。

module:開,bundle關。使用模塊打包(module 選項),一個Java包對應一個模塊。對於模塊,必須在程序中只有一個main方法,它將是從中計算模塊依賴圖的全局入口點。主模塊(具備主方法的模塊)將直接或可傳遞地使用全部其餘模塊。主模塊評估結束時將調用main方法。

因爲模塊,最好在應用程序中只有一個主要方法。

靜態和繼承依賴項
在TypeScript中,程序員須要處理與靜態字段和初始化程序有關的類的排序。一般,沒法使用還沒有定義的類的靜態成員初始化靜態成員。此外,類不能擴展還沒有定義的類。這個前向依賴性問題在評估生成的JavaScript代碼時會觸發運行時錯誤,這對程序員來講可能很是煩人,而且可能須要使用外部JavaScript捆綁工具,例如Br​​owserify。

JSweet的靜態延遲初始化容許在給定文件中的靜態前向引用,並在bundle 設置選項時在整個包內。此外,在捆綁一組文件時,JSweet會分析繼承樹並執行部分順序排列以消除繼承樹中的前向引用。請注意,TypeScript包提供了相似的功能,但須要手動聲明引用,這對程序員來講不方便。

總結一下,如下是程序員遵循的指導方針,具體取決於打包方法:

module:關閉,bundle:關閉。每一個Java文件生成一個JavaScript文件。程序員必須注意在HTML頁面中以正確的順序包含文件,這樣就沒有關於繼承和靜態的前向引用。在給定文件中,容許靜態轉發引用,但尚不支持繼承轉發引用(這將在即將發佈的版本中支持)。

module:關閉,bundle開啓。此配置生成一個獨特的瀏覽器兼容的捆綁文件,該文件能夠包含在HTML頁面中。在這裏,程序員沒必要關注文件中的全部前向引用。與Java徹底同樣,順序可有可無。在一個文件中,程序員仍然須要處理繼承轉發引用(換句話說,子類必須在其父類以後聲明)(這將在即將發佈的版本中獲得支持)。

module:commonjs,amd或umd,bundle:off。此配置爲每一個Java包生成一個模塊文件,以即可以在模塊系統中使用它們。例如,使用commonjs模塊類將容許程序在Node.js上運行。在該配置中,程序應該包含一個main方法,而且只應加載包含main方法的模塊文件(由於它會當心加載全部其餘模塊)。此配置在單個文件中強制使用相同的約束(繼承中沒有前向引用)。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<h1><a href="#jsweet-language-specifications" id="jsweet-language-specifications">JSweet Language Specifications</a>
</h1>
<p>Version: 2.x (snapshot)</p>
<p>Author : Renaud Pawlak</p>
<p>Author assistant: Louis Grignon</p>
<p>JSweet JavaDoc API: http://www.jsweet.org/core-api-javadoc/</p>
<p>Note: this markdown is automatically generated from the Latex source file. Do not modify directly.</p>
<h2><a href="#content" id="content">Content</a></h2>
<ul>
  <li><a href="#basic-concepts">Basic concepts</a>
    <ul>
      <li><a href="#core-types-and-objects">Core types and objects</a></li>
      <li><a href="#classes">Classes</a></li>
      <li><a href="#interfaces">Interfaces</a></li>
      <li><a href="#untyped-objects-maps">Untyped objects (maps)</a></li>
      <li><a href="#enums">Enums</a></li>
      <li><a href="#globals">Globals</a></li>
      <li><a href="#optional-parameters-and-overloading">Optional parameters and
        overloading</a></li>
    </ul>
  </li>
  <li><a href="#bridging-to-external-javascript-elements">Bridging to external JavaScript
    elements</a>
    <ul>
      <li><a href="#examples">Examples</a></li>
      <li><a href="#rules-for-writing-definitions-a.k.a.-bridges">Rules for writing definitions (a.k.a.
        bridges)</a></li>
      <li><a href="#untyped-accesses">Untyped accesses</a></li>
      <li><a href="#mixins">Mixins</a></li>
      <li><a href="#generating-jsweet-candies-from-existing-typescript-definitions">Generating JSweet candies from
        existing TypeScript
        definitions</a></li>
    </ul>
  </li>
  <li><a href="#auxiliary-types">Auxiliary types</a>
    <ul>
      <li><a href="#functional-types">Functional types</a></li>
      <li><a href="#object-types">Object types</a></li>
      <li><a href="#string-types">String types</a></li>
      <li><a href="#tuple-types">Tuple types</a></li>
      <li><a href="#union-types">Union types</a></li>
      <li><a href="#intersection-types">Intersection types</a></li>
    </ul>
  </li>
  <li><a href="#semantics">Semantics</a>
    <ul>
      <li><a href="#main-methods">Main methods</a></li>
      <li><a href="#initializers">Initializers</a></li>
      <li><a href="#arrays-initialization-and-allocation">Arrays initialization and
        allocation</a></li>
      <li><a href="#asynchronous-programming">Asynchronous programming</a></li>
      <li><a href="#name-clashes">Name clashes</a></li>
      <li><a href="#testing-the-type-of-an-object">Testing the type of an object</a></li>
      <li><a href="#variable-scoping-in-lambda-expressions">Variable scoping in lambda
        expressions</a></li>
      <li><a href="#scope-of-this">Scope of <em>this</em></a></li>
    </ul>
  </li>
  <li><a href="#packaging">Packaging</a>
    <ul>
      <li><a href="#use-your-files-without-any-packaging">Use your files without any
        packaging</a></li>
      <li><a href="#creating-a-bundle-for-a-browser">Creating a bundle for a
        browser</a></li>
      <li><a href="#packaging-with-modules">Packaging with modules</a></li>
      <li><a href="#root-packages">Root packages</a></li>
      <li><a href="#packaging-a-jsweet-jar-candy">Packaging a JSweet jar (candy)</a></li>
    </ul>
  </li>
  <li><a href="#extending-the-transpiler">Extending the transpiler</a>
    <ul>
      <li><a href="#core-annotations">Core annotations</a></li>
      <li><a href="#centralizing-annotations-in-jsweetconfig.json">Centralizing annotations in
        <code>jsweetconfig.json</code></a></li>
      <li><a href="#programmatic-tuning-with-adapters">Programmatic tuning with
        adapters</a></li>
      <li><a href="#extension-examples">Extension examples</a></li>
    </ul>
  </li>
  <li><a href="#appendix-1-jsweet-transpiler-options">Appendix 1: JSweet transpiler
    options</a></li>
  <li><a href="#appendix-2-packaging-and-static-behavior">Appendix 2: packaging and static
    behavior</a>
    <ul>
      <li><a href="#when-main-methods-are-invoked">When main methods are invoked</a></li>
      <li><a href="#static-and-inheritance-dependencies">Static and inheritance
        dependencies</a></li>
    </ul>
  </li>
</ul>
<h2><a href="#basic-concepts" id="basic-concepts">Basic concepts</a></h2>
<p>This section presents the JSweet language basic concepts. One must keep
  in mind that JSweet, as a Java-to-JavaScript transpiler, is an extension
  of Java at compile-time, and executes as JavaScript at runtime. JSweet
  aims at being a trade-off between Java and JavaScript, by respecting as
  much as possible the Java semantics, but without loosing
  interoperability with JavaScript. So, in a way, JSweet can be seen as a
  fusion between Java and JavaScript, trying to get the best of both
  worlds in one unique and consistent language. In some cases, it is hard
  to get the best of both worlds and JSweet makes convenient and practical
  choices.</p>
<p>Because JSweet is an open JavaScript transpiler, the user can tune the
  JavaScript generation without much efforts, thus making other choices
  than default ones to map Java to JavaScript. For example, if the way
  JSweet implements Java maps does not suit your context or use case, you
  can program a JSweet extension to override the default strategy.
  Programming and activating a JSweet extension is fully explained in
  Section
  <a href="#extending-the-transpiler" data-reference-type="ref" data-reference="extending-the-transpiler">6</a>.</p>
<h3><a href="#core-types-and-objects" id="core-types-and-objects">Core types and objects</a></h3>
<p>JSweet allows the use of primitive Java types, core Java objects
  (defined in <code>java.lang</code>, many JDK classes (especially <code>java.util</code> but
  not only), and of core JavaScript objects, which are defined in the
  <code>def.js</code> package. Next, we describe the use of such core types and
  objects.</p>
<h4><a href="#primitive-java-types" id="primitive-java-types">Primitive Java types</a></h4>
<p>JSweet allows the use of Java primitive types (and associated literals).</p>
<ul>
  <li>
    <p><code>int</code>, <code>byte</code>, <code>short</code>, <code>double</code>, <code>float</code> are all
      converted to
      JavaScript numbers (TypeScript <code>number</code> type). Precision usually
      does not matter in JSweet, however, casting to <code>int</code>, <code>byte</code>, or
      <code>short</code> forces the number to be rounded to the right-length integer.</p>
  </li>
  <li>
    <p><code>char</code> follows the Java typing rules but is converted to a
      JavaScript <code>string</code> by the transpiler.</p>
  </li>
  <li>
    <p><code>boolean</code> corresponds to the JavaScript <code>boolean</code>.</p>
  </li>
  <li>
    <p><code>java.lang.String</code> corresponds to the JavaScript <code>string</code>. (not per
      say a primitive type, but is immutable and used as the class of
      string literals in Java)</p>
  </li>
</ul>
<p>A direct consequence of that conversion is that it is not always
  possible in JSweet to safely overload methods with numbers or
  chars/strings. For instance, the methods <code>pow(int, int)</code> and
  <code>pow(double, double)</code> may raise overloading issues. With a JSweet
  context, the transpiler will be able to select the right method, but the
  JavaScript interoperability may be a problem. In short, since there is
  no difference between <code>n instanceof Integer</code> and <code>n instanceof Double</code>
  (it both means <code>typeof n === ’number’</code>) calling <code>pow(number, number)</code>
  from JavaScript will randomly select one implementation or the other.
  This should not be always a problem, but in some particular cases, it
  can raise subtle errors. Note that in these cases, the programmers will
  be able to tune the JavaScript generation, as it is fully explained in
  Section
  <a href="#extending-the-transpiler" data-reference-type="ref" data-reference="extending-the-transpiler">6</a>.</p>
<p>Examples of valid statements:</p>
<pre><code class="java">// warning '==' behaves like JavaScript '===' at runtime
int i = 2;
assert i == 2;
double d = i + 4;
assert d == 6;
String s = &quot;string&quot; + '0' + i;
assert s == &quot;string02&quot;;
boolean b = false;
assert !b;
</code></pre>
<p>The <code>==</code> operator behaves like the JavaScript strict equals operator
  <code>===</code> so that it is close to the Java semantics. Similarly, <code>!=</code> is
  mapped to <code>!==</code>. There is an exception to that behavior which is when
  comparing an object to a <code>null</code> literal. In that case, JSweet translates
  to the loose equality operators so that the programmers see no
  distinction between <code>null</code> and <code>undefined</code> (which are different in
  JavaScript but it may be confusing to Java programmers). To control
  whether JSweet generates strict or loose operators, you can use the
  following helper methods: <code>jsweet.util.Lang.$strict</code> and
  <code>jsweet.util.Lang.$loose</code>. Wrapping a comparison operator in such a
  macro will force JSweet to generate a strict or loose operator. For
  example:</p>
<pre><code class="java">import static jsweet.util.Lang.$loose;
[...]
int i = 2;
assert i == 2; // generates i === 2
assert !((Object)&quot;2&quot; == i);
assert $loose((Object)&quot;2&quot; == i); // generates &quot;2&quot; == i
</code></pre>
<h4><a href="#allowed-java-objects" id="allowed-java-objects">Allowed Java objects</a></h4>
<p>By default, JSweet maps core Java objects and methods to JavaScript
  through the use of built-in macros. It means that the Java code is
  directly substituted with a valid JavaScript code that implements
  similar behavior. A default mapping is implemented for most useful core
  Java classes (<code>java.lang</code>, <code>java.util</code>). When possible (and when it
  makes sense), some partial mapping is implemented for other JDK classes
  such as input and output streams, locales, calendars, reflection, etc.</p>
<p>With the default behavior, we can point the following limitations:</p>
<ul>
  <li>
    <p>Extending a JDK class is in general not possible, except for some
      particular contexts. If extending a JDK class is required, should
      should consider to refactor your program, or use a JavaScript
      runtime (such as J4TS), which would allow it.</p>
  </li>
  <li>
    <p>The Java reflection API (<code>java.lang.reflect</code>) is limited to very
      basic operations. It is possible to access the classes and the
      members, but it is not possible to access types. A more complete
      support of Java reflection would be possible, but it would require a
      JSweet extension.</p>
  </li>
  <li>
    <p>Java 8 streams are not supported yet, but it would be simple to
      support them partially (contributions are welcome).</p>
  </li>
</ul>
<p>Examples of valid statements:</p>
<pre><code class="java">Integer i = 2;
assert i == 2;
Double d = i + 4d;
assert d.toString() == &quot;6&quot;;
assert !((Object) d == &quot;6&quot;);
BiFunction&lt;String, Integer, String&gt; f = (s, i) -&gt; { return s.substring(i); };
assert &quot;bc&quot; == f.apply(&quot;abc&quot;, 1);
</code></pre>
<h4><a href="#getting-more-java-apis" id="getting-more-java-apis">Getting more Java APIs</a></h4>
<p>With JSweet, it is possible to add a runtime that implements Java APIs
  in JavaScript, so that programmers can access more Java APIs and thus
  share the same code between Java and JavaScript. The core project for
  implementing Java APIs for JSweet is J4TS
  (<a href="https://github.com/cincheo/j4ts">https://github.com/cincheo/j4ts</a>) and contains a quite complete
  implementation of <code>java.util.*</code> classes and other core package. J4TS is
  based on a fork of the GWT’s JRE emulation, but it is adapted to be
  compiled with JSweet. Programmers can use J4TS as a regular JavaScript
  library available in our Maven repository.</p>
<p>Although J4TS cannot directly implement the Java core types that
  conflict with JavaScript ones (<code>Boolean</code>, <code>Byte</code>, <code>Short</code>, <code>Integer</code>,
  <code>Long</code>, <code>Float</code>, <code>Double</code>, <code>Character</code>, <code>String</code>), J4TS
  contributes to
  supporting the static part of them by providing helpers for each class
  (<code>javaemul.internal.BooleanHelper</code>, <code>javaemul.internal.ByteHelper</code>,
  ...). When the JSweet transpiler meets a static Java method on a type
  <code>java.lang.T</code> that is not supported as a built-in macro, it delegates to
  <code>javaemul.internal.THelper</code>, which can provide a JavaScript
  implementation for the given static method. That way, by using J4TS,
  programmers can use even more of the core JRE API.</p>
<h4><a href="#java-arrays" id="java-arrays">Java arrays</a></h4>
<p>Arrays can be used in JSweet and are transpiled to JavaScript arrays.
  Array initialization, accesses and and iteration are all valid
  statements.</p>
<pre><code class="java">int[] arrayOfInts = { 1, 2, 3, 4};
assert arrayOfInts.length == 4;
assert arrayOfInts[0] == 1;
int i = 0;
for (int intItem : arrayOfInts) {
    assert arrayOfInts[i++] == intItem;
}
</code></pre>
<h4><a href="#core-javascript-api" id="core-javascript-api">Core JavaScript API</a></h4>
<p>The core JavaScript API is defined in <code>def.js</code> (the full documentation
  can be found at <a href="http://www.jsweet.org/core-api-javadoc/">http://www.jsweet.org/core-api-javadoc/</a>). Main
  JavaScript classes are:</p>
<ul>
  <li>
    <p><code>def.js.Object</code>: JavaScript Object class. Common ancestor for
      JavaScript objects functions and properties.</p>
  </li>
  <li>
    <p><code>def.js.Boolean</code>: JavaScript Boolean class. A wrapper for boolean
      values.</p>
  </li>
  <li>
    <p><code>def.js.Number</code>: JavaScript Number class. A wrapper for numerical
      values.</p>
  </li>
  <li>
    <p><code>def.js.String</code>: JavaScript String class. A wrapper and constructor
      for strings.</p>
  </li>
  <li>
    <p><code>def.js.Function</code>: JavaScript Function class. A constructor for
      functions.</p>
  </li>
  <li>
    <p><code>def.js.Date</code>: JavaScript Date class, which enables basic storage
      and retrieval of dates and times.</p>
  </li>
  <li>
    <p><code>def.js.Array&lt;T&gt;</code>: JavaScript Array class. It is used in the
      construction of arrays, which are high-level, list-like objects.</p>
  </li>
  <li>
    <p><code>def.js.Error</code>: JavaScript Error class. This class implements
      <code>java.lang.RuntimeException</code> and can be thrown and caught with <code>try</code>
      ... <code>catch</code> statements.</p>
  </li>
</ul>
<p>When using JavaScript frameworks, programmers should use this API most
  of the time, which is HTML5 compatible and follows the JavaScript latest
  supported versions. However, for objects that need to be used with Java
  literals (numbers, booleans, and strings), the use of the <code>java.lang</code>
  package classes is recommended. For instance, the jQuery API declares
  <code>$(java.lang.String)</code> instead of <code>$(def.js.String)</code>. This allows the
  programmer to write expressions using literals, such as <code>$(&quot;a&quot;)</code> (for
  selecting all links in a document).</p>
<p>With JSweet, programmers can easily switch from the Java to JavaScript
  API (and conversely) depending on their needs. The <code>jsweet.util.Lang</code>
  class defines convenient static methods to cast back and forth core Java
  objects to their corresponding JavaScript objects. For instance the
  <code>string(...)</code> method will allow the programmer to switch from the Java
  to the JavaScript strings and conversely.</p>
<pre><code class="java">import static jsweet.util.Lang.string;
// str is a Java string, but is actually a JavaScript string at runtime
String str = &quot;This is a test string&quot;;
// str is exactly the same string object, but shown through the JS API
def.js.String str2 = string(str);
// valid: toLowerCase it defined both in Java and JavaScript
str.toLowerCase();
// this method is not JS-compatible, so a macro generates the JS code
str.equalsIgnoreCase(&quot;abc&quot;);
// direct call to the JS substr method on the JavaScript string
string(str).substr(1);
// or
str2.substr(1);
</code></pre>
<p>Note: for code sharing between a JavaScript client and a Java server for
  instance, it is better to use Java APIs only and avoid JavaScript ones.
  JavaScript API will compile valid Java bytecode but trying to execute
  them on a JVM will raise unsatisfied link errors.</p>
<p>Here is another example that shows the use of the <code>array</code> method to
  access the <code>push</code> method available on JavaScript arrays.</p>
<pre><code class="java">import static jsweet.util.Lang.array;
String[] strings = { &quot;a&quot;, &quot;b&quot;, &quot;c&quot; };
array(strings).push(&quot;d&quot;);
assert strings[3] == &quot;d&quot;;
</code></pre>
<h3><a href="#classes" id="classes">Classes</a></h3>
<p>Classes in JSweet fully support all types of Java classes declarations.
  For example:</p>
<pre><code class="java">public class BankAccount {
    public double balance = 0;
    public double deposit(double credit) {
        balance += credit;
        return this.balance;
    }
}
</code></pre>
<p>Which is transpiled to the following JavaScript code:</p>
<pre><code class="java">var BankAccount = (function () {
    function BankAccount() {
        this.balance = 0;
    }
    BankAccount.prototype.deposit = function(credit) {
        this.balance += credit;
        return this.balance;
    };
    return BankAccount;
})();
</code></pre>
<p>Classes can define constructors, have super classes and be instantiated
  exactly like in Java. Similarly to Java, inner classes and anonymous
  classes are allowed in JSweet (since version 1.1.0). JSweet supports
  both static and regular inner/anonymous classes, which can share state
  with enclosing classes. Still like in Java, anonymous classes can access
  final variables declared in their scope. For example, the following
  declarations are valid in JSweet and will mimic the Java semantics at
  runtime so that Java programmers can benefit all the features of the
  Java language.</p>
<pre><code class="java">abstract class C {
    public abstract int m();
}
public class ContainerClass {
    // inner class
    public class InnerClass {
        public I aMethod(final int i) {
            // anonymous class
            return new C() {
                @Override
                public int m() {
                    // access to final variable i
                    return i;
                }
            }
        }
    }
}
</code></pre>
<h3><a href="#interfaces" id="interfaces">Interfaces</a></h3>
<p>In JSweet, an interface can be use like in Java. However, on contrary to
  Java, there is no associated class available as runtime. When using
  interfaces, JSweet generates code to emulate specific Java behaviors
  (such as <code>instanceof</code> on interfaces).</p>
<p>JSweet supports Java 8 static and default methods. However default
  methods are experimental so far and you should use them at your own
  risks.</p>
<p>In JSweet, interfaces are more similar to interfaces in TypeScript than
  in Java. It means that they must be seen as object signatures, which can
  specify functions, but also properties. In order to allow using fields
  as properties when defining interfaces, JSweet allows the use of regular
  classes annotated with <code>@jsweet.lang.Interface</code>. For example, the
  following interface types an object <code>Point</code> with 2 properties.</p>
<pre><code class="java">@Interface
public class Point {
    public double x;
    public double y;
}
</code></pre>
<p>To Java programmers, this may look like a very odd way to define an
  object, but you must remember that it is not a class, but a type for a
  JavaScript object. As such, it does not go against the OOP principles.
  We can create a JavaScript object typed after the interface. Note that
  the following code is not actually creating an instance of the <code>Point</code>
  interface, it is creating an object that conforms to the interface.</p>
<pre><code class="java">Point p1 = new Point() {{ x=1; y=1; }};
</code></pre>
<p>This object creation mechanism is a TypeScript/JavaScript mechanism and
  shall not be confused with anonymous classes, which is a Java-like
  construction. Because <code>Point</code> is annotated with <code>@Interface</code>, the
  transpiled JavaScript code will be similar to:</p>
<pre><code class="java">var p1 = Object.defineProperty({ x:1, y:1 }, &quot;_interfaces&quot;, [&quot;Point&quot;]);
</code></pre>
<p>Note that, for each object, JSweet keeps track of which interface it was
  created from and of all the potential interfaces implemented by its
  class. This interface tracking system is implemented as a special object
  property called <code>__interfaces</code>. Using that property, JSweet allows the
  use of the <code>instanceof</code> operator on interfaces like in Java.</p>
<h4><a href="#optional-fields-in-interfaces" id="optional-fields-in-interfaces">Optional fields in interfaces</a></h4>
<p>Interfaces can define <em>optional fields</em>, which are used to report errors
  when the programmer forgets to initialize a mandatory field in an
  object. Supporting optional fields in JSweet is done through the use of
  <code>@jsweet.lang.Optional</code> annotations. For instance:</p>
<pre><code class="java">@Interface
public class Point {
    public double x;
    public double y;
    @Optional
    public double z = 0;
}
</code></pre>
<p>It is the JSweet compiler that will check that the fields are correctly
  initialized, when constructing an object from an interface.</p>
<pre><code class="java">// no errors (z is optional)
Point p1 = new Point() {{ x=1; y=1; }};
// JSweet reports a compile error since y is not optional
Point p2 = new Point() {{ x=1; z=1; }};
</code></pre>
<h4><a href="#special-javascript-functions-in-interfaces" id="special-javascript-functions-in-interfaces">Special
  JavaScript functions in interfaces</a></h4>
<p>In JavaScript, objects can have properties and functions, but can also
  (not exclusively), be used as constructors and functions themselves.
  This is not possible in Java, so JSweet defines special functions for
  handling these cases.</p>
<ul>
  <li>
    <p><code>$apply</code> is used to state that the object can be used as a function.</p>
  </li>
  <li>
    <p><code>$new</code> is used to state that the object can be used as a
      constructor.</p>
  </li>
</ul>
<p>For instance, if an object <code>o</code> is of interface <code>O</code> that defines
  <code>$apply()</code>, writing:</p>
<pre><code class="java">o.$apply();
</code></pre>
<p>Will transpile to:</p>
<pre><code class="java">o();
</code></pre>
<p>Similarly, if <code>O</code> defines <code>$new()</code>:</p>
<pre><code class="java">o.$new();
</code></pre>
<p>Will transpile to:</p>
<pre><code class="java">new o();
</code></pre>
<p>Yes, it does not make sense in Java, but in JavaScript it does!</p>
<h3><a href="#untyped-objects-maps" id="untyped-objects-maps">Untyped objects (maps)</a></h3>
<p>In JavaScript, object can be seen as maps containing key-value pairs
  (key is often called <em>index</em>, especially when it is a number). So, in
  JSweet, all objects define the special functions (defined on
  <code>def.js.Object</code>):</p>
<ul>
  <li>
    <p><code>$get(key)</code> accesses a value with the given key.</p>
  </li>
  <li>
    <p><code>$set(key,value)</code> sets or replace a value for the given key.</p>
  </li>
  <li>
    <p><code>$delete(key)</code> deletes the value for the given key.</p>
  </li>
</ul>
<h4><a href="#reflectiveuntyped-accesses" id="reflectiveuntyped-accesses">Reflective/untyped accesses</a></h4>
<p>The functions <code>$get(key)</code>, <code>$set(key,value)</code> and <code>$delete(key)</code> can be
  seen as a simple reflective API to access object fields and state. Note
  also the static method <code>def.js.Object.keys(object)</code>, which returns all
  the keys defined on a given object.</p>
<p>The following code uses this API to introspect the state of an object
  <code>o</code>.</p>
<pre><code class="java">for(String key : def.js.Object.keys(o)) {
  console.log(&quot;key=&quot; + key +  &quot; value=&quot; + o.$get(key));
});
</code></pre>
<p>When not having the typed API of a given object, this API can be useful
  to manipulate the object in an untyped way (of course it should be
  avoided as much as possible).</p>
<h4><a href="#untyped-objects-initialization" id="untyped-objects-initialization">Untyped objects initialization</a>
</h4>
<p>One can use the <code>$set(key,value)</code> function to create new untyped object.
  For instance:</p>
<pre><code class="java">Object point = new def.js.Object() {{ $set(&quot;x&quot;, 1); $set(&quot;y&quot;, 1); }};
</code></pre>
<p>It transpiles also to:</p>
<pre><code class="java">var point = { &quot;x&quot;: 1, &quot;y&quot;: 1};
</code></pre>
<p>As a shortcut, one can use the <code>jsweet.util.Lang.$map</code> function, which
  transpiles to the exact same JavaScript code:</p>
<pre><code class="java">import static jsweet.util.Lang.$map;
[...]
Object point = $map(&quot;x&quot;, 1, &quot;y&quot;, 1);
</code></pre>
<h4><a href="#indexed-objects" id="indexed-objects">Indexed objects</a></h4>
<p>The type of keys and values can be overloaded for every object. For
  example, the <code>Array&lt;T&gt;</code> class, will define keys as numbers and values as
  objects conforming to type <code>T</code>.</p>
<p>In the case of objects indexed with number keys, it is allowed to
  implement the <code>java.lang.Iterable</code> interface so that it is possible to
  use they in <em>foreach</em> loops. For instance, the <code>NodeList</code> type (from the
  DOM) defines an indexed function:</p>
<pre><code class="java">@Interface
class NodeList implements java.lang.Iterable {
    public double length;
    public Node item(double index);
    public Node $get(double index);
}
</code></pre>
<p>In JSweet, you can access the node list elements with the <code>$get</code>
  function, and you can also iterate with the <em>foreach</em> syntax. The
  following code generates fully valid JavaScript code.</p>
<pre><code class="java">NodeList nodes = ...
for (int i = 0; i &lt; nodes.length; i++) {
    HTMLElement element = (HTMLElement) nodes.$get(i);
    [...]
}
// same as:
NodeList nodes = ...
for (Node node : nodes) {
    HTMLElement element = (HTMLElement) node;
    [...]
}
</code></pre>
<h3><a href="#enums" id="enums">Enums</a></h3>
<p>JSweet allows the definition of enums similarly to Java. The following
  code declares an enum with tree possible values (<code>A</code>, <code>B</code>, and <code>C</code>).</p>
<pre><code class="java">enum MyEnum {
    A, B, C
}
</code></pre>
<p>The following statements are valid statements in JSweet.</p>
<pre><code class="java">MyEnum e = MyEnum.A;
assert MyEnum.A == e;
assert e.name() == &quot;A&quot;;
assert e.ordinal() == 0;
assert MyEnum.valueOf(&quot;A&quot;) == e;
assert array(MyEnum.values()).indexOf(MyEnum.valueOf(&quot;C&quot;)) == 2;
</code></pre>
<p>Like Java enums, additional methods, constructors and fields can be
  added to enums.</p>
<pre><code class="java">enum ScreenRatio {
    FREE_RATIO(null),
    RATIO_4_3(4f / 3),
    RATIO_3_2(1.5f),
    RATIO_16_9(16f / 9),
    RATIO_2_1(2f / 1f),
    SQUARE_RATIO(1f);

    private final Float value;

    private MyComplexEnum(Float value) {
        this.value = value;
    }

    public Float getValue() {
        return value;
    }
}
</code></pre>
<h4><a href="#enums-portability-notes" id="enums-portability-notes">Enums portability notes</a></h4>
<p>Simple enums are translated to regular TypeScript enums, that is to say
  numbers. In JavaScript, at runtime, an enum instance is simple encode as
  its ordinal. So, JSweet enums are easy to share with TypeScript enums
  and a JSweet program can interoperate with a TypeScript program even
  when using enums.</p>
<p>Enums with additional members are also mapped to TypeScript enums, but
  an additional class is generated to store the additional information.
  When interoperating with TypeScript, the ordinal will remain, but the
  additional information will be lost. The programmers wanting to share
  enums with TypeScript should be aware of that behavior.</p>
<h3><a href="#globals" id="globals">Globals</a></h3>
<p>In Java, on contrary to JavaScript, there is no such thing as global
  variables or functions (there are only static members, but even those
  must belong to a class). Thus, JSweet introduces reserved <code>Globals</code>
  classes and <code>globals</code> packages. These have two purposes:</p>
<ul>
  <li>
    <p>Generate code that has global variables and functions (this is
      discouraged in Java)</p>
  </li>
  <li>
    <p>Bind to existing JavaScript code that defines global variables and
      functions (as many JavaScript frameworks do)</p>
  </li>
</ul>
<p>In Globals classes, only static fields (global variables) and static
  methods (global functions) are allowed. Here are the main constraints
  applying to Globals classes:</p>
<ul>
  <li>
    <p>no non-static members</p>
  </li>
  <li>
    <p>no super class</p>
  </li>
  <li>
    <p>cannot be extended</p>
  </li>
  <li>
    <p>cannot be used as types like regular classes</p>
  </li>
  <li>
    <p>no public constructor (empty private constructor is OK)</p>
  </li>
  <li>
    <p>cannot use $get, $set and $delete within the methods</p>
  </li>
</ul>
<p>For instance, the following code snippets will raise transpilation
  errors.</p>
<pre><code class="java">class Globals {
    public int a;
    // error: public constructors are not allowed
    public Globals() {
        this.a = 3;
    }
    public static void test() {
        // error: no instance is available
        $delete(&quot;key&quot;);
    }
}
</code></pre>
<pre><code class="java">// error: Globals classes cannot be used as types
Globals myVariable = null;
</code></pre>
<p>One must remember that <code>Globals</code> classes and <code>global</code> packages are
  erased at runtime so that their members will be directly accessible. For
  instance <code>mypackage.Globals.m()</code> in a JSweet program corresponds to the
  <code>mypackage.m()</code> function in the generated code and in the JavaScript VM
  at runtime. Also, <code>mypackage.globals.Globals.m()</code> corresponds to <em>m()</em>.</p>
<p>In order to erase packages in the generated code, programmers can also
  use the <code>@Root</code> annotation, which will be explained in Section
  <a href="#packaging" data-reference-type="ref" data-reference="packaging">5</a>.</p>
<h3><a href="#optional-parameters-and-overloading" id="optional-parameters-and-overloading">Optional parameters and
  overloading</a></h3>
<p>In JavaScript, parameters can be optional, in the sense that a parameter
  value does not need to be provided when calling a function. Except for
  varargs, which are fully supported in JSweet, the general concept of an
  optional parameter does not exist in Java. To simulate optional
  parameters, JSweet programmers can use method overloading, which is
  supported in Java. Here are some examples of supported overloads in
  JSweet:</p>
<pre><code class="java">String m(String s, double n) { return s + n; }
// simple overloading (JSweet transpiles to optional parameter)
String m(String s) { return m(s, 0); }
// complex overloading (JSweet generates more complex code to mimic the Java behavior)
String m(String s) { return s; }
</code></pre>
<h2><a href="#bridging-to-external-javascript-elements" id="bridging-to-external-javascript-elements">Bridging to
  external JavaScript elements</a></h2>
<p>It can be the case that programmers need to use existing libraries from
  JSweet. In most cases, one should look up in the available candies,
  a.k.a. bridges at <a href="http://www.jsweet.org/jsweet-candies/">http://www.jsweet.org/jsweet-candies/</a>. When the
  candy does not exist, or does not entirely cover what is needed, one can
  create new definitions in the program just by placing them in the
  <code>def.libname</code> package. Definitions only specify the types of external
  libraries, but no implementations. Definitions are similar to
  TypeScript’s <code>*.d.ts</code> definition files (actually JSweet generates
  intermediate TypeScript definition files for compilation purposes).
  Definitions can also be seen as similar to <code>*.h</code> C/C++ header files.</p>
<h3><a href="#examples" id="examples">Examples</a></h3>
<p>The following example shows the backbone store class made accessible to
  the JSweet programmer with a simple definition. This class is only for
  typing and will be generated as a TypeScript definition, and erased
  during the JavaScript generation.</p>
<pre><code class="java">package def.backbone;
class Store {
    public Store(String dbName) {}
}
</code></pre>
<p>Note that definition classes constructors must have an empty body. Also,
  definition classes methods must be <code>native</code>. For instance:</p>
<pre><code class="java">package def.mylib;
class MyExternalJavaScriptClass {
    public native myExternalJavaScriptMethod();
}
</code></pre>
<p>It is possible to define properties in definitions, however, these
  properties cannot be initialized.</p>
<h3><a href="#rules-for-writing-definitions-aka-bridges" id="rules-for-writing-definitions-aka-bridges">Rules for
  writing definitions (a.k.a. bridges)</a></h3>
<p>By convention, putting the classes in a <code>def.libname</code> package defines a
  set of definitions for the <code>libname</code> external JavaScript library called
  <code>libname</code>. Note that this mechanism is similar to the TypeScript <code>d.ts</code>
  definition files.</p>
<p>Candies (bridges to external JavaScript libraries) use definitions. For
  instance, the jQuery candy defines all the jQuery API in the
  <code>def.jquery</code> package.</p>
<p>Here is a list of rules and constraints that need to be followed when
  writing definitions.</p>
<ul>
  <li>
    <p>Interfaces are preferred over classes, because interfaces can be
      merged and classes can be instantiated. Classes should be used only
      if the API defines an explicit constructor (objects can be created
      with <code>new</code>). To define an interface in JSweet, just annotate a class
      with <code>@jsweet.lang.Interface</code>.</p>
  </li>
  <li>
    <p>Top-level functions and variables must be defined as <code>public static</code>
      members in a <code>Globals</code> class.</p>
  </li>
  <li>
    <p>All classes, interfaces and packages, should be documented with
      comments following the Javadoc standard.</p>
  </li>
  <li>
    <p>When several types are possible for a function parameter, method
      overloading should be preferred over using union types. When method
      overloading is not possible, it can be more convenient to simply use
      the <code>Object</code> type. It is less strongly typed but it is easier to
      use.</p>
  </li>
  <li>
    <p>One can use string types to provide function overloading depending
      on a string parameter value.</p>
  </li>
  <li>
    <p>In a method signature, optional parameters can be defined with the
      <code>@jsweet.lang.Optional</code> annotation.</p>
  </li>
  <li>
    <p>In an interface, optional fields can be defined with the
      <code>@jsweet.lang.Optional</code> annotation.</p>
  </li>
</ul>
<p>Definitions can be embedded directly in a JSweet project to access an
  external library in a typed way.</p>
<p>Definitions can also be packaged in a candy (a Maven artifact), so that
  they can be shared by other projects. See the <em>Packaging</em> section for
  full details on how to create a candy. Note that you do not need to
  write definitions when a library is written with JSweet because the Java
  API is directly accessible and the TypeScript definitions can be
  automatically generated by JSweet using the <code>declaration</code> option.</p>
<h3><a href="#untyped-accesses" id="untyped-accesses">Untyped accesses</a></h3>
<p>Sometimes, definitions are not available or are not correct, and just a
  small patch is required to access a functionality. Programmers have to
  keep in mind that JSweet is just a syntactic layer and that it is always
  possible to bypass typing in order to access a field or a function that
  is not explicitly specified in an API.</p>
<p>Although, having a well-typed API is the preferred and advised way, when
  such an API is not available, the use of <code>def.js.Object.$get</code> allows
  reflective access to methods and properties that can then be cast to the
  right type. For accessing functions in an untyped way, one can cast to
  <code>def.js.Function</code> and call the generic and untyped method <code>$apply</code> on
  it. For example, here is how to invoke the jQuery <code>$</code> method when the
  jQuery API is not available :</p>
<pre><code class="java">import def.dom.Globals.window;
[...]
Function $ = (Function)window.$get(&quot;$&quot;);
$.$apply(&quot;aCssSelector&quot;):
</code></pre>
<p>The <code>$get</code> function is available on instances of <code>def.js.Object</code> (or
  subclasses). For a <code>def.js.Object</code>, you can cast it using the
  <code>jsweet.util.Lang.object</code> helper method. For example:</p>
<pre><code class="java">import static jsweet.dom.Lang.object;
[...]
object(anyObject).$get(&quot;$&quot;);
</code></pre>
<p>In last resort, the <code>jsweet.util.Lang.$insert</code> helper method allows the
  user to insert any TypeScript expression within the program. Invalid
  expressions will raise a TypeScript compilation error, but it is however
  not recommended to use this technique.</p>
<pre><code class="java">import static jsweet.dom.Lang.$get;
import static jsweet.dom.Lang.$apply;
[...]
// generate anyObject[&quot;prop&quot;](&quot;param&quot;);
$apply($get(anyObject, &quot;prop&quot;), &quot;param&quot;);
</code></pre>
<p>Finally, note also the use of the <code>jsweet.util.Lang.any</code> helper method,
  which can be extremely useful to erase typing. Since the <code>any</code> method
  generates a cast to the <code>any</code> type in TypeScript, it is more radical
  than a cast to <code>Object</code> for instance. The following example shows how to
  use the <code>any</code> method to cast an <code>Int32Array</code> to a Java <code>int[]</code> (and then
  allow direct indexed accesses to it.</p>
<pre><code class="java">ArrayBuffer arb = new ArrayBuffer(2 * 2 * 4);
int[] array = any(new Int32Array(arb));
int whatever = array[0];
</code></pre>
<h3><a href="#mixins" id="mixins">Mixins</a></h3>
<p>In JavaScript, it is common practice to enhance an existing class with
  news elements (field and methods). It is an extension mechanism used
  when a framework defines plugins for instance. Typically, jQuery plugins
  add new elements to the <code>JQuery</code> class. For example the jQuery timer
  plugin adds a <code>timer</code> field to the <code>JQuery</code> class. As a consequence, the
  <code>JQuery</code> class does not have the same prototype if you are using jQuery
  alone, or jQuery enhanced with its timer plugin.</p>
<p>In Java, this extension mechanism is problematic because the Java
  language does not support mixins or any extension of that kind by
  default.</p>
<h4><a href="#untyped-accesses-to-mixins" id="untyped-accesses-to-mixins">Untyped accesses to mixins</a></h4>
<p>Programmers can access the added element with <code>$get</code> accessors and/or
  with brute-force casting.</p>
<p>Here is an example using <code>$get</code> for the timer plugin case:</p>
<pre><code class="java">((Timer)$(&quot;#myId&quot;).$get(&quot;timer&quot;)).pause();
</code></pre>
<p>Here is an other way to do it exampled through the use of the jQuery UI
  plugin (note that this solution forces the use of <code>def.jqueryui.JQuery</code>
  instead of <code>def.jquery.JQuery</code> in order to access the <code>menu()</code> function,
  added by the UI plugin):</p>
<pre><code class="java">import def.jqueryui.JQuery;
[...]
Object obj = $(&quot;#myMenu&quot;);
JQuery jq = (JQuery) obj;
jq.menu();
</code></pre>
<p>However, these solutions are not fully satisfying because clearly unsafe
  in terms of typing.</p>
<h4><a href="#typed-accesses-with-mixins" id="typed-accesses-with-mixins">Typed accesses with mixins</a></h4>
<p>When cross-candy dynamic extension is needed, JSweet defines the notion
  of a mixin. A mixin is a class that defines members that will end up
  being directly accessible within a target class (mixin-ed class). Mixins
  are defined with a <code>@Mixin</code> annotation. Here is the excerpt of the
  <code>def.jqueryui.JQuery</code> mixin:</p>
<pre><code class="java">package def.jqueryui;
import def.dom.MouseEvent;
import def.js.Function;
import def.js.Date;
import def.js.Array;
import def.js.RegExp;
import def.dom.Element;
import def.jquery.JQueryEventObject;
@jsweet.lang.Interface
@jsweet.lang.Mixin(target=def.jquery.JQuery.class)
public abstract class JQuery extends def.jquery.JQuery {
    native public JQuery accordion();
    native public void accordion(jsweet.util.StringTypes.destroy methodName);
    native public void accordion(jsweet.util.StringTypes.disable methodName);
    native public void accordion(jsweet.util.StringTypes.enable methodName);
    native public void accordion(jsweet.util.StringTypes.refresh methodName);
    ...
    native public def.jqueryui.JQuery menu();
    ...
</code></pre>
<p>One can notice the <code>@jsweet.lang.Mixin(target=def.jquery.JQuery.class)</code>
  that states that this mixin will be merged to the <code>def.jquery.JQuery</code> so
  that users will be able to use all the UI plugin members directly and in
  a well-typed way.</p>
<h4><a href="#how-to-use" id="how-to-use">How to use</a></h4>
<p>TBD.</p>
<h3><a href="#generating-jsweet-candies-from-existing-typescript-definitions"
       id="generating-jsweet-candies-from-existing-typescript-definitions">Generating JSweet candies from existing
  TypeScript definitions</a></h3>
<p>TBD.</p>
<h2><a href="#auxiliary-types" id="auxiliary-types">Auxiliary types</a></h2>
<p>JSweet uses most Java typing features (including functional types) but
  also extends the Java type system with so-called <em>auxiliary types</em>. The
  idea behind auxiliary types is to create classes or interfaces that can
  hold the typing information through the use of type parameters (a.k.a
  <em>generics</em>), so that the JSweet transpiler can cover more typing
  scenarios. These types have been mapped from TypeScript type system,
  which is much richer than the Java one (mostly because JavaScript is a
  dynamic language and requires more typing scenarios than Java).</p>
<h3><a href="#functional-types" id="functional-types">Functional types</a></h3>
<p>For functional types, JSweet reuses the <code>java.Runnable</code> and
  <code>java.util.function</code> functional interfaces of Java 8. These interfaces
  are generic but only support up to 2-parameter functions. Thus, JSweet
  adds some support for more parameters in <code>jsweet.util.function</code>, since
  it is a common case in JavaScript APIs.</p>
<p>Here is an example using the <code>Function</code> generic functional type:</p>
<pre><code class="java">import java.util.function.Function;

public class C {

    String test(Function&lt;String, String&gt; f) {
        f.apply(&quot;a&quot;);
    }

    public static void main(String[] args) {
        String s = new C().test(p -&gt; p);
        assert s == &quot;a&quot;;
    }
}
</code></pre>
<p>We encourage programmers to use the generic functional interfaces
  defined in the <code>jsweet.util.function</code> and <code>java.util.function</code> (besides
  <code>java.lang.Runnable</code>). When requiring functions with more parameters,
  programmers can define their own generic functional types in
  <code>jsweet.util.function</code> by following the same template as the existing
  ones.</p>
<p>In some cases, programmers will prefer defining their own specific
  functional interfaces. This is supported by JSweet. For example:</p>
<pre><code class="java">@FunctionalInterface
interface MyFunction {
    void run(int i, String s);
}

public class C {
    void m(MyFunction f) {
        f.run(1, &quot;test&quot;);
    }
    public static void main(String[] args) {
        new C().m((i, s) -&gt; {
            // do something with i and s
        });
    }
}
</code></pre>
<p>Important warning: it is to be noted here that, on contrary to Java, the
  use of the <code>@FunctionInterface</code> annotation is mandatory.</p>
<p>Note also the possible use of the <code>apply</code> function, which is by
  convention always a functional definition on the target object (unless
  if <code>apply</code> is annotated with the <code>@Name</code> annotation). Defining/invoking
  <code>apply</code> can done on any class/object (because in JavaScript any object
  can become a functional object).</p>
<h3><a href="#object-types" id="object-types">Object types</a></h3>
<p>Object types are similar to interfaces: they define a set of fields and
  methods that are applicable to an object (but remember that it is a
  compile-time contract). In TypeScript, object types are inlined and
  anonymous. For instance, in TypeScript, the following method <code>m</code> takes a
  parameter, which is an object containing an <code>index</code> field:</p>
<pre><code class="java">// TypeScript:
public class C {
    public m(param : { index : number }) { ... }
}
</code></pre>
<p>Object types are a convenient way to write shorter code. One can pass an
  object that is correctly typed by constructing an object on the fly:</p>
<pre><code class="java">// TypeScript:
var c : C = ...;
c.m({ index : 2 });
</code></pre>
<p>Obviously, object types are a way to make the typing of JavaScript
  programs very easy to programmers, which is one of the main goals of
  TypeScript. It makes the typing concise, intuitive and straightforward
  to JavaScript programmers. In Java/JSweet, no similar inlined types
  exist and Java programmers are used to defining classes or interfaces
  for such cases. So, in JSweet, programmers have to define auxiliary
  classes annotated with <code>@ObjectType</code> for object types. This may seem
  more complicated, but it has the advantage to force the programmers to
  name all the types, which, in the end, can lead to more readable and
  maintenable code depending on the context. Note that similarily to
  interfaces, object types are erased at runtime. Also <code>@ObjectType</code>
  annotated classes can be inner classes so that they are used locally.</p>
<p>Here is the JSweet version of the previous TypeScript program.</p>
<pre><code class="java">public class C {
    @ObjectType
    public static class Indexed {
        int index;
    }
    public void m(Indexed param) { ... }
}
</code></pre>
<p>Using an object type is similar to using an interface:</p>
<pre><code class="java">C c = ...;
c.m(new Indexed() {{ index = 2; }});
</code></pre>
<p>When object types are shared objects and represent a typing entity that
  can be used in several contexts, it is recommended to use the
  <code>@Interface</code> annotation instead of <code>@ObjectType</code>. Here is the
  interface-based version.</p>
<pre><code class="java">@Interface
public class Indexed {
    int index;
}

public class C {
    public m(Indexed param) { ... }
}

C c = ...;
c.m(new Indexed {{ index = 2; }});
</code></pre>
<h3><a href="#string-types" id="string-types">String types</a></h3>
<p>In TypeScript, string types are a way to simulate function overloading
  depending on the value of a string parameter. For instance, here is a
  simplified excerpt of the DOM TypeScript definition file:</p>
<pre><code class="java">// TypeScript:
interface Document {
    [...]
    getElementsByTagName(tagname: &quot;a&quot;): NodeListOf&lt;HTMLAnchorElement&gt;;
    getElementsByTagName(tagname: &quot;b&quot;): NodeListOf&lt;HTMLPhraseElement&gt;;
    getElementsByTagName(tagname: &quot;body&quot;): NodeListOf&lt;HTMLBodyElement&gt;;
    getElementsByTagName(tagname: &quot;button&quot;): NodeListOf&lt;HTMLButtonElement&gt;;
    [...]
}
</code></pre>
<p>In this code, the <code>getElementsByTagName</code> functions are all overloads
  that depend on the strings passed to the <code>tagname</code> parameter. Not only
  string types allow function overloading (which is in general not allowed
  in TypeScript/JavaScript), but they also constrain the string values
  (similarly to an enumeration), so that the compiler can automatically
  detect typos in string values and raise errors.</p>
<p>This feature being useful for code quality, JSweet provides a mechanism
  to simulate string types with the same level of type safety. A string
  type is a public static field annotated with <code>@StringType</code>. It must be
  typed with an interface of the same name declared in the same container
  type.</p>
<p>For JSweet translated libraries (candies), all string types are declared
  in a the <code>jsweet.util.StringTypes</code> class, so that it is easy for the
  programmers to find them. For instance, if a <code>&quot;body&quot;</code> string type needs
  to be defined, a Java interface called <code>body</code> and a static final field
  called <code>body</code> are defined in a <code>jsweet.util.StringTypes</code>.</p>
<p>Note that each candy may have its own string types defined in the
  <code>jsweet.util.StringTypes</code> class. The JSweet transpiler merges all these
  classes at the bytecode level so that all the string types of all
  candies are available in the same <code>jsweet.util.StringTypes</code> utility
  class. As a result, the JSweet DOM API will look like:</p>
<pre><code class="java">@Interface
public class Document {
    [...]
    public native NodeListOf&lt;HTMLAnchorElement&gt; getElementsByTagName(a tagname);
    public native NodeListOf&lt;HTMLPhraseElement&gt; getElementsByTagName(b tagname);
    public native NodeListOf&lt;HTMLBodyElement&gt; getElementsByTagName(body tagname);
    public native NodeListOf&lt;HTMLButtonElement&gt; getElementsByTagName(button tagname);
    [...]
}
</code></pre>
<p>In this API, <code>a</code>, <code>b</code>, <code>body</code> and <code>button</code> are interfaces defined in the
  <code>jsweet.util.StringTypes</code> class. When using one the method of
  <code>Document</code>, the programmer just need to use the corresponding type
  instance (of the same name). For instance:</p>
<pre><code class="java">Document doc = ...;
NodeListOf&lt;HTMLAnchorElement&gt; elts = doc.getElementsByTagName(StringTypes.a);
</code></pre>
<p>Note: if the string value is not a valid Java identifier (for instance
  <code>&quot;2d&quot;</code> or <code>&quot;string-with-dashes&quot;</code>), it is then translated to a valid one
  and annotated with <code>@Name(&quot;originalName&quot;)</code>, so that the JSweet
  transpiler knows what actual string value must be used in the generated
  code. For instance, by default, <code>&quot;2d&quot;</code> and <code>&quot;string-with-dashes&quot;</code> will
  correspond to the interfaces <code>StringTypes._2d</code> and
  <code>StringTypes.string_with_dashes</code> with <code>@Name</code> annotations.</p>
<p>Programmers can define string types for their own needs, as shown below:</p>
<pre><code class="java">import jsweet.lang.Erased;
import jsweet.lang.StringType;

public class CustomStringTypes {
    @Erased
    public interface abc {}

    @StringType
    public static final abc abc = null;

    // This method takes a string type parameter
    void m2(abc arg) {
    }

    public static void main(String[] args) {
        new CustomStringTypes().m2(abc);
    }
}
</code></pre>
<p>Note the use of the <code>@Erased</code> annotation, which allows the declaration
  of the <code>abc</code> inner interface. This interface is used to type the string
  type field <code>abc</code>. In general, we advise the programmer to group all the
  string types of a program in the same utility class so that it is easy
  to find them.</p>
<h3><a href="#tuple-types" id="tuple-types">Tuple types</a></h3>
<p>Tuple types represent JavaScript arrays with individually tracked
  element types. For tuple types, JSweet defines parameterized auxiliary
  classes <code>TupleN&lt;T0, ... TN-1&gt;</code>, which define <code>$0</code>, <code>$1</code>, ... <code>$N-1</code>
  public fields to simulate typed array accessed (field <code>$i</code> is typed with
  <code>Ti</code>).</p>
<p>For instance, given the following tuple of size 2:</p>
<pre><code class="java">Tuple2&lt;String, Integer&gt; tuple = new Tuple2&lt;String, Integer&gt;(&quot;test&quot;, 10);
</code></pre>
<p>We can expect the following (well-typed) behavior:</p>
<pre><code class="java">assert tuple.$0 == &quot;test&quot;;
assert tuple.$1 == 10;
tuple.$0 = &quot;ok&quot;;
tuple.$1--;
assert tuple.$0 == &quot;ok&quot;;
assert tuple.$1 == 9;
</code></pre>
<p>Tuple types are all defined (and must be defined) in the
  <code>jsweet.util.tuple</code> package. By default classes <code>Tuple[2..6]</code> are
  defined. Other tuples ( &gt; 6) are automatically generated when
  encountered in the candy APIs. Of course, when requiring larger tuples
  that cannot be found in the <code>jsweet.util.tuple</code> package, programmers can
  add their own tuples in that package depending on their needs, just by
  following the same template as existing tuples.</p>
<h3><a href="#union-types" id="union-types">Union types</a></h3>
<p>Union types represent values that may have one of several distinct
  representations. When such a case happens within a method signature (for
  instance a method allowing several types for a given parameter), JSweet
  takes advantage of the <em>method overloading</em> mechanism available in Java.
  For instance, the following <code>m</code> method accept a parameter <code>p</code>, which can
  be either a <code>String</code> or a <code>Integer</code>.</p>
<pre><code class="java">public void m(String p) {...}
public void m(Integer p) {...}
</code></pre>
<p>In the previous case, the use of explicit union types is not required.
  For more general cases, JSweet defines an auxiliary interface
  <code>Union&lt;T1, T2&gt;</code> (and <code>UnionN&lt;T1, ... TN&gt;</code>) in the <code>jsweet.util.union</code>
  package. By using this auxiliary type and a <code>union</code> utility method,
  programmers can cast back and forth between union types and union-ed
  type, so that JSweet can ensure similar properties as TypeScript union
  types.</p>
<p>The following code shows a typical use of union types in JSweet. It
  simply declares a variable as a union between a string and a number,
  which means that the variable can actually be of one of that types (but
  of no other types). The switch from a union type to a regular type is
  done through the <code>jsweet.util.Lang.union</code> helper method. This helper
  method is completely untyped, allowing from a Java perspective any union
  to be transformed to another type. It is actually the JSweet transpiler
  that checks that the union type is consistently used.</p>
<pre><code class="java">import static jsweet.util.Lang.union;
import jsweet.util.union.Union;
[...]
Union&lt;String, Number&gt; u = ...;
// u can be used as a String
String s = union(u);
// or a number
Number n = union(u);
// but nothing else
Date d = union(u); // JSweet error
</code></pre>
<p>The <code>union</code> helper can also be used the other way, to switch from a
  regular type back to a union type, when expected.</p>
<pre><code class="java">import static jsweet.util.Lang.union;
import jsweet.util.union.Union3;
[...]
public void m(Union3&lt;String, Number, Date&gt;&gt; u) { ... }
[...]
// u can be a String, a Number or a Date
m(union(&quot;a string&quot;));
// but nothing else
m(union(new RegExp(&quot;.*&quot;))); // compile error
</code></pre>
<p>Note: the use of Java function overloading is preferred over union types
  when typing function parameters. For example:</p>
<pre><code class="java">// with union types (discouraged)
native public void m(Union3&lt;String, Number, Date&gt;&gt; u);
// with overloading (preferred way)
native public void m(String s);
native public void m(Number n);
native public void m(Date d);
</code></pre>
<h3><a href="#intersection-types" id="intersection-types">Intersection types</a></h3>
<p>TypeScript defines the notion of type intersection. When types are
  intersected, it means that the resulting type is a larger type, which is
  the sum of all the intersected types. For instance, in TypeScript,
  <code>A &amp; B</code> corresponds to a type that defines both <code>A</code> and <code>B</code> members.</p>
<p>Intersection types in Java cannot be implemented easily for many
  reasons. So, the practical choice being made here is to use union types
  in place of intersection types. In JSweet, <code>A &amp; B</code> is thus defined as
  <code>Union&lt;A, B&gt;</code>, which means that the programmer can access both <code>A</code> and
  <code>B</code> members by using the <code>jsweet.util.Lang.union</code> helper method. It is
  of course less convenient than the TypeScript version, but it is still
  type safe.</p>
<h2><a href="#semantics" id="semantics">Semantics</a></h2>
<p>Semantics designate how a given program behaves when executed. Although
  JSweet relies on the Java syntax, programs are transpiled to JavaScript
  and do not run in a JRE. As a consequence, the JavaScript semantics will
  impact the final semantics of a JSweet program compared to a Java
  program. In this section, we discuss the semantics by focusing on
  differences or commonalities between Java/JavaSript and JSweet.</p>
<h3><a href="#main-methods" id="main-methods">Main methods</a></h3>
<p>Main methods are the program execution entry points and will be invoked
  globally when a class containing a <code>main</code> method is evaluated. For
  instance:</p>
<pre><code class="java">public class C {
    private int n;
    public static C instance;
    public static void main(String[] args) {
        instance = new C();
        instance.n = 4;
    }
    public int getN() {
        return n;
    }
}
// when the source file containing C has been evaluated:
assert C.instance != null;
assert C.instance.getN() == 4;
</code></pre>
<p>The way main methods are globally invoked depends on how the program is
  packaged. See the appendixes for more details.</p>
<h3><a href="#initializers" id="initializers">Initializers</a></h3>
<p>Initializers behave like in Java.</p>
<p>For example:</p>
<pre><code class="java">public class C1 {
    int n;
    {
        n = 4;
    }
}
assert new C1().n == 4;
</code></pre>
<p>And similarly with static initializers:</p>
<pre><code class="java">public class C2 {
    static int n;
    static {
        n = 4;
    }
}
assert C2.n == 4;
</code></pre>
<p>While regular initializers are evaluated when the class is instantiated,
  static initializers are lazily evaluated in order to avoid
  forward-dependency issues, and mimic the Java behavior for initializers.
  With JSweet, it is possible for a programmer to define a static field or
  a static intializer that relies on a static field that has not yet been
  initialized.</p>
<p>More details on this behavior can be found in the appendixes.</p>
<h3><a href="#arrays-initialization-and-allocation" id="arrays-initialization-and-allocation">Arrays initialization and
  allocation</a></h3>
<p>Arrays can be used like in Java.</p>
<pre><code class="java">String[] strings = { &quot;a&quot;, &quot;b&quot;, &quot;c&quot; };
assert strings[1] == &quot;b&quot;;
</code></pre>
<p>When specifying dimensions, arrays are pre-allocated (like in Java), so
  that they are initialized with the right length, and with the right
  sub-arrays in case of multiple-dimensions arrays.</p>
<pre><code class="java">String[][] strings = new String[2][2];
assert strings.length == 2;
assert strings[0].length == 2;
strings[0][0] = &quot;a&quot;;
assert strings[0][0] == &quot;a&quot;;
</code></pre>
<p>The JavaScript API can be used on an array by casting to a
  <code>def.js.Array</code> with <code>jsweet.util.Lang.array</code>.</p>
<pre><code class="java">import static jsweet.util.Lang.array;
[...]
String[] strings = { &quot;a&quot;, &quot;b&quot;, &quot;c&quot; };
assert strings.length == 3;
array(strings).push(&quot;d&quot;);
assert strings.length == 4;
assert strings[3] == &quot;d&quot;;
</code></pre>
<p>In some cases it is preferable to use the <code>def.js.Array</code> class directly.</p>
<pre><code class="java">Array&lt;String&gt; strings = new Array&lt;String&gt;(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;);
// same as: Array&lt;String&gt; strings = array(new String[] { &quot;a&quot;, &quot;b&quot;, &quot;c&quot; });
// same as: Array&lt;String&gt; strings = new Array&lt;String&gt;(); strings.push(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;);
assert strings.length == 3;
strings.push(&quot;d&quot;);
assert strings.length == 4;
assert strings.$get(3) == &quot;d&quot;;
</code></pre>
<h3><a href="#asynchronous-programming" id="asynchronous-programming">Asynchronous programming</a></h3>
<p>JSweet supports advanced asynchronous programming beyond the basic
  callback concepts with the help of the ES2015+ Promise API.</p>
<h4><a href="#promises" id="promises">Promises</a></h4>
<p>It is very simple to define an asynchronous method by declaring a
  <code>Promise</code> return type. The following method’s <code>Promise</code> will be
  <em>fulfilled</em> when millis milliseconds elapsed.</p>
<pre><code class="java">Promise&lt;Void&gt; delay(int millis) {
  return new Promise&lt;Void&gt;((Consumer&lt;Void&gt; resolve, Consumer&lt;Object&gt; reject) -&gt; {
    setTimeout(resolve, millis);
  });
}
</code></pre>
<p>You can then chain synchronous and asynchronous actions to be executed
  once the promise is fulfilled.</p>
<pre><code class="java">delay(1000)
  // chain with a synchronous action with &quot;then&quot;. Here we just return a constant.
  .then(() -&gt; {
    System.out.println(&quot;wait complete&quot;);
    return 42;
  })
  // chain with an asynchronous action with &quot;thenAsync&quot;. Here it is implied that anotherAsyncAction(String) returns a Promise&lt;...&gt;
  .thenAsync((Integer result) -&gt; {
    System.out.println(&quot;previous task result: &quot; + result); // will print &quot;previous task result: 42&quot;

    return anotherAsyncAction(&quot;param&quot;);
  })
  // this chained action will be executed once anotherAsyncAction finishes its execution.
  .then((String result) -&gt; {

    System.out.println(&quot;anotherAsyncAction returned &quot; + result);
  })
  // catch errors during process using this method
  .Catch(error -&gt; {
    System.out.println(&quot;error is &quot; + error);
  });
</code></pre>
<p>This allows a totally type-safe and fluent asynchronous programming
  model.</p>
<h4><a href="#asyncawait" id="asyncawait">async/await</a></h4>
<p><code>Promise</code>s are really interesting to avoid callback but writing it still
  requires a lot of boilerplate code. It is better than pure callbacks but
  less readable and straightforward than linear programming. That’s where
  <code>async/await</code> comes to help.</p>
<p>With the <code>await</code> keyword, you can tell the runtime to wait for a
  <code>Promise</code> to be fulfilled without having to write a then method. The
  code after the <code>await</code> &quot;is&quot; the <code>then</code> part. The result is that you can
  write your asynchronous code with linear programming.</p>
<pre><code class="java">import static jsweet.util.Lang.await;

// wait for the Promise returned by the delay method to be fulfilled
await(delay(1000));

System.out.println(&quot;wait complete&quot;);
</code></pre>
<p>It goes the same for error handling. You can just use the plain old
  <code>try / catch</code> idiom to handle your exceptions.</p>
<pre><code class="java">import static jsweet.util.Lang.await;
import def.js.Error;

try {
  Integer promiseResult = await(getANumber());
  assert promiseResult == 42;
} catch(Error e) {
  System.err.println(&quot;something unexpected happened: &quot; + e);
}
</code></pre>
<p>You have to declare as <code>async</code> every asynchronous method / lambda (i.e.
  every method which would await something).</p>
<pre><code class="java">import static jsweet.util.Lang.await;
import static jsweet.util.Lang.async;
import static jsweet.util.Lang.function;

import jsweet.lang.Async;
import def.js.Function;

@Async
Promise&lt;Integer&gt; findAnswer() {
  await(delay(1000)); // won't compile if the enclosing method isn't @Async
  return asyncReturn(42); // converts to Promise
}

@Async
void askAnswerThenVerifyAndPrintIt() {

  try {

    Integer answer = await(findAnswer());

    // lambda expressions can be async
    Function verifyAnswerAsync = async(function(() -&gt; {
      return await(answerService.verifyAnswer(answer));
    }))

    Boolean verified = await(verifyAnswerAsync.$apply());

    if (!verified) {
      throw new Error(&quot;cannot verify this answer&quot;);
    }

    console.log(&quot;answer found: &quot; + answer);

  } catch (Error e) {
    console.error(e, &quot;asynchronous process failed&quot;);
  }
}
</code></pre>
<p>Sweet, isn’t it? ;)</p>
<h3><a href="#name-clashes" id="name-clashes">Name clashes</a></h3>
<p>On contrary to TypeScript/JavaScript, Java makes a fundamental
  difference between methods, fields, and packages. Java also support
  method overloading (methods having different signatures with the same
  name). In JavaScript, object variables and functions are stored within
  the same object map, which basically means that you cannot have the same
  key for several object members (this also explains that method
  overloading in the Java sense is not possible in JavaScript). Because of
  this, some Java code may contain name clashes when generated as is in
  TypeScript. JSweet will avoid name clashes automatically when possible,
  and will report sound errors in the other cases.</p>
<h4><a href="#methods-and-fields-names-clashes" id="methods-and-fields-names-clashes">Methods and fields names
  clashes</a></h4>
<p>JSweet performs a transformation to automatically allow methods and
  private fields to have the same name. On the other hand, methods and
  public fields of the same name are not allowed within the same class or
  within classes having a subclassing link.</p>
<p>To avoid programming mistakes due to this JavaScript behavior, JSweet
  adds a semantics check to detect duplicate names in classes (this also
  takes into account members defined in parent classes). As an example:</p>
<pre><code class="java">public class NameClashes {

    // error: field name clashes with existing method name
    public String a;

    // error: method name clashes with existing field name
    public void a() {
        return a;
    }

}
</code></pre>
<h4><a href="#method-overloading" id="method-overloading">Method overloading</a></h4>
<p>On contrary to TypeScript and JavaScript (but similarly to Java), it is
  possible in JSweet to have several methods with the same name but with
  different parameters (so-called overloads). We make a distinction
  between simple overloads and complex overloads. Simple overloading is
  the use of method overloading for defining optional parameters. JSweet
  allows this idiom under the condition that it corresponds to the
  following template:</p>
<pre><code class="java">String m(String s, double n) { return s + n; }
// valid overloading (JSweet transpiles to optional parameter)
String m(String s) { return m(s, 0); }
</code></pre>
<p>In that case, JSweet will generate JavaScript code with only one method
  having default values for the optional parameters, so that the behavior
  of the generated program corresponds to the original one. In this case:</p>
<pre><code class="java">function m(s, n = 0) { return s + n; }
</code></pre>
<p>If the programmer tries to use overloading differently, for example by
  defining two different implementations for the same method name, JSweet
  will fallback on a complex overload, which consists of generating a root
  implementation (the method that hold the more parameters) and one
  subsidiary implementation per overloading method (named with a suffix
  representing the method signature). The root implementation is generic
  and dispatches to other implementations by testing the values and types
  of the given parameters. For example:</p>
<pre><code class="java">String m(String s, double n) { return s + n; }
String m(String s) { return s; }
</code></pre>
<p>Generates the following (slightly simplified) JavaScript code:</p>
<pre><code class="java">function m(s, n) {
    if(typeof s === 'string' &amp;&amp; typeof n === 'number') {
        return s + n;
    } else if(typeof s === 'string' &amp;&amp; n === undefined) {
        return this.m$java_lang_String(s);
    } else {
        throw new Error(&quot;invalid overload&quot;);
    }
}

function m$java_lang_String(s) { return s; }
</code></pre>
<h4><a href="#local-variable-names" id="local-variable-names">Local variable names</a></h4>
<p>In TypeScript/JavaScript, local variables can clash with the use of a
  global method. For instance, using the <code>alert</code> global method from the
  DOM (<code>jsweet.dom.Globals.alert</code>) requires that no local variable hides
  it:</p>
<pre><code class="java">import static jsweet.dom.Globals.alert;

[...]

public void m1(boolean alert) {
    // JSweet compile error: name clash between parameter and method call
    alert(&quot;test&quot;);
}

public void m2() {
    // JSweet compile error: name clash between local variable and method call
    String alert = &quot;test&quot;;
    alert(alert);
}
</code></pre>
<p>Note that this problem also happens when using fully qualified names
  when calling the global methods (that is because the qualification gets
  erased in TypeScript/JavaScript). In any case, JSweet will report sound
  errors when such problems happen so that programmers can adjust local
  variable names to avoid clashes with globals.</p>
<h3><a href="#testing-the-type-of-an-object" id="testing-the-type-of-an-object">Testing the type of an object</a></h3>
<p>To test the type of a given object at runtime, one can use the
  <code>instanceof</code> Java operator, but also the <code>Object.getClass()</code> function.</p>
<h4><a href="#instanceof" id="instanceof"><code>instanceof</code></a></h4>
<p>The <code>instanceof</code> is the advised and preferred way to test types at
  runtime. JSweet will transpile to a regular <code>instanceof</code> or to a
  <code>typeof</code> operator depending on the tested type (it will fallback on
  <code>typeof</code> for <code>number</code>, <code>string</code>, and <code>boolean</code> core types).</p>
<p>Although not necessary, it is also possible to directly use the <code>typeof</code>
  operator from JSweet with the <code>jsweet.util.Lang.typeof</code> utility method.
  Here are some examples of valid type tests:</p>
<pre><code class="java">import static jsweet.util.Lang.typeof;
import static jsweet.util.Lang.equalsStrict;
[...]
Number n1 = 2;
Object n2 = 2;
int n3 = 2;
Object s = &quot;test&quot;;
MyClass c = new MyClass();

assert n1 instanceof Number; // transpiles to a typeof
assert n2 instanceof Number; // transpiles to a typeof
assert n2 instanceof Integer; // transpiles to a typeof
assert !(n2 instanceof String); // transpiles to a typeof
assert s instanceof String; // transpiles to a typeof
assert !(s instanceof Integer); // transpiles to a typeof
assert c instanceof MyClass;
assert typeof(n3) == &quot;number&quot;;
</code></pre>
<p>From JSweet version 1.1.0, the <code>instanceof</code> operator is also allowed on
  interfaces, because JSweet keeps track of all the implemented interfaces
  for all objects. This interface tracking is ensured through an
  additional hidden property in the objects called <code>__interfaces</code> and
  containing the names of all the interfaces implemented by the objects
  (either directly or through its class inheritance tree determined at
  compile time). So, in case the type argument of the <code>instanceof</code>
  operator is an interface, JSweet simply checks out if the object’s
  <code>__interfaces</code> field exists and contains the given interface. For
  example, this code is fully valid in JSweet when <code>Point</code> is an
  interface:</p>
<pre><code class="java">Point p1 = new Point() {{ x=1; y=1; }};
[...]
assert p1 instanceof Point
</code></pre>
<h4><a href="#objectgetclass-and-xclass" id="objectgetclass-and-xclass"><code>Object.getClass()</code> and
  <code>X.class</code></a></h4>
<p>In JSweet, using the <code>Object.getClass()</code> on any instance is possible. It
  will actually return the constructor function of the class. Using
  <code>X.class</code> will also return the constructor if <code>X</code> is a class. So the
  following assertion will hold in JSweet:</p>
<pre><code class="java">String s = &quot;abc&quot;;
assert String.class == s.getClass()
</code></pre>
<p>On a class, you can call the <code>getSimpleName()</code> or <code>getName()</code> functions.</p>
<pre><code class="java">String s = &quot;abc&quot;;
assert &quot;String&quot; == s.getClass().getSimpleName()
assert String.class.getSimpleName() == s.getClass().getSimpleName()
</code></pre>
<p>Note that <code>getSimpleName()</code> or <code>getName()</code> functions will also work on
  an interface. However, you have to be aware that <code>X.class</code> will be
  encoded in a string (holding the interface’s name) if <code>X</code> is is an
  interface.</p>
<h4><a href="#limitations-and-constraints" id="limitations-and-constraints">Limitations and constraints</a></h4>
<p>Since all numbers are mapped to JavaScript numbers, JSweet make no
  distinction between integers and floats for example. So,
  <code>n instanceof Integer</code> and <code>n instanceof Float</code> will always give the
  same result whatever the actual type of <code>n</code> is. The same limitation
  exists for strings and chars, which are not distinguishable at runtime,
  but also for functions that have the same number of parameters. For
  example, an instance of <code>IntFunction&lt;R&gt;</code> will not be distinguishable at
  runtime from a <code>Function&lt;String,R&gt;</code>.</p>
<p>These limitations have a direct impact on function overloading, since
  overloading uses the <code>instanceof</code> operator to decide which overload to
  be called.</p>
<p>Like it is usually the case when working in JavaScript, serialized
  objects must be properly &quot;revived&quot; with their actual classes so that the
  <code>instanceof</code> operator can work again. For example a point object created
  through <code>Point p = (Point)JSON.parse(&quot;{x:1,y:1}&quot;)</code> will not work with
  regard to the <code>instanceof</code> operator. In case you meet such a use case,
  you can contact us to get some useful JSweet code to properly revive
  object types.</p>
<h3><a href="#variable-scoping-in-lambda-expressions" id="variable-scoping-in-lambda-expressions">Variable scoping in
  lambda expressions</a></h3>
<p>JavaScript variable scoping is known to pose some problems to the
  programmers, because it is possible to change the reference to a
  variable from outside of a lambda that would use this variable. As a
  consequence, a JavaScript programmer cannot rely on a variable declared
  outside of a lambda scope, because when the lambda is executed, the
  variable may have been modified somewhere else in the program. For
  instance, the following program shows a typical case:</p>
<pre><code class="java">NodeList nodes = document.querySelectorAll(&quot;.control&quot;);
for (int i = 0; i &lt; nodes.length; i++) {
    HTMLElement element = (HTMLElement) nodes.$get(i); // final
    element.addEventListener(&quot;keyup&quot;, (evt) -&gt; {
        // this element variable will not change here
        element.classList.add(&quot;hit&quot;);
    });
}
</code></pre>
<p>In JavaScript (note that EcmaScript 6 fixes this issue), such a program
  would fail its purpose because the <code>element</code> variable used in the event
  listener is modified by the for loop and does not hold the expected
  value. In JSweet, such problems are dealt with similarly to final Java
  variables. In our example, the <code>element</code> variable is re-scoped in the
  lambda expression so that the enclosing loop does not change its value
  and so that the program behaves like in Java (as expected by most
  programmers).</p>
<h3><a href="#scope-of-this" id="scope-of-this">Scope of <em>this</em></a></h3>
<p>On contrary to JavaScript and similarly to Java, using a method as a
  lambda will prevent loosing the reference to <code>this</code>. For instance, in
  the <code>action</code> method of the following program, <code>this</code> holds the right
  value, even when <code>action</code> was called as a lambda in the <code>main</code> method.
  Although this seem logical to Java programmers, it is not a given that
  the JavaScript semantics ensures this behavior.</p>
<pre><code class="java">package example;
import static jsweet.dom.Globals.console;

public class Example {
    private int i = 8;
    public Runnable getAction() {
        return this::action;
    }
    public void action() {
        console.log(this.i); // this.i is 8
    }
    public static void main(String[] args) {
        Example instance = new Example();
        instance.getAction().run();
    }
}
</code></pre>
<p>It is important to stress that the <code>this</code> correct value is ensured
  thanks to a similar mechanism as the ES5 <code>bind</code> function. A consequence
  is that function references are wrapped in functions, which means that
  function pointers (such as <code>this::action</code>) create wrapping functions on
  the fly. It has side effects when manipulating function pointers, which
  are well described in this issue
  <a href="https://github.com/cincheo/jsweet/issues/65">https://github.com/cincheo/jsweet/issues/65</a>.</p>
<h2><a href="#packaging" id="packaging">Packaging</a></h2>
<p>Packaging is one of the complex point of JavaScript, especially when
  coming from Java. Complexity with JavaScript packaging boils down to the
  fact that JavaScript did not define any packaging natively. As a
  consequence, many <em>de facto</em> solutions and guidelines came up along the
  years, making the understanding of packaging uneasy for regular Java
  programmers. JSweet provides useful options and generates code in order
  to simplify the life of Java programmers by making the packaging issues
  much more transparent and as &quot;easy&quot; as in Java for most cases. In this
  section, we will describe and explain typical packaging scenarios.</p>
<h3><a href="#use-your-files-without-any-packaging" id="use-your-files-without-any-packaging">Use your files without any
  packaging</a></h3>
<p>The most common and simple case for running a program is just to include
  each generated file in an HTML page. This is the default mode when not
  precising any packaging options. For example, when your program defines
  two classes <code>x.y.z.A</code> and <code>x.y.z.B</code> in two separated files, you can use
  them as following:</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;target/js/x/y/z/A.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;target/js/x/y/z/B.js&quot;&gt;&lt;/script&gt;
[...]
&lt;!-- access a method later in the file --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;x.y.z.B.myMethod()&lt;/script&gt;
</code></pre>
<p>When doing so, programmers need to be extremely cautious to avoid
  forward static dependencies between the files. In other words, the <code>A</code>
  class cannot use anything from <code>B</code> in static fields, static
  initializers, or static imports, otherwise leading to runtime errors
  when trying to load the page. Additionally, the <code>A</code> class cannot extend
  the <code>B</code> class. These constraints come from JavaScript/TypeScript and
  have nothing to do with JSweet.</p>
<p>As you can imagine, running simple programs with this manual technique
  is fine, but can become really uncomfortable for developing complex
  applications. Complex applications most of the time bundle and/or
  package the program with appropriate tools in order to avoid having to
  manually handle dependencies between JavaScript files.</p>
<h3><a href="#creating-a-bundle-for-a-browser" id="creating-a-bundle-for-a-browser">Creating a bundle for a browser</a>
</h3>
<p>To avoid having to take care of the dependencies manually, programmers
  use bundling tools to bundle up their classes into a single file. Such a
  bundle is included in any web page using something like this:</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;target/js/bundle.js&quot;&gt;&lt;/script&gt;
[...]
&lt;!-- access a method later in the file --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;x.y.z.B.myMethod()&lt;/script&gt;
</code></pre>
<p>JSweet comes with such a bundling facility. To create a bundle file,
  just set to <code>true</code> the <code>bundle</code> option of JSweet. Note that you can also
  set to <code>true</code> the <code>declaration</code> option that will ask JSweet to generate
  the TypeScript definition file (<code>bundle.d.ts</code>). This file allows you to
  use/compile your JSweet program from TypeScript in a well-typed way.</p>
<p>The &quot;magic&quot; with JSweet bundling option is that it analyzes the
  dependencies in the source code and takes care of solving forward
  references when building the bundle. In particular, JSweet implements a
  lazy initialization mechanism for static fields and initializers in
  order to break down static forward references across the classes. There
  are no specific additional declarations to be made by the programmers to
  make it work (on contrary to TypeScript).</p>
<p>Note that there are still some minor limitations to it (when using inner
  and anonymous classes for instance), but these limitations will be
  rarely encountered and will be removed in future releases.</p>
<p>Note also that JSweet will raise an error if you specify the <code>module</code>
  option along with the <code>bundle</code> option.</p>
<h3><a href="#packaging-with-modules" id="packaging-with-modules">Packaging with modules</a></h3>
<p>First, let us start by explaining modules and focus on the difference
  between Java <em>packages</em> (or TypeScript <em>namespaces</em>) and <em>modules</em>. If
  you feel comfortable with the difference, just skip this section.</p>
<p>Packages and modules are two similar concepts but for different
  contexts. Java packages must be understood as compile-time <em>namespaces</em>.
  They allow a compile-time structuration of the programs through name
  paths, with implicit or explicit visibility rules. Packages have usually
  not much impact on how the program is actually bundled and deployed.</p>
<p>Modules must be understood as deployment / runtime &quot;bundles&quot;, which can
  be <code>required</code> by other modules. The closest concept to a module in the
  Java world would probably be an OSGi bundle. A module defines imported
  and exported elements so that they create a strong runtime structure
  that can be used for deploying software components independently and
  thus avoiding name clashes. For instance, with modules, two different
  libraries may define a <code>util.List</code> class and be actually running and
  used on the same VM with no naming issues (as long as the libraries are
  bundled in different modules).</p>
<p>Nowadays, a lot of libraries are packaged and accessible through
  modules. The standard way to use modules in a browser is the AMD, but in
  Node.js it is the commonjs module system.</p>
<h4><a href="#modules-in-jsweet" id="modules-in-jsweet">Modules in JSweet</a></h4>
<p>JSweet supports AMD, commonjs, and UMD module systems for packaging.
  JSweet defines a <code>module</code> option (value: <code>amd</code>, <code>commonjs</code> or <code>umd</code>).
  When specifying this option, JSweet automatically creates a default
  module organization following the simple rule: one file = one module.</p>
<p>For example, when packaged with the <code>module</code> option set to <code>commonjs</code>,
  one can write:</p>
<pre><code>&gt; node target/js/x/y/z/MyMainClass.js
</code></pre>
<p>Where <code>MyMainClass</code> contains a <code>main</code> method.</p>
<p>The module system will automatically take care of the references and
  require other modules when needed. Under the hood, JSweet analysis the
  Java import statements and transform them to <code>require</code> instructions.</p>
<p>Note: once the program has been compiled with the <code>module</code> option, it is
  easy to package it as a bundle using appropriate tools such as
  Browserify, which would give similar output as using the <code>bundle</code> option
  of JSweet. Note also that JSweet will raise an error when specifying
  both <code>module</code> and <code>bundle</code>, which are exclusive options.</p>
<h4><a href="#external-modules" id="external-modules">External modules</a></h4>
<p>When compiling JSweet programs with the <code>module</code> options, all external
  libraries and components must be required as external modules. JSweet
  can automatically require modules, simply by using the <code>@Module(name)</code>
  annotation. In JSweet, importing or using a class or a member annotated
  with <code>@Module(name)</code> will automatically require the corresponding module
  at runtime. Please not that it is true only when the code is generated
  with the <code>module</code> option. If the <code>module</code> option is off, the <code>@Module</code>
  annotations are ignored.</p>
<pre><code class="java">package def.jquery;
public final class Globals extends def.js.Object {
    ...
    @jsweet.lang.Module(&quot;jquery&quot;)
    native public static def.jquery.JQuery $(java.lang.String selector);
    ...
}
</code></pre>
<p>The above code shows an excerpt of the JSweet jQuery API. As we can
  notice, the <code>$</code> function is annotated with <code>@Module(&quot;jquery&quot;)</code>. As a
  consequence, any call to this function will trigger the require of the
  <code>jquery</code> module.</p>
<p>Note: the notion of manual require of a module may be available in
  future releases. However, automatic require is sufficient for most
  programmers and hides the complexity of having to require modules
  explicitly. It also brings the advantage of having the same code whether
  modules are used or not.</p>
<p>Troubleshooting: when a candy does not define properly the <code>@Module</code>
  annotation, it is possible to force the declaration within the comment
  of a special file called <code>module_defs.java</code>. For example, to force the
  <code>BABYLON</code> namespace of the Babylonjs candy to be exported as a
  <code>babylonjs</code> module, you can write the following file:</p>
<pre><code class="java">package myprogram;
// declare module &quot;babylonjs&quot; {
//    export = BABYLON;
// }
</code></pre>
<p>Note that a JSweet project can only define one <code>module_defs.java</code> file,
  which shall contain all the module declarations in a comment. Note also
  that it is a hack and the preferred method would be to contribute to the
  candy to fix the problem.</p>
<h3><a href="#root-packages" id="root-packages">Root packages</a></h3>
<p>Root packages are a way to tune the generated code so that JSweet
  packages are erased in the generated code and thus at runtime. To set a
  root package, just define a <code>package-info.java</code> file and use the <code>@Root</code>
  annotation on the package, as follows:</p>
<pre><code class="java">@Root
package a.b.c;
</code></pre>
<p>The above declaration means that the <code>c</code> package is a root package, i.e.
  it will be erased in the generated code, as well as all its parent
  packages. Thus, if <code>c</code> contains a package <code>d</code>, and a class <code>C</code>, these
  will be top-level objects at runtime. In other words, <code>a.b.c.d</code> becomes
  <code>d</code>, and <code>a.b.c.C</code> becomes <code>C</code>.</p>
<p>Note that since that packaged placed before the <code>@Root</code> package are
  erased, there cannot be any type defined before a <code>@Root</code> package. In
  the previous example, the <em>a</em> and <em>b</em> packages are necessarily empty
  packages.</p>
<h4><a href="#behavior-when-not-using-modules-default" id="behavior-when-not-using-modules-default">Behavior when not
  using modules (default)</a></h4>
<p>By default, root packages do not change the folder hierarchy of the
  generated files. For instance, the <code>a.b.c.C</code> class will still be
  generated in the <code>&lt;jsout&gt;/a/b/c/C.js</code> file (relatively to the <code>&lt;jsout&gt;</code>
  output directory). However, switching on the <code>noRootDirectories</code> option
  will remove the root directories so that the <code>a.b.c.C</code> class gets
  generated to the <code>&lt;jsout&gt;/C.js</code> file.</p>
<p>When not using modules (default), it is possible to have several <code>@Root</code>
  packages (but a <code>@Root</code> package can never contain another <code>@Root</code>
  package).</p>
<h4><a href="#behavior-when-using-modules" id="behavior-when-using-modules">Behavior when using modules</a></h4>
<p>When using modules (see the <em>module</em> option), only one <code>@Root</code> package
  is allowed, and when having one <code>@Root</code> package, no other package or
  type can be outside of the scope of that <code>@Root</code> package. The generated
  folder/file hierarchy then starts at the root package so that all the
  folders before it are actually erased.</p>
<h3><a href="#packaging-a-jsweet-jar-candy" id="packaging-a-jsweet-jar-candy">Packaging a JSweet jar (candy)</a></h3>
<p>A candy is a Maven artifact that contains everything required to easily
  access a JavaScript library from a JSweet client program. This library
  can be an external JavaScript library, a TypeScript program, or another
  JSweet program.</p>
<h4><a href="#anatomy-of-a-candy" id="anatomy-of-a-candy">Anatomy of a candy</a></h4>
<p>Like any Maven artifact, a candy has a group id, a artifact id (name),
  and a version. Besides, a typical candy should contain the following
  elements:</p>
<ol>
  <li>
    <p>The compiled Java files (*.class), so that your client program that
      uses the candy can compile.</p>
  </li>
  <li>
    <p>A <code>META-INF/candy-metadata.json</code> file that contains the expected
      target version of the transpiler (to be adapted to your target
      transpiler version).</p>
  </li>
  <li>
    <p>The program’s declarations in <code>d.ts</code> files, to be placed in the
      <code>src/typings</code> directory of the jar. Note that these definitions are
      not mandatory if you intend to use JSweet for generating TypeScript
      source code (<code>tsOnly</code> option). In that case, you may delegate the
      JavaScript generation to an external <code>tsc</code> compiler and access the
      TypeScript definitions from another source.</p>
  </li>
  <li>
    <p>Optionally, the JavaScript bundle of the library, which can in turn
      be automatically extracted and used by the JSweet client programs.
      JSweet expects the JavaScript to be packaged following the Webjars
      conventions: <a href="http://www.webjars.org/">http://www.webjars.org/</a>. When packaged this way, a
      JSweet transpiler using your candy will automatically extract the
      bundled JavaScript in a directory given by the <code>candiesJsOut</code> option
      (default: <code>js/candies</code>).</p>
  </li>
</ol>
<p>Here is an example of the <code>META-INF/candy-metadata.json</code> file:</p>
<pre><code class="java">{
   &quot;transpilerVersion&quot;: &quot;2.0.0&quot;
}
</code></pre>
<h4><a href="#how-to-create-a-candy-from-a-jsweet-program" id="how-to-create-a-candy-from-a-jsweet-program">How to
  create a candy from a JSweet program</a></h4>
<p>A typical use case when building applications with JSweet, is to share a
  common library or module between several other JSweet
  modules/applications. Note that since a JSweet candy is a regular Maven
  artifact, it can also be used by a regular Java program as long as it
  does not use any JavaScript APIs.</p>
<p>So, a typical example in a project is to have a <em>commons</em> library
  containing DTOs and common utility functions, which can be shared
  between a Web client written in JSweet (for example using the angular or
  knockout libraries) and a mobile client written also in JSweet (for
  example using the ionic library). The great news is that this <em>commons</em>
  library can also be used by the Java server (JEE, Spring, ...) as is,
  because the DTOs do not use any JavaScript, and that the compiled Java
  code packaged in the candy can run on a Java VM. This this extremely
  helpful, because it means that when you develop this project in your
  favorite IDE, you will be able to refactor some DTOs and common APIs,
  and it will directly impact your Java server code, your Web client code,
  and your mobile client code!</p>
<p>We provide a quick start project to help you starting with such a use
  case: <a
          href="https://github.com/cincheo/jsweet-candy-quickstart">https://github.com/cincheo/jsweet-candy-quickstart</a>
</p>
<h4><a href="#how-to-create-a-candy-for-an-existing-javascript-or-typescript-library"
       id="how-to-create-a-candy-for-an-existing-javascript-or-typescript-library">How to create a candy for an existing
  JavaScript or TypeScript library</a></h4>
<p>We provide a quick start project to help you starting with such a use
  case: <a href="https://github.com/cincheo/jsweet-candy-js-quickstart">https://github.com/cincheo/jsweet-candy-js-quickstart</a>
</p>
<h2><a href="#extending-the-transpiler" id="extending-the-transpiler">Extending the transpiler</a></h2>
<p>JSweet is an Open Transpiler from Java to TypeScript. It means that it
  provides ways for programmers to tune/extend how JSweet generates the
  intermediate TypeScript code. Tuning the transpiler is a solution to
  avoid repetitive tasks and automatize them.</p>
<p>For instance, say you have a legacy Java code that uses the Java API for
  serializing objects (<code>writeObject</code>/<code>readObject</code>). With JSweet, you can
  easily erase these methods from your program, so that the generated
  JavaScript code is free from any Java-specific serialization idioms.</p>
<p>As another example, say you have a Java legacy code base that uses a
  Java API, which is close to (but not exactly) a JavaScript API you want
  to use in your final JavaScript code. With JSweet, you can write an
  adapter that will automatically map all the Java calls to the
  corresponding JavaScript calls.</p>
<p>Last but not least, you can tune JSweet to take advantage of some
  specific APIs depending on the context. For instance, you may use ES6
  maps if you know that your targeted browser supports them, or just use
  an emulation or a simpler implementation in other cases. You may adapt
  the code to avoid using some canvas or WebGL primitives when knowing
  they are not well supported for a given mobile browser. An so on...
  Using an Open Transpiler such as JSweet has many practical applications,
  which you may or may not have to use, but in any case it is good to be
  aware of what is possible.</p>
<p>Tuning can be done declaratively (as opposed to programmatically) using
  annotations. Annotations can be added to the Java program (hard-coded),
  or they can be centralized in a unique configuration file so that they
  don’t even appear in the Java code (we call them soft annotations).
  Using annotations is quite simple and intuitive. However, when complex
  customization of the transpiler is required, it is most likely that
  annotations are not sufficient anymore. In that case, programmers shall
  use the JSweet extension API, which entails all the tuning that can be
  done with annotations, and much more. The extension API gives access to
  a Java AST (Abstract Syntax Tree) within the context of so-called
  <em>printer adapters</em>. Printer adapters follow a decorator pattern so that
  they can be chained to extend and/or override the way JSweet will print
  out the intermediate TypeScript code.</p>
<h3><a href="#core-annotations" id="core-annotations">Core annotations</a></h3>
<p>The package <code>jsweet.lang</code> defines various annotations that can be used
  to tune the way JSweet generates the intermediate TypeScript code. Here
  we explain these annotations and give examples on how to use them.</p>
<ul>
  <li>
    <p><code>@Erased</code>: This annotation type is used on elements that should be
      erased at generation time. It can be applied to any program element.
      If applied to a type, casts and constructor invocations will
      automatically be removed, potentially leading to program
      inconsistencies. If applied to a method, invocations will be
      removed, potentially leading to program inconsistency, especially
      when the invocation’s result is used in an expression. Because of
      potential inconsistencies, programmers should use this annotation
      carefully, and applied to unused elements (also erasing using
      elements).</p>
  </li>
  <li>
    <p><code>@Root</code>: This package annotation is used to specify a root package
      for the transpiled TypeScript/JavaScript, which means that all
      transpiled references in this package and subpackages will be
      relative to this root package. As an example, given the
      <code>org.mycompany.mylibrary</code> root package (annotated with <code>@Root</code>), the
      class <code>org.mycompany.mylibrary.MyClass</code> will actually correspond to
      <code>MyClass</code> in the JavaScript runtime. Similarly, the
      <code>org.mycompany.mylibrary.mypackage.MyClass</code> will transpile to
      <code>mypackage.MyClass</code>.</p>
  </li>
  <li>
    <p><code>@Name(String value)</code>: This annotation allows the definition of a
      name that will be used for the final generated code (rather than the
      Java name). It can be used when the name of an element is not a
      valid Java identifier. By convention, JSweet implements a built-in
      convention to save the use of @Name annotations: <code>Keyword</code> in Java
      transpiles to <code>keyword</code>, when <code>keyword</code> is a Java keyword (such as
      <code>catch</code>, <code>finally</code>, <code>int</code>, <code>long</code>, and so forth).</p>
  </li>
  <li>
    <p><code>@Replace(String value)</code>: This annotation allows the programmer to
      substitute a method body implementation by a TypeScript
      implementation. The annotation’s value contains TypeScript which is
      generated as is by the JSweet transpiler. The code will be checked
      by the TypeScript transpiler. The replacing code can contain
      variables substituted using a mustache-like convention
      (<code>{{variableName</code>}}). Here is the list of supported variables:</p>
    <ul>
      <li>
        <p><code>{{className}}</code>: the current class.</p>
      </li>
      <li>
        <p><code>{{methodName}}</code>: the current method name.</p>
      </li>
      <li>
        <p><code>{{body}}</code>: the body of the current method. A typical use of
          this variable is to wrap the original behavior in a lambda. For
          instance:
          <code>/* before code */ let _result = () =&gt; { {{body}} }(); /* after code */ return _result;</code>.</p>
      </li>
      <li>
        <p><code>{{baseIndent}}</code>: the indentation of the replaced method. Can be
          used to generate well-formatted code.</p>
      </li>
      <li>
        <p><code>{{indent}}</code>: substituted with an indentation. Can be used to
          generate well-formatted code.</p>
      </li>
    </ul>
  </li>
</ul>
<h4><a href="#example" id="example">Example</a></h4>
<p>The following example illustrates the use of the <code>@Erased</code> and
  <code>@Replace</code> annotations. Here, the <code>@Erased</code> annotation is used to remove
  the <code>readObject</code> method from the generated code, because it does not
  make sense in JavaScript (it is a Java-serialization specific method).
  The <code>@Replace</code> annotation allows defining a direct TypeScript/JavaScript
  implementation for the <code>searchAddress</code> method.</p>
<pre><code class="java">class Person {

  List&lt;String&gt; addresses = new ArrayList&lt;String&gt;();

  @Erased
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    [...]
  }

  @Replace(&quot;return this.addresses.filter(address =&gt; address.match(regex))[0]&quot;)
  public String searchAddress(String regex) {
          Optional&lt;String&gt; match = addresses.stream().filter(address -&gt; address.matches(regex)).findFirst();
          return match.isPresent()?match.get():null;
  }
}
</code></pre>
<p>Using JSweet annotations makes it possible to share classes between Java
  and JavaScript in a flexible way. Useless methods in JavaScript are
  erased, and some methods can have different implementations for Java and
  JavaScript.</p>
<h3><a href="#centralizing-annotations-in-jsweetconfigjson" id="centralizing-annotations-in-jsweetconfigjson">Centralizing
  annotations in <code>jsweetconfig.json</code></a></h3>
<p>JSweet supports the definition of annotations within a unique
  configuration file (<code>jsweetconfig.json</code>). There are many reasons why
  programmers would want to define annotations within that file instead of
  defining annotations in the Java source code.</p>
<ol>
  <li>
    <p>Annotations or annotation contents may differ depending on the
      context. It may be convenient to have different configuration files
      depending on the context. It is easier to switch a configuration
      file with another than having to change all the annotations in the
      program.</p>
  </li>
  <li>
    <p>Adding annotations to the Java program is convenient to tune the
      program locally (on a given element). However, in some cases,
      similar annotations should apply on a set of program elements, in
      order to automatize global tuning of the program. In that case, it
      is more convenient to install annotations by using an expression,
      that will match a set of program elements at once. This mechanism is
      similar to the <em>pointcut</em> mechanism that can be found in Aspect
      Oriented Software Design. It allows capturing a global modification
      in a declarative manner.</p>
  </li>
  <li>
    <p>Using annotations in the Java source code entails a reference to the
      JSweet API (the <code>jsweet.lang</code> package) that may be seen as an
      unwanted dependency for some programmers who want their Java code to
      remain as &quot;pure&quot; as possible.</p>
  </li>
</ol>
<p>The JSweet configuration file (<code>jsweetconf.json</code>) is a JSON file
  containing a list of configuration entries. Among the configuration
  entries, so-called global filters can be defined using the following
  structure:</p>
<pre><code class="java">&lt;annotation&gt;: {
      &quot;include&quot;: &lt;match_expressions&gt;,
      &quot;exclude&quot;: &lt;match_expressions&gt;
}
</code></pre>
<p>Where <code>&lt;annotation&gt;</code> is the annotation to be added, with potential
  parameters, and <code>include</code> and <code>exclude</code> are lists of match expressions.
  An element in the program will be annotated with the annotation, if its
  signature matches any of the expressions in the <code>include</code> list and does
  not match any the expressions in the <code>exclude</code> list.</p>
<p>A match expression is a sort of simplified regular expression,
  supporting the following wildcards:</p>
<ol>
  <li>
    <p><code>*</code> matches any token or token sub-part in the signature of the
      program element (a token is an identifier part of a signature, for
      instance <code>A.m(java.lang.String)</code> contains the tokens <code>A</code>, <code>m</code>, and
      <code>java.lang.String</code>).</p>
  </li>
  <li>
    <p><code>**</code> matches any list of tokens in signature of the program element.</p>
  </li>
  <li>
    <p><code>..</code> matches any list of tokens in signature of the program element.
      (same as <code>**</code>)</p>
  </li>
  <li>
    <p><code>!</code> negates the expression (first character only).</p>
  </li>
</ol>
<p>For example:</p>
<pre><code class="java">// all the elements and subelements (fields, methods, ...) in the x.y.z package
x.y.z.**

// all the methods in the x.y.z.A class
x.y.z.A.*(..)

// all the methods taking 2 arguments in the \texttt{x.y.z.A} class
x.y.z.A.*(*,*)

// all fields called aField in all the classes of the program
**.aField
</code></pre>
<p>Here is a more complete example with a full <code>jsweetconfig.json</code>
  configuration file.</p>
<pre><code class="java">{
  // all classes and packages in x.y.z will become top level
  &quot;@Root&quot;: {
    &quot;include&quot;: [ &quot;x.y.z&quot; ]
  },
  // do not generate any TypeScript code for Java-specific methods
  &quot;@Erased&quot;: {
    &quot;include&quot;: [ &quot;**.writeObject(..)&quot;, &quot;**.readObject(..)&quot;, &quot;**.hashCode(..)&quot; ]
  },
  // inject logging in all setters and getters of the x.y.z.A class
  &quot;@Replace('console.info('entering {{methodName}}'); let _result = () =&gt; { {{body}} }(); console.info('returning '+_result); return _result;')&quot;: {
    &quot;include&quot;: [ &quot;x.y.z.A.set*(*)&quot;, &quot;x.y.z.A.get*()&quot;, &quot;x.y.z.A.is*()&quot; ]
  }
}
</code></pre>
<p>Note that annotations are defined with simple names only. That’s because
  they are core JSweet annotations (defined in <code>jsweet.lang</code>). Non-core
  annotations can be added the same way, but the programmer must use fully
  qualified names.</p>
<h3><a href="#programmatic-tuning-with-adapters" id="programmatic-tuning-with-adapters">Programmatic tuning with
  adapters</a></h3>
<p>Declarative tuning through annotation rapidly hits limitations when
  tuning the generation for specific purposes (typically when supporting
  additional Java libraries). Hence, JSweet provides an API so that
  programmers can extend the way JSweet generates the intermediate
  TypeScript code. Writing such an adaptation program is similar to
  writing a regular Java program, except that it will apply to your
  programs to transform them. As such, it falls into the category of
  so-called meta-programs (i.e. programs use other programs as data).
  Since programmers may write extensions that leads to invalid code, that
  is where it becomes really handy to have an intermediate compilation
  layer. If the generated code is invalid, the TypeScript to JavaScript
  compilation will raise errors, thus allowing the programmer to fix the
  extension code.</p>
<h4><a href="#introducing-the-extension-api" id="introducing-the-extension-api">Introducing the extension API</a></h4>
<p>The extension API is available in the <code>org.jsweet.transpiler.extension</code>
  package. It is based on a factory pattern
  (<code>org.jsweet.transpiler.JSweetFactory</code>) that allows the programmer to
  adapt all the main components of the transpiler by subclassing them. In
  practice, most adaptations can be done by creating new printer adapters,
  as subclasses of <code>org.jsweet.transpiler.extension.PrinterAdapter</code>.
  Adapters are the core extension mechanism because they are chainable and
  can be composed (it is a sort of decorator pattern). JSweet uses default
  adapters in a default adaptation chain and tuning JSweet will then
  consist in adding new adapters to the chain.</p>
<p>An adapter will typically perform three kinds of operations to tune the
  generated code:</p>
<ol>
  <li>
    <p>Map Java types to TypeScript ones.</p>
  </li>
  <li>
    <p>Add annotations to the program either in a declarative way (with
      global filters) or in a programmatic way (with annotation managers).</p>
  </li>
  <li>
    <p>Override printing methods defined in <code>PrinterAdapter</code> in order to
      override the TypeScript core that is generated by default. Printing
      methods take program elements, which are based on the standard
      <code>javax.lang.model.element</code> API. It provides an extension of that API
      for program elements that are expressions and statements
      (<code>org.jsweet.transpiler.extension.model</code>).</p>
  </li>
</ol>
<p>The following template shows the typical sections when programming an
  adapter. First, an adapter must extend <code>PrinterAdapter</code> or any other
  adapter. It must define a constructor taking the parent adapter, which
  will be set by JSweet when inserting the adapter in the chain.</p>
<pre><code class="java">public class MyAdapter extends PrinterAdapter {

    public MyAdapter(PrinterAdapter parent) {
        super(parent);
        ...
</code></pre>
<p>In the constructor, an adapter typically maps Java types to TypeScript
  types.</p>
<pre><code class="java">        // will change the type in variable/parameters declarations
        addTypeMapping(&quot;AJavaType&quot;, &quot;ATypeScriptType&quot;);
        // you may want to erase type checking by mapping to 'any'
        addTypeMapping(&quot;AJavaType2&quot;, &quot;any&quot;);
        [...]
</code></pre>
<p>In the constructor, an adapter can also add annotations in a more
  flexible way than when using the <code>jsweetconfig.json</code> syntax.</p>
<pre><code class="java">        // add annotations dynamically to the AST, with global filters
        addAnnotation(&quot;jsweet.lang.Erased&quot;, //
                &quot;**.readObject(..)&quot;, //
                &quot;**.writeObject(..)&quot;, //
                &quot;**.hashCode(..)&quot;);
        // or with annotation managers (see the Javadoc and the example below)
        addAnnotationManager(new AnnotationManager() { ... });
    }
</code></pre>
<p>Most importantly, an adapter can override substitution methods for most
  important AST elements. By overriding these methods, an adapter will
  change the way JSweet generates the intermediate TypeScript code. To
  print out code, you can use the <code>print</code> method, which is defined in the
  root <code>PrinterAdapter</code> class. For example, the following code will
  replace all <code>new AJavaType(...)</code> with <code>new ATypeScriptType(...)</code>.</p>
<pre><code class="java">    @Override
    public boolean substituteNewClass(NewClassElement newClass) {
        // check if the 'new' applies to the right class
        if (&quot;AJavaType&quot;.equals(newClass.getTypeAsElement().toString())) {
            // the 'print' method will generate intermediate TypeScript code
            print(&quot;new ATypeScriptType(&quot;)
                    .printArgList(newClass.getArguments()).print(&quot;)&quot;);
            // once some code has been printed, you should return true to break
            // the adapter chain, so your code will replace the default one
            return true;
        }
        // if not substituted, delegate to the adapter chain
        return super.substituteNewClass(newClass);
    }
</code></pre>
<p>Most useful substitution method remains invocation substitution, which
  is typically used to map a Java API to a similar JavaScript API.</p>
<pre><code class="java">    @Override
    public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
        // substitute potential method invocation here
        [...]
        // delegate to the adapter chain
        return super.substituteMethodInvocation(invocation);
    }
}
</code></pre>
<p>Note also a special method to insert code after a Java type has been
  printed out:</p>
<pre><code class="java">    @Override
    public void afterType(TypeElement type) {
        super.afterType(type);
        // insert whatever TypeScript you need here
        [...]
    }
</code></pre>
<p>There are many applications to adapters (see the examples below).
  Besides tuning the code generation and supporting Java APIs at
  compile-time, adapters can also be used to raise errors when the
  compiled code does not conform to expected standards depending on the
  target context. Another very useful use case it to allow the generation
  of proxies. For instance one can write an adapter that will generate
  JavaScript stubs to invoke Java services deployed with JAX-RS.</p>
<h4><a href="#installing-and-activating-adapters" id="installing-and-activating-adapters">Installing and activating
  adapters</a></h4>
<p>Once you have written an adapter, you need to compile it and add it to
  the adapter chain. The simplest way to do it with JSweet is to put it in
  the <code>jsweet_extension</code> directory that you need to create at the root of
  your project JSweet. In that directory, you can directly add Java source
  files for adapters, that will be compiled by JSweet on the fly. For
  instance, you may add two custom adapters <code>CustomAdapter1.java</code> and
  <code>CustomAdapter2.java</code> in <code>jsweet_extension/com/mycompany/</code>.</p>
<p>Then, in order to activate that adapter, you just need to add the
  <code>jsweetconfig.json</code> file at the root of the project and define the
  <code>adapters</code> configuration option, like this:</p>
<pre><code class="java">{
  // JSweet will add the declared adapters at the beginning of the default
  // chain... you can add as many adapters as you need
  adapters: [ &quot;com.mycompany.CustomAdapter1&quot;, &quot;com.mycompany.CustomAdapter2&quot; ]
}
</code></pre>
<h4><a href="#hello-world-adapter" id="hello-world-adapter">Hello world adapter</a></h4>
<p>Here, we will step through how to tune the JSweet generation to generate
  strings in place of dates when finding <code>java.util.Date</code> types in the
  Java program.</p>
<p>First, create the <code>HelloWorldAdapter.java</code> file in the
  <code>jsweet_extension</code> directory at the root of your project. Copy and paste
  the following code in that file:</p>
<pre><code class="java">import org.jsweet.transpiler.extension.PrinterAdapter;
public class HelloWorldAdapter extends PrinterAdapter {
    public HelloWorldAdapter(PrinterAdapter parent) {
        super(parent);
        addTypeMapping(java.util.Date.class.getName(), &quot;string&quot;);
    }
}
</code></pre>
<p>Second, in the project’s root directory, create the <code>jsweetconfig.json</code>
  file with the following configuration:</p>
<pre><code class="java">{
  adapters: [ &quot;HelloWorldAdapter&quot; ]
}
</code></pre>
<p>Done. Now you can just try this extension on the following simple Java
  DTO:</p>
<pre><code class="java">package source.extension;
import java.util.Date;
/**
 * A Hello World DTO.
 *
 * @author Renaud Pawlak
 */
public class HelloWorldDto {
    private Date date;
    /**
     * Gets the date.
     */
    public Date getDate() {
        return date;
    }
    /**
     * Sets the date.
     */
    public void setDate(Date date) {
        this.date = date;
    }
}
</code></pre>
<p>The generated code should look like:</p>
<pre><code class="java">/* Generated from Java with JSweet 2.XXX - http://www.jsweet.org */
namespace source.extension {
    /**
     * A Hello World DTO.
     *
     * @author Renaud Pawlak
     * @class
     */
    export class HelloWorldDto {
        /*private*/ date : string;
        public constructor() {
            this.date = null;
        }
        /**
         * Gets the date.
         * @return {string}
         */
        public getDate() : string {
            return this.date;
        }
        /**
         * Sets the date.
         * @param {string} date
         */
        public setDate(date : string) {
            this.date = date;
        }
    }
    HelloWorldDto[&quot;__class&quot;] = &quot;source.extension.HelloWorldDto&quot;;
}
</code></pre>
<p>Note that all the date types have been translated to strings as
  expected. By the way, note also the JSDoc support, which makes JSweet a
  powerful tool to create well-documented JavaScript APIs from Java (doc
  comments are also tunable in adapters!).</p>
<h3><a href="#extension-examples" id="extension-examples">Extension examples</a></h3>
<p>The following sections illustrate the use of JSweet adapters with 5
  real-life examples. Most of these adapters are built-in with JSweet (in
  the <code>org.jsweet.transpiler.extension</code> package) and can just be activated
  by adding them to the adapter chain as explained above. If you want to
  modify the adapters, just copy-paste the code in the <code>jsweet_extension</code>
  directory and change the names.</p>
<h4><a href="#example-1-an-adapter-to-rename-private-fields" id="example-1-an-adapter-to-rename-private-fields">Example
  1: an adapter to rename private fields</a></h4>
<p>This simple adapter renames non-public members by adding two underscores
  as a prefix. Note that this could be dangerous to use for protected
  fields if wanting to access them from subclasses declared in other
  JSweet projects. So you may want to use carefully or to modify the code
  for your own needs.</p>
<p>This adapter is a good example for demonstrating how to use annotation
  managers. Annotation managers are used to add (soft) annotations to
  program elements driven by some Java code (programmatically). Annotation
  managers are added to the context and will be chained to other existing
  annotation managers (potentially added by other adapters). An annotation
  manager must implement the <code>manageAnnotation</code> method, that will tell if
  a given annotation should be added, removed, or left unchanged on a
  given element. If the annotation has parameters, an annotation manager
  shall implement the <code>getAnnotationValue</code> in order to specify the values.</p>
<p>In this example, the annotation manager adds the <code>@jsweet.lang.Name</code>
  annotation to all non-public elements in order to rename them and add
  the underscores to the initial name.</p>
<pre><code class="java">package org.jsweet.transpiler.extension;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import org.jsweet.transpiler.util.Util;

public class AddPrefixToNonPublicMembersAdapter extends PrinterAdapter {

    public AddPrefixToNonPublicMembersAdapter(PrinterAdapter parentAdapter) {
        super(parentAdapter);
        // add a custom annotation manager to the chain
        addAnnotationManager(new AnnotationManager() {

            @Override
            public Action manageAnnotation(Element element, String annotationType) {
                // add the @Name annotation to non-public elements
                return &quot;jsweet.lang.Name&quot;.equals(annotationType)
                        &amp;&amp; isNonPublicMember(element) ? Action.ADD : Action.VOID;
            }

            @Override
            public &lt;T&gt; T getAnnotationValue(Element element,
                    String annotationType, String propertyName,
                    Class&lt;T&gt; propertyClass, T defaultValue) {
                // set the name of the added @Name annotation (value)
                if (&quot;jsweet.lang.Name&quot;.equals(annotationType) &amp;&amp; isNonPublicMember(element)) {
                    return propertyClass.cast(&quot;__&quot; + element.getSimpleName());
                } else {
                    return null;
                }
            }

            private boolean isNonPublicMember(Element element) {
                return (element instanceof VariableElement || element instanceof ExecutableElement)
                        &amp;&amp; element.getEnclosingElement() instanceof TypeElement
                        &amp;&amp; !element.getModifiers().contains(Modifier.PUBLIC)
                        &amp;&amp; Util.isSourceElement(element);
            }
        });
    }
}
</code></pre>
<h4><a href="#example-2-an-adapter-to-use-es6-maps" id="example-2-an-adapter-to-use-es6-maps">Example 2: an adapter to
  use ES6 Maps</a></h4>
<p>JSweet default implementation of maps behaves as follows:</p>
<ul>
  <li>
    <p>If the key type is a string, the map is transpiled to a regular
      JavaScript object, where property names will be the keys.</p>
  </li>
  <li>
    <p>If the key type is an object (any other than a string), the map is
      transpiled as a list of entries. The implementation is quite
      inefficient because finding a key requires iterating over the
      entries to find the right entry key.</p>
  </li>
</ul>
<p>In some contexts, you may want to get more efficient map
  implementations. If you target modern browsers (or expect to have the
  appropriate polyfill available), you can simply use the <code>Map</code> object,
  which was standardized with ES6. Doing so requires an adapter that
  performs the following actions:</p>
<ul>
  <li>
    <p>Erase the Java <code>Map</code> type and replace it with the JavaScript <code>Map</code>
      type, or actually the <code>any</code> type, since you may want to keep the
      <code>Object</code> implementation when keys are strings.</p>
  </li>
  <li>
    <p>Substitute the construction of a map with the corresponding
      JavaScript construction.</p>
  </li>
  <li>
    <p>Substitute the invocations on Java maps with the corresponding
      JavaScript invocations.</p>
  </li>
</ul>
<p>Note that the following adapter is a partial implementation that shall
  be extended to support more cases and adapted to your own requirements.
  Additionally, this implementation generates untyped JavaScript in order
  to avoid having to have the ES6 API in the compilation path.</p>
<pre><code class="java">package org.jsweet.transpiler.extension;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.TreeMap;
import javax.lang.model.element.Element;
import org.jsweet.transpiler.model.MethodInvocationElement;
import org.jsweet.transpiler.model.NewClassElement;

public class MapAdapter extends PrinterAdapter {

    // all the Java types that will be translated to ES6 maps
    static String[] mapTypes = {
        Map.class.getName(), HashMap.class.getName(),
        TreeMap.class.getName(), Hashtable.class.getName() };

    public MapAdapter(PrinterAdapter parent) {
        super(parent);
        // rewrite all Java map and compatible map implementations types
        // note that we rewrite to 'any' because we don't want to require the
        // ES6 API to compile (all subsequent accesses will be untyped)
        for (String mapType : mapTypes) {
            addTypeMapping(mapType, &quot;any&quot;);
        }
    }

    @Override
    public boolean substituteNewClass(NewClassElement newClass) {
        String className = newClass.getTypeAsElement().toString();
        // map the map constructor to the global 'Map' variable (untyped access)
        if (Arrays.binarySearch(mapTypes, className) &gt;= 0) {
            // this access is browser/node-compatible
            print(&quot;new (typeof window == 'undefined'?global:window)['Map'](&quot;)
                    .printArgList(newClass.getArguments()).print(&quot;)&quot;);
            return true;
        }
        // delegate to the adapter chain
        return super.substituteNewClass(newClass);
    }

    @Override
    public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
        if (invocation.getTargetExpression() != null) {
            Element targetType = invocation.getTargetExpression().getTypeAsElement();
            if (Arrays.binarySearch(mapTypes, targetType.toString()) &gt;= 0) {
                // Java Map methods are mapped to their JavaScript equivalent
                switch (invocation.getMethodName()) {
                case &quot;put&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression()).print(&quot;.set(&quot;)
                            .printArgList(invocation.getArguments())
                            .print(&quot;)&quot;);
                    return true;
                // although 'get' has the same name, we still rewrite it in case
                // another extension would provide it's own implementation
                case &quot;get&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression()).print(&quot;.get(&quot;)
                            .printArgList(invocation.getArguments())
                            .print(&quot;)&quot;);
                    return true;
                case &quot;containsKey&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression()).print(&quot;.has(&quot;)
                            .printArgList(invocation.getArguments())
                            .print(&quot;)&quot;);
                    return true;
                // we use the ES6 'Array.from' method in an untyped way to
                // transform the iterator in an array
                case &quot;keySet&quot;:
                    printMacroName(invocation.getMethodName());
                    print(&quot;(&lt;any&gt;Array).from(&quot;)
                            .print(invocation.getTargetExpression()).print(&quot;.keys())&quot;);
                    return true;
                case &quot;values&quot;:
                    printMacroName(invocation.getMethodName());
                    print(&quot;(&lt;any&gt;Array).from(&quot;)
                            .print(invocation.getTargetExpression()).print(&quot;.values())&quot;);
                    return true;
                // in ES6 maps, 'size' is a property, not a method
                case &quot;size&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression()).print(&quot;.size&quot;);
                    return true;
                }
            }

        }
        // delegate to the adapter chain
        return super.substituteMethodInvocation(invocation);
    }
}
</code></pre>
<h4><a href="#example-3-an-adapter-to-support-java-bigdecimal" id="example-3-an-adapter-to-support-java-bigdecimal">Example
  3: an adapter to support Java BigDecimal</a></h4>
<p>Java’s BigDecimal API is a really good API to avoid typical floating
  point precision issues, especially when working on currencies. This API
  is not available by default in JavaScript and would be quite difficult
  to emulate. GWT provides an emulation of the BigDecimal API, which is
  implemented with Java, but JSweet proposes another way to do it, which
  consists of mapping the BigDecimal API to an existing JavaScript API
  called Big.js. Mapping to an existing JS library has several advantages
  compared to emulating an API:</p>
<ol>
  <li>
    <p>The implementation is already available in JavaScript, so there is
      less work emulating the Java library.</p>
  </li>
  <li>
    <p>The implementation is pure JavaScript and is made specifically for
      JavaScript. So we can assume that will be more efficient that an
      emulation, and even more portable.</p>
  </li>
  <li>
    <p>The generated code is free from any Java APIs, which makes it more
      JavaScript friendly and more inter-operable with existing JavaScript
      programs (legacy JavaScript clearly uses Big.js objects, and if not,
      we can decide to tune the adapter).</p>
  </li>
</ol>
<p>The following code shows the adapter that tunes the JavaScript
  generation to map the Java’s BigDecimal API to the Big JavaScript
  library. This extension requires the big.js candy to be available in the
  JSweet classpath: https://github.com/jsweet-candies/candy-bigjs.</p>
<pre><code class="java">package org.jsweet.transpiler.extension;

import java.math.BigDecimal;
import javax.lang.model.element.Element;
import org.jsweet.transpiler.extension.PrinterAdapter;
import org.jsweet.transpiler.model.MethodInvocationElement;
import org.jsweet.transpiler.model.NewClassElement;

public class BigDecimalAdapter extends PrinterAdapter {

    public BigDecimalAdapter(PrinterAdapter parent) {
        super(parent);
        // all BigDecimal types are mapped to Big
        addTypeMapping(BigDecimal.class.getName(), &quot;Big&quot;);
    }

    @Override
    public boolean substituteNewClass(NewClassElement newClass) {
        String className = newClass.getTypeAsElement().toString();
        // map the BigDecimal constructors
        if (BigDecimal.class.getName().equals(className)) {
            print(&quot;new Big(&quot;).printArgList(newClass.getArguments()).print(&quot;)&quot;);
            return true;
        }
        // delegate to the adapter chain
        return super.substituteNewClass(newClass);
    }

    @Override
    public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
        if (invocation.getTargetExpression() != null) {
            Element targetType = invocation.getTargetExpression().getTypeAsElement();
            if (BigDecimal.class.getName().equals(targetType.toString())) {
                // BigDecimal methods are mapped to their Big.js equivalent
                switch (invocation.getMethodName()) {
                case &quot;multiply&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression())
                            .print(&quot;.times(&quot;).printArgList(invocation.getArguments())
                            .print(&quot;)&quot;);
                    return true;
                case &quot;add&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression())
                            .print(&quot;.plus(&quot;).printArgList(invocation.getArguments())
                            .print(&quot;)&quot;);
                    return true;
                case &quot;scale&quot;:
                    printMacroName(invocation.getMethodName());
                    // we assume that we always have a scale of 2, which is a
                    // good default if we deal with currencies...
                    // to be changed/implemented further
                    print(&quot;2&quot;);
                    return true;
                case &quot;setScale&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression())
                            .print(&quot;.round(&quot;).print(invocation.getArguments().get(0))
                            .print(&quot;)&quot;);
                    return true;
                case &quot;compareTo&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression()).print(&quot;.cmp(&quot;)
                            .print(invocation.getArguments().get(0))
                            .print(&quot;)&quot;);
                    return true;
                case &quot;equals&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression()).print(&quot;.eq(&quot;)
                            .print(invocation.getArguments().get(0))
                            .print(&quot;)&quot;);
                    return true;
                }
            }

        }
        // delegate to the adapter chain
        return super.substituteMethodInvocation(invocation);
    }
}
</code></pre>
<h4><a href="#example-4-an-adapter-to-map-enums-to-strings" id="example-4-an-adapter-to-map-enums-to-strings">Example 4:
  an adapter to map enums to strings</a></h4>
<p>This example tunes the JavaScript generation to remove enums and replace
  them with strings. It only applies to enums that are annotated with
  @<code>jsweet.lang.StringType</code>.</p>
<p>For instance: <code>@StringType enum MyEnum { A, B, C }</code> will be erased and
  all subsequent accesses to the enum constants will be mapped to simple
  strings (<code>MyEnum.A =&gt; &quot;A&quot;, MyEnum.B =&gt; &quot;B&quot;, MyEnum.C =&gt; &quot;C&quot;</code>).
  Typically, a method declaration such as <code>void m(MyEnum e) {...}</code> will be
  printed as <code>void m(e : string) {...}</code>. And of course, the invocation
  <code>xxx.m(MyEnum.A)</code> will be printed as <code>xxx.m(&quot;A&quot;)</code>.</p>
<pre><code class="java">package org.jsweet.transpiler.extension;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import org.jsweet.JSweetConfig;
import org.jsweet.transpiler.model.CaseElement;
import org.jsweet.transpiler.model.ExtendedElement;
import org.jsweet.transpiler.model.MethodInvocationElement;
import org.jsweet.transpiler.model.VariableAccessElement;

public class StringEnumAdapter extends PrinterAdapter {

    private boolean isStringEnum(Element element) {
        // note: this function could be improved to exclude enums that have
        // fields or methods other than the enum constants
        return element.getKind() == ElementKind.ENUM
                &amp;&amp; hasAnnotationType(element, JSweetConfig.ANNOTATION_STRING_TYPE);
    }

    public StringEnumAdapter(PrinterAdapter parent) {
        super(parent);
        // eligible enums will be translated to string in JS
        addTypeMapping((typeTree, name) -&gt;
                isStringEnum(typeTree.getTypeAsElement()) ? &quot;string&quot; : null);

        // ignore enum declarations with a programmatic annotation manager
        addAnnotationManager(new AnnotationManager() {
            @Override
            public Action manageAnnotation(Element element, String annotationType) {
                // add the @Erased annotation to string enums
                return JSweetConfig.ANNOTATION_ERASED.equals(annotationType)
                        &amp;&amp; isStringEnum(element) ? Action.ADD : Action.VOID;
            }
        });

    }

    @Override
    public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
        if (invocation.getTargetExpression() != null) {
            Element targetType = invocation.getTargetExpression().getTypeAsElement();
            // enum API must be erased and use plain strings instead
            if (isStringEnum(targetType)) {
                switch (invocation.getMethodName()) {
                case &quot;name&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getTargetExpression());
                    return true;
                case &quot;valueOf&quot;:
                    printMacroName(invocation.getMethodName());
                    print(invocation.getArgument(0));
                    return true;
                case &quot;equals&quot;:
                    printMacroName(invocation.getMethodName());
                    print(&quot;(&quot;).print(invocation.getTargetExpression()).print(&quot; == &quot;)
                            .print(invocation.getArguments().get(0)).print(&quot;)&quot;);
                    return true;
                }
            }
        }
        return super.substituteMethodInvocation(invocation);
    }

    @Override
    public boolean substituteVariableAccess(VariableAccessElement variableAccess) {
        // accessing an enum field is replaced by a simple string value
        // (MyEnum.A =&gt; &quot;A&quot;)
        if (isStringEnum(variableAccess.getTargetElement())) {
            print(&quot;\&quot;&quot; + variableAccess.getVariableName() + &quot;\&quot;&quot;);
            return true;
        }
        return super.substituteVariableAccess(variableAccess);
    }

    @Override
    public boolean substituteCaseStatementPattern(CaseElement caseStatement,
            ExtendedElement pattern) {
        // map enums to strings in case statements
        if (isStringEnum(pattern.getTypeAsElement())) {
            print(&quot;\&quot;&quot; + pattern + &quot;\&quot;&quot;);
            return true;
        }
        return super.substituteCaseStatementPattern(caseStatement, pattern);
    }
}
</code></pre>
<h4><a href="#example-5-an-adapter-to-generate-javascript-jax-rs-proxiesstubs"
       id="example-5-an-adapter-to-generate-javascript-jax-rs-proxiesstubs">Example 5: an adapter to generate JavaScript
  JAX-RS proxies/stubs</a></h4>
<p>It is a common use case to implement a WEB or mobile application with
  Java on the server and JavaScript on the client. Typically, a
  JEE/Jackson server will expose a REST API through the JAX-RS
  specifications, and the HTML5 client will have to invoke this API using
  <code>XMLHttpRequest</code> or higher-level libraries such as jQuery. However,
  manually coding the HTTP invocations comes with many drawbacks:</p>
<ul>
  <li>
    <p>It requires the use of specific APIs (XHR, jQuery), which is not
      easy for all programmers and may imply different programming styles
      that would make the code more difficult to read and maintain.</p>
  </li>
  <li>
    <p>It requires the programmers to handle manually the
      serialization/deserialization, while it can be done automatically
      trough the use of annotation-driven generative programming.</p>
  </li>
  <li>
    <p>It leads to unchecked invocations, which means that it is easy for
      the programmer to make an error in the name of the
      service/path/parameters, and in the expected DTOs. No refactoring
      and content-assist is available.</p>
  </li>
</ul>
<p>With a JSweet adapter, using the <code>afterType</code> method it is easy to
  automatically generate a TypeScript stub that is well-typed and performs
  the required operations for invoking the REST service, simply by using
  the service API and the JAX-RS annotations. This type of tooling falls
  in the category of so-called Generative Programming.</p>
<p>The following code is only a partial implementation of an adapter that
  would introspect the program’s model and generate the appropriate stubs
  in TypeScript. It is not meant to be operational, so you need to modify
  to fit your own use case.</p>
<pre><code class="java">import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;

class JaxRSStubAdapter extends PrinterAdapter {

    public JaxRSStubAdapter(PrinterAdapter parent) {
        super(parent);
        // erase service classes (server-side only)
        addAnnotationManager(new AnnotationManager() {
            @Override
            public Action manageAnnotation(Element element, String annotationType) {
                return JSweetConfig.ANNOTATION_ERASED.equals(annotationType)
                        &amp;&amp; hasAnnotationType(element, Path.class.getName()) ?
                        Action.ADD : Action.VOID;
            }
        });
    }

    @Override
    public void afterType(TypeElement type) {
        super.afterType(type);
        if (hasAnnotationType(type, Path.class.getName())) {
            // actually generates the JAX-RS stub
            println().printIndent();
            print(&quot;class &quot;).print(type.getSimpleName()).print(&quot; {&quot;);
            startIndent();
            String typePathAnnotationValue = getAnnotationValue(type,
                    Path.class.getName(), String.class, null);
            String typePath = typePathAnnotationValue != null ? typePathAnnotationValue : &quot;&quot;;
            for (Element e : type.getEnclosedElements()) {
                if (e instanceof ExecutableElement
                        &amp;&amp; hasAnnotationType(e, GET.class.getName(),
                                PUT.class.getName(), Path.class.getName())) {
                    ExecutableElement method = (ExecutableElement) e;
                    println().printIndent().print(method.getSimpleName().toString())
                            .print(&quot;(&quot;);
                    for (VariableElement parameter : method.getParameters()) {
                        print(parameter.getSimpleName())
                                .print(&quot; : &quot;).print(getMappedType(parameter.asType()))
                                .print(&quot;, &quot;);
                    }
                    print(&quot;successHandler : (&quot;);
                    if (method.getReturnType().getKind() != TypeKind.VOID) {
                        print(&quot;result : &quot;).print(getMappedType(method.getReturnType()));
                    }
                    print(&quot;) =&gt; void, errorHandler?: () =&gt; void&quot;).print(&quot;) : void&quot;);
                    print(&quot; {&quot;).println().startIndent().printIndent();
                    String pathAnnotationValue = getAnnotationValue(e, Path.class.getName(),
                            String.class, null);
                    String path = pathAnnotationValue != null ? pathAnnotationValue : &quot;&quot;;
                    String httpMethod = &quot;POST&quot;;
                    if(hasAnnotationType(e, GET.class.getName())) {
                        httpMethod = &quot;GET&quot;;
                    }
                    if(hasAnnotationType(e, POST.class.getName())) {
                        httpMethod = &quot;POST&quot;;
                    }
                    String[] consumes = getAnnotationValue(e, &quot;javax.ws.rs.Consumes&quot;,
                            String[].class, null);
                    if (consumes == null) {
                        consumes = new String[] { &quot;application/json&quot; };
                    }
                    // actual code to be done
                    print(&quot;// modify JaxRSStubAdapter to generate an HTTP invocation here&quot;)
                            .println().printIndent();
                    print(&quot;//   - httpMethod: &quot; + httpMethod).println().printIndent();
                    print(&quot;//   - path: &quot; + typePath + path).println().printIndent();
                    print(&quot;//   - consumes: &quot; + consumes[0]);
                    println().endIndent().printIndent().print(&quot;}&quot;);
                }
            }
            println().endIndent().printIndent().print(&quot;}&quot;);
        }
    }
}
</code></pre>
<p>NOTE: for compilation, you need the JAX-RS API in your classpath.</p>
<pre><code>&lt;dependency&gt;
    &lt;groupId&gt;javax.ws.rs&lt;/groupId&gt;
    &lt;artifactId&gt;javax.ws.rs-api&lt;/artifactId&gt;
    &lt;version&gt;2.1-m07&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<p>As an example, let us consider the following JAX-RS service.</p>
<pre><code class="java">@Path(&quot;/hello&quot;)
public class HelloWorldService {
    @GET
    @Path(&quot;/{param}&quot;)
    @Produces(MediaType.APPLICATION_JSON)
    public HelloWorldDto getMsg(@PathParam(&quot;param&quot;) String msg) {
        String output = &quot;service says : &quot; + msg;
        return new HelloWorldDto(output);
    }
}
</code></pre>
<p>Using the following DTO:</p>
<pre><code class="java">public class HelloWorldDto {
    private String msg;
    public HelloWorldDto(String msg) {
        super();
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
</code></pre>
<p>If you apply JSweet enhanced with <code>JaxRSStubAdapter</code>, you will get the
  following TypeScript code (and corresponding JavaScript):</p>
<pre><code class="java">export class HelloWorldDto {
    /*private*/ msg : string;
    public constructor(msg : string) {
        this.msg = msg;
    }
    public getMsg() : string {
        return this.msg;
    }
    public setMsg(msg : string) {
        this.msg = msg;
    }
}
HelloWorldDto[&quot;__class&quot;] = &quot;HelloWorldDto&quot;;

class HelloWorldService {
    getMsg(msg : string,
            successHandler : (result : HelloWorldDto) =&gt; void,
            errorHandler?: () =&gt; void) : void {
        // modify JaxRSStubAdapter to generate an HTTP invocation here
        //   - httpMethod: GET
        //   - path: /hello/{param}
        //   - consumes: application/json
    }
}
</code></pre>
<p>So, all you need to do is to modify the code of the adapter to generate
  the actual invocation code in place of the comment. Once it is done, you
  can use the generated JavaScript code as a bundle to access your service
  in a well-typed way. Moreover, you can use JSweet to generate the
  TypeScript definitions of your services and DTOs, so that your
  TypeScript client are well-typed (see the JSweet’s <code>declaration</code>
  option).</p>
<h4><a href="#example-6-an-adapter-to-disallow-global-variables" id="example-6-an-adapter-to-disallow-global-variables">Example
  6: an adapter to disallow global variables</a></h4>
<p>This is a quite special adapter since it does not really generate any
  code, but it reports errors when the source code does not conform to
  certain coding standards. Here, we implement a simple constraint that
  reports errors when the user tries to declare global variables (i.e. in
  JSweet non-final static field declared in a <code>Globals</code> class).</p>
<pre><code class="java">package org.jsweet.transpiler.extension;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;

import org.jsweet.transpiler.JSweetProblem;

public class DisallowGlobalVariablesAdapter extends PrinterAdapter {

    public DisallowGlobalVariablesAdapter(PrinterAdapter parentAdapter) {
        super(parentAdapter);
    }

    @Override
    public void afterType(TypeElement type) {
        // we only check for static variables that are in a Globals class but
        // this could be generalized to any static variable
        if (!type.getQualifiedName().toString().startsWith(&quot;def.&quot;)
                &amp;&amp; type.getSimpleName().toString().equals(&quot;Globals&quot;)) {
            for (Element member : type.getEnclosedElements()) {
                if (member.getKind() == ElementKind.FIELD) {
                    VariableElement field = (VariableElement) member;
                    // only non-final static variable have side effect
                    if (field.getModifiers().contains(Modifier.STATIC)
                            &amp;&amp; !field.getModifiers().contains(Modifier.FINAL)) {
                        report(field, JSweetProblem.USER_ERROR, &quot;global variables are not allowed&quot;);
                    }
                }
            }
        }
        super.afterType(type);
    }

}
</code></pre>
<p>This adapter falls into the category of static analysis, which can be
  useful (along with code generation) to check that the input complies to
  the expected coding guidelines. It would be easy to enhance this adapter
  to add check on any static fields. A nice feature would be to disable
  the check when the field is annotated with a specific annotation (for
  instance <code>@AllowSideEffect</code>).</p>
<h2><a href="#appendix-1-jsweet-transpiler-options" id="appendix-1-jsweet-transpiler-options">Appendix 1: JSweet
  transpiler options</a></h2>
<pre><code>  [-h|--help]

  [-w|--watch]
        Start a process that watches the input directories for changes and
        re-run transpilation on-the-fly.

  [-v|--verbose]
        Turn on all levels of logging.

  [--encoding &lt;encoding&gt;]
        Force the Java compiler to use a specific encoding (UTF-8, UTF-16, ...).
        (default: UTF-8)

  [--jdkHome &lt;jdkHome&gt;]
        Set the JDK home directory to be used to find the Java compiler. If not
        set, the transpiler will try to use the JAVA_HOME environment variable.
        Note that the expected JDK version is greater or equals to version 8.

  (-i|--input) input1:input2:...:inputN
        An input directory (or column-separated input directories) containing
        Java files to be transpiled. Java files will be recursively looked up in
        sub-directories. Inclusion and exclusion patterns can be defined with
        the 'includes' and 'excludes' options.

  [--includes includes1:includes2:...:includesN ]
        A column-separated list of expressions matching files to be included
        (relatively to the input directory).

  [--excludes excludes1:excludes2:...:excludesN ]
        A column-separated list of expressions matching files to be excluded
        (relatively to the input directory).

  [(-d|--defInput) defInput1:defInput2:...:defInputN ]
        An input directory (or column-separated input directories) containing
        TypeScript definition files (*.d.ts) to be used for transpilation.
        Definition files will be recursively looked up in sub-diredctories.

  [--noRootDirectories]
        Skip the root directories (i.e. packages annotated with
        @jsweet.lang.Root) so that the generated file hierarchy starts at the
        root directories rather than including the entire directory structure.

  [--tsout &lt;tsout&gt;]
        Specify where to place generated TypeScript files. (default: .ts)

  [(-o|--jsout) &lt;jsout&gt;]
        Specify where to place generated JavaScript files (ignored if jsFile is
        specified). (default: js)

  [--disableSinglePrecisionFloats]
        By default, for a target version &gt;=ES5, JSweet will force Java floats to
        be mapped to JavaScript numbers that will be constrained with ES5
        Math.fround function. If this option is true, then the calls to
        Math.fround are erased and the generated program will use the JavaScript
        default precision (double precision).

  [--tsOnly]
        Do not compile the TypeScript output (let an external TypeScript
        compiler do so).

  [--ignoreDefinitions]
        Ignore definitions from def.* packages, so that they are not generated
        in d.ts definition files. If this option is not set, the transpiler
        generates d.ts definition files in the directory given by the tsout
        option.

  [--declaration]
        Generate the d.ts files along with the js files, so that other programs
        can use them to compile.

  [--dtsout &lt;dtsout&gt;]
        Specify where to place generated d.ts files when the declaration option
        is set (by default, d.ts files are generated in the JavaScript output
        directory - next to the corresponding js files).

  [--candiesJsOut &lt;candiesJsOut&gt;]
        Specify where to place extracted JavaScript files from candies.
        (default: js/candies)

  [--sourceRoot &lt;sourceRoot&gt;]
        Specify the location where debugger should locate Java files instead of
        source locations. Use this flag if the sources will be located at
        run-time in a different location than that at design-time. The location
        specified will be embedded in the sourceMap to direct the debugger where
        the source files will be located.

  [--classpath &lt;classpath&gt;]
        The JSweet transpilation classpath (candy jars). This classpath should
        at least contain the core candy.

  [(-m|--module) &lt;module&gt;]
        The module kind (none, commonjs, amd, system or umd). (default: none)

  [-b|--bundle]
        Bundle up all the generated code in a single file, which can be used in
        the browser. The bundle files are called 'bundle.ts', 'bundle.d.ts', or
        'bundle.js' depending on the kind of generated code. NOTE: bundles are
        not compatible with any module kind other than 'none'.

  [(-f|--factoryClassName) &lt;factoryClassName&gt;]
        Use the given factory to tune the default transpiler behavior.

  [--sourceMap]
        Generate source map files for the Java files, so that it is possible to
        debug Java files directly with a debugger that supports source maps
        (most JavaScript debuggers).

  [--enableAssertions]
        Java 'assert' statements are transpiled as runtime JavaScript checks.

  [--header &lt;header&gt;]
        A file that contains a header to be written at the beginning of each
        generated file. If left unspecified, JSweet will generate a default
        header.

  [--workingDir &lt;workingDir&gt;]
        The directory JSweet uses to store temporary files such as extracted
        candies. JSweet uses '.jsweet' if left unspecified.

  [--targetVersion &lt;targetVersion&gt;]
        The EcmaScript target (JavaScript) version. Possible values: [ES3, ES5,
        ES6] (default: ES3)
</code></pre>
<h2><a href="#appendix-2-packaging-and-static-behavior" id="appendix-2-packaging-and-static-behavior">Appendix 2:
  packaging and static behavior</a></h2>
<p>This appendix explains some static behavior with regards to packaging.</p>
<h3><a href="#when-main-methods-are-invoked" id="when-main-methods-are-invoked">When main methods are invoked</a></h3>
<p>When main methods are invoked depends on the way the program is
  packaged.</p>
<ul>
  <li>
    <p><code>module</code>: off, <code>bundle</code>: off. With default packaging, one Java
      source file corresponds to one generated JavaScript file. In that
      case, when loading a file in the browser, all the main methods will
      be invoked right at the end of the file.</p>
  </li>
  <li>
    <p><code>module</code>: off, <code>bundle</code>: on. When the <code>bundle</code> option is on and the
      <code>module</code> option is off, main methods are called at the end of the
      bundle.</p>
  </li>
  <li>
    <p><code>module</code>: on, <code>bundle</code>: off. With module packaging (<code>module</code>
      option), one Java package corresponds to one module. With modules,
      it is mandatory to have only one main method in the program, which
      will be the global entry point from which the module dependency
      graph will be calculated. The main module (the one with the main
      method) will use directly or transitively all the other modules. The
      main method will be invoked at the end of the main module
      evaluation.</p>
  </li>
</ul>
<p>Because of modules, it is good practice to have only one main method in
  an application.</p>
<h3><a href="#static-and-inheritance-dependencies" id="static-and-inheritance-dependencies">Static and inheritance
  dependencies</a></h3>
<p>In TypeScript, programmers need to take care of the ordering of classes
  with regards to static fields and initializers. Typically, a static
  member cannot be initialized with a static member of a class that has
  not yet been defined. Also, a class cannot extend a class that has not
  been defined yet. This forward-dependency issue triggers runtime errors
  when evaluating the generated JavaScript code, which can be quite
  annoying for the programmers and may requires the use of external
  JavaScript bundling tools, such as Browserify.</p>
<p>JSweet’s statics lazy initialization allows static forward references
  within a given file, and within an entire bundle when the <code>bundle</code>
  option is set. Also, when bundling a set of files, JSweet analyses the
  inheritance tree and performs a partial order permutation to eliminate
  forward references in the inheritance tree. Note that TypeScript bundle
  provide a similar feature, but the references need to be manually
  declared, which is not convenient for programmers.</p>
<p>To wrap it up, here are the guidelines to be followed by the programmers
  depending on the packaging method:</p>
<ul>
  <li>
    <p><code>module</code>: off, <code>bundle</code>: off. One JavaScript file is generated per
      Java file. The programmer must take care of including the files in
      the right order in the HTML page, so that there are no forward
      references with regard to inheritance and statics. Within a given
      file, static forward references are allowed, but inheritance forward
      reference are not supported yet (this will be supported in coming
      releases).</p>
  </li>
  <li>
    <p><code>module</code>: off, <code>bundle</code>: on. This configuration produces a unique
      browser-compatible bundle file that can be included in an HTML page.
      Here, the programmer does not have to take care at all of the
      forward references across files. Exactly like in Java, the order
      does not matter. Within a single file, the programmer still have to
      take care of the inheritance forward references (in other words, a
      subclass must be declared after its parent class) (this will be
      supported in coming releases).</p>
  </li>
  <li>
    <p><code>module</code>: commonjs, amd or umd, <code>bundle</code>: off. This configuration
      produces one module file per Java package so that they can be used
      within a module system. For instance, using the <code>commonjs</code> module
      kind will allow the program to run on Node.js. In that
      configuration, the program should contain one main method and only
      the module file containing the main method should be loaded (because
      it will take care loading all the other modules). This configuration
      imposes the same constraint within a single file (no
      forward-references in inheritance).</p>
  </li>
</ul>


</body>
</html>
相關文章
相關標籤/搜索