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