diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml
index 3c0d1f2a998..9d98ad5f809 100644
--- a/.github/workflows/full-check.yml
+++ b/.github/workflows/full-check.yml
@@ -1,7 +1,7 @@
-# Run all tests and builds all aspects of GWT using Java 8. Runs nightly (plus
-# or minus timzeones) on the main branch, and will also run right away on a
-# push to a release branch. Release zips are uploaded as part of the build,
-# though maven snapshots are not yet deployed.
+# Run all tests and builds all aspects of GWT using Java 8, 11, and 17. Runs
+# nightly (plus or minus timzeones) on the main branch, and will also run right
+# away on a push to a release branch. Release zips are uploaded as part of the
+# build, though maven snapshots are not yet deployed.
name: Full build
on:
schedule:
@@ -18,6 +18,9 @@ on:
jobs:
build:
runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ java-version: [ '8', '11', '17' ]
steps:
- name: Checkout GWT itself into one directory
uses: actions/checkout@v2
@@ -28,11 +31,11 @@ jobs:
with:
repository: 'gwtproject/tools'
path: 'tools'
- - name: Set up JDK 8
- # GWT presently requires Java8 to build, but can run on newer Java versions
+ - name: Set up JDK ${{ matrix.java-version }}
+ # GWT presently requires Java8 to build just the SDK and some tests, or 11 to build everything, but can run on newer Java versions
uses: actions/setup-java@v3
with:
- java-version: '8'
+ java-version: ${{ matrix.java-version }}
distribution: 'temurin'
- name: Build, style/api checks, test, produce docs
@@ -62,27 +65,27 @@ jobs:
uses: actions/upload-artifact@v2
if: always()
with:
- name: checkstyle-reports
+ name: checkstyle-reports-java${{ matrix.java-version }}
path: 'gwt/build/out/**/checkstyle*.xml'
- name: Upload test xml files for manual review in its own artifact
uses: actions/upload-artifact@v2
if: always()
with:
- name: junit-reports
+ name: junit-reports-java${{ matrix.java-version }}
path: 'gwt/build/out/**/test/**/reports/TEST-*.xml'
- name: On success, upload the release zip
uses: actions/upload-artifact@v2
with:
- name: gwt
+ name: gwt-java${{ matrix.java-version }}
path: 'gwt/build/dist/gwt-*.zip'
- name: Set up sonatype credentials
# Using the same java version as above, set up a settings.xml file
uses: actions/setup-java@v3
- if: github.event_name == 'schedule' && github.repository_owner == 'gwtproject'
+ if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '17' }}
with:
- java-version: '8'
+ java-version: ${{ matrix.java-version }}
distribution: 'temurin'
# Define the ID for the server to put in settings.xml, and the env vars that will contain the secrets
server-id: sonatype-snapshots
@@ -90,7 +93,7 @@ jobs:
server-password: SONATYPE_PASSWORD
- name: Nightly builds should be deployed as snapshots to sonatype
- if: github.event_name == 'schedule' && github.repository_owner == 'gwtproject'
+ if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '17' }}
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml
index c4755ad99ad..75c861c4699 100644
--- a/.github/workflows/quick-check.yml
+++ b/.github/workflows/quick-check.yml
@@ -6,6 +6,9 @@ on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ java-version: ['8', '11', '17']
steps:
- name: Checkout GWT itself into one directory
uses: actions/checkout@v2
@@ -18,11 +21,11 @@ jobs:
with:
repository: 'gwtproject/tools'
path: 'tools'
- - name: Set up JDK 8
- # GWT presently requires Java8 to build, but can run on newer Java versions
- uses: actions/setup-java@v2
+ - name: Set up JDK ${{ matrix.java-version }}
+ # GWT presently requires Java8 to build just the SDK and some tests, or 11+ to build everything, and can run on newer Java versions
+ uses: actions/setup-java@v3
with:
- java-version: '8'
+ java-version: ${{ matrix.java-version }}
distribution: 'temurin'
- name: Set up reviewdog for easier checks on the PR's checkstyle output
uses: reviewdog/action-setup@v1
@@ -41,8 +44,8 @@ jobs:
ANT_OPTS=-Xmx2g
ant clean dist doc checkstyle apicheck
- - name: Create pull request comments/annotations for checkstyle, even on failure
- if: always() && github.event_name == 'pull_request'
+ - name: Create pull request comments/annotations for checkstyle from the java 17 build, even on failure
+ if: ${{ always() && github.event_name == 'pull_request' && matrix.java-version == '17' }}
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
@@ -55,8 +58,8 @@ jobs:
done
- name: Upload checkstyle xml for manual review
uses: actions/upload-artifact@v2
- if: always()
+ if: ${{ matrix.java-version == '17' }}
with:
- name: checkstyle-reports
+ name: checkstyle-reports-java${{ matrix.java-version }}
path: 'gwt/build/out/**/checkstyle*.xml'
retention-days: 5
diff --git a/README.md b/README.md
index a91c49ce934..71354ce75ba 100644
--- a/README.md
+++ b/README.md
@@ -28,10 +28,6 @@
`$ ant clean dist-dev`
- or if you don't have `python` and `g++` just run
-
- `$ ant clean dist-dev`
-
Then you will get all `.jar` files in the folder `build/lib` and
the redistributable file will be: `build/dist/gwt-0.0.0.zip`
@@ -42,6 +38,8 @@
- To compile everything including examples you have to run
`$ ant clean dist`
+
+ - To create maven artifacts (after building .jar using ant), use [following guide](./maven/README.txt).
### How to verify GWT code conventions:
diff --git a/build.xml b/build.xml
index c10eea6f2c5..4ab2c6e8f58 100755
--- a/build.xml
+++ b/build.xml
@@ -98,7 +98,7 @@
-
+
diff --git a/build_tools/doctool/build.xml b/build_tools/doctool/build.xml
index abd3026bae9..c4870197b61 100644
--- a/build_tools/doctool/build.xml
+++ b/build_tools/doctool/build.xml
@@ -3,17 +3,15 @@
-
-
-
-
-
-
-
+
+
-
+
diff --git a/build_tools/doctool/src/com/google/doctool/JreDocTool.java b/build_tools/doctool/src/com/google/doctool/JreDocTool.java
deleted file mode 100644
index 55195bf6640..00000000000
--- a/build_tools/doctool/src/com/google/doctool/JreDocTool.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.google.doctool;
-
-import com.google.doctool.custom.EztDoclet;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Uses the Javadoc tool to produce wiki output documenting the JRE emulation
- * classes in GWT.
- */
-public class JreDocTool {
-
- public static void main(String[] args) {
- JreDocToolFactory factory = new JreDocToolFactory();
- String arg;
-
- for (int i = 0; i < args.length; i++) {
- if (tryParseFlag(args, i, "-help")) {
- printHelp();
- return;
- } else if (null != (arg = tryParseArg(args, i, "-classpath"))) {
- i++;
- factory.setClasspath(arg);
- } else if (null != (arg = tryParseArg(args, i, "-out"))) {
- i++;
- factory.setOutputFile(arg);
- } else if (null != (arg = tryParseArg(args, i, "-packages"))) {
- i++;
- factory.setPackages(arg);
- } else if (null != (arg = tryParseArg(args, i, "-sourcepath"))) {
- i++;
- factory.setSourcepath(arg);
- }
- }
-
- JreDocTool docTool = factory.create(System.err);
- if (docTool != null) {
- docTool.process();
- }
- }
-
- /**
- * Prints help for using JreDocTool.
- */
- private static void printHelp() {
- String s = "";
- s += "JreDocTool\n";
- s += " Creates EZT format member listing from Java source";
- s += " for emulated JRE classes.\n";
- s += "\n";
- s += "Required arguments:\n";
- s += " -classpath\n";
- s += " The path to find imported classes for this doc set.\n";
- s += " -sourcepath\n";
- s += " The path to find Java source for this doc set.\n";
- s += " E.g. /gwt/src/trunk/user/super/com/google/gwt/emul\n";
- s += " -out\n";
- s += " The path and filename of the output file\n";
- s += " -packages\n";
- s += " A semicolon-separated list of fully-qualified package names.\n";
- s += " E.g. java.lang;java.lang.annotation;java.util;java.io;java.sql\n";
- s += "\n";
- System.out.println(s);
- }
-
- /**
- * Parse a flag with a argument.
- */
- private static String tryParseArg(String[] args, int i, String name) {
- if (i < args.length) {
- if (args[i].equals(name)) {
- if (i + 1 < args.length) {
- String arg = args[i + 1];
- if (arg.startsWith("-")) {
- System.out.println("Warning: arg to " + name
- + " looks more like a flag: " + arg);
- }
- return arg;
- } else {
- throw new IllegalArgumentException("Expecting an argument after "
- + name);
- }
- }
- }
- return null;
- }
-
- /**
- * Parse just a flag with no subsequent argument.
- */
- private static boolean tryParseFlag(String[] args, int i, String name) {
- if (i < args.length) {
- if (args[i].equals(name)) {
- return true;
- }
- }
- return false;
- }
-
- private String classpath;
-
- private String outputFile;
-
- private String packages;
-
- private String sourcepath;
-
- JreDocTool(String classpath, String outputFile, String packages,
- String sourcepath) {
- this.classpath = classpath;
- this.outputFile = outputFile;
- this.packages = packages;
- this.sourcepath = sourcepath;
- }
-
- private void process() {
- List args = new ArrayList();
-
- args.add("-public");
-
- args.add("-quiet");
-
- args.add("-source");
- args.add("1.8");
-
- args.add("-doclet");
- args.add(EztDoclet.class.getName());
-
- args.add("-classpath");
- args.add(this.classpath);
-
- args.add("-sourcepath");
- args.add(this.sourcepath);
-
- args.add(EztDoclet.OPT_EZTFILE);
- args.add(this.outputFile);
-
- args.addAll(Arrays.asList(this.packages.split(";")));
-
- com.sun.tools.javadoc.Main.execute(args.toArray(new String[0]));
- }
-}
diff --git a/build_tools/doctool/src/com/google/doctool/JreDocToolFactory.java b/build_tools/doctool/src/com/google/doctool/JreDocToolFactory.java
deleted file mode 100644
index 0e7ac661f75..00000000000
--- a/build_tools/doctool/src/com/google/doctool/JreDocToolFactory.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.google.doctool;
-
-import java.io.PrintStream;
-
-/**
- * Supports two-phase creation of {@link JreDocTool} objects.
- */
-public class JreDocToolFactory {
-
- private String classpath;
-
- private String outputFile;
-
- private String packages;
-
- private String sourcepath;
-
- public JreDocTool create(PrintStream err) {
- if (this.classpath == null) {
- err.println("You must specify the -classpath");
- return null;
- }
-
- if (this.outputFile == null) {
- err.println("You must specify the output file (-out)");
- return null;
- }
-
- if (this.packages == null) {
- err.println("You must specify the -packages");
- return null;
- }
-
- if (this.sourcepath == null) {
- err.println("You must specify the -sourcepath");
- return null;
- }
-
- return new JreDocTool(classpath, outputFile, packages, sourcepath);
- }
-
- public void setClasspath(String classpath) {
- this.classpath = classpath;
- }
-
- public void setOutputFile(String outputFile) {
- this.outputFile = outputFile;
- }
-
- public void setPackages(String packages) {
- this.packages = packages;
- }
-
- public void setSourcepath(String sourcePath) {
- this.sourcepath = sourcePath;
- }
-}
diff --git a/build_tools/doctool/src/com/google/doctool/LinkResolver.java b/build_tools/doctool/src/com/google/doctool/LinkResolver.java
deleted file mode 100644
index f16777d5470..00000000000
--- a/build_tools/doctool/src/com/google/doctool/LinkResolver.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.doctool;
-
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.Doc;
-import com.sun.javadoc.MemberDoc;
-import com.sun.javadoc.MethodDoc;
-import com.sun.javadoc.PackageDoc;
-import com.sun.javadoc.Parameter;
-import com.sun.javadoc.SourcePosition;
-import com.sun.javadoc.Tag;
-
-/**
- * Methods related to resolving cross-references in source.
- */
-public class LinkResolver {
-
- /**
- * Abstracts out mechanisms for finding different bits of doc.
- */
- public interface ExtraClassResolver {
- ClassDoc findClass(String className);
- }
-
- public static SourcePosition resolveLink(Tag tag) {
- return resolveLink(tag, null);
- }
-
- public static SourcePosition resolveLink(Tag tag,
- ExtraClassResolver classResolver) {
- String linkText = tag.text();
- String className;
- String methodSig;
- int pos = linkText.indexOf('#');
- if (pos >= 0) {
- className = linkText.substring(0, pos);
- methodSig = linkText.substring(pos + 1);
- } else {
- className = linkText;
- methodSig = null;
- }
-
- ClassDoc containingClass = null;
- Doc holder = tag.holder();
- if (holder instanceof ClassDoc) {
- containingClass = (ClassDoc) holder;
- } else if (holder instanceof MemberDoc) {
- containingClass = ((MemberDoc) holder).containingClass();
- }
-
- ClassDoc targetClass = null;
- if (className.length() == 0) {
- targetClass = containingClass;
- } else if (holder instanceof PackageDoc) {
- targetClass = ((PackageDoc) holder).findClass(className);
- } else {
- targetClass = containingClass.findClass(className);
- }
-
- if (targetClass == null) {
- if (classResolver != null) {
- targetClass = classResolver.findClass(className);
- }
- if (targetClass == null) {
- System.err.println(tag.position().toString()
- + ": unable to resolve class " + className + " for " + tag);
- System.exit(1);
- }
- }
-
- if (methodSig == null) {
- return targetClass.position();
- }
-
- String paramSig = methodSig.substring(methodSig.indexOf('(') + 1,
- methodSig.lastIndexOf(')'));
- String[] resolvedParamTypes;
- if (paramSig.length() > 0) {
- String[] unresolvedParamTypes = paramSig.split("\\s*,\\s*");
- resolvedParamTypes = new String[unresolvedParamTypes.length];
- for (int i = 0; i < unresolvedParamTypes.length; ++i) {
- ClassDoc paramType = containingClass.findClass(unresolvedParamTypes[i]);
- if (paramType == null && classResolver != null) {
- paramType = classResolver.findClass(unresolvedParamTypes[i]);
- }
- if (paramType == null) {
- System.err.println(tag.position().toString()
- + ": unable to resolve class " + unresolvedParamTypes[i]
- + " for " + tag);
- System.exit(1);
- }
- resolvedParamTypes[i] = paramType.qualifiedTypeName();
- }
- } else {
- resolvedParamTypes = new String[0];
- }
-
- String possibleOverloads = "";
-
- MethodDoc[] methods = targetClass.methods();
- outer : for (int i = 0; i < methods.length; ++i) {
- MethodDoc methodDoc = methods[i];
- if (methodSig.startsWith(methodDoc.name())) {
- possibleOverloads += "\n" + methodDoc.flatSignature();
- Parameter[] tryParams = methodDoc.parameters();
- if (resolvedParamTypes.length != tryParams.length) {
- // param count mismatch
- continue outer;
- }
- for (int j = 0; j < tryParams.length; ++j) {
- if (!tryParams[j].type().qualifiedTypeName().equals(
- resolvedParamTypes[j])) {
- // param type mismatch
- continue outer;
- }
- }
- return methodDoc.position();
- }
- }
-
- System.err.println(tag.position().toString()
- + ": unable to resolve method for " + tag);
- if (possibleOverloads.length() > 0) {
- System.err.println("Possible overloads: " + possibleOverloads);
- }
- System.exit(1);
- return null;
- }
-
-}
diff --git a/build_tools/doctool/src/com/google/doctool/ResourceIncluder.java b/build_tools/doctool/src/com/google/doctool/ResourceIncluder.java
index 97833c298f6..71fe1a01d22 100644
--- a/build_tools/doctool/src/com/google/doctool/ResourceIncluder.java
+++ b/build_tools/doctool/src/com/google/doctool/ResourceIncluder.java
@@ -15,12 +15,11 @@
*/
package com.google.doctool;
-import com.sun.javadoc.Tag;
-
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
/**
* Utility methods related to including external resources in doc.
@@ -28,30 +27,23 @@
public class ResourceIncluder {
/**
- * Copied from {@link com.google.gwt.util.tools.Utility#close(InputStream)}.
+ * Copied from {@link com.google.gwt.util.tools.Utility#close(AutoCloseable)}.
*/
- public static void close(InputStream is) {
+ public static void close(AutoCloseable is) {
try {
if (is != null) {
is.close();
}
- } catch (IOException e) {
+ } catch (Exception e) {
}
}
- public static String getResourceFromClasspathScrubbedForHTML(Tag tag) {
- String partialPath = tag.text();
- try {
- String contents;
- contents = getFileFromClassPath(partialPath);
- contents = scrubForHtml(contents);
- return contents;
- } catch (IOException e) {
- System.err.println(tag.position().toString()
- + ": unable to include resource " + partialPath + " for tag " + tag);
- System.exit(1);
- return null;
- }
+ public static String getResourceFromClasspathScrubbedForHTML(String partialPath)
+ throws IOException {
+ String contents;
+ contents = getFileFromClassPath(partialPath);
+ contents = scrubForHtml(contents);
+ return contents;
}
/**
@@ -67,11 +59,20 @@ private static String getFileFromClassPath(String partialPath)
throw new FileNotFoundException(partialPath);
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
- int ch;
- while ((ch = in.read()) != -1) {
- os.write(ch);
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while (true) {
+ bytesRead = in.read(buffer);
+ if (bytesRead >= 0) {
+ // Copy the bytes out.
+ os.write(buffer, 0, bytesRead);
+ } else {
+ // End of input stream.
+ break;
+ }
}
- return new String(os.toByteArray(), "UTF-8");
+
+ return os.toString(StandardCharsets.UTF_8);
} finally {
close(in);
}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/AbstractTaglet.java b/build_tools/doctool/src/com/google/doctool/custom/AbstractTaglet.java
new file mode 100644
index 00000000000..9c2959757a7
--- /dev/null
+++ b/build_tools/doctool/src/com/google/doctool/custom/AbstractTaglet.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2022 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.doctool.custom;
+
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.EndElementTree;
+import com.sun.source.doctree.EntityTree;
+import com.sun.source.doctree.StartElementTree;
+import com.sun.source.doctree.TextTree;
+import com.sun.source.util.DocTreeScanner;
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Taglet;
+
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+
+/**
+ * Abstract taglet baseclass to facilitate some basic operations.
+ */
+public abstract class AbstractTaglet implements Taglet {
+ protected DocletEnvironment env;
+
+ @Override
+ public void init(DocletEnvironment env, Doclet doclet) {
+ this.env = env;
+ }
+
+ /**
+ * Given a tag, returns the html within that tag.
+ *
+ * @param tag the tag to read the text from
+ * @return the tags, entities, and text within that tag, as an html string
+ */
+ protected String getHtmlContent(DocTree tag) {
+ StringBuilder sb = new StringBuilder();
+ tag.accept(new DocTreeScanner() {
+ @Override
+ public Void visitStartElement(StartElementTree node, Void unused) {
+ sb.append("<").append(node.getName());
+ if (!node.getAttributes().isEmpty()) {
+ sb.append(" ");
+ // super only scans attributes
+ super.visitStartElement(node, unused);
+ }
+ if (node.isSelfClosing()) {
+ sb.append("/>");
+ } else {
+ sb.append(">");
+ }
+
+ return null;
+ }
+
+ @Override
+ public Void visitEndElement(EndElementTree node, Void unused) {
+ sb.append("").append(node.getName()).append(">");
+ return null;
+ }
+
+ @Override
+ public Void visitText(TextTree node, Void unused) {
+ // Only includes non-entity text
+ sb.append(node.getBody());
+ return null;
+ }
+
+ @Override
+ public Void visitEntity(EntityTree node, Void unused) {
+ // Entities need to be wrapped in &/;, but we aren't worrying about illegal
+ // entities here, assuming they are handled elsewhere
+ sb.append("&").append(node.getName()).append(";");
+ return null;
+ }
+ }, null);
+ return sb.toString();
+ }
+
+ /**
+ * Helper method to log a diagnostic message to the user about a particular element+doctree.
+ *
+ * @param kind the kind of message to log
+ * @param message the message text to write
+ * @param element the element that the message applies to
+ * @param docTree the doctree node that the message applies to
+ */
+ protected void printMessage(Diagnostic.Kind kind, String message, Element element,
+ DocTree docTree) {
+ env.getDocTrees().printMessage(
+ kind,
+ message,
+ docTree,
+ env.getDocTrees().getDocCommentTree(element),
+ env.getDocTrees().getPath(element).getCompilationUnit()
+ );
+ }
+}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/ExampleTaglet.java b/build_tools/doctool/src/com/google/doctool/custom/ExampleTaglet.java
index 788e604f67d..544a6a4535b 100644
--- a/build_tools/doctool/src/com/google/doctool/custom/ExampleTaglet.java
+++ b/build_tools/doctool/src/com/google/doctool/custom/ExampleTaglet.java
@@ -15,116 +15,154 @@
*/
package com.google.doctool.custom;
-import com.google.doctool.LinkResolver;
-import com.google.doctool.LinkResolver.ExtraClassResolver;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.DocTreePath;
+import com.sun.source.util.DocTrees;
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.SourcePosition;
-import com.sun.javadoc.Tag;
-import com.sun.tools.doclets.Taglet;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
import java.io.IOException;
-import java.util.Map;
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+import java.io.Reader;
+import java.nio.CharBuffer;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
/**
* A taglet for slurping examples into javadoc output.
*/
-public class ExampleTaglet implements Taglet {
-
- public static void register(Map tagletMap) {
- ExampleTaglet tag = new ExampleTaglet();
- Taglet t = (Taglet) tagletMap.get(tag.getName());
- if (t != null) {
- tagletMap.remove(tag.getName());
- }
- tagletMap.put(tag.getName(), tag);
- }
+public class ExampleTaglet extends AbstractTaglet {
+ @Override
public String getName() {
return "example";
}
- public boolean inConstructor() {
- return true;
- }
+ @Override
+ public String toString(List extends DocTree> list, Element element) {
+ StringBuilder results = new StringBuilder();
+ DocTrees trees = env.getDocTrees();
+ for (DocTree tag : list) {
+ String linkText = getHtmlContent(tag);
+
+ // Using the linktext and the current element as context, find the referenced Element if any
+ final Element targetElement = trees.getElement(
+ new DocTreePath(
+ new DocTreePath(
+ trees.getPath(element),
+ trees.getDocCommentTree(element)
+ ),
+ trees.getDocTreeFactory().newReferenceTree(linkText)
+ )
+ );
+ if (targetElement == null) {
+ String message = "Unable to resolve " + linkText + " found in javadoc for " + element;
+ printMessage(Diagnostic.Kind.ERROR, message, element, tag);
+ // return empty so the docs continue, fail
+ return "";
+ }
- public boolean inField() {
- return true;
- }
+ // having found the specified element, get its position in the source file
+ Tree tree = trees.getTree(targetElement);
- public boolean inMethod() {
- return true;
- }
+ // find the compilation unit that was contains this
+ CompilationUnitTree cu = trees.getPath(targetElement).getCompilationUnit();
+ try (Reader reader = cu.getSourceFile().openReader(false)) {
+ long startPosition = trees.getSourcePositions().getStartPosition(cu, tree);
- public boolean inOverview() {
- return true;
- }
+ String slurpSource = slurpSource(reader, startPosition);
+ // The
tag still requires '<' and '>' characters to be escaped
+ slurpSource = slurpSource.replace("<", "<");
+ slurpSource = slurpSource.replace(">", ">");
+ results.append("
").append(slurpSource).append("
");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
- public boolean inPackage() {
- return true;
+ return results.toString();
}
- public boolean inType() {
- return true;
+ @Override
+ public Set getAllowedLocations() {
+ return EnumSet.allOf(Location.class);
}
+ @Override
public boolean isInlineTag() {
return true;
}
- public String toString(Tag tag) {
- SourcePosition position = LinkResolver.resolveLink(tag,
- new ExtraClassResolver() {
- public ClassDoc findClass(String className) {
- return GWTJavaDoclet.root.classNamed(className);
+ /**
+ * Read the content of the reader line by line until the start character is found in a line.
+ * Remove leading whitespace on each line to match the first, and stop when closing curly
+ * brackets match opening brackets.
+ *
+ * @param reader the reader to get bytes from
+ * @param startChar the first character of the file that we're interested in
+ * @return a newline-joined, html-escaped string
+ */
+ private static String slurpSource(Reader reader, long startChar) throws IOException {
+ // We want to skip until the line that contains character startChar - can't use BufferedReader
+ // for this as it won't count characters (and the newlines could be two chars etc)
+
+ // style guide says 100, actual max is around 190
+ CharBuffer line = CharBuffer.allocate(250);
+ // position starts at 0, since we incr at the same time as we read
+ int position = -1;
+ // accumulate finished lines to return
+ StringBuilder lines = new StringBuilder();
+ // indent starts at -1 meaning "we don't know the indentation level yet"
+ int indent = -1;
+
+ // braceDepth lets us tell when we finish the target element, but we have to be sure we saw at
+ // least one open/close set, or semicolon.
+ int braceDepth = 0;
+ boolean seenSemiColonOrBrace = false;
+
+ // read each character - if \r (check for a \n to follow) or \n end the line and record the
+ // position of the end of the line.
+ int ch = reader.read();
+ position++;
+ while (true) {
+ if (ch == '\n' || ch == '\r' || ch == -1) {
+ if (ch == '\r') {
+ ch = reader.read();
+ position++;
+ if (ch == '\n') {
+ ch = reader.read();
+ position++;
}
- });
-
- String slurpSource = slurpSource(position);
- // The
tag still requires '<' and '>' characters to be escaped
- slurpSource = slurpSource.replace("<", "<");
- slurpSource = slurpSource.replace(">", ">");
- return "
" + slurpSource + "
";
- }
-
- public String toString(Tag[] tags) {
- if (tags == null || tags.length == 0) {
- return null;
- }
- String result = "";
- for (int i = 0; i < tags.length; i++) {
- result += toString(tags[i]);
- }
- return result;
- }
-
- private static String slurpSource(SourcePosition position) {
- BufferedReader br = null;
- try {
- br = new BufferedReader(new FileReader(position.file()));
- for (int i = 0, n = position.line() - 1; i < n; ++i) {
- br.readLine();
- }
-
- StringBuffer lines = new StringBuffer();
- String line = br.readLine();
- int braceDepth = 0;
- int indent = -1;
- boolean seenSemiColonOrBrace = false;
- while (line != null) {
+ } else if (ch == '\n') {
+ ch = reader.read();
+ position++;
+ } // else EOF, nothing to do
+
+ // We've read a full line (and are ready to start the next one).
+ // If position < startChar, we haven't yet reached our content, continue
+ if (position <= startChar) {
+ line.clear();
+ continue;
+ }
+ // make the written chars available to be read
+ line.flip();
if (indent == -1) {
+ // this is our first line, read the indentation level
for (indent = 0; Character.isWhitespace(line.charAt(indent)); ++indent) {
// just accumulate
}
}
-
+ // remove the indent chars from this line, and append it
+ String lineStr;
if (line.length() >= indent) {
- line = line.substring(indent);
+ lineStr = line.subSequence(indent, line.length()).toString();
+ } else {
+ lineStr = line.toString();
}
- lines.append(line).append("\n");
+ lines.append(lineStr).append('\n');
for (int i = 0, n = line.length(); i < n; ++i) {
char c = line.charAt(i);
if (c == '{') {
@@ -137,26 +175,23 @@ private static String slurpSource(SourcePosition position) {
}
}
- if (braceDepth > 0 || !seenSemiColonOrBrace) {
- line = br.readLine();
- } else {
+ // now that we've written the line, check if it was our final line
+ if ((braceDepth <= 0 && seenSemiColonOrBrace) || ch == -1) {
break;
}
- }
- return lines.toString();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (br != null) {
- br.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
+ // free up the buffer to have new chars written to it
+ line.clear();
+ } else {
+ // we're in the middle of a line, record the character and continue
+ line.put((char) ch);
+
+ ch = reader.read();
+ position++;
}
}
- return "";
+
+ return lines.toString();
}
}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/EztDoclet.java b/build_tools/doctool/src/com/google/doctool/custom/EztDoclet.java
deleted file mode 100644
index 37853a92338..00000000000
--- a/build_tools/doctool/src/com/google/doctool/custom/EztDoclet.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.google.doctool.custom;
-
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.DocErrorReporter;
-import com.sun.javadoc.ExecutableMemberDoc;
-import com.sun.javadoc.FieldDoc;
-import com.sun.javadoc.PackageDoc;
-import com.sun.javadoc.RootDoc;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-
-/**
- * A doclet for using producing EZT output listing the specified classes and
- * their methods and constructors.
- */
-public class EztDoclet {
-
- public static final String OPT_EZTFILE = "-eztfile";
-
- private static EztDoclet EZT_DOCLET;
-
- private static final String JAVADOC_URL = "https://docs.oracle.com/javase/8/docs/api/";
-
- public static int optionLength(String option) {
- if (option.equals(OPT_EZTFILE)) {
- return 2;
- }
- return 0;
- }
-
- public static boolean start(RootDoc root) {
- getDoclet().process(root);
- return true;
- }
-
- public static boolean validOptions(String[][] options,
- DocErrorReporter reporter) {
- return getDoclet().analyzeOptions(options, reporter);
- }
-
- private static EztDoclet getDoclet() {
- if (EZT_DOCLET == null) {
- EZT_DOCLET = new EztDoclet();
- }
- return EZT_DOCLET;
- }
-
- private String outputFile;
-
- private boolean analyzeOptions(String[][] options, DocErrorReporter reporter) {
- for (int i = 0; i < options.length; i++) {
- if (options[i][0] == OPT_EZTFILE) {
- outputFile = options[i][1];
- }
- }
-
- if (outputFile == null) {
- reporter.printError("You must specify an output filepath with "
- + OPT_EZTFILE);
- return false;
- }
-
- return true;
- }
-
- private String createFieldList(Collection fields) {
- StringBuffer buffer = new StringBuffer();
- Iterator iter = fields.iterator();
- while (iter.hasNext()) {
- FieldDoc field = iter.next();
- buffer.append(field.name());
- if (iter.hasNext()) {
- buffer.append(", ");
- }
- }
- return buffer.toString();
- }
-
- private String createMemberList(Collection members) {
- StringBuffer buffer = new StringBuffer();
- Iterator iter = members.iterator();
- while (iter.hasNext()) {
- ExecutableMemberDoc member = iter.next();
- buffer.append(member.name() + member.flatSignature());
- if (iter.hasNext()) {
- buffer.append(", ");
- }
- }
- return buffer.toString();
- }
-
- private void process(RootDoc root) {
- try {
- File outFile = new File(outputFile);
- outFile.getParentFile().mkdirs();
- FileWriter fw = new FileWriter(outFile);
- PrintWriter pw = new PrintWriter(fw, true);
-
- pw.println("");
- for (PackageDoc pack : root.specifiedPackages()) {
- pw.format("
\n", packURL,
- cls.name(), cls.name());
-
- // Print out all fields
- Collection fields = new ArrayList();
- fields.addAll(Arrays.asList(cls.fields(true)));
-
- if (!fields.isEmpty()) {
- pw.format("
%s
\n", createFieldList(fields));
- }
-
- // Print out all constructors and methods
- Collection members = new ArrayList();
- members.addAll(Arrays.asList(cls.constructors(true)));
- members.addAll(Arrays.asList(cls.methods(true)));
-
- if (!members.isEmpty()) {
- pw.format("
\n");
- }
- pw.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/FindPackages.java b/build_tools/doctool/src/com/google/doctool/custom/FindPackages.java
index ee280bd1b98..fb00872b4a5 100644
--- a/build_tools/doctool/src/com/google/doctool/custom/FindPackages.java
+++ b/build_tools/doctool/src/com/google/doctool/custom/FindPackages.java
@@ -26,7 +26,7 @@
import java.util.regex.Pattern;
/**
- * Used by trunk/doc/build.xml to generate the packages.properties file.
+ * Used by doc/build.xml to generate the packages.properties file.
*/
public class FindPackages {
@@ -55,13 +55,20 @@ public class FindPackages {
private static final String[] JAVA_PKGS = {
"java.beans",
"java.io",
- "java.lang", "java.lang.annotation", "java.lang.reflect",
+ "java.lang",
+ "java.lang.annotation",
+ "java.lang.reflect",
"java.math",
"java.nio.charset",
"java.security",
"java.sql",
"java.text",
- "java.util", "java.util.concurrent", "java.util.concurrent.atomic", "java.util.function", "java.util.logging", "java.util.stream"
+ "java.util",
+ "java.util.concurrent",
+ "java.util.concurrent.atomic",
+ "java.util.function",
+ "java.util.logging",
+ "java.util.stream"
};
/**
@@ -90,14 +97,14 @@ public class FindPackages {
"user/src/com/google/gwt/i18n/server/GwtLocaleFactoryImpl.java",
"user/src/com/google/gwt/i18n/server/GwtLocaleImpl.java"};
- private static Pattern exclusions;
+ private static final Pattern exclusions;
static {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < EXCLUSIONS.length; i++) {
String ex = EXCLUSIONS[i];
ex = ex.replace(".", "\\.");
if (i < EXCLUSIONS.length - 1) {
- sb.append(ex + "|");
+ sb.append(ex).append("|");
} else {
sb.append(ex);
}
@@ -128,14 +135,16 @@ public static void main(String[] args) {
out.println("JAVA_PKGS=\\");
for (int i = 0; i < JAVA_PKGS.length; i++) {
if (i < JAVA_PKGS.length - 1) {
- out.println(JAVA_PKGS[i] + ";\\");
+ out.println(JAVA_PKGS[i] + ",\\");
} else {
out.println(JAVA_PKGS[i]);
}
}
out.println("# The last package should not have a trailing semicolon");
- out.println("");
- out.println("# Individual classes to include when we don't want to include an entire package");
+ out.println();
+ out.println(
+ "# Individual classes to include when we don't want to include an entire package"
+ );
out.println("USER_CLASSES=\\");
// Output a package-info.java once for each package
@@ -145,15 +154,15 @@ public static void main(String[] args) {
String classPath = className.substring(0, className.lastIndexOf('/'));
if (!classPaths.contains(classPath)) {
classPaths.add(classPath);
- out.println("${gwt.root}/" + classPath + "/package-info.java" + ":\\");
+ out.println("${gwt.root}/" + classPath + "/package-info.java" + ",\\");
}
if (i < USER_CLASSES.length - 1) {
- out.println("${gwt.root}/" + className + ":\\");
+ out.println("${gwt.root}/" + className + ",\\");
} else {
out.println("${gwt.root}/" + className);
}
}
- out.println("");
+ out.println();
out.println("# Packages to include");
out.println("USER_PKGS=\\");
@@ -171,7 +180,7 @@ public static void main(String[] args) {
for (int i = 0; i < packages.size(); i++) {
if (i < packages.size() - 1) {
- out.println(packageList.get(i) + ";\\");
+ out.println(packageList.get(i) + ",\\");
} else {
out.println(packageList.get(i));
}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/GWTJavaDoclet.java b/build_tools/doctool/src/com/google/doctool/custom/GWTJavaDoclet.java
deleted file mode 100644
index ad9e747b3bd..00000000000
--- a/build_tools/doctool/src/com/google/doctool/custom/GWTJavaDoclet.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.doctool.custom;
-
-import com.sun.javadoc.Doclet;
-import com.sun.javadoc.RootDoc;
-import com.sun.tools.doclets.standard.Standard;
-import com.sun.tools.javadoc.Main;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A doclet for using GWT-specific tags in standard javadoc output.
- */
-public class GWTJavaDoclet extends Doclet {
-
- static RootDoc root = null;
-
- private static final String[] TAGLET_ARGS = new String[] {
- "-taglet", ExampleTaglet.class.getName(), "-taglet",
- TipTaglet.class.getName(), "-taglet", IncludeTaglet.class.getName()};
-
- public static void main(String[] args) {
- List examplePackages = new ArrayList();
- List filteredArgs = new ArrayList();
-
- // filter out and save packages args
- for (int i = 0; i < args.length; ++i) {
- if (args[i].equalsIgnoreCase("-examplepackages")) {
- String nextArg = args[++i];
- String[] split = nextArg.split(":|;");
- for (int j = 0; j < split.length; ++j) {
- examplePackages.add(split[j]);
- }
- } else if (args[i].equalsIgnoreCase("-packages")) {
- String nextArg = args[++i];
- String[] split = nextArg.split(":|;");
- for (int j = 0; j < split.length; ++j) {
- filteredArgs.add(split[j]);
- }
- } else {
- filteredArgs.add(args[i]);
- }
- }
-
- // Build a javadoc structure that includes example packages for reference
- String name = GWTJavaDoclet.class.getName();
- List myArgs = new ArrayList();
- myArgs.addAll(filteredArgs);
- myArgs.addAll(examplePackages);
- Main.execute(name, name, (String[]) myArgs.toArray(new String[] {}));
-
- // Now delegate to the real javadoc without the example packages
- filteredArgs.addAll(0, Arrays.asList(TAGLET_ARGS));
- Main.execute((String[]) filteredArgs.toArray(new String[] {}));
- }
-
- public static int optionLength(String option) {
- // delegate
- return Standard.optionLength(option);
- }
-
- public static boolean start(RootDoc root) {
- // cache the root; ExampleTag will use it for reference later.
- GWTJavaDoclet.root = root;
- return true;
- }
-
-}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/IncludeTaglet.java b/build_tools/doctool/src/com/google/doctool/custom/IncludeTaglet.java
index 26e18bf9a51..80ac4443f39 100644
--- a/build_tools/doctool/src/com/google/doctool/custom/IncludeTaglet.java
+++ b/build_tools/doctool/src/com/google/doctool/custom/IncludeTaglet.java
@@ -17,65 +17,54 @@
import com.google.doctool.ResourceIncluder;
-import com.sun.javadoc.Tag;
-import com.sun.tools.doclets.Taglet;
+import com.sun.source.doctree.DocTree;
-import java.util.Map;
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
/**
* A taglet for slurping in the content of artbitrary files appearing on the
* classpath into javadoc.
*/
-public class IncludeTaglet implements Taglet {
-
- public static void register(Map tagletMap) {
- IncludeTaglet tag = new IncludeTaglet();
- Taglet t = (Taglet) tagletMap.get(tag.getName());
- if (t != null) {
- tagletMap.remove(tag.getName());
- }
- tagletMap.put(tag.getName(), tag);
- }
+public class IncludeTaglet extends AbstractTaglet {
+ @Override
public String getName() {
return "gwt.include";
}
- public boolean inConstructor() {
- return true;
- }
-
- public boolean inField() {
- return true;
- }
-
- public boolean inMethod() {
- return true;
- }
-
- public boolean inOverview() {
- return true;
+ @Override
+ public String toString(List extends DocTree> list, Element element) {
+ StringBuilder results = new StringBuilder();
+ for (DocTree docTree : list) {
+ String text = getHtmlContent(docTree);
+
+ try {
+ String contents = ResourceIncluder.getResourceFromClasspathScrubbedForHTML(text);
+ results.append("
").append(contents).append("
");
+ } catch (IOException e) {
+ e.printStackTrace();
+ printMessage(Diagnostic.Kind.ERROR, "Error in reading file: " + e.getMessage(), element,
+ docTree);
+ // return empty to let javadoc report this
+ return "";
+ }
+ }
+ return results.toString();
}
- public boolean inPackage() {
- return true;
- }
-
- public boolean inType() {
- return true;
+ @Override
+ public Set getAllowedLocations() {
+ return EnumSet.allOf(Location.class);
}
+ @Override
public boolean isInlineTag() {
return true;
}
- public String toString(Tag tag) {
- String contents = ResourceIncluder.getResourceFromClasspathScrubbedForHTML(tag);
- return "
" + contents + "
";
- }
-
- public String toString(Tag[] tags) {
- return null;
- }
-
}
diff --git a/build_tools/doctool/src/com/google/doctool/custom/JavaEmulSummaryDoclet.java b/build_tools/doctool/src/com/google/doctool/custom/JavaEmulSummaryDoclet.java
new file mode 100644
index 00000000000..1b8a5ce21be
--- /dev/null
+++ b/build_tools/doctool/src/com/google/doctool/custom/JavaEmulSummaryDoclet.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.doctool.custom;
+
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * A doclet for listing the specified classes and
+ * their methods and constructors.
+ */
+public class JavaEmulSummaryDoclet implements Doclet {
+
+ public static final String OPT_OUTFILE = "-outfile";
+ private static final String JAVADOC_URL = "https://docs.oracle.com/en/java/javase/11/docs/api/";
+
+ private Reporter reporter;
+ private String outputFile;
+
+ @Override
+ public boolean run(DocletEnvironment env) {
+ try {
+
+ File outFile = new File(outputFile);
+ outFile.getParentFile().mkdirs();
+ try (FileWriter fw = new FileWriter(outFile);
+ PrintWriter pw = new PrintWriter(fw, true)) {
+
+ pw.println("");
+ getSpecifiedPackages(env)
+ .forEach(pack -> {
+ pw.format("
";
- return result;
+ result.append("");
+ return result.toString();
+ }
+
+ @Override
+ public boolean isInlineTag() {
+ return false;
}
}
diff --git a/common.ant.xml b/common.ant.xml
index 7c5d26ea669..36a56b4882d 100755
--- a/common.ant.xml
+++ b/common.ant.xml
@@ -28,11 +28,11 @@
-
+
+
+
@@ -62,8 +62,7 @@
-
-
+
@@ -158,8 +157,7 @@
-
-
+
@@ -172,7 +170,7 @@
@@ -251,6 +249,7 @@
+
@@ -273,6 +272,7 @@
+
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
index d6b333a1e17..273e63cf4f2 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
@@ -30,7 +30,6 @@
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlets.GzipFilter;
import java.io.BufferedReader;
import java.io.File;
@@ -125,7 +124,7 @@ void start(final TreeLogger logger) throws UnableToCompleteException {
connector.setReuseAddress(false);
newServer.addConnector(connector);
- ServletContextHandler newHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ ServletContextHandler newHandler = new ServletContextHandler(ServletContextHandler.GZIP);
newHandler.setContextPath("/");
newHandler.addServlet(new ServletHolder(new HttpServlet() {
@Override
@@ -134,7 +133,6 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
handleRequest(request.getPathInfo(), request, response, logger);
}
}), "/*");
- newHandler.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
newServer.setHandler(newHandler);
try {
newServer.start();
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/installLocationIframe.js b/dev/core/src/com/google/gwt/core/ext/linker/impl/installLocationIframe.js
index 59fca5c907f..c9c39393862 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/installLocationIframe.js
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/installLocationIframe.js
@@ -46,8 +46,10 @@ function setupInstallLocation() {
// throwing away the current document.
//
// In IE, it ensures that the element is immediately available.
- frameDoc.open();
- var doctype = (document.compatMode == 'CSS1Compat') ? '' : '';
- frameDoc.write(doctype + '');
- frameDoc.close();
+ if (navigator.userAgent.indexOf("Chrome") == -1) {
+ frameDoc.open();
+ var doctype = (document.compatMode == 'CSS1Compat') ? '' : '';
+ frameDoc.write(doctype + '');
+ frameDoc.close();
+ }
}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js b/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js
index 725505e0bf0..2df43d26150 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js
@@ -9,7 +9,9 @@ function installScript(filename) {
var docbody = doc.body;
var script = doc.createElement('script');
script.language='javascript';
- script.crossOrigin='';
+ if (location.host) {
+ script.crossOrigin='';
+ }
script.src = code;
if (__MODULE_FUNC__.__errFn) {
script.onerror = function() {
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js b/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js
index 0e2712b130d..85bd6e62090 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js
@@ -19,29 +19,15 @@ function installScript(filename) {
var doc = getInstallLocationDoc();
var docbody = doc.body;
var script;
- // for sourcemaps, we inject textNodes into the script element on Chrome
- if (navigator.userAgent.indexOf("Chrome") > -1 && window.JSON) {
- var scriptFrag = doc.createDocumentFragment()
- // surround code with eval until crbug #90707
- scriptFrag.appendChild(doc.createTextNode("eval(\""));
- for (var i = 0; i < code.length; i++) {
- // escape newlines, backslashes, and quotes with JSON.stringify
- // rather than create multiple script tags which mess up line numbers, we use 1 tag, multiple text nodes
- var c = window.JSON.stringify(code[i]);
- // trim beginning/end quotes
- scriptFrag.appendChild(doc.createTextNode(c.substring(1, c.length - 1)));
- }
- // close the eval
- scriptFrag.appendChild(doc.createTextNode("\");"));
+ // for sourcemaps, we inject the code as a single string for Chrome
+ if (navigator.userAgent.indexOf("Chrome") > -1) {
script = doc.createElement('script');
- script.language='javascript';
- script.appendChild(scriptFrag);
+ script.text = code.join('');
docbody.appendChild(script);
removeScript(docbody, script);
} else {
for (var i = 0; i < code.length; i++) {
script = doc.createElement('script');
- script.language='javascript';
script.text = code[i];
docbody.appendChild(script);
removeScript(docbody, script);
diff --git a/dev/core/src/com/google/gwt/core/ext/soyc/impl/StoryRecorder.java b/dev/core/src/com/google/gwt/core/ext/soyc/impl/StoryRecorder.java
index beada0d13e1..bfa7223d38b 100644
--- a/dev/core/src/com/google/gwt/core/ext/soyc/impl/StoryRecorder.java
+++ b/dev/core/src/com/google/gwt/core/ext/soyc/impl/StoryRecorder.java
@@ -169,16 +169,13 @@ private void analyzeFragment(MemberFactory memberFactory, TreeSet c
assert info != null;
// Infer dependency information
- if (!dependencyScope.isEmpty()) {
-
+ while (!dependencyScope.isEmpty() && !dependencyScope.peek().range.contains(range)) {
/*
* Pop frames until we get back to a container, using this as a chance
* to build up our list of non-overlapping Ranges to report back to the
* user.
*/
- while (!dependencyScope.peek().range.contains(range)) {
- popAndRecord(dependencyScope, fragment);
- }
+ popAndRecord(dependencyScope, fragment);
}
// Possibly create and record Members
@@ -271,7 +268,7 @@ private void emitStory(StoryImpl story, Range range) throws IOException {
builder.append("\"/>\n\n");
} else {
builder.append("\">");
- SizeMapRecorder.escapeXml(jsCode, start, end, false, builder);
+ SizeMapRecorder.escapeXml(jsCode, start, Math.min(end,jsCode.length()), false, builder);
builder.append("\n\n");
}
}
@@ -297,7 +294,7 @@ private void popAndRecord(Stack dependencyScope, int fragment) throws
* Make a new Range for the gap between the popped Range and whatever we
* last stored.
*/
- if (lastEnd < toStore.getStart()) {
+ if (lastEnd < toStore.getStart() && !dependencyScope.isEmpty()) {
Range newRange = new Range(lastEnd, toStore.getStart());
assert !dependencyScope.isEmpty();
@@ -351,7 +348,9 @@ private void recordStory(SourceInfo info, int fragment, int length, Range range)
theStory = new StoryImpl(storyCache.get(info), length);
}
- emitStory(theStory, range);
+ if (range.getStart() < js[curHighestFragment].length()) {
+ emitStory(theStory, range);
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js b/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
index 53d168da3d6..30cfb179c3e 100644
--- a/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
+++ b/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
@@ -93,15 +93,21 @@ function __MODULE_FUNC__() {
,markerId = "__gwt_marker___MODULE_NAME__"
,markerScript;
- $doc.write('');
- markerScript = $doc.getElementById(markerId);
-
- // Our script element is assumed to be the closest previous script element
- // to the marker, so start at the marker and walk backwards until we find
- // a script.
- thisScript = markerScript && markerScript.previousSibling;
- while (thisScript && thisScript.tagName != 'SCRIPT') {
- thisScript = thisScript.previousSibling;
+ if ($doc.currentScript) {
+ // document.currentScript is not supported by IE 11.
+ thisScript = $doc.currentScript;
+ } else {
+ // may fail in extension or anywhere else with inability to use document.write
+ $doc.write('');
+ markerScript = $doc.getElementById(markerId);
+
+ // Our script element is assumed to be the closest previous script element
+ // to the marker, so start at the marker and walk backwards until we find
+ // a script.
+ thisScript = markerScript && markerScript.previousSibling;
+ while (thisScript && thisScript.tagName != 'SCRIPT') {
+ thisScript = thisScript.previousSibling;
+ }
}
// Gets the part of a url up to and including the 'path' portion.
diff --git a/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java b/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java
index 762c4228ed8..a70120930ba 100644
--- a/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java
@@ -56,7 +56,7 @@ private static class CompileDependencyVisitor extends ClassVisitor {
private Map methods = new HashMap();
public CompileDependencyVisitor() {
- super(Opcodes.ASM7);
+ super(Opcodes.ASM9);
}
public String getSignature() {
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
index 6f7f003dc0d..0066c2f7628 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
@@ -66,7 +66,7 @@ private static class AnonymousClassVisitor extends EmptyVisitor {
public AnonymousClassVisitor() {
- this.mv = new org.objectweb.asm.MethodVisitor(Opcodes.ASM7, this.mv) {
+ this.mv = new org.objectweb.asm.MethodVisitor(Opcodes.ASM9, this.mv) {
@Override
public void visitCode() {
++sawCode;
diff --git a/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java b/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java
index 95fcc52fc0b..2d26d19d577 100644
--- a/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java
+++ b/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java
@@ -79,7 +79,7 @@ public static class MyAnnotationArrayVisitor extends AnnotationVisitor {
private final List
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -125,24 +116,25 @@
- Building JRE emulation EZT
+ Building JRE emulation summary
-
-
+
+
-
-
-
-
-
-
-
+
-
+
diff --git a/maven/README.txt b/maven/README.txt
index 25bb9a5c6c2..17adaf94b9d 100644
--- a/maven/README.txt
+++ b/maven/README.txt
@@ -1,11 +1,11 @@
push-gwt.sh packages and deploys GWT to a local or remote Maven
repository
-To build GWT from trunk and deploy to your local repo:
+To build GWT from main and deploy to your local repo:
-> cd trunk
+> git switch main
> ant clean dist-dev
-> maven/push-gwt.sh
+> maven/push-gwtproject.sh
Follow the prompts to set the GWT version # and path to the
distribution ZIP (it will automatically find it in build/dist if
@@ -19,9 +19,9 @@ script. If the remote repo requires a username and password, define
the repo in your ~/.m2/settings.xml as below and set GWT_MAVEN_REPO_ID
= server id. In this example, GWT_MAVEN_REPO_ID would be "sonatype".
-> cd trunk
+> git switch main
> ant clean dist # must be dist, not dist-dev, to generate Javadocs
-> maven/push-gwt.sh
+> maven/push-gwtproject.sh
~/.m2/settings.xml:
diff --git a/user/build.xml b/user/build.xml
index 1c5aa2e3c72..df5fc64d077 100755
--- a/user/build.xml
+++ b/user/build.xml
@@ -15,18 +15,24 @@
-
+ value="**/*JreSuite.class,**/OptimizedOnly*"
+ else="**/*JreSuite.class,**/OptimizedOnly*,**/*Java9Suite.class,**/*Java10Suite.class,**/*Java11Suite.class">
+
+
+
+
+
+
+
+
-
+ value="**/EmulSuite.class,**/JSONSuite.class,**/RunAsyncSuite.class,**/*CompilerSuite.class,**/*JsInteropSuite.class,**/*JreSuite.class,**/OptimizedOnly*"
+ else="**/EmulSuite.class,**/JSONSuite.class,**/RunAsyncSuite.class,**/*CompilerSuite.class,**/*JsInteropSuite.class,**/*JreSuite.class,**/OptimizedOnly*,**/*Java9Suite.class,**/*Java10Suite.class,**/*Java11Suite.class">
@@ -67,8 +73,8 @@
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/util/EnumMap_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/util/EnumMap_CustomFieldSerializer.java
index b25b5099ad9..e2be8558a47 100644
--- a/user/src/com/google/gwt/user/client/rpc/core/java/util/EnumMap_CustomFieldSerializer.java
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/util/EnumMap_CustomFieldSerializer.java
@@ -19,9 +19,9 @@
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+import com.google.gwt.user.server.rpc.EnumMapUtil;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
+import java.io.IOException;
import java.util.EnumMap;
/**
@@ -55,24 +55,13 @@ public static EnumMap instantiate(SerializationStreamReader streamReader)
*/
public static void serialize(SerializationStreamWriter streamWriter, EnumMap instance)
throws SerializationException {
- Class c = instance.getClass();
- Field keyUniverseField;
- Object keyUniverse = null;
-
+ Class extends Enum>> keyType;
try {
- keyUniverseField = c.getDeclaredField("keyUniverse");
- keyUniverseField.setAccessible(true);
- keyUniverse = keyUniverseField.get(instance);
- } catch (IllegalArgumentException e) {
- throw new SerializationException(e);
- } catch (IllegalAccessException e) {
- throw new SerializationException(e);
- } catch (SecurityException e) {
- throw new SerializationException(e);
- } catch (NoSuchFieldException e) {
+ keyType = EnumMapUtil.getKeyType(instance);
+ } catch (ClassNotFoundException | IOException e) {
throw new SerializationException(e);
}
- Object exemplar = Array.get(keyUniverse, 0);
+ Object exemplar = keyType.getEnumConstants()[0];
streamWriter.writeObject(exemplar);
Map_CustomFieldSerializerBase.serialize(streamWriter, instance);
}
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
index 440bfca1f17..42b7c3f7522 100644
--- a/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
@@ -20,7 +20,10 @@
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -105,15 +108,31 @@ private static boolean getAccessOrder(LinkedHashMap instance) {
if (!reflectionHasFailed.get()) {
try {
Field f = accessOrderField.get();
- if (f == null || !f.isAccessible()) {
+ boolean isAccessible = f != null && f.isAccessible();
+ if (!isAccessible) {
f = LinkedHashMap.class.getDeclaredField("accessOrder");
synchronized (f) {
- // Ensure all threads can see the accessibility.
- f.setAccessible(true);
+ try {
+ // see if we can *try* setting the accessOrder field accessible:
+ final Method trySetAccessible = AccessibleObject.class.getDeclaredMethod(
+ "trySetAccessible");
+ // no exception, then we are on Java 9 or beyond
+ if ((boolean) trySetAccessible.invoke(f)) {
+ accessOrderField.set(f);
+ isAccessible = true;
+ }
+ } catch (NoSuchMethodException e) {
+ // Java <= 8: it won't create a warning but it may fail with an exception
+ // Ensure all threads can see the accessibility.
+ f.setAccessible(true);
+ accessOrderField.set(f);
+ isAccessible = true;
+ }
}
- accessOrderField.set(f);
}
- return ((Boolean) f.get(instance)).booleanValue();
+ if (isAccessible) {
+ return ((Boolean) f.get(instance)).booleanValue();
+ }
} catch (SecurityException e) {
// fall through
} catch (NoSuchFieldException e) {
@@ -122,6 +141,8 @@ private static boolean getAccessOrder(LinkedHashMap instance) {
// fall through
} catch (IllegalAccessException e) {
// fall through
+ } catch (InvocationTargetException e) {
+ // fall through
}
reflectionHasFailed.set(true);
}
diff --git a/user/src/com/google/gwt/user/server/rpc/EnumMap.java b/user/src/com/google/gwt/user/server/rpc/EnumMap.java
new file mode 100644
index 00000000000..37744ea69fd
--- /dev/null
+++ b/user/src/com/google/gwt/user/server/rpc/EnumMap.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2022 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.server.rpc;
+
+/**
+ * A serialization-compatible mock for {@link java.util.EnumMap} that uses an equal
+ * {@link #serialVersionUID} and a compatible set of fields. When de-serializing an
+ * {@link java.util.EnumMap} instance into an instance of this class, e.g., by overriding
+ * {@link ObjectInputStream}'s {@link ObjectInputStream#resolveClass} method such that it delivers
+ * this class instead of {@link java.util.EnumMap}, the fields are made accessible through getters;
+ * in particular, {@link #getKeyType()} reveals the original {@link java.util.EnumMap}'s key type,
+ * even if the map is empty.
+ *
+ *
+ * The {@link EnumMap#getEnumMapKeyType(java.util.EnumMap)} method can be used to determine the key
+ * type of any {@link java.util.EnumMap}, even if it's empty.
+ */
+class EnumMap, V> extends java.util.EnumMap {
+ private final Class keyType;
+ private transient K[] keyUniverse;
+ private transient Object[] vals;
+ private transient int size = 0;
+ private static final long serialVersionUID = 458661240069192865L;
+
+ EnumMap(Class c) {
+ super(c);
+ keyType = null;
+ }
+
+ public K[] getKeyUniverse() {
+ return keyUniverse;
+ }
+
+ public Object[] getVals() {
+ return vals;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public Class getKeyType() {
+ return keyType;
+ }
+
+ /**
+ * Reconstitute the EnumMap instance from a stream (i.e., deserialize it).
+ */
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException,
+ ClassNotFoundException {
+ // Read in the key type and any hidden stuff
+ s.defaultReadObject();
+ // Read in size (number of Mappings)
+ int numberOfMappings = s.readInt();
+ // Read the keys and values, and put the mappings in the HashMap
+ for (int i = 0; i < numberOfMappings; i++) {
+ s.readObject(); // key
+ s.readObject(); // value
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/user/server/rpc/EnumMapUtil.java b/user/src/com/google/gwt/user/server/rpc/EnumMapUtil.java
new file mode 100644
index 00000000000..b8fd7d750fe
--- /dev/null
+++ b/user/src/com/google/gwt/user/server/rpc/EnumMapUtil.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2022 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.server.rpc;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+
+/**
+ * A utility to extract the key type of any {@link java.util.EnumMap}, even if it is empty. Some
+ * frameworks have tried this by using reflection on the map's private field {@code keyType}, but
+ * that approach breaks with Java 17 where reflection on private elements of any {@code java.*}
+ * class is forbidden unless the {@code --add-opens} VM argument is used which is a fairly unsafe
+ * thing to do.
+ *