# HG changeset patch # User Jaroslav Tulach # Date 1360770872 -3600 # Node ID ad7be5819f5d9e9a8062eccc89164f79d08f8597 # Parent ef50c4f07e4ffab5b9311b0dbd52edf438beb9f2# Parent 5d1c3bc8d2976fa75c14856e685a24dbdaed759a Merging in initial version of the IDE improving module. Includes conversion hint by Lahvac and Igor and @JavaScriptBody coloring by Tomas Z. diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/pom.xml Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,198 @@ + + + 4.0.0 + + ide + org.apidesign.bck2brwsr + 0.3-SNAPSHOT + + + org.apidesign.bck2brwsr.ide.editor + editor + 0.3-SNAPSHOT + nbm + + Editor Support for Bck2Brwsr + + + UTF-8 + RELEASE72 + ${project.build.directory}/endorsed + + + + + + netbeans + NetBeans + http://bits.netbeans.org/maven2/ + + false + + + + + + + org.netbeans.api + org-netbeans-api-annotations-common + ${netbeans.version} + + + org.netbeans.api + org-netbeans-modules-java-source + ${netbeans.version} + + + org.netbeans.api + org-netbeans-libs-javacapi + ${netbeans.version} + + + org.netbeans.api + org-netbeans-spi-java-hints + ${netbeans.version} + + + org.netbeans.api + org-netbeans-modules-parsing-api + ${netbeans.version} + + + org.netbeans.api + org-netbeans-spi-editor-hints + ${netbeans.version} + + + org.netbeans.api + org-openide-util + ${netbeans.version} + + + org.netbeans.api + org-netbeans-modules-java-lexer + ${netbeans.version} + + + org.netbeans.api + org-netbeans-modules-lexer + ${netbeans.version} + + + org.apidesign.bck2brwsr + core + 0.3-SNAPSHOT + jar + test + + + org.netbeans.api + org-netbeans-modules-java-hints-test + ${netbeans.version} + test + + + org.netbeans.api + org-netbeans-libs-junit4 + ${netbeans.version} + test + + + org.netbeans.modules + org-netbeans-lib-nbjavac + ${netbeans.version} + test + + + org.testng + testng + test + + + + + + + org.codehaus.mojo + nbm-maven-plugin + 3.8 + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.6 + 1.6 + + ${endorsed.dir} + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + endorsed + validate + + copy + + + + + ${endorsed.dir} + true + + + org.netbeans.api + org-netbeans-libs-javacapi + ${netbeans.version} + + + org.netbeans.external + nb-javac-api + ${netbeans.version} + + + org.netbeans.modules + org-netbeans-libs-javacimpl + ${netbeans.version} + + + org.netbeans.external + nb-javac-impl + ${netbeans.version} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Djava.endorsed.dirs=${endorsed.dir} + + + + + diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JNIHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JNIHelper.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,80 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * JNI Helper. + * To facilitate lookup of methods by name and signature, instead of manually parsing signatures, + * constructs the map of all methods and uses Class.getName() to generate almost-correct signatures. + */ +class JNIHelper { + + static Method method(String clazz, String method, String signature) { + final Map methods = methodMap(JNIHelper.clazz(clazz)); + return methods.get(methodKey(method, signature)); + } + + static Class clazz(String clazz) { + try { + return Class.forName(clazz); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + + static Map methodMap(final Class clazz) { + final Map map = new HashMap(); + final Method[] methods = clazz.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + final Method method = methods[i]; + map.put(methodKey(method.getName(), signature(method)), method); + } + return map; + } + + static String methodKey(String method, String signature) { + return method + '@' + signature; + } + + static String signature(final Method method) { + final Class[] parameterTypes = method.getParameterTypes(); + final StringBuilder b = new StringBuilder(); + for (int j = 0; j < parameterTypes.length; j++) { + b.append(signature(parameterTypes[j])); + } + return b.toString(); + } + + static String signature(final Class clazz) { + if (clazz == boolean.class) return "Z"; + else if (clazz == byte.class) return "B"; + else if (clazz == char.class) return "C"; + else if (clazz == double.class) return "D"; + else if (clazz == float.class) return "F"; + else if (clazz == int.class) return "I"; + else if (clazz == long.class) return "J"; + else if (clazz == short.class) return "S"; + else if (clazz == void.class) return "V"; + else if (clazz.isArray()) return clazz.getName().replace('.','/'); + else return "L" + clazz.getName().replace('.','/') + ";"; + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSEmbeddingProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSEmbeddingProvider.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,188 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.LiteralTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import com.sun.source.util.Trees; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.lang.model.element.TypeElement; +import javax.swing.text.Document; +import org.netbeans.api.editor.mimelookup.MimeRegistration; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.java.source.JavaParserResultTask; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.lexer.Language; +import org.netbeans.api.lexer.TokenHierarchy; +import org.netbeans.api.lexer.TokenSequence; +import org.netbeans.modules.parsing.api.Snapshot; +import org.netbeans.modules.parsing.spi.Parser; +import org.netbeans.modules.parsing.spi.Scheduler; +import org.netbeans.modules.parsing.spi.SchedulerEvent; +import org.netbeans.modules.parsing.spi.SchedulerTask; +import org.netbeans.modules.parsing.spi.TaskFactory; +import org.openide.util.Exceptions; + +/** + * + * @author Tomas Zezula + */ +public final class JSEmbeddingProvider extends JavaParserResultTask { + + private static final int PRIORITY = 1000; + private static final String JS_ANNOTATION = "org.apidesign.bck2brwsr.core.JavaScriptBody"; //NOI18N + private static final String BODY = "body"; //NOI18N + private static final String JAVA_MIME_TYPE = "text/x-java"; //NOI18N + private static final String JAVASCRIPT_MIME_TYPE = "text/javascript"; //NOI18N + private final AtomicBoolean canceled = new AtomicBoolean(); + + private JSEmbeddingProvider() { + super(JavaSource.Phase.ELEMENTS_RESOLVED); + } + + @Override + public int getPriority() { + return PRIORITY; + } + + @Override + public void cancel() { + canceled.set(true); + } + + @Override + public Class getSchedulerClass() { + return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER; + } + + @Override + public void run(Parser.Result t, SchedulerEvent se) { + canceled.set(false); + final CompilationInfo ci = CompilationInfo.get(t); + final CompilationUnitTree cu = ci.getCompilationUnit(); + final Trees trees = ci.getTrees(); + final SourcePositions sp = trees.getSourcePositions(); + final Finder f = new Finder(trees); + final List result = new ArrayList(); + f.scan(cu, result); + if (!result.isEmpty()) { + try { + final TokenHierarchy tk = TokenHierarchy.get(ci.getDocument()); + final Language java = Language.find(JAVA_MIME_TYPE); + final Language javaScript = Language.find(JAVASCRIPT_MIME_TYPE); + if (java != null && javaScript != null) { + final TokenSequence seq = tk.tokenSequence(java); + if (seq != null) { + for (LiteralTree lt : result) { + final int start = (int) sp.getStartPosition(cu, lt); + final int end = (int) sp.getEndPosition(cu, lt); + seq.move(start); + while (seq.moveNext() && seq.offset() < end) { + seq.createEmbedding(javaScript, 1, 1, true); + } + } + } + } + } catch (IOException ioe) { + Exceptions.printStackTrace(ioe); + } + } + } + + + + + private static final class Finder extends TreePathScanner> { + + private final Trees trees; + private CompilationUnitTree cu; + private boolean inEmbedding; + + Finder(final Trees trees) { + this.trees = trees; + } + + @Override + public Void visitCompilationUnit( + final CompilationUnitTree unit, + final List p) { + this.cu = unit; + return super.visitCompilationUnit(unit, p); + } + + + + @Override + public Void visitMethod( + final MethodTree m, + final List p) { + for (AnnotationTree a : m.getModifiers().getAnnotations()) { + final TypeElement ae = (TypeElement) trees.getElement(TreePath.getPath(cu, a.getAnnotationType())); + if (ae != null && JS_ANNOTATION.contentEquals(ae.getQualifiedName())) { + final List args = a.getArguments(); + for (ExpressionTree kvp : args) { + if (kvp instanceof AssignmentTree) { + final AssignmentTree assignemt = (AssignmentTree) kvp; + if (BODY.equals(assignemt.getVariable().toString())) { + inEmbedding = true; + try { + scan(assignemt.getExpression(), p); + } finally { + inEmbedding = false; + } + } + } + } + } + } + return null; + } + + @Override + public Void visitLiteral(LiteralTree node, List p) { + if (inEmbedding) { + p.add(node); + } + return super.visitLiteral(node, p); + } + + } + + @MimeRegistration( + service = TaskFactory.class, + mimeType = JAVA_MIME_TYPE) + public static final class Factory extends TaskFactory { + @Override + public Collection create(Snapshot snpsht) { + return Collections.singleton(new JSEmbeddingProvider()); + } + } + +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBody.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBody.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,149 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.LiteralTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.TreePath; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.java.lexer.JavaTokenId; +import static org.netbeans.api.java.lexer.JavaTokenId.BLOCK_COMMENT; +import static org.netbeans.api.java.lexer.JavaTokenId.JAVADOC_COMMENT; +import static org.netbeans.api.java.lexer.JavaTokenId.LINE_COMMENT; +import static org.netbeans.api.java.lexer.JavaTokenId.WHITESPACE; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.java.source.TreeMaker; +import org.netbeans.api.lexer.Token; +import org.netbeans.api.lexer.TokenSequence; +import org.netbeans.spi.editor.hints.ErrorDescription; +import org.netbeans.spi.editor.hints.Fix; +import org.netbeans.spi.java.hints.ErrorDescriptionFactory; +import org.netbeans.spi.java.hints.Hint; +import org.netbeans.spi.java.hints.HintContext; +import org.netbeans.spi.java.hints.JavaFix; +import org.netbeans.spi.java.hints.TriggerTreeKind; +import org.openide.util.NbBundle.Messages; + +@Hint(displayName = "#DN_JSNI2JavaScriptBody", description = "#DESC_JSNI2JavaScriptBody", category = "general") +@Messages({ + "DN_JSNI2JavaScriptBody=JSNI to @JavaScriptBody", + "DESC_JSNI2JavaScriptBody=JSNI to @JavaScriptBody" +}) +public class JSNI2JavaScriptBody { + + @TriggerTreeKind(Kind.METHOD) + @Messages("ERR_JSNI2JavaScriptBody=Can convert JSNI to @JavaScriptBody") + public static ErrorDescription computeWarning(final HintContext ctx) { + Token token = findBlockToken(ctx.getInfo(), ctx.getPath(), ctx); + + if (token == null) { + return null; + } + + Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath()).toEditorFix(); + return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_JSNI2JavaScriptBody(), fix); + } + + private static Token findBlockToken(CompilationInfo info, TreePath path, HintContext ctx) { + int end = (int) info.getTrees().getSourcePositions().getEndPosition(path.getCompilationUnit(), path.getLeaf()); + TokenSequence ts = info.getTokenHierarchy().tokenSequence(JavaTokenId.language()); + + if (ts == null) return null; + + ts.move(end); + + if ((ctx != null && ctx.isCanceled()) || !ts.movePrevious() || ts.token().id() != JavaTokenId.SEMICOLON) return null; + + OUTER: while (ts.movePrevious()) { + if (ctx != null && ctx.isCanceled()) return null; + + switch (ts.token().id()) { + case WHITESPACE: break; + case LINE_COMMENT: break; + case JAVADOC_COMMENT: break; + case BLOCK_COMMENT: + final CharSequence tok = ts.token().text(); + final int l = tok.length(); + if (l > 4 + && tok.subSequence(0, 4).toString().equals("/*-{") // NOI18N + && tok.subSequence(l - 4, l).toString().equals("}-*/") // NOI18N + ) { + return ts.offsetToken(); + } + break; + default: + break OUTER; + } + } + + return null; + } + + private static final class FixImpl extends JavaFix { + + public FixImpl(CompilationInfo info, TreePath tp) { + super(info, tp); + } + + @Override + @Messages("FIX_JSNI2JavaScriptBody=Convert JSNI to @JavaScriptBody") + protected String getText() { + return Bundle.FIX_JSNI2JavaScriptBody(); + } + + @Override + protected void performRewrite(TransformationContext ctx) { + Token jsniComment = findBlockToken(ctx.getWorkingCopy(), ctx.getPath(), null); + + if (jsniComment == null) { + //XXX: warn? + return ; + } + + JsniCommentTokenizer tok = new JsniCommentTokenizer(); + ManglingSink ms = new ManglingSink(); + final CharSequence cmnt = jsniComment.text(); + tok.process(cmnt.subSequence(4, cmnt.length() - 4), ms); + + TreeMaker make = ctx.getWorkingCopy().getTreeMaker(); + MethodTree mt = (MethodTree) ctx.getPath().getLeaf(); + List params = new ArrayList(); + + for (VariableTree p : mt.getParameters()) { + params.add(make.Literal(p.getName().toString())); + } + + AnnotationTree jsBody = make.Annotation(make.QualIdent("org.apidesign.bck2brwsr.core.JavaScriptBody"), + Arrays.asList( + make.Assignment(make.Identifier("args"), make.NewArray(null, Collections.emptyList(), params)), + make.Assignment(make.Identifier("body"), make.Literal(ms.out.toString())) + ) + ); + + + ctx.getWorkingCopy().rewrite(mt.getModifiers(), make.addModifiersAnnotation(mt.getModifiers(), jsBody)); + } + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizer.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,70 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +final class JsniCommentTokenizer { + + /** + * Tokenize the contents of JSNI comment into the provided {@linkplain Sink}. + * @param in the contents of JSNI comment + * @param out the sink that consumes parsed tokens + */ + public void process(final CharSequence in, final Sink out) { + final Matcher member = Pattern.compile("@([^:]+)::([a-zA-Z_$][a-zA-Z\\d_$]*)").matcher(in); + final Matcher signature = Pattern.compile("\\(([^\\)]*)\\)").matcher(in); + + int i = 0; + while (true) { + if (member.find(i)) { + final int memberStart = member.start(); + final int memberEnd = member.end(); + if (memberStart > i) out.javascript(in.subSequence(i, memberStart).toString()); + + final String clazz = member.group(1); + final String name = member.group(2); + + if (in.charAt(memberEnd) == '(') { + if (!signature.find(memberEnd)) { + throw new IllegalStateException("Expected method signature"); + } + assert signature.start() == memberEnd; + out.method(clazz, name, signature.group(1)); + i = signature.end(); + } else { + out.field(clazz, name); + i = memberEnd; + } + } else { + out.javascript(in.subSequence(i, in.length()).toString()); + break; + } + } + } + + + static interface Sink { + void javascript(String s); + + void method(String clazz, String method, String signature); + + void field(String clazz, String field); + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/ManglingSink.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/ManglingSink.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,71 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +/** + * An implementation of {@linkplain JsniCommentTokenizer.Sink} that generates B2B + */ +class ManglingSink implements JsniCommentTokenizer.Sink { + + final StringBuilder out = new StringBuilder(); + + public void javascript(String s) { + out.append(s); + } + + public void method(String clazz, String method, String signature) { + out.append(mangle(clazz, method, signature)); + } + + public void field(String clazz, String field) { +// out.append(field); + out.append('_').append(field).append('(').append(')'); + } + + + @Override + public String toString() { + return out.toString(); + } + + + static String mangle(String clazz, String method, String signature) { + final StringBuilder builder = new StringBuilder(); + builder.append(method); + builder.append("__"); + builder.append(mangle(JNIHelper.signature(JNIHelper.method(clazz, method, signature).getReturnType()))); + builder.append(mangle(signature)); + return builder.toString(); + } + + + static String mangle(String txt) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < txt.length(); i++) { + final char ch = txt.charAt(i); + switch (ch) { + case '/': sb.append('_'); break; + case '_': sb.append("_1"); break; + case ';': sb.append("_2"); break; + case '[': sb.append("_3"); break; + default: sb.append(ch); break; + } + } + return sb.toString(); + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/nbm/manifest.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/nbm/manifest.mf Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jackpot30/test/hints/Bundle.properties diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/main/resources/org/netbeans/modules/jackpot30/test/hints/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/main/resources/org/netbeans/modules/jackpot30/test/hints/Bundle.properties Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,21 @@ +# +# Back 2 Browser Bytecode Translator +# Copyright (C) 2012 Jaroslav Tulach +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. Look for COPYING file in the top folder. +# If not, see http://opensource.org/licenses/GPL-2.0. +# + +OpenIDE-Module-Name=Bck2Brwsr Editor Support +OpenIDE-Module-Short-Description=Provides hints, coloring, etc. for the bck2brwsr.apidesign.org project +OpenIDE-Module-Display-Category=Java diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/DejsniReaderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/DejsniReaderTest.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,84 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.netbeans.modules.java.hints.test.api.HintTest; +import org.openide.filesystems.FileUtil; +import org.testng.annotations.Test; + +public class DejsniReaderTest { + + @Test + public void test1() throws Exception { + String s = "class Test {\n" + + " /** javadoc */\n" + + " public native void test() /*-{\n" + + " // body\n" + + " }-*/;\n" + + "}\n"; + + String expected = " import org.apidesign.bck2brwsr.core.JavaScriptBody;\n" + + "class Test {\n" + + "\n" + + " /** javadoc */\n" + + " @JavaScriptBody(args = {}, body = \"\\n // body\\n \")\n" + + " public native void test();\n" + + "}\n"; + + HintTest.create() + .input(s) + .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation())) + .run(JSNI2JavaScriptBody.class) + .findWarning("2:23-2:27:verifier:" + Bundle.ERR_JSNI2JavaScriptBody()) + .applyFix() + .assertCompilable() + .assertOutput(expected); + } + + + @Test + public void test2() throws Exception { + String s = "class Test {\n" + + " /** javadoc */\n" + + " @SuppressWarnings(\"unused\")\n" + + " // comment\n" + + " public native void test() /*-{\n" + + " // body\n" + + " }-*/;\n" + + "}\n"; + + String expected = " import org.apidesign.bck2brwsr.core.JavaScriptBody;\n" + + "class Test {\n" + + "\n" + + " /** javadoc */\n" + + " @SuppressWarnings(\"unused\")\n" + + " // comment\n" + + " @JavaScriptBody(args = {}, body = \"\\n // body\\n \")\n" + + " public native void test();\n" + + "}\n"; + HintTest.create() + .input(s) + .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation())) + .run(JSNI2JavaScriptBody.class) + .findWarning("4:23-4:27:verifier:" + Bundle.ERR_JSNI2JavaScriptBody()) + .applyFix() + .assertCompilable() + .assertOutput(expected); + } +} \ No newline at end of file diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBodyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBodyTest.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,46 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.netbeans.modules.java.hints.test.api.HintTest; +import org.openide.filesystems.FileUtil; +import org.testng.annotations.Test; + +public class JSNI2JavaScriptBodyTest { + + @Test + public void testFixWorking() throws Exception { + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public native void run(int a) /*-{ this.a = a; }-*/;\n" + + "}\n") + .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation())) + .run(JSNI2JavaScriptBody.class) + .findWarning("2:23-2:26:verifier:" + Bundle.ERR_JSNI2JavaScriptBody()) + .applyFix() + .assertCompilable() + .assertOutput("package test;\n" + + "import org.apidesign.bck2brwsr.core.JavaScriptBody;\n" + + "public class Test {\n" + + " @JavaScriptBody(args = {\"a\"}, body = \" this.a = a; \")\n" + + " public native void run(int a);\n" + + "}\n"); + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizerTest.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,154 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class JsniCommentTokenizerTest { + + private static class MockSink implements JsniCommentTokenizer.Sink { + final List out = new ArrayList(); + + public void javascript(String s) { + out.add("J " + s); + } + + public void method(String clazz, String method, String signature) { + out.add("M " + clazz + "|" + method + "|" + signature); + } + + public void field(String clazz, String field) { + out.add("F " + clazz + "|" + field); + } + } + + + @Test + public void testProcess_nop() throws IOException { + final String in = "foo bar"; + final List expected = new ArrayList(); + expected.add("J foo bar"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } + + @Test + public void testProcess_read_static_field() throws IOException { + final String in = " @com.google.gwt.examples.JSNIExample::myStaticField = val + \" and stuff\";"; + final List expected = new ArrayList(); + expected.add("J "); + expected.add("F com.google.gwt.examples.JSNIExample|myStaticField"); + expected.add("J = val + \" and stuff\";"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } + + @Test + public void testProcess_write_instance_field() throws IOException { + final String in = " x.@com.google.gwt.examples.JSNIExample::myInstanceField = val + \" and stuff\";"; + final List expected = new ArrayList(); + expected.add("J x."); + expected.add("F com.google.gwt.examples.JSNIExample|myInstanceField"); + expected.add("J = val + \" and stuff\";"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } + + @Test + public void testProcess_read_instance_field() throws IOException { + final String in = " var val = this.@com.google.gwt.examples.JSNIExample::myInstanceField;"; + final List expected = new ArrayList(); + expected.add("J var val = this."); + expected.add("F com.google.gwt.examples.JSNIExample|myInstanceField"); + expected.add("J ;"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } + + + @Test + public void testProcess_static_method() throws IOException { + final String in = " @com.google.gwt.examples.JSNIExample::staticFoo(Ljava/lang/String;)(s);"; + final List expected = new ArrayList(); + expected.add("J "); + expected.add("M com.google.gwt.examples.JSNIExample|staticFoo|Ljava/lang/String;"); + expected.add("J (s);"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } + + + @Test + public void testProcess_instance_method() throws IOException { + final String in = " x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);"; + final List expected = new ArrayList(); + expected.add("J x."); + expected.add("M com.google.gwt.examples.JSNIExample|instanceFoo|Ljava/lang/String;"); + expected.add("J (s);"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } + + + @Test + public void testProcess_multiline() throws IOException { + final String in = + " x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);" + + " @com.google.gwt.examples.JSNIExample::myStaticField = val + \" and stuff\";"; + final List expected = new ArrayList(); + expected.add("J x."); + expected.add("M com.google.gwt.examples.JSNIExample|instanceFoo|Ljava/lang/String;"); + expected.add("J (s); "); + expected.add("F com.google.gwt.examples.JSNIExample|myStaticField"); + expected.add("J = val + \" and stuff\";"); + + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer(); + final MockSink out = new MockSink(); + jsniCommentTokenizer.process(in, out); + + Assert.assertEquals(expected, out.out); + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/ManglingSinkTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/ManglingSinkTest.java Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,58 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.ide.editor; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class ManglingSinkTest { + + @Test + public void testMangle_1() { + Assert.assertEquals( + "binarySearch__I_3BIIB", + ManglingSink.mangle("java.util.Arrays", "binarySearch", "[BIIB") + ); + } + + @Test + public void testMangle_2() { + Assert.assertEquals( + "sort__V_3I", + ManglingSink.mangle("java.util.Arrays", "sort", "[I") + ); + } + + @Test + public void testMangle_3() { + Assert.assertEquals( + "binarySearch__I_3Ljava_lang_Object_2IILjava_lang_Object_2", + ManglingSink.mangle("java.util.Arrays", "binarySearch", "[Ljava/lang/Object;IILjava/lang/Object;") + ); + } + + + @Test + public void testField() { + final ManglingSink manglingSink = new ManglingSink(); + manglingSink.field(null, "value"); + + Assert.assertEquals("_value()", manglingSink.toString()); + } +} diff -r ef50c4f07e4f -r ad7be5819f5d ide/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide/pom.xml Wed Feb 13 16:54:32 2013 +0100 @@ -0,0 +1,17 @@ + + + 4.0.0 + + bck2brwsr + org.apidesign + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + ide + 0.3-SNAPSHOT + pom + IDE Support + + editor + + diff -r ef50c4f07e4f -r ad7be5819f5d pom.xml --- a/pom.xml Tue Feb 12 12:07:55 2013 +0100 +++ b/pom.xml Wed Feb 13 16:54:32 2013 +0100 @@ -17,6 +17,7 @@ benchmarks launcher vmtest + ide