This is an automated email from the ASF dual-hosted git repository.

geertjan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 7aeeab1  Supporting HTML/Java API/UI constructs in the editor (#380)
7aeeab1 is described below

commit 7aeeab1ea2d15a2835da307137cefe46f57b8b2e
Author: Jaroslav Tulach <[email protected]>
AuthorDate: Wed Jan 31 18:48:44 2018 +0100

    Supporting HTML/Java API/UI constructs in the editor (#380)
    
    OK, thanks, looks good, merging.
---
 editor.htmlui/build.xml                            |  25 +++
 editor.htmlui/manifest.mf                          |   6 +
 editor.htmlui/nbproject/project.properties         |  21 +++
 editor.htmlui/nbproject/project.xml                | 132 ++++++++++++++
 .../modules/editor/htmlui/Bundle.properties        |  26 +++
 .../modules/editor/htmlui/JSEmbeddingProvider.java | 191 +++++++++++++++++++++
 .../modules/editor/htmlui/JSNI2JavaScriptBody.java | 158 +++++++++++++++++
 .../editor/htmlui/JSNI2JavaScriptBodyTest.java     | 190 ++++++++++++++++++++
 nbbuild/cluster.properties                         |   1 +
 9 files changed, 750 insertions(+)

diff --git a/editor.htmlui/build.xml b/editor.htmlui/build.xml
new file mode 100644
index 0000000..83d76a5
--- /dev/null
+++ b/editor.htmlui/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project basedir="." default="netbeans" name="editor.htmlui">
+    <description>Builds, tests, and runs the project 
org.netbeans.modules.editor.htmlui</description>
+    <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/editor.htmlui/manifest.mf b/editor.htmlui/manifest.mf
new file mode 100644
index 0000000..9e1c589
--- /dev/null
+++ b/editor.htmlui/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: true
+OpenIDE-Module: org.netbeans.modules.editor.htmlui
+OpenIDE-Module-Localizing-Bundle: 
org/netbeans/modules/editor/htmlui/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/editor.htmlui/nbproject/project.properties 
b/editor.htmlui/nbproject/project.properties
new file mode 100644
index 0000000..ee62dfc
--- /dev/null
+++ b/editor.htmlui/nbproject/project.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+is.eager=true
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
+
diff --git a/editor.htmlui/nbproject/project.xml 
b/editor.htmlui/nbproject/project.xml
new file mode 100644
index 0000000..119854a
--- /dev/null
+++ b/editor.htmlui/nbproject/project.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1";>
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3";>
+            <code-name-base>org.netbeans.modules.editor.htmlui</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.libs.javacapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.7</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.32</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.java.lexer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.27</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.java.source.base</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.55</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.parsing.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.spi.editor.hints</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0</release-version>
+                        <specification-version>1.34</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.spi.java.hints</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.20</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>net.java.html.boot</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.libs.testng</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.java.hints.test</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.parsing.nb</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
diff --git 
a/editor.htmlui/src/org/netbeans/modules/editor/htmlui/Bundle.properties 
b/editor.htmlui/src/org/netbeans/modules/editor/htmlui/Bundle.properties
new file mode 100644
index 0000000..e72dbe2
--- /dev/null
+++ b/editor.htmlui/src/org/netbeans/modules/editor/htmlui/Bundle.properties
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+OpenIDE-Module-Display-Category=JavaScript
+OpenIDE-Module-Long-Description=\
+    Mixing Java and JavaScript? \
+    Now it is going to be more easy with a module like this!\n\n\
+    Convert GWT JavaScript2Native comments to annotation based form that can 
execute on real HotSpot virtual machine.\n\n\
+    Highlight JavaScript inside of Java sources (if put into the 
@JavaScriptBody annotation).\n\n\
+    Generate, test, execute and debug (both languages at once) projects that 
mix Java and JavaScript seemlessly switching from one language to another (only 
available with NetBeans 8.0 and JDK8).
+OpenIDE-Module-Name=Editor Support for HTML/Java API
+OpenIDE-Module-Short-Description=Mixing Java and JavaScript code made easy.
diff --git 
a/editor.htmlui/src/org/netbeans/modules/editor/htmlui/JSEmbeddingProvider.java 
b/editor.htmlui/src/org/netbeans/modules/editor/htmlui/JSEmbeddingProvider.java
new file mode 100644
index 0000000..a653b97
--- /dev/null
+++ 
b/editor.htmlui/src/org/netbeans/modules/editor/htmlui/JSEmbeddingProvider.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.editor.htmlui;
+
+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 java.util.logging.Level;
+import java.util.logging.Logger;
+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;
+
+/**
+ *
+ * @author Tomas Zezula
+ */
+public final class JSEmbeddingProvider extends 
JavaParserResultTask<Parser.Result> {
+    private static final Logger LOG = 
Logger.getLogger(JSEmbeddingProvider.class.getName());
+
+    private static final int PRIORITY = 1000;
+    private static final String JS_ANNOTATION = 
"net.java.html.js.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<? extends Scheduler> 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<LiteralTree> result = new ArrayList<LiteralTree>();
+        f.scan(cu, result);
+        if (!result.isEmpty()) {
+            try {
+                final TokenHierarchy<Document> 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) {
+                LOG.log(Level.WARNING, null, ioe);
+            }
+        }
+    }
+
+
+
+
+    private static final class Finder extends TreePathScanner<Void, List<? 
super LiteralTree>> {
+
+        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<? super LiteralTree> p) {
+            this.cu = unit;
+            return super.visitCompilationUnit(unit, p);
+        }
+
+
+
+        @Override
+        public Void visitMethod(
+                final MethodTree m,
+                final List<? super LiteralTree> 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<? extends ExpressionTree> 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<? super LiteralTree> 
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<? extends SchedulerTask> create(Snapshot snpsht) {
+            return Collections.singleton(new JSEmbeddingProvider());
+        }
+    }
+
+}
diff --git 
a/editor.htmlui/src/org/netbeans/modules/editor/htmlui/JSNI2JavaScriptBody.java 
b/editor.htmlui/src/org/netbeans/modules/editor/htmlui/JSNI2JavaScriptBody.java
new file mode 100644
index 0000000..38511d7
--- /dev/null
+++ 
b/editor.htmlui/src/org/netbeans/modules/editor/htmlui/JSNI2JavaScriptBody.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.editor.htmlui;
+
+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.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<JavaTokenId> 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<JavaTokenId> findBlockToken(CompilationInfo info, 
TreePath path, HintContext ctx) {
+        int end = (int) 
info.getTrees().getSourcePositions().getEndPosition(path.getCompilationUnit(), 
path.getLeaf());
+        TokenSequence<JavaTokenId> 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<JavaTokenId> jsniComment = 
findBlockToken(ctx.getWorkingCopy(), ctx.getPath(), null);
+
+            if (jsniComment == null) {
+                //XXX: warn?
+                return ;
+            }
+
+            TreeMaker make = ctx.getWorkingCopy().getTreeMaker();
+            MethodTree mt = (MethodTree) ctx.getPath().getLeaf();
+            List<LiteralTree> params = new ArrayList<LiteralTree>();
+
+            for (VariableTree p : mt.getParameters()) {
+                params.add(make.Literal(p.getName().toString()));
+            }
+
+            String body = jsniComment.text().toString().replace("\"", "\\\"");
+            body = body.replace("/*-{", "").replace("}-*/", "");
+
+            List<ExpressionTree> arr = new ArrayList<ExpressionTree>();
+            arr.add(make.Assignment(make.Identifier("args"), 
make.NewArray(null, Collections.<ExpressionTree>emptyList(), params)));
+            if (body.contains("@") && body.contains("::")) {
+                arr.add(make.Assignment(make.Identifier("javacall"), 
make.Literal(true)));
+            }
+            final String[] lines = body.split("\n");
+            StringBuilder jsB = new StringBuilder();
+            String sep = "\"";
+            for (int i = 0; i < lines.length; i++) {
+                String line = lines[i];
+                if (i < lines.length - 1) {
+                    line = line + "\\n";
+                }
+                jsB.append(sep).append(line).append("\"");
+                sep = " + \n\"";
+            }
+            arr.add(make.Assignment(make.Identifier("body"), 
make.Identifier(jsB.toString())));
+
+            AnnotationTree jsBody = 
make.Annotation(make.QualIdent("net.java.html.js.JavaScriptBody"), arr);
+            ctx.getWorkingCopy().rewrite(mt.getModifiers(), 
make.addModifiersAnnotation(mt.getModifiers(), jsBody));
+        }
+    }
+}
diff --git 
a/editor.htmlui/test/unit/src/org/netbeans/modules/editor/htmlui/JSNI2JavaScriptBodyTest.java
 
b/editor.htmlui/test/unit/src/org/netbeans/modules/editor/htmlui/JSNI2JavaScriptBodyTest.java
new file mode 100644
index 0000000..6a3160f
--- /dev/null
+++ 
b/editor.htmlui/test/unit/src/org/netbeans/modules/editor/htmlui/JSNI2JavaScriptBodyTest.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.editor.htmlui;
+
+import net.java.html.js.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 net.java.html.js.JavaScriptBody;\n" +
+                              "public class Test {\n" +
+                              "    @JavaScriptBody(args = {\"a\"}, body = \" 
this.a = a; \")\n" +
+                              "    public native void run(int a);\n" +
+                              "}\n");
+    }
+
+    @Test public void testUseQuote() throws Exception {
+        HintTest.create()
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    public native void alert() /*-{ alert(\"Pozor!\"); 
}-*/;\n" +
+                       "}\n")
+                
.classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
+                .run(JSNI2JavaScriptBody.class)
+                .findWarning("2:23-2:28:verifier:" + 
Bundle.ERR_JSNI2JavaScriptBody())
+                .applyFix()
+                .assertCompilable()
+                .assertOutput("package test;\n" +
+                              "import net.java.html.js.JavaScriptBody;\n" +
+                              "public class Test {\n" +
+                              "    @JavaScriptBody(args = {}, body = \" 
alert(\\\"Pozor!\\\"); \")\n" +
+                              "    public native void alert();\n" +
+                              "}\n");
+    }
+
+    @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 net.java.html.js.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 net.java.html.js.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);
+    }
+
+    static String append(StringBuilder sb, String x) {
+        sb.append(x);
+        return sb.toString();
+    }
+
+    @Test
+    public void testWithStaticMethodCall() throws Exception {
+        String s = "class Test {\n"
+            + "    /** javadoc */\n"
+            + "    @SuppressWarnings(\"unused\")\n"
+            + "    // comment\n"
+            + "    public native void test(String builder) /*-{\n"
+            + "        
@org.netbeans.modules.project.jsjava.JSNI2JavaScriptBodyTest::append(Ljava/lang/StringBuilder;Ljava/lang/String;)(builder,
 'Ahoj');\n"
+            + "    }-*/;\n"
+            + "}\n";
+
+        String expected = " import net.java.html.js.JavaScriptBody;\n"
+            + "class Test {\n"
+            + "\n"
+            + "    /** javadoc */\n"
+            + "    @SuppressWarnings(\"unused\")\n"
+            + "    // comment\n"
+            + "    @JavaScriptBody(args = {\"builder\"}, javacall = true, body 
= \"\\n\" + "
+            + "    \"    
@org.netbeans.modules.project.jsjava.JSNI2JavaScriptBodyTest::append(Ljava/lang/StringBuilder;Ljava/lang/String;)(builder,
 'Ahoj');\\n\" + \"  \")\n"
+            + "    public native void test(String builder);\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);
+    }
+
+    @Test
+    public void testWithInstanceMethodCall() throws Exception {
+        String s = "class Test {\n"
+            + "    /** javadoc */\n"
+            + "    @SuppressWarnings(\"unused\")\n"
+            + "    // comment\n"
+            + "    public native void test(String builder) /*-{\n"
+            + "        
[email protected]::append(Ljava/lang/String;)('Ahoj');\n"
+            + "    }-*/;\n"
+            + "}\n";
+
+        String expected = " import net.java.html.js.JavaScriptBody;\n"
+            + "class Test {\n"
+            + "\n"
+            + "    /** javadoc */\n"
+            + "    @SuppressWarnings(\"unused\")\n"
+            + "    // comment\n"
+            + "    @JavaScriptBody(args = {\"builder\"}, javacall = true, body 
= \"\\n\" + \""
+            + "        
[email protected]::append(Ljava/lang/String;)('Ahoj');\\n\" + \" 
   \")"
+            + "    public native void test(String builder);\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);
+    }
+
+}
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index e0ff36b..6fe1b25 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -565,6 +565,7 @@ nb.cluster.java=\
         debugger.jpda.projectsui,\
         debugger.jpda.ui,\
         debugger.jpda.visual,\
+        editor.htmlui,\
         findbugs.installer,\
         form,\
         form.j2ee,\

-- 
To stop receiving notification emails like this one, please contact
[email protected].

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to