8169069: Module system implementation refresh (11/2016)

Co-authored-by: Jonathan Gibbons <jonathan.gibbons@oracle.com>
Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com>
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Co-authored-by: Bhavesh Patel <bhavesh.x.patel@oracle.com>
Co-authored-by: Andrey Nazarov <andrey.x.nazarov@oracle.com>
Reviewed-by: mcimadamore, jjg, mchung, anazarov
This commit is contained in:
Alan Bateman 2016-12-01 09:02:42 +00:00
parent 51f50b64e5
commit 22e233b2e9
214 changed files with 5453 additions and 1175 deletions

View file

@ -96,10 +96,12 @@ public interface ModuleElement extends Element, QualifiedNameable {
* @since 9 * @since 9
*/ */
enum DirectiveKind { enum DirectiveKind {
/** A "requires [public] module-name" directive. */ /** A "requires (static|transitive)* module-name" directive. */
REQUIRES, REQUIRES,
/** An "exports package-name [to module-name-list]" directive. */ /** An "exports package-name [to module-name-list]" directive. */
EXPORTS, EXPORTS,
/** An "opens package-name [to module-name-list]" directive. */
OPENS,
/** A "uses service-name" directive. */ /** A "uses service-name" directive. */
USES, USES,
/** A "provides service-name with implementation-name" directive. */ /** A "provides service-name with implementation-name" directive. */
@ -127,10 +129,16 @@ public interface ModuleElement extends Element, QualifiedNameable {
*/ */
interface RequiresDirective extends Directive { interface RequiresDirective extends Directive {
/** /**
* Returns whether or not this is a public dependency. * Returns whether or not this is a static dependency.
* @return whether or not this is a public dependency * @return whether or not this is a static dependency
*/ */
boolean isPublic(); boolean isStatic();
/**
* Returns whether or not this is a transitive dependency.
* @return whether or not this is a transitive dependency
*/
boolean isTransitive();
/** /**
* Returns the module that is required * Returns the module that is required
@ -144,6 +152,7 @@ public interface ModuleElement extends Element, QualifiedNameable {
* @since 9 * @since 9
*/ */
interface ExportsDirective extends Directive { interface ExportsDirective extends Directive {
/** /**
* Returns the package being exported. * Returns the package being exported.
* @return the package being exported * @return the package being exported
@ -159,6 +168,27 @@ public interface ModuleElement extends Element, QualifiedNameable {
List<? extends ModuleElement> getTargetModules(); List<? extends ModuleElement> getTargetModules();
} }
/**
* An opened package of a module.
* @since 9
*/
interface OpensDirective extends Directive {
/**
* Returns the package being opened.
* @return the package being opened
*/
PackageElement getPackage();
/**
* Returns the specific modules to which the package is being open
* or null, if the package is open all modules which
* have readability to this module.
* @return the specific modules to which the package is being opened
*/
List<? extends ModuleElement> getTargetModules();
}
/** /**
* An implementation of a service provided by a module. * An implementation of a service provided by a module.
* @since 9 * @since 9
@ -171,10 +201,10 @@ public interface ModuleElement extends Element, QualifiedNameable {
TypeElement getService(); TypeElement getService();
/** /**
* Returns the implementation of the service being provided. * Returns the implementations of the service being provided.
* @return the implementation of the service being provided * @return the implementations of the service being provided
*/ */
TypeElement getImplementation(); List<? extends TypeElement> getImplementations();
} }
/** /**

View file

@ -39,11 +39,12 @@ import java.util.List;
* @since 9 * @since 9
*/ */
public interface ExportsTree extends DirectiveTree { public interface ExportsTree extends DirectiveTree {
/** /**
* Returns the name of the package to be exported. * Returns the name of the package to be exported.
* @return the name of the package to be exported * @return the name of the package to be exported
*/ */
ExpressionTree getExportName(); ExpressionTree getPackageName();
/** /**
* Returns the names of the modules to which the package is exported, * Returns the names of the modules to which the package is exported,

View file

@ -33,7 +33,8 @@ import java.util.List;
* *
* For example: * For example:
* <pre> * <pre>
* module <em>module-name</em> { * <em>annotations</em>
* [open] module <em>module-name</em> {
* <em>directives</em> * <em>directives</em>
* } * }
* </pre> * </pre>
@ -41,6 +42,18 @@ import java.util.List;
* @since 9 * @since 9
*/ */
public interface ModuleTree extends Tree { public interface ModuleTree extends Tree {
/**
* Returns the annotations associated with this module declaration.
* @return the annotations
*/
List<? extends AnnotationTree> getAnnotations();
/**
* Returns the type of this module.
* @return the type of this module
*/
ModuleKind getModuleType();
/** /**
* Returns the name of the module. * Returns the name of the module.
* @return the name of the module * @return the name of the module
@ -52,4 +65,19 @@ public interface ModuleTree extends Tree {
* @return the directives in the module declaration * @return the directives in the module declaration
*/ */
List<? extends DirectiveTree> getDirectives(); List<? extends DirectiveTree> getDirectives();
/**
* The kind of the module.
*/
enum ModuleKind {
/**
* Open module.
*/
OPEN,
/**
* Strong module.
*/
STRONG;
}
} }

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.source.tree;
import java.util.List;
/**
* A tree node for an 'opens' directive in a module declaration.
*
* For example:
* <pre>
* opens <em>package-name</em>;
* opens <em>package-name</em> to <em>module-name</em>;
* </pre>
*
* @since 9
*/
public interface OpensTree extends DirectiveTree {
/**
* Returns the name of the package to be opened.
* @return the name of the package to be opened
*/
ExpressionTree getPackageName();
/**
* Returns the names of the modules to which the package is opened,
* or null, if the package is opened to all modules.
*
* @return the names of the modules to which the package is opened, or null
*/
List<? extends ExpressionTree> getModuleNames();
}

View file

@ -25,6 +25,8 @@
package com.sun.source.tree; package com.sun.source.tree;
import java.util.List;
/** /**
* A tree node for a 'provides' directive in a module declaration. * A tree node for a 'provides' directive in a module declaration.
* *
@ -43,8 +45,8 @@ public interface ProvidesTree extends DirectiveTree {
ExpressionTree getServiceName(); ExpressionTree getServiceName();
/** /**
* Returns the name of the implementation type being provided. * Returns the names of the implementation types being provided.
* @return the name of the implementation type being provided * @return the names of the implementation types being provided
*/ */
ExpressionTree getImplementationName(); List<? extends ExpressionTree> getImplementationNames();
} }

View file

@ -31,17 +31,24 @@ package com.sun.source.tree;
* For example: * For example:
* <pre> * <pre>
* requires <em>module-name</em>; * requires <em>module-name</em>;
* requires public <em>module-name</em>; * requires static <em>module-name</em>;
* requires transitive <em>module-name</em>;
* </pre> * </pre>
* *
* @since 9 * @since 9
*/ */
public interface RequiresTree extends DirectiveTree { public interface RequiresTree extends DirectiveTree {
/** /**
* Returns true if this is a "requires public" directive. * Returns true if this is a "requires static" directive.
* @return true if this is a "requires public" directive * @return true if this is a "requires static" directive
*/ */
boolean isPublic(); boolean isStatic();
/**
* Returns true if this is a "requires transitive" directive.
* @return true if this is a "requires transitive" directive
*/
boolean isTransitive();
/** /**
* Returns the name of the module that is required. * Returns the name of the module that is required.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -610,25 +610,31 @@ public interface Tree {
/** /**
* Used for instances of {@link ExportsTree} representing * Used for instances of {@link ExportsTree} representing
* export directives in a module declaration. * exports directives in a module declaration.
*/ */
EXPORTS(ExportsTree.class), EXPORTS(ExportsTree.class),
/**
* Used for instances of {@link ExportsTree} representing
* opens directives in a module declaration.
*/
OPENS(OpensTree.class),
/** /**
* Used for instances of {@link ProvidesTree} representing * Used for instances of {@link ProvidesTree} representing
* export directives in a module declaration. * provides directives in a module declaration.
*/ */
PROVIDES(ProvidesTree.class), PROVIDES(ProvidesTree.class),
/** /**
* Used for instances of {@link RequiresTree} representing * Used for instances of {@link RequiresTree} representing
* export directives in a module declaration. * requires directives in a module declaration.
*/ */
REQUIRES(RequiresTree.class), REQUIRES(RequiresTree.class),
/** /**
* Used for instances of {@link UsesTree} representing * Used for instances of {@link UsesTree} representing
* export directives in a module declaration. * uses directives in a module declaration.
*/ */
USES(UsesTree.class), USES(UsesTree.class),

View file

@ -497,6 +497,14 @@ public interface TreeVisitor<R,P> {
*/ */
R visitExports(ExportsTree node, P p); R visitExports(ExportsTree node, P p);
/**
* Visits an OpensTree node.
* @param node the node being visited
* @param p a parameter value
* @return a result value
*/
R visitOpens(OpensTree node, P p);
/** /**
* Visits a ProvidesTree node. * Visits a ProvidesTree node.
* @param node the node being visited * @param node the node being visited

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -728,6 +728,11 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
return defaultAction(node, p); return defaultAction(node, p);
} }
@Override
public R visitOpens(OpensTree node, P p) {
return defaultAction(node, p);
}
@Override @Override
public R visitProvides(ProvidesTree node, P p) { public R visitProvides(ProvidesTree node, P p) {
return defaultAction(node, p); return defaultAction(node, p);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -846,28 +846,41 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
return r; return r;
} }
@Override
public R visitModule(ModuleTree node, P p) { public R visitModule(ModuleTree node, P p) {
R r = scan(node.getName(), p); R r = scan(node.getAnnotations(), p);
r = scanAndReduce(node.getName(), p, r);
r = scanAndReduce(node.getDirectives(), p, r); r = scanAndReduce(node.getDirectives(), p, r);
return r; return r;
} }
@Override
public R visitExports(ExportsTree node, P p) { public R visitExports(ExportsTree node, P p) {
R r = scan(node.getExportName(), p); R r = scan(node.getPackageName(), p);
r = scanAndReduce(node.getModuleNames(), p, r); r = scanAndReduce(node.getModuleNames(), p, r);
return r; return r;
} }
public R visitProvides(ProvidesTree node, P p) { @Override
R r = scan(node.getServiceName(), p); public R visitOpens(OpensTree node, P p) {
r = scanAndReduce(node.getImplementationName(), p, r); R r = scan(node.getPackageName(), p);
r = scanAndReduce(node.getModuleNames(), p, r);
return r; return r;
} }
@Override
public R visitProvides(ProvidesTree node, P p) {
R r = scan(node.getServiceName(), p);
r = scanAndReduce(node.getImplementationNames(), p, r);
return r;
}
@Override
public R visitRequires(RequiresTree node, P p) { public R visitRequires(RequiresTree node, P p) {
return scan(node.getModuleName(), p); return scan(node.getModuleName(), p);
} }
@Override
public R visitUses(UsesTree node, P p) { public R visitUses(UsesTree node, P p) {
return scan(node.getServiceName(), p); return scan(node.getServiceName(), p);
} }

View file

@ -29,13 +29,16 @@ import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
import javax.tools.JavaFileManager; import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardJavaFileManager; import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation; import javax.tools.StandardLocation;
@ -558,17 +561,17 @@ public class ClassFinder {
if (wantClassFiles && (classLocn != null)) { if (wantClassFiles && (classLocn != null)) {
fillIn(p, classLocn, fillIn(p, classLocn,
fileManager.list(classLocn, list(classLocn,
packageName, p,
classKinds, packageName,
false)); classKinds));
} }
if (wantSourceFiles && (sourceLocn != null)) { if (wantSourceFiles && (sourceLocn != null)) {
fillIn(p, sourceLocn, fillIn(p, sourceLocn,
fileManager.list(sourceLocn, list(sourceLocn,
packageName, p,
sourceKinds, packageName,
false)); sourceKinds));
} }
} }
@ -620,23 +623,23 @@ public class ClassFinder {
String packageName = p.fullname.toString(); String packageName = p.fullname.toString();
if (wantSourceFiles && !haveSourcePath) { if (wantSourceFiles && !haveSourcePath) {
fillIn(p, CLASS_PATH, fillIn(p, CLASS_PATH,
fileManager.list(CLASS_PATH, list(CLASS_PATH,
packageName, p,
kinds, packageName,
false)); kinds));
} else { } else {
if (wantClassFiles) if (wantClassFiles)
fillIn(p, CLASS_PATH, fillIn(p, CLASS_PATH,
fileManager.list(CLASS_PATH, list(CLASS_PATH,
packageName, p,
classKinds, packageName,
false)); classKinds));
if (wantSourceFiles) if (wantSourceFiles)
fillIn(p, SOURCE_PATH, fillIn(p, SOURCE_PATH,
fileManager.list(SOURCE_PATH, list(SOURCE_PATH,
packageName, p,
sourceKinds, packageName,
false)); sourceKinds));
} }
} }
@ -645,12 +648,12 @@ public class ClassFinder {
*/ */
private void scanPlatformPath(PackageSymbol p) throws IOException { private void scanPlatformPath(PackageSymbol p) throws IOException {
fillIn(p, PLATFORM_CLASS_PATH, fillIn(p, PLATFORM_CLASS_PATH,
fileManager.list(PLATFORM_CLASS_PATH, list(PLATFORM_CLASS_PATH,
p.fullname.toString(), p,
allowSigFiles ? EnumSet.of(JavaFileObject.Kind.CLASS, p.fullname.toString(),
JavaFileObject.Kind.OTHER) allowSigFiles ? EnumSet.of(JavaFileObject.Kind.CLASS,
: EnumSet.of(JavaFileObject.Kind.CLASS), JavaFileObject.Kind.OTHER)
false)); : EnumSet.of(JavaFileObject.Kind.CLASS)));
} }
// where // where
@SuppressWarnings("fallthrough") @SuppressWarnings("fallthrough")
@ -662,10 +665,7 @@ public class ClassFinder {
for (JavaFileObject fo : files) { for (JavaFileObject fo : files) {
switch (fo.getKind()) { switch (fo.getKind()) {
case OTHER: case OTHER:
boolean sigFile = location == PLATFORM_CLASS_PATH && if (!isSigFile(location, fo)) {
allowSigFiles &&
fo.getName().endsWith(".sig");
if (!sigFile) {
extraFileActions(p, fo); extraFileActions(p, fo);
break; break;
} }
@ -682,10 +682,61 @@ public class ClassFinder {
} }
default: default:
extraFileActions(p, fo); extraFileActions(p, fo);
break;
} }
} }
} }
boolean isSigFile(Location location, JavaFileObject fo) {
return location == PLATFORM_CLASS_PATH &&
allowSigFiles &&
fo.getName().endsWith(".sig");
}
Iterable<JavaFileObject> list(Location location,
PackageSymbol p,
String packageName,
Set<Kind> kinds) throws IOException {
Iterable<JavaFileObject> listed = fileManager.list(location,
packageName,
EnumSet.allOf(Kind.class),
false);
return () -> new Iterator<JavaFileObject>() {
private final Iterator<JavaFileObject> original = listed.iterator();
private JavaFileObject next;
@Override
public boolean hasNext() {
if (next == null) {
while (original.hasNext()) {
JavaFileObject fo = original.next();
if (fo.getKind() != Kind.CLASS &&
fo.getKind() != Kind.SOURCE &&
!isSigFile(currentLoc, fo)) {
p.flags_field |= Flags.HAS_RESOURCE;
}
if (kinds.contains(fo.getKind())) {
next = fo;
break;
}
}
}
return next != null;
}
@Override
public JavaFileObject next() {
if (!hasNext())
throw new NoSuchElementException();
JavaFileObject result = next;
next = null;
return result;
}
};
}
/** /**
* Used for bad class definition files, such as bad .class files or * Used for bad class definition files, such as bad .class files or
* for .java files with unexpected package or class names. * for .java files with unexpected package or class names.

View file

@ -53,7 +53,8 @@ public abstract class Directive implements ModuleElement.Directive {
/** Flags for RequiresDirective. */ /** Flags for RequiresDirective. */
public enum RequiresFlag { public enum RequiresFlag {
PUBLIC(0x0020), TRANSITIVE(0x0010),
STATIC_PHASE(0x0020),
SYNTHETIC(0x1000), SYNTHETIC(0x1000),
MANDATED(0x8000), MANDATED(0x8000),
EXTRA(0x10000); EXTRA(0x10000);
@ -73,17 +74,44 @@ public abstract class Directive implements ModuleElement.Directive {
public final int value; public final int value;
} }
/** Flags for ExportsDirective. */
public enum ExportsFlag {
SYNTHETIC(0x1000),
MANDATED(0x8000);
// overkill? move to ClassWriter?
public static int value(Set<ExportsFlag> s) {
int v = 0;
for (ExportsFlag f: s)
v |= f.value;
return v;
}
ExportsFlag(int value) {
this.value = value;
}
public final int value;
}
/** /**
* 'exports' Package ';' * 'exports' Package ';'
* 'exports' Package 'to' ModuleList ';'
*/ */
public static class ExportsDirective extends Directive public static class ExportsDirective extends Directive
implements ModuleElement.ExportsDirective { implements ModuleElement.ExportsDirective {
public final PackageSymbol packge; public final PackageSymbol packge;
public final List<ModuleSymbol> modules; public final List<ModuleSymbol> modules;
public final Set<ExportsFlag> flags;
public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) { public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
this(packge, modules, EnumSet.noneOf(ExportsFlag.class));
}
public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<ExportsFlag> flags) {
this.packge = packge; this.packge = packge;
this.modules = modules; this.modules = modules;
this.flags = flags;
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
@ -92,12 +120,12 @@ public abstract class Directive implements ModuleElement.Directive {
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public PackageElement getPackage() { public PackageSymbol getPackage() {
return packge; return packge;
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public java.util.List<? extends ModuleElement> getTargetModules() { public java.util.List<ModuleSymbol> getTargetModules() {
return modules == null return modules == null
? null ? null
: Collections.unmodifiableList(modules); : Collections.unmodifiableList(modules);
@ -112,17 +140,83 @@ public abstract class Directive implements ModuleElement.Directive {
} }
} }
/** Flags for OpensDirective. */
public enum OpensFlag {
SYNTHETIC(0x1000),
MANDATED(0x8000);
// overkill? move to ClassWriter?
public static int value(Set<OpensFlag> s) {
int v = 0;
for (OpensFlag f: s)
v |= f.value;
return v;
}
OpensFlag(int value) {
this.value = value;
}
public final int value;
}
/**
* 'opens' Package ';'
* 'opens' Package 'to' ModuleList ';'
*/
public static class OpensDirective extends Directive
implements ModuleElement.OpensDirective {
public final PackageSymbol packge;
public final List<ModuleSymbol> modules;
public final Set<OpensFlag> flags;
public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
this(packge, modules, EnumSet.noneOf(OpensFlag.class));
}
public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<OpensFlag> flags) {
this.packge = packge;
this.modules = modules;
this.flags = flags;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public ModuleElement.DirectiveKind getKind() {
return ModuleElement.DirectiveKind.OPENS;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public PackageSymbol getPackage() {
return packge;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public java.util.List<ModuleSymbol> getTargetModules() {
return modules == null
? null
: Collections.unmodifiableList(modules);
}
@Override
public String toString() {
if (modules == null)
return "Opens[" + packge + "]";
else
return "Opens[" + packge + ":" + modules + "]";
}
}
/** /**
* 'provides' ServiceName 'with' QualifiedIdentifer ';' * 'provides' ServiceName 'with' QualifiedIdentifer ';'
*/ */
public static class ProvidesDirective extends Directive public static class ProvidesDirective extends Directive
implements ModuleElement.ProvidesDirective { implements ModuleElement.ProvidesDirective {
public final ClassSymbol service; public final ClassSymbol service;
public final ClassSymbol impl; public final List<ClassSymbol> impls;
public ProvidesDirective(ClassSymbol service, ClassSymbol impl) { public ProvidesDirective(ClassSymbol service, List<ClassSymbol> impls) {
this.service = service; this.service = service;
this.impl = impl; this.impls = impls;
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
@ -131,37 +225,39 @@ public abstract class Directive implements ModuleElement.Directive {
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public TypeElement getService() { public ClassSymbol getService() {
return service; return service;
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public TypeElement getImplementation() { public List<ClassSymbol> getImplementations() {
return impl; return impls;
} }
@Override @Override
public String toString() { public String toString() {
return "Provides[" + service + "," + impl + "]"; return "Provides[" + service + "," + impls + "]";
} }
// TODO: delete?
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof ProvidesDirective)) { if (!(obj instanceof ProvidesDirective)) {
return false; return false;
} }
ProvidesDirective other = (ProvidesDirective)obj; ProvidesDirective other = (ProvidesDirective)obj;
return service == other.service && impl == other.impl; return service == other.service && impls.equals(other.impls);
} }
// TODO: delete?
@Override @Override
public int hashCode() { public int hashCode() {
return service.hashCode() * 31 + impl.hashCode() * 37; return service.hashCode() * 31 + impls.hashCode() * 37;
} }
} }
/** /**
* 'requires' ['public'] ModuleName ';' * 'requires' ('static' | 'transitive')* ModuleName ';'
*/ */
public static class RequiresDirective extends Directive public static class RequiresDirective extends Directive
implements ModuleElement.RequiresDirective { implements ModuleElement.RequiresDirective {
@ -183,12 +279,17 @@ public abstract class Directive implements ModuleElement.Directive {
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public boolean isPublic() { public boolean isStatic() {
return flags.contains(RequiresFlag.PUBLIC); return flags.contains(RequiresFlag.STATIC_PHASE);
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public ModuleElement getDependency() { public boolean isTransitive() {
return flags.contains(RequiresFlag.TRANSITIVE);
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public ModuleSymbol getDependency() {
return module; return module;
} }
@ -215,7 +316,7 @@ public abstract class Directive implements ModuleElement.Directive {
} }
@Override @DefinedBy(Api.LANGUAGE_MODEL) @Override @DefinedBy(Api.LANGUAGE_MODEL)
public TypeElement getService() { public ClassSymbol getService() {
return service; return service;
} }
@ -224,6 +325,7 @@ public abstract class Directive implements ModuleElement.Directive {
return "Uses[" + service + "]"; return "Uses[" + service + "]";
} }
// TODO: delete?
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof UsesDirective)) { if (!(obj instanceof UsesDirective)) {
@ -233,6 +335,7 @@ public abstract class Directive implements ModuleElement.Directive {
return service == other.service; return service == other.service;
} }
// TODO: delete?
@Override @Override
public int hashCode() { public int hashCode() {
return service.hashCode() * 31; return service.hashCode() * 31;

View file

@ -293,10 +293,20 @@ public class Flags {
*/ */
public static final long SYSTEM_MODULE = 1L<<53; public static final long SYSTEM_MODULE = 1L<<53;
/**
* Flag to indicate the given symbol has a @Deprecated annotation.
*/
public static final long DEPRECATED_ANNOTATION = 1L<<54;
/** /**
* Flag to indicate the given symbol has been deprecated and marked for removal. * Flag to indicate the given symbol has been deprecated and marked for removal.
*/ */
public static final long DEPRECATED_REMOVAL = 1L<<54; public static final long DEPRECATED_REMOVAL = 1L<<55;
/**
* Flag to indicate the given PackageSymbol contains any non-.java and non-.class resources.
*/
public static final long HAS_RESOURCE = 1L<<56;
/** Modifier masks. /** Modifier masks.
*/ */
@ -408,7 +418,11 @@ public class Flags {
LAMBDA_METHOD(Flags.LAMBDA_METHOD), LAMBDA_METHOD(Flags.LAMBDA_METHOD),
TYPE_TRANSLATED(Flags.TYPE_TRANSLATED), TYPE_TRANSLATED(Flags.TYPE_TRANSLATED),
MODULE(Flags.MODULE), MODULE(Flags.MODULE),
DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL); AUTOMATIC_MODULE(Flags.AUTOMATIC_MODULE),
SYSTEM_MODULE(Flags.SYSTEM_MODULE),
DEPRECATED_ANNOTATION(Flags.DEPRECATED_ANNOTATION),
DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL),
HAS_RESOURCE(Flags.HAS_RESOURCE);
Flag(long flag) { Flag(long flag) {
this.value = flag; this.value = flag;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View file

@ -28,6 +28,7 @@ package com.sun.tools.javac.code;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited; import java.lang.annotation.Inherited;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -47,6 +48,7 @@ import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.ClassFinder.BadEnclosingMethodAttr; import com.sun.tools.javac.code.ClassFinder.BadEnclosingMethodAttr;
import com.sun.tools.javac.code.Directive.RequiresFlag;
import com.sun.tools.javac.code.Kinds.Kind; import com.sun.tools.javac.code.Kinds.Kind;
import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.code.Scope.WriteableScope;
@ -359,6 +361,10 @@ public abstract class Symbol extends AnnoConstruct implements Element {
return (flags_field & DEPRECATED) != 0; return (flags_field & DEPRECATED) != 0;
} }
public boolean hasDeprecatedAnnotation() {
return (flags_field & DEPRECATED_ANNOTATION) != 0;
}
public boolean isDeprecatedForRemoval() { public boolean isDeprecatedForRemoval() {
return (flags_field & DEPRECATED_REMOVAL) != 0; return (flags_field & DEPRECATED_REMOVAL) != 0;
} }
@ -907,6 +913,7 @@ public abstract class Symbol extends AnnoConstruct implements Element {
public List<com.sun.tools.javac.code.Directive> directives; public List<com.sun.tools.javac.code.Directive> directives;
public List<com.sun.tools.javac.code.Directive.RequiresDirective> requires; public List<com.sun.tools.javac.code.Directive.RequiresDirective> requires;
public List<com.sun.tools.javac.code.Directive.ExportsDirective> exports; public List<com.sun.tools.javac.code.Directive.ExportsDirective> exports;
public List<com.sun.tools.javac.code.Directive.OpensDirective> opens;
public List<com.sun.tools.javac.code.Directive.ProvidesDirective> provides; public List<com.sun.tools.javac.code.Directive.ProvidesDirective> provides;
public List<com.sun.tools.javac.code.Directive.UsesDirective> uses; public List<com.sun.tools.javac.code.Directive.UsesDirective> uses;
@ -917,6 +924,7 @@ public abstract class Symbol extends AnnoConstruct implements Element {
public List<Symbol> enclosedPackages = List.nil(); public List<Symbol> enclosedPackages = List.nil();
public Completer usesProvidesCompleter = Completer.NULL_COMPLETER; public Completer usesProvidesCompleter = Completer.NULL_COMPLETER;
public final Set<ModuleFlags> flags = EnumSet.noneOf(ModuleFlags.class);
/** /**
* Create a ModuleSymbol with an associated module-info ClassSymbol. * Create a ModuleSymbol with an associated module-info ClassSymbol.
@ -942,6 +950,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
return name.isEmpty() && owner == null; return name.isEmpty() && owner == null;
} }
@Override
public boolean isDeprecated() {
return hasDeprecatedAnnotation();
}
public boolean isNoModule() { public boolean isNoModule() {
return false; return false;
} }
@ -1007,6 +1020,26 @@ public abstract class Symbol extends AnnoConstruct implements Element {
} }
public enum ModuleFlags {
OPEN(0x0020),
SYNTHETIC(0x1000),
MANDATED(0x8000);
public static int value(Set<ModuleFlags> s) {
int v = 0;
for (ModuleFlags f: s)
v |= f.value;
return v;
}
private ModuleFlags(int value) {
this.value = value;
}
public final int value;
}
/** A class for package symbols /** A class for package symbols
*/ */
public static class PackageSymbol extends TypeSymbol public static class PackageSymbol extends TypeSymbol

View file

@ -237,6 +237,9 @@ public class TypeAnnotations {
// TYPE_PARAMETER doesn't aid in distinguishing between // TYPE_PARAMETER doesn't aid in distinguishing between
// Type annotations and declaration annotations on an // Type annotations and declaration annotations on an
// Element // Element
} else if (e.value.name == names.MODULE) {
if (s.kind == MDL)
return AnnotationType.DECLARATION;
} else { } else {
Assert.error("annotationTargetType(): unrecognized Attribute name " + e.value.name + Assert.error("annotationTargetType(): unrecognized Attribute name " + e.value.name +
" (" + e.value.name.getClass() + ")"); " (" + e.value.name.getClass() + ")");

View file

@ -45,6 +45,7 @@ import javax.tools.JavaFileObject;
import java.util.*; import java.util.*;
import static com.sun.tools.javac.code.Flags.SYNTHETIC; import static com.sun.tools.javac.code.Flags.SYNTHETIC;
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
import static com.sun.tools.javac.code.Kinds.Kind.MTH; import static com.sun.tools.javac.code.Kinds.Kind.MTH;
import static com.sun.tools.javac.code.Kinds.Kind.VAR; import static com.sun.tools.javac.code.Kinds.Kind.VAR;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
@ -337,9 +338,9 @@ public class Annotate {
// Note: @Deprecated has no effect on local variables and parameters // Note: @Deprecated has no effect on local variables and parameters
if (!c.type.isErroneous() if (!c.type.isErroneous()
&& toAnnotate.owner.kind != MTH && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH)
&& types.isSameType(c.type, syms.deprecatedType)) { && types.isSameType(c.type, syms.deprecatedType)) {
toAnnotate.flags_field |= Flags.DEPRECATED; toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
Attribute fr = c.member(names.forRemoval); Attribute fr = c.member(names.forRemoval);
if (fr instanceof Attribute.Constant) { if (fr instanceof Attribute.Constant) {
Attribute.Constant v = (Attribute.Constant) fr; Attribute.Constant v = (Attribute.Constant) fr;

View file

@ -4432,6 +4432,17 @@ public class Attr extends JCTree.Visitor {
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {
tree.sym.completeUsesProvides(); tree.sym.completeUsesProvides();
ModuleSymbol msym = tree.sym;
Lint lint = env.outer.info.lint = env.outer.info.lint.augment(msym);
Lint prevLint = chk.setLint(lint);
chk.checkDeprecatedAnnotation(tree, msym);
try {
deferredLintHandler.flush(tree.pos());
} finally {
chk.setLint(prevLint);
}
} }
/** Finish the attribution of a class. */ /** Finish the attribution of a class. */

View file

@ -227,10 +227,18 @@ public class Check {
void warnDeprecated(DiagnosticPosition pos, Symbol sym) { void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
if (sym.isDeprecatedForRemoval()) { if (sym.isDeprecatedForRemoval()) {
if (!lint.isSuppressed(LintCategory.REMOVAL)) { if (!lint.isSuppressed(LintCategory.REMOVAL)) {
removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location()); if (sym.kind == MDL) {
removalHandler.report(pos, "has.been.deprecated.for.removal.module", sym);
} else {
removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location());
}
} }
} else if (!lint.isSuppressed(LintCategory.DEPRECATION)) { } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); if (sym.kind == MDL) {
deprecationHandler.report(pos, "has.been.deprecated.module", sym);
} else {
deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
}
} }
} }
@ -3245,7 +3253,7 @@ public class Check {
void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) { void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
if ( (s.isDeprecatedForRemoval() if ( (s.isDeprecatedForRemoval()
|| s.isDeprecated() && !other.isDeprecated()) || s.isDeprecated() && !other.isDeprecated())
&& s.outermostClass() != other.outermostClass()) { && (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)) {
deferredLintHandler.report(new DeferredLintHandler.LintLogger() { deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
@Override @Override
public void report() { public void report() {
@ -3851,7 +3859,7 @@ public class Check {
} }
if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) { if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) {
//check that relativeTo.modle requires public what.modle, somehow: //check that relativeTo.modle requires transitive what.modle, somehow:
List<ModuleSymbol> todo = List.of(inPackage.modle); List<ModuleSymbol> todo = List.of(inPackage.modle);
while (todo.nonEmpty()) { while (todo.nonEmpty()) {
@ -3860,13 +3868,13 @@ public class Check {
if (current == whatPackage.modle) if (current == whatPackage.modle)
return ; //OK return ; //OK
for (RequiresDirective req : current.requires) { for (RequiresDirective req : current.requires) {
if (req.isPublic()) { if (req.isTransitive()) {
todo = todo.prepend(req.module); todo = todo.prepend(req.module);
} }
} }
} }
log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredPublic(kindName(what), what, what.packge().modle)); log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredTransitive(kindName(what), what, what.packge().modle));
} }
} }
} }

View file

@ -167,6 +167,9 @@ public class Enter extends JCTree.Visitor {
*/ */
ListBuffer<ClassSymbol> uncompleted; ListBuffer<ClassSymbol> uncompleted;
/** The queue of modules whose imports still need to be checked. */
ListBuffer<JCCompilationUnit> unfinishedModules = new ListBuffer<>();
/** A dummy class to serve as enclClass for toplevel environments. /** A dummy class to serve as enclClass for toplevel environments.
*/ */
private JCClassDecl predefClassDef; private JCClassDecl predefClassDef;
@ -308,6 +311,10 @@ public class Enter extends JCTree.Visitor {
boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
JavaFileObject.Kind.SOURCE); JavaFileObject.Kind.SOURCE);
if (TreeInfo.isModuleInfo(tree)) { if (TreeInfo.isModuleInfo(tree)) {
JCPackageDecl pd = tree.getPackage();
if (pd != null) {
log.error(pd.pos(), Errors.NoPkgInModuleInfoJava);
}
tree.packge = syms.rootPackage; tree.packge = syms.rootPackage;
Env<AttrContext> topEnv = topLevelEnv(tree); Env<AttrContext> topEnv = topLevelEnv(tree);
classEnter(tree.defs, topEnv); classEnter(tree.defs, topEnv);
@ -509,7 +516,9 @@ public class Enter extends JCTree.Visitor {
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {
Env<AttrContext> moduleEnv = moduleEnv(tree, env); Env<AttrContext> moduleEnv = moduleEnv(tree, env);
typeEnvs.put(tree.sym, moduleEnv); typeEnvs.put(tree.sym, moduleEnv);
todo.append(moduleEnv); if (modules.isInModuleGraph(tree.sym)) {
todo.append(moduleEnv);
}
} }
/** Default class enter visitor method: do nothing. /** Default class enter visitor method: do nothing.
@ -552,7 +561,19 @@ public class Enter extends JCTree.Visitor {
prevUncompleted.append(clazz); prevUncompleted.append(clazz);
} }
typeEnter.ensureImportsChecked(trees); if (!modules.modulesInitialized()) {
for (JCCompilationUnit cut : trees) {
if (cut.getModuleDecl() != null) {
unfinishedModules.append(cut);
} else {
typeEnter.ensureImportsChecked(List.of(cut));
}
}
} else {
typeEnter.ensureImportsChecked(unfinishedModules.toList());
unfinishedModules.clear();
typeEnter.ensureImportsChecked(trees);
}
} }
} finally { } finally {
uncompleted = prevUncompleted; uncompleted = prevUncompleted;

View file

@ -2387,6 +2387,7 @@ public class Lower extends TreeTranslator {
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {
ModuleSymbol msym = tree.sym; ModuleSymbol msym = tree.sym;
ClassSymbol c = msym.module_info; ClassSymbol c = msym.module_info;
c.setAttributes(msym);
c.flags_field |= Flags.MODULE; c.flags_field |= Flags.MODULE;
createInfoClass(List.<JCAnnotation>nil(), tree.sym.module_info); createInfoClass(List.<JCAnnotation>nil(), tree.sym.module_info);
} }

View file

@ -50,9 +50,14 @@ import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind; import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation; import javax.tools.StandardLocation;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.tools.javac.code.ClassFinder; import com.sun.tools.javac.code.ClassFinder;
import com.sun.tools.javac.code.DeferredLintHandler;
import com.sun.tools.javac.code.Directive; import com.sun.tools.javac.code.Directive;
import com.sun.tools.javac.code.Directive.ExportsDirective; import com.sun.tools.javac.code.Directive.ExportsDirective;
import com.sun.tools.javac.code.Directive.ExportsFlag;
import com.sun.tools.javac.code.Directive.OpensDirective;
import com.sun.tools.javac.code.Directive.OpensFlag;
import com.sun.tools.javac.code.Directive.RequiresDirective; import com.sun.tools.javac.code.Directive.RequiresDirective;
import com.sun.tools.javac.code.Directive.RequiresFlag; import com.sun.tools.javac.code.Directive.RequiresFlag;
import com.sun.tools.javac.code.Directive.UsesDirective; import com.sun.tools.javac.code.Directive.UsesDirective;
@ -66,6 +71,7 @@ import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.Completer; import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.ModuleFlags;
import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Symtab;
@ -78,14 +84,18 @@ import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCDirective;
import com.sun.tools.javac.tree.JCTree.JCExports; import com.sun.tools.javac.tree.JCTree.JCExports;
import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCModuleDecl; import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
import com.sun.tools.javac.tree.JCTree.JCOpens;
import com.sun.tools.javac.tree.JCTree.JCPackageDecl; import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
import com.sun.tools.javac.tree.JCTree.JCProvides; import com.sun.tools.javac.tree.JCTree.JCProvides;
import com.sun.tools.javac.tree.JCTree.JCRequires; import com.sun.tools.javac.tree.JCTree.JCRequires;
import com.sun.tools.javac.tree.JCTree.JCUses; import com.sun.tools.javac.tree.JCTree.JCUses;
import com.sun.tools.javac.tree.JCTree.Tag;
import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic;
@ -96,20 +106,15 @@ import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.Options;
import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import com.sun.tools.javac.tree.JCTree.JCDirective;
import com.sun.tools.javac.tree.JCTree.Tag;
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Position; import com.sun.tools.javac.util.Position;
import static com.sun.tools.javac.code.Flags.ABSTRACT; import static com.sun.tools.javac.code.Flags.ABSTRACT;
import static com.sun.tools.javac.code.Flags.ENUM; import static com.sun.tools.javac.code.Flags.ENUM;
import static com.sun.tools.javac.code.Flags.PUBLIC; import static com.sun.tools.javac.code.Flags.PUBLIC;
import static com.sun.tools.javac.tree.JCTree.Tag.MODULEDEF; import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
import static com.sun.tools.javac.code.Kinds.Kind.MTH;
import static com.sun.tools.javac.code.TypeTag.CLASS;
/** /**
* TODO: fill in * TODO: fill in
@ -127,6 +132,8 @@ public class Modules extends JCTree.Visitor {
private final Names names; private final Names names;
private final Symtab syms; private final Symtab syms;
private final Attr attr; private final Attr attr;
private final Check chk;
private final DeferredLintHandler deferredLintHandler;
private final TypeEnvs typeEnvs; private final TypeEnvs typeEnvs;
private final Types types; private final Types types;
private final JavaFileManager fileManager; private final JavaFileManager fileManager;
@ -169,6 +176,8 @@ public class Modules extends JCTree.Visitor {
names = Names.instance(context); names = Names.instance(context);
syms = Symtab.instance(context); syms = Symtab.instance(context);
attr = Attr.instance(context); attr = Attr.instance(context);
chk = Check.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
typeEnvs = TypeEnvs.instance(context); typeEnvs = TypeEnvs.instance(context);
moduleFinder = ModuleFinder.instance(context); moduleFinder = ModuleFinder.instance(context);
types = Types.instance(context); types = Types.instance(context);
@ -276,6 +285,10 @@ public class Modules extends JCTree.Visitor {
return defaultModule; return defaultModule;
} }
public boolean modulesInitialized() {
return allModules != null;
}
private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) { private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) {
Set<ModuleSymbol> modules = new LinkedHashSet<>(); Set<ModuleSymbol> modules = new LinkedHashSet<>();
for (JCCompilationUnit tree : trees) { for (JCCompilationUnit tree : trees) {
@ -292,9 +305,9 @@ public class Modules extends JCTree.Visitor {
private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set<ModuleSymbol> modules) { private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set<ModuleSymbol> modules) {
boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE); boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
boolean isModuleDecl = toplevel.defs.nonEmpty() && toplevel.defs.head.hasTag(MODULEDEF); boolean isModuleDecl = toplevel.getModuleDecl() != null;
if (isModuleDecl) { if (isModuleDecl) {
JCModuleDecl decl = (JCModuleDecl) toplevel.defs.head; JCModuleDecl decl = toplevel.getModuleDecl();
if (!isModuleInfo) { if (!isModuleInfo) {
log.error(decl.pos(), Errors.ModuleDeclSbInModuleInfoJava); log.error(decl.pos(), Errors.ModuleDeclSbInModuleInfoJava);
} }
@ -352,8 +365,8 @@ public class Modules extends JCTree.Visitor {
if (locn != null) { if (locn != null) {
Name name = names.fromString(fileManager.inferModuleName(locn)); Name name = names.fromString(fileManager.inferModuleName(locn));
ModuleSymbol msym; ModuleSymbol msym;
if (tree.defs.head.hasTag(MODULEDEF)) { JCModuleDecl decl = tree.getModuleDecl();
JCModuleDecl decl = (JCModuleDecl) tree.defs.head; if (decl != null) {
msym = decl.sym; msym = decl.sym;
if (msym.name != name) { if (msym.name != name) {
log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name)); log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
@ -449,17 +462,14 @@ public class Modules extends JCTree.Visitor {
} }
private Location getModuleLocation(JCCompilationUnit tree) throws IOException { private Location getModuleLocation(JCCompilationUnit tree) throws IOException {
switch (tree.defs.head.getTag()) { if (tree.getModuleDecl() != null) {
case MODULEDEF: return getModuleLocation(tree.sourcefile, null);
return getModuleLocation(tree.sourcefile, null); } else if (tree.getPackage() != null) {
JCPackageDecl pkg = tree.getPackage();
case PACKAGEDEF: return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid));
JCPackageDecl pkg = (JCPackageDecl) tree.defs.head; } else {
return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid)); // code in unnamed module
return null;
default:
// code in unnamed module
return null;
} }
} }
@ -535,6 +545,7 @@ public class Modules extends JCTree.Visitor {
String pack = binName.lastIndexOf('.') != (-1) ? binName.substring(0, binName.lastIndexOf('.')) : ""; //unnamed package???? String pack = binName.lastIndexOf('.') != (-1) ? binName.substring(0, binName.lastIndexOf('.')) : ""; //unnamed package????
if (seenPackages.add(pack)) { if (seenPackages.add(pack)) {
ExportsDirective d = new ExportsDirective(syms.enterPackage(msym, names.fromString(pack)), null); ExportsDirective d = new ExportsDirective(syms.enterPackage(msym, names.fromString(pack)), null);
//TODO: opens?
directives.add(d); directives.add(d);
exports.add(d); exports.add(d);
} }
@ -562,7 +573,7 @@ public class Modules extends JCTree.Visitor {
if (ms == syms.unnamedModule || ms == msym) if (ms == syms.unnamedModule || ms == msym)
continue; continue;
Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ? Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ?
EnumSet.of(RequiresFlag.PUBLIC) : EnumSet.noneOf(RequiresFlag.class); EnumSet.of(RequiresFlag.TRANSITIVE) : EnumSet.noneOf(RequiresFlag.class);
RequiresDirective d = new RequiresDirective(ms, flags); RequiresDirective d = new RequiresDirective(ms, flags);
directives.add(d); directives.add(d);
requires.add(d); requires.add(d);
@ -585,9 +596,10 @@ public class Modules extends JCTree.Visitor {
ModuleVisitor v = new ModuleVisitor(); ModuleVisitor v = new ModuleVisitor();
JavaFileObject prev = log.useSource(tree.sourcefile); JavaFileObject prev = log.useSource(tree.sourcefile);
try { try {
tree.defs.head.accept(v); JCModuleDecl moduleDecl = tree.getModuleDecl();
checkCyclicDependencies((JCModuleDecl) tree.defs.head); moduleDecl.accept(v);
completeModule(msym); completeModule(msym);
checkCyclicDependencies(moduleDecl);
} finally { } finally {
log.useSource(prev); log.useSource(prev);
msym.flags_field &= ~UNATTRIBUTED; msym.flags_field &= ~UNATTRIBUTED;
@ -605,17 +617,25 @@ public class Modules extends JCTree.Visitor {
class ModuleVisitor extends JCTree.Visitor { class ModuleVisitor extends JCTree.Visitor {
private ModuleSymbol sym; private ModuleSymbol sym;
private final Set<ModuleSymbol> allRequires = new HashSet<>(); private final Set<ModuleSymbol> allRequires = new HashSet<>();
private final Set<PackageSymbol> allExports = new HashSet<>(); private final Map<PackageSymbol,List<ExportsDirective>> allExports = new HashMap<>();
private final Map<PackageSymbol,List<OpensDirective>> allOpens = new HashMap<>();
@Override @Override
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {
sym = Assert.checkNonNull(tree.sym); sym = Assert.checkNonNull(tree.sym);
if (tree.getModuleType() == ModuleKind.OPEN) {
sym.flags.add(ModuleFlags.OPEN);
}
sym.flags_field |= (tree.mods.flags & Flags.DEPRECATED);
sym.requires = List.nil(); sym.requires = List.nil();
sym.exports = List.nil(); sym.exports = List.nil();
sym.opens = List.nil();
tree.directives.forEach(t -> t.accept(this)); tree.directives.forEach(t -> t.accept(this));
sym.requires = sym.requires.reverse(); sym.requires = sym.requires.reverse();
sym.exports = sym.exports.reverse(); sym.exports = sym.exports.reverse();
sym.opens = sym.opens.reverse();
ensureJavaBase(); ensureJavaBase();
} }
@ -629,8 +649,10 @@ public class Modules extends JCTree.Visitor {
} else { } else {
allRequires.add(msym); allRequires.add(msym);
Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class); Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class);
if (tree.isPublic) if (tree.isTransitive)
flags.add(RequiresFlag.PUBLIC); flags.add(RequiresFlag.TRANSITIVE);
if (tree.isStaticPhase)
flags.add(RequiresFlag.STATIC_PHASE);
RequiresDirective d = new RequiresDirective(msym, flags); RequiresDirective d = new RequiresDirective(msym, flags);
tree.directive = d; tree.directive = d;
sym.requires = sym.requires.prepend(d); sym.requires = sym.requires.prepend(d);
@ -642,31 +664,125 @@ public class Modules extends JCTree.Visitor {
Name name = TreeInfo.fullName(tree.qualid); Name name = TreeInfo.fullName(tree.qualid);
PackageSymbol packge = syms.enterPackage(sym, name); PackageSymbol packge = syms.enterPackage(sym, name);
attr.setPackageSymbols(tree.qualid, packge); attr.setPackageSymbols(tree.qualid, packge);
if (!allExports.add(packge)) {
log.error(tree.qualid.pos(), Errors.DuplicateExports(packge)); if (tree.hasTag(Tag.OPENS) && sym.flags.contains(ModuleFlags.OPEN)) {
log.error(tree.pos(), Errors.NoOpensUnlessStrong);
}
List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil());
for (ExportsDirective d : exportsForPackage) {
reportExportsConflict(tree, packge);
} }
List<ModuleSymbol> toModules = null; List<ModuleSymbol> toModules = null;
if (tree.moduleNames != null) { if (tree.moduleNames != null) {
Set<ModuleSymbol> to = new HashSet<>(); Set<ModuleSymbol> to = new LinkedHashSet<>();
for (JCExpression n: tree.moduleNames) { for (JCExpression n: tree.moduleNames) {
ModuleSymbol msym = lookupModule(n); ModuleSymbol msym = lookupModule(n);
if (msym.kind != MDL) { if (msym.kind != MDL) {
log.error(n.pos(), Errors.ModuleNotFound(msym)); log.error(n.pos(), Errors.ModuleNotFound(msym));
} else if (!to.add(msym)) { } else {
log.error(n.pos(), Errors.DuplicateExports(msym)); for (ExportsDirective d : exportsForPackage) {
checkDuplicateExportsToModule(n, msym, d);
}
if (!to.add(msym)) {
reportExportsConflictToModule(n, msym);
}
} }
} }
toModules = List.from(to); toModules = List.from(to);
} }
if (toModules == null || !toModules.isEmpty()) { if (toModules == null || !toModules.isEmpty()) {
ExportsDirective d = new ExportsDirective(packge, toModules); Set<ExportsFlag> flags = EnumSet.noneOf(ExportsFlag.class);
tree.directive = d; ExportsDirective d = new ExportsDirective(packge, toModules, flags);
sym.exports = sym.exports.prepend(d); sym.exports = sym.exports.prepend(d);
tree.directive = d;
allExports.put(packge, exportsForPackage.prepend(d));
} }
} }
private void reportExportsConflict(JCExports tree, PackageSymbol packge) {
log.error(tree.qualid.pos(), Errors.ConflictingExports(packge));
}
private void checkDuplicateExportsToModule(JCExpression name, ModuleSymbol msym,
ExportsDirective d) {
if (d.modules != null) {
for (ModuleSymbol other : d.modules) {
if (msym == other) {
reportExportsConflictToModule(name, msym);
}
}
}
}
private void reportExportsConflictToModule(JCExpression name, ModuleSymbol msym) {
log.error(name.pos(), Errors.ConflictingExportsToModule(msym));
}
@Override
public void visitOpens(JCOpens tree) {
Name name = TreeInfo.fullName(tree.qualid);
PackageSymbol packge = syms.enterPackage(sym, name);
attr.setPackageSymbols(tree.qualid, packge);
if (sym.flags.contains(ModuleFlags.OPEN)) {
log.error(tree.pos(), Errors.NoOpensUnlessStrong);
}
List<OpensDirective> opensForPackage = allOpens.computeIfAbsent(packge, p -> List.nil());
for (OpensDirective d : opensForPackage) {
reportOpensConflict(tree, packge);
}
List<ModuleSymbol> toModules = null;
if (tree.moduleNames != null) {
Set<ModuleSymbol> to = new LinkedHashSet<>();
for (JCExpression n: tree.moduleNames) {
ModuleSymbol msym = lookupModule(n);
if (msym.kind != MDL) {
log.error(n.pos(), Errors.ModuleNotFound(msym));
} else {
for (OpensDirective d : opensForPackage) {
checkDuplicateOpensToModule(n, msym, d);
}
if (!to.add(msym)) {
reportOpensConflictToModule(n, msym);
}
}
}
toModules = List.from(to);
}
if (toModules == null || !toModules.isEmpty()) {
Set<OpensFlag> flags = EnumSet.noneOf(OpensFlag.class);
OpensDirective d = new OpensDirective(packge, toModules, flags);
sym.opens = sym.opens.prepend(d);
tree.directive = d;
allOpens.put(packge, opensForPackage.prepend(d));
}
}
private void reportOpensConflict(JCOpens tree, PackageSymbol packge) {
log.error(tree.qualid.pos(), Errors.ConflictingOpens(packge));
}
private void checkDuplicateOpensToModule(JCExpression name, ModuleSymbol msym,
OpensDirective d) {
if (d.modules != null) {
for (ModuleSymbol other : d.modules) {
if (msym == other) {
reportOpensConflictToModule(name, msym);
}
}
}
}
private void reportOpensConflictToModule(JCExpression name, ModuleSymbol msym) {
log.error(name.pos(), Errors.ConflictingOpensToModule(msym));
}
@Override @Override
public void visitProvides(JCProvides tree) { } public void visitProvides(JCProvides tree) { }
@ -706,10 +822,14 @@ public class Modules extends JCTree.Visitor {
Env<AttrContext> env = typeEnvs.get(msym); Env<AttrContext> env = typeEnvs.get(msym);
UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env); UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile); JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
JCModuleDecl decl = env.toplevel.getModuleDecl();
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(decl.pos());
try { try {
env.toplevel.defs.head.accept(v); decl.accept(v);
} finally { } finally {
log.useSource(prev); log.useSource(prev);
deferredLintHandler.setPos(prevLintPos);
} }
}; };
} }
@ -718,8 +838,8 @@ public class Modules extends JCTree.Visitor {
private final ModuleSymbol msym; private final ModuleSymbol msym;
private final Env<AttrContext> env; private final Env<AttrContext> env;
private final Set<Directive.UsesDirective> allUses = new HashSet<>(); private final Set<ClassSymbol> allUses = new HashSet<>();
private final Set<Directive.ProvidesDirective> allProvides = new HashSet<>(); private final Map<ClassSymbol, Set<ClassSymbol>> allProvides = new HashMap<>();
public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) { public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) {
this.msym = msym; this.msym = msym;
@ -752,6 +872,15 @@ public class Modules extends JCTree.Visitor {
msym.directives = msym.directives.prepend(tree.directive); msym.directives = msym.directives.prepend(tree.directive);
} }
@Override
public void visitOpens(JCOpens tree) {
if (tree.directive.packge.members().isEmpty() &&
((tree.directive.packge.flags() & Flags.HAS_RESOURCE) == 0)) {
log.error(tree.qualid.pos(), Errors.PackageEmptyOrNotFound(tree.directive.packge));
}
msym.directives = msym.directives.prepend(tree.directive);
}
MethodSymbol noArgsConstructor(ClassSymbol tsym) { MethodSymbol noArgsConstructor(ClassSymbol tsym) {
for (Symbol sym : tsym.members().getSymbolsByName(names.init)) { for (Symbol sym : tsym.members().getSymbolsByName(names.init)) {
MethodSymbol mSym = (MethodSymbol)sym; MethodSymbol mSym = (MethodSymbol)sym;
@ -762,34 +891,61 @@ public class Modules extends JCTree.Visitor {
return null; return null;
} }
MethodSymbol factoryMethod(ClassSymbol tsym) {
for (Symbol sym : tsym.members().getSymbolsByName(names.provider, sym -> sym.kind == MTH)) {
MethodSymbol mSym = (MethodSymbol)sym;
if (mSym.isStatic() && (mSym.flags() & Flags.PUBLIC) != 0 && mSym.params().isEmpty()) {
return mSym;
}
}
return null;
}
Map<Directive.ProvidesDirective, JCProvides> directiveToTreeMap = new HashMap<>(); Map<Directive.ProvidesDirective, JCProvides> directiveToTreeMap = new HashMap<>();
@Override @Override
public void visitProvides(JCProvides tree) { public void visitProvides(JCProvides tree) {
Type st = attr.attribType(tree.serviceName, env, syms.objectType); Type st = attr.attribType(tree.serviceName, env, syms.objectType);
Type it = attr.attribType(tree.implName, env, syms.objectType);
ClassSymbol service = (ClassSymbol) st.tsym; ClassSymbol service = (ClassSymbol) st.tsym;
ClassSymbol impl = (ClassSymbol) it.tsym; ListBuffer<ClassSymbol> impls = new ListBuffer<>();
if (!types.isSubtype(it, st)) { for (JCExpression implName : tree.implNames) {
log.error(tree.implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface); Type it = attr.attribType(implName, env, syms.objectType);
} ClassSymbol impl = (ClassSymbol) it.tsym;
if ((impl.flags() & ABSTRACT) != 0) { //find provider factory:
log.error(tree.implName.pos(), Errors.ServiceImplementationIsAbstract(impl)); MethodSymbol factory = factoryMethod(impl);
} else if (impl.isInner()) { if (factory != null) {
log.error(tree.implName.pos(), Errors.ServiceImplementationIsInner(impl)); Type returnType = factory.type.getReturnType();
} else { if (!types.isSubtype(returnType, st)) {
MethodSymbol constr = noArgsConstructor(impl); log.error(implName.pos(), Errors.ServiceImplementationProviderReturnMustBeSubtypeOfServiceInterface);
if (constr == null) { }
log.error(tree.implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl)); } else {
} else if ((constr.flags() & PUBLIC) == 0) { if (!types.isSubtype(it, st)) {
log.error(tree.implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl)); log.error(implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface);
} else if ((impl.flags() & ABSTRACT) != 0) {
log.error(implName.pos(), Errors.ServiceImplementationIsAbstract(impl));
} else if (impl.isInner()) {
log.error(implName.pos(), Errors.ServiceImplementationIsInner(impl));
} else {
MethodSymbol constr = noArgsConstructor(impl);
if (constr == null) {
log.error(implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl));
} else if ((constr.flags() & PUBLIC) == 0) {
log.error(implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl));
}
}
}
if (it.hasTag(CLASS)) {
// For now, we just check the pair (service-type, impl-type) is unique
// TODO, check only one provides per service type as well
if (allProvides.computeIfAbsent(service, s -> new HashSet<>()).add(impl)) {
impls.append(impl);
} else {
log.error(implName.pos(), Errors.DuplicateProvides(service, impl));
}
} }
} }
if (st.hasTag(CLASS) && it.hasTag(CLASS)) { if (st.hasTag(CLASS) && !impls.isEmpty()) {
Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impl); Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impls.toList());
if (!allProvides.add(d)) {
log.error(tree.pos(), Errors.DuplicateProvides(service, impl));
}
msym.provides = msym.provides.prepend(d); msym.provides = msym.provides.prepend(d);
msym.directives = msym.directives.prepend(d); msym.directives = msym.directives.prepend(d);
directiveToTreeMap.put(d, tree); directiveToTreeMap.put(d, tree);
@ -799,6 +955,7 @@ public class Modules extends JCTree.Visitor {
@Override @Override
public void visitRequires(JCRequires tree) { public void visitRequires(JCRequires tree) {
if (tree.directive != null) { if (tree.directive != null) {
chk.checkDeprecated(tree.moduleName.pos(), msym, tree.directive.module);
msym.directives = msym.directives.prepend(tree.directive); msym.directives = msym.directives.prepend(tree.directive);
} }
} }
@ -811,53 +968,58 @@ public class Modules extends JCTree.Visitor {
log.error(tree.qualid.pos(), Errors.ServiceDefinitionIsEnum(st.tsym)); log.error(tree.qualid.pos(), Errors.ServiceDefinitionIsEnum(st.tsym));
} else if (st.hasTag(CLASS)) { } else if (st.hasTag(CLASS)) {
ClassSymbol service = (ClassSymbol) st.tsym; ClassSymbol service = (ClassSymbol) st.tsym;
Directive.UsesDirective d = new Directive.UsesDirective(service); if (allUses.add(service)) {
if (!allUses.add(d)) { Directive.UsesDirective d = new Directive.UsesDirective(service);
msym.uses = msym.uses.prepend(d);
msym.directives = msym.directives.prepend(d);
} else {
log.error(tree.pos(), Errors.DuplicateUses(service)); log.error(tree.pos(), Errors.DuplicateUses(service));
} }
msym.uses = msym.uses.prepend(d);
msym.directives = msym.directives.prepend(d);
} }
} }
private void checkForCorrectness() { private void checkForCorrectness() {
for (Directive.ProvidesDirective provides : allProvides) { for (Directive.ProvidesDirective provides : msym.provides) {
JCProvides tree = directiveToTreeMap.get(provides); JCProvides tree = directiveToTreeMap.get(provides);
/* The implementation must be defined in the same module as the provides directive for (ClassSymbol impl : provides.impls) {
* (else, error) /* The implementation must be defined in the same module as the provides directive
*/ * (else, error)
PackageSymbol implementationDefiningPackage = provides.impl.packge(); */
if (implementationDefiningPackage.modle != msym) { PackageSymbol implementationDefiningPackage = impl.packge();
log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle)); if (implementationDefiningPackage.modle != msym) {
} // TODO: should use tree for the implentation name, not the entire provides tree
// TODO: should improve error message to identify the implementation type
/* There is no inherent requirement that module that provides a service should actually log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle));
* use it itself. However, it is a pointless declaration if the service package is not
* exported and there is no uses for the service.
*/
PackageSymbol interfaceDeclaringPackage = provides.service.packge();
boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym;
boolean isInterfaceExportedFromAReadableModule =
msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage;
if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) {
// ok the interface is declared in this module. Let's check if it's exported
boolean warn = true;
for (ExportsDirective export : msym.exports) {
if (interfaceDeclaringPackage == export.packge) {
warn = false;
break;
}
} }
if (warn) {
for (UsesDirective uses : msym.uses) { /* There is no inherent requirement that module that provides a service should actually
if (provides.service == uses.service) { * use it itself. However, it is a pointless declaration if the service package is not
* exported and there is no uses for the service.
*/
PackageSymbol interfaceDeclaringPackage = provides.service.packge();
boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym;
boolean isInterfaceExportedFromAReadableModule =
msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage;
if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) {
// ok the interface is declared in this module. Let's check if it's exported
boolean warn = true;
for (ExportsDirective export : msym.exports) {
if (interfaceDeclaringPackage == export.packge) {
warn = false; warn = false;
break; break;
} }
} }
} if (warn) {
if (warn) { for (UsesDirective uses : msym.uses) {
log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service)); if (provides.service == uses.service) {
warn = false;
break;
}
}
}
if (warn) {
log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service));
}
} }
} }
} }
@ -973,6 +1135,10 @@ public class Modules extends JCTree.Visitor {
allModules = result; allModules = result;
} }
public boolean isInModuleGraph(ModuleSymbol msym) {
return allModules == null || allModules.contains(msym);
}
private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) { private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
List<ModuleSymbol> todo = List.nil(); List<ModuleSymbol> todo = List.nil();
@ -1019,7 +1185,8 @@ public class Modules extends JCTree.Visitor {
return ; return ;
} }
ModuleSymbol msym = (ModuleSymbol) sym; ModuleSymbol msym = (ModuleSymbol) sym;
Set<ModuleSymbol> allModules = allModules(); Set<ModuleSymbol> allModules = new HashSet<>(allModules());
allModules.remove(syms.unnamedModule);
for (ModuleSymbol m : allModules) { for (ModuleSymbol m : allModules) {
m.complete(); m.complete();
} }
@ -1033,7 +1200,7 @@ public class Modules extends JCTree.Visitor {
}; };
} }
private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>(); private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresTransitiveCache = new HashMap<>();
private void completeModule(ModuleSymbol msym) { private void completeModule(ModuleSymbol msym) {
if (inInitModules) { if (inInitModules) {
@ -1079,34 +1246,36 @@ public class Modules extends JCTree.Visitor {
} }
Set<ModuleSymbol> readable = new LinkedHashSet<>(); Set<ModuleSymbol> readable = new LinkedHashSet<>();
Set<ModuleSymbol> requiresPublic = new HashSet<>(); Set<ModuleSymbol> requiresTransitive = new HashSet<>();
for (RequiresDirective d : msym.requires) { for (RequiresDirective d : msym.requires) {
d.module.complete(); d.module.complete();
readable.add(d.module); readable.add(d.module);
Set<ModuleSymbol> s = retrieveRequiresPublic(d.module); Set<ModuleSymbol> s = retrieveRequiresTransitive(d.module);
Assert.checkNonNull(s, () -> "no entry in cache for " + d.module); Assert.checkNonNull(s, () -> "no entry in cache for " + d.module);
readable.addAll(s); readable.addAll(s);
if (d.flags.contains(RequiresFlag.PUBLIC)) { if (d.flags.contains(RequiresFlag.TRANSITIVE)) {
requiresPublic.add(d.module); requiresTransitive.add(d.module);
requiresPublic.addAll(s); requiresTransitive.addAll(s);
} }
} }
requiresPublicCache.put(msym, requiresPublic); requiresTransitiveCache.put(msym, requiresTransitive);
initVisiblePackages(msym, readable); initVisiblePackages(msym, readable);
for (ExportsDirective d: msym.exports) { for (ExportsDirective d: msym.exports) {
d.packge.modle = msym; if (d.packge != null) {
d.packge.modle = msym;
}
} }
} }
private Set<ModuleSymbol> retrieveRequiresPublic(ModuleSymbol msym) { private Set<ModuleSymbol> retrieveRequiresTransitive(ModuleSymbol msym) {
Set<ModuleSymbol> requiresPublic = requiresPublicCache.get(msym); Set<ModuleSymbol> requiresTransitive = requiresTransitiveCache.get(msym);
if (requiresPublic == null) { if (requiresTransitive == null) {
//the module graph may contain cycles involving automatic modules or --add-reads edges //the module graph may contain cycles involving automatic modules or --add-reads edges
requiresPublic = new HashSet<>(); requiresTransitive = new HashSet<>();
Set<ModuleSymbol> seen = new HashSet<>(); Set<ModuleSymbol> seen = new HashSet<>();
List<ModuleSymbol> todo = List.of(msym); List<ModuleSymbol> todo = List.of(msym);
@ -1116,14 +1285,14 @@ public class Modules extends JCTree.Visitor {
todo = todo.tail; todo = todo.tail;
if (!seen.add(current)) if (!seen.add(current))
continue; continue;
requiresPublic.add(current); requiresTransitive.add(current);
current.complete(); current.complete();
Iterable<? extends RequiresDirective> requires; Iterable<? extends RequiresDirective> requires;
if (current != syms.unnamedModule) { if (current != syms.unnamedModule) {
Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym); Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym);
requires = current.requires; requires = current.requires;
for (RequiresDirective rd : requires) { for (RequiresDirective rd : requires) {
if (rd.isPublic()) if (rd.isTransitive())
todo = todo.prepend(rd.module); todo = todo.prepend(rd.module);
} }
} else { } else {
@ -1133,10 +1302,10 @@ public class Modules extends JCTree.Visitor {
} }
} }
requiresPublic.remove(msym); requiresTransitive.remove(msym);
} }
return requiresPublic; return requiresTransitive;
} }
private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) { private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) {

View file

@ -160,8 +160,6 @@ public class TypeEnter implements Completer {
// if there remain any unimported toplevels (these must have // if there remain any unimported toplevels (these must have
// no classes at all), process their import statements as well. // no classes at all), process their import statements as well.
for (JCCompilationUnit tree : trees) { for (JCCompilationUnit tree : trees) {
if (tree.defs.nonEmpty() && tree.defs.head.hasTag(MODULEDEF))
continue;
if (!tree.starImportScope.isFilled()) { if (!tree.starImportScope.isFilled()) {
Env<AttrContext> topEnv = enter.topLevelEnv(tree); Env<AttrContext> topEnv = enter.topLevelEnv(tree);
finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); }); finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); });
@ -344,13 +342,22 @@ public class TypeEnter implements Completer {
throw new FatalError(diags.fragment("fatal.err.no.java.lang")); throw new FatalError(diags.fragment("fatal.err.no.java.lang"));
importAll(make.at(tree.pos()).Import(make.QualIdent(javaLang), false), javaLang, env); importAll(make.at(tree.pos()).Import(make.QualIdent(javaLang), false), javaLang, env);
JCModuleDecl decl = tree.getModuleDecl();
// Process the package def and all import clauses. // Process the package def and all import clauses.
if (tree.getPackage() != null) if (tree.getPackage() != null && decl == null)
checkClassPackageClash(tree.getPackage()); checkClassPackageClash(tree.getPackage());
for (JCImport imp : tree.getImports()) { for (JCImport imp : tree.getImports()) {
doImport(imp); doImport(imp);
} }
if (decl != null) {
//check @Deprecated:
markDeprecated(decl.sym, decl.mods.annotations, env);
// process module annotations
annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle, null);
}
} finally { } finally {
this.env = prevEnv; this.env = prevEnv;
chk.setLint(prevLint); chk.setLint(prevLint);
@ -745,12 +752,7 @@ public class TypeEnter implements Completer {
} }
} }
// Annotations. markDeprecated(sym, tree.mods.annotations, baseEnv);
// In general, we cannot fully process annotations yet, but we
// can attribute the annotation types and then check to see if the
// @Deprecated annotation is present.
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
handleDeprecatedAnnotation(tree.mods.annotations, sym);
chk.checkNonCyclicDecl(tree); chk.checkNonCyclicDecl(tree);
} }
@ -765,32 +767,6 @@ public class TypeEnter implements Completer {
return superType; return superType;
} }
/**
* If a list of annotations contains a reference to java.lang.Deprecated,
* set the DEPRECATED flag.
* If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
**/
private void handleDeprecatedAnnotation(List<JCAnnotation> annotations, Symbol sym) {
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
if (a.annotationType.type == syms.deprecatedType) {
sym.flags_field |= Flags.DEPRECATED;
a.args.stream()
.filter(e -> e.hasTag(ASSIGN))
.map(e -> (JCAssign) e)
.filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval)
.findFirst()
.ifPresent(assign -> {
JCExpression rhs = TreeInfo.skipParens(assign.rhs);
if (rhs.hasTag(LITERAL)
&& Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
sym.flags_field |= DEPRECATED_REMOVAL;
}
});
}
}
}
@Override @Override
public void complete(Symbol sym) throws CompletionFailure { public void complete(Symbol sym) throws CompletionFailure {
Assert.check((topLevelPhase instanceof ImportsPhase) || Assert.check((topLevelPhase instanceof ImportsPhase) ||
@ -1135,4 +1111,41 @@ public class TypeEnter implements Completer {
List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null; List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null;
return make.Exec(make.Apply(typeargs, meth, make.Idents(params))); return make.Exec(make.Apply(typeargs, meth, make.Idents(params)));
} }
/**
* Mark sym deprecated if annotations contain @Deprecated annotation.
*/
public void markDeprecated(Symbol sym, List<JCAnnotation> annotations, Env<AttrContext> env) {
// In general, we cannot fully process annotations yet, but we
// can attribute the annotation types and then check to see if the
// @Deprecated annotation is present.
attr.attribAnnotationTypes(annotations, env);
handleDeprecatedAnnotations(annotations, sym);
}
/**
* If a list of annotations contains a reference to java.lang.Deprecated,
* set the DEPRECATED flag.
* If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
**/
private void handleDeprecatedAnnotations(List<JCAnnotation> annotations, Symbol sym) {
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
if (a.annotationType.type == syms.deprecatedType) {
sym.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
a.args.stream()
.filter(e -> e.hasTag(ASSIGN))
.map(e -> (JCAssign) e)
.filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval)
.findFirst()
.ifPresent(assign -> {
JCExpression rhs = TreeInfo.skipParens(assign.rhs);
if (rhs.hasTag(LITERAL)
&& Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
sym.flags_field |= DEPRECATED_REMOVAL;
}
});
}
}
}
} }

View file

@ -29,6 +29,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
@ -128,7 +129,7 @@ public abstract class BaseFileManager implements JavaFileManager {
protected String classLoaderClass; protected String classLoaderClass;
protected Locations locations; protected final Locations locations;
/** /**
* A flag for clients to use to indicate that this file manager should * A flag for clients to use to indicate that this file manager should
@ -209,7 +210,10 @@ public abstract class BaseFileManager implements JavaFileManager {
addReadsMethod.invoke(thisModule, targetModule); addReadsMethod.invoke(thisModule, targetModule);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
// ignore // ignore
} catch (Exception e) { } catch (IllegalAccessException
| IllegalArgumentException
| SecurityException
| InvocationTargetException e) {
throw new Abort(e); throw new Abort(e);
} }
return targetLoader; return targetLoader;
@ -324,12 +328,12 @@ public abstract class BaseFileManager implements JavaFileManager {
@SuppressWarnings("cast") @SuppressWarnings("cast")
public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) { public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
String encodingName = getEncodingName(); String encName = getEncodingName();
CharsetDecoder decoder; CharsetDecoder decoder;
try { try {
decoder = getDecoder(encodingName, ignoreEncodingErrors); decoder = getDecoder(encName, ignoreEncodingErrors);
} catch (IllegalCharsetNameException | UnsupportedCharsetException e) { } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
log.error("unsupported.encoding", encodingName); log.error("unsupported.encoding", encName);
return (CharBuffer)CharBuffer.allocate(1).flip(); return (CharBuffer)CharBuffer.allocate(1).flip();
} }
@ -365,7 +369,7 @@ public abstract class BaseFileManager implements JavaFileManager {
unmappable.append(String.format("%02X", inbuf.get())); unmappable.append(String.format("%02X", inbuf.get()));
} }
String charsetName = charset == null ? encodingName : charset.name(); String charsetName = charset == null ? encName : charset.name();
log.error(dest.limit(), log.error(dest.limit(),
Errors.IllegalCharForEncoding(unmappable.toString(), charsetName)); Errors.IllegalCharForEncoding(unmappable.toString(), charsetName));

View file

@ -1091,7 +1091,8 @@ public class Locations {
} }
// finally clean up the module name // finally clean up the module name
mn = mn.replaceAll("[^A-Za-z0-9]", ".") // replace non-alphanumeric mn = mn.replaceAll("(\\.|\\d)*$", "") // remove trailing version
.replaceAll("[^A-Za-z0-9]", ".") // replace non-alphanumeric
.replaceAll("(\\.)(\\1)+", ".") // collapse repeating dots .replaceAll("(\\.)(\\1)+", ".") // collapse repeating dots
.replaceAll("^\\.", "") // drop leading dots .replaceAll("^\\.", "") // drop leading dots
.replaceAll("\\.$", ""); // drop trailing dots .replaceAll("\\.$", ""); // drop trailing dots

View file

@ -129,8 +129,11 @@ public class ClassFile {
* String Translation Routines * String Translation Routines
***********************************************************************/ ***********************************************************************/
/** Return internal representation of buf[offset..offset+len-1], /**
* converting '/' to '.'. * Return internal representation of buf[offset..offset+len-1], converting '/' to '.'.
*
* Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
* which defines "internal name" to be the form using "/" instead of "."
*/ */
public static byte[] internalize(byte[] buf, int offset, int len) { public static byte[] internalize(byte[] buf, int offset, int len) {
byte[] translated = new byte[len]; byte[] translated = new byte[len];
@ -142,15 +145,21 @@ public class ClassFile {
return translated; return translated;
} }
/** Return internal representation of given name, /**
* converting '/' to '.'. * Return internal representation of given name, converting '/' to '.'.
*
* Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
* which defines "internal name" to be the form using "/" instead of "."
*/ */
public static byte[] internalize(Name name) { public static byte[] internalize(Name name) {
return internalize(name.getByteArray(), name.getByteOffset(), name.getByteLength()); return internalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
} }
/** Return external representation of buf[offset..offset+len-1], /**
* converting '.' to '/'. * Return external representation of buf[offset..offset+len-1], converting '.' to '/'.
*
* Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
* which defines "internal name" to be the form using "/" instead of "."
*/ */
public static byte[] externalize(byte[] buf, int offset, int len) { public static byte[] externalize(byte[] buf, int offset, int len) {
byte[] translated = new byte[len]; byte[] translated = new byte[len];
@ -162,8 +171,11 @@ public class ClassFile {
return translated; return translated;
} }
/** Return external representation of given name, /**
* converting '/' to '.'. * Return external representation of given name, converting '/' to '.'.
*
* Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
* which defines "internal name" to be the form using "/" instead of "."
*/ */
public static byte[] externalize(Name name) { public static byte[] externalize(Name name) {
return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength()); return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());

View file

@ -62,7 +62,9 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.Kinds.Kind.*;
import com.sun.tools.javac.code.Scope.LookupKind; import com.sun.tools.javac.code.Scope.LookupKind;
import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.TYPEVAR; import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
@ -159,6 +161,9 @@ public class ClassReader {
*/ */
protected ModuleSymbol currentModule = null; protected ModuleSymbol currentModule = null;
// FIXME: temporary compatibility code
private boolean readNewModuleAttribute;
/** The buffer containing the currently read class file. /** The buffer containing the currently read class file.
*/ */
byte[] buf = new byte[INITIAL_BUFFER_SIZE]; byte[] buf = new byte[INITIAL_BUFFER_SIZE];
@ -584,6 +589,53 @@ public class ClassReader {
throw badClassFile("bad.module-info.name"); throw badClassFile("bad.module-info.name");
} }
/** Read the name of a module.
* The name is stored in a CONSTANT_Utf8 entry, in
* JVMS 4.2 internal form (with '/' instead of '.')
*/
Name readModuleName(int i) {
Name name = readName(i);
// FIXME: temporary compatibility code
if (readNewModuleAttribute) {
return names.fromUtf(internalize(name));
} else {
return name;
}
}
/** Read module_flags.
*/
Set<ModuleFlags> readModuleFlags(int flags) {
Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class);
for (ModuleFlags f : ModuleFlags.values()) {
if ((flags & f.value) != 0)
set.add(f);
}
return set;
}
/** Read exports_flags.
*/
Set<ExportsFlag> readExportsFlags(int flags) {
Set<ExportsFlag> set = EnumSet.noneOf(ExportsFlag.class);
for (ExportsFlag f: ExportsFlag.values()) {
if ((flags & f.value) != 0)
set.add(f);
}
return set;
}
/** Read opens_flags.
*/
Set<OpensFlag> readOpensFlags(int flags) {
Set<OpensFlag> set = EnumSet.noneOf(OpensFlag.class);
for (OpensFlag f: OpensFlag.values()) {
if ((flags & f.value) != 0)
set.add(f);
}
return set;
}
/** Read requires_flags. /** Read requires_flags.
*/ */
Set<RequiresFlag> readRequiresFlags(int flags) { Set<RequiresFlag> readRequiresFlags(int flags) {
@ -996,7 +1048,9 @@ public class ClassReader {
new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) { protected void read(Symbol sym, int attrLen) {
sym.flags_field |= DEPRECATED; Symbol s = sym.owner.kind == MDL ? sym.owner : sym;
s.flags_field |= DEPRECATED;
} }
}, },
@ -1228,11 +1282,20 @@ public class ClassReader {
ModuleSymbol msym = (ModuleSymbol) sym.owner; ModuleSymbol msym = (ModuleSymbol) sym.owner;
ListBuffer<Directive> directives = new ListBuffer<>(); ListBuffer<Directive> directives = new ListBuffer<>();
// FIXME: temporary compatibility code
if (readNewModuleAttribute) {
Name moduleName = readModuleName(nextChar());
if (currentModule.name != moduleName) {
throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
}
}
msym.flags.addAll(readModuleFlags(nextChar()));
ListBuffer<RequiresDirective> requires = new ListBuffer<>(); ListBuffer<RequiresDirective> requires = new ListBuffer<>();
int nrequires = nextChar(); int nrequires = nextChar();
for (int i = 0; i < nrequires; i++) { for (int i = 0; i < nrequires; i++) {
Name name = readName(nextChar()); ModuleSymbol rsym = syms.enterModule(readModuleName(nextChar()));
ModuleSymbol rsym = syms.enterModule(name);
Set<RequiresFlag> flags = readRequiresFlags(nextChar()); Set<RequiresFlag> flags = readRequiresFlags(nextChar());
requires.add(new RequiresDirective(rsym, flags)); requires.add(new RequiresDirective(rsym, flags));
} }
@ -1244,6 +1307,7 @@ public class ClassReader {
for (int i = 0; i < nexports; i++) { for (int i = 0; i < nexports; i++) {
Name n = readName(nextChar()); Name n = readName(nextChar());
PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n))); PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
Set<ExportsFlag> flags = readExportsFlags(nextChar());
int nto = nextChar(); int nto = nextChar();
List<ModuleSymbol> to; List<ModuleSymbol> to;
if (nto == 0) { if (nto == 0) {
@ -1251,13 +1315,36 @@ public class ClassReader {
} else { } else {
ListBuffer<ModuleSymbol> lb = new ListBuffer<>(); ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
for (int t = 0; t < nto; t++) for (int t = 0; t < nto; t++)
lb.append(syms.enterModule(readName(nextChar()))); lb.append(syms.enterModule(readModuleName(nextChar())));
to = lb.toList(); to = lb.toList();
} }
exports.add(new ExportsDirective(p, to)); exports.add(new ExportsDirective(p, to, flags));
} }
msym.exports = exports.toList(); msym.exports = exports.toList();
directives.addAll(msym.exports); directives.addAll(msym.exports);
ListBuffer<OpensDirective> opens = new ListBuffer<>();
int nopens = nextChar();
if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) {
throw badClassFile("module.non.zero.opens", currentModule.name);
}
for (int i = 0; i < nopens; i++) {
Name n = readName(nextChar());
PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
Set<OpensFlag> flags = readOpensFlags(nextChar());
int nto = nextChar();
List<ModuleSymbol> to;
if (nto == 0) {
to = null;
} else {
ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
for (int t = 0; t < nto; t++)
lb.append(syms.enterModule(readModuleName(nextChar())));
to = lb.toList();
}
opens.add(new OpensDirective(p, to, flags));
}
msym.opens = opens.toList();
directives.addAll(msym.opens);
msym.directives = directives.toList(); msym.directives = directives.toList();
@ -1271,17 +1358,21 @@ public class ClassReader {
ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>(); ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
int nprovides = nextChar(); int nprovides = nextChar();
for (int i = 0; i < nprovides; i++) { for (int p = 0; p < nprovides; p++) {
Name srvc = readClassName(nextChar()); Name srvc = readClassName(nextChar());
Name impl = readClassName(nextChar()); int nimpls = nextChar();
provides.add(new InterimProvidesDirective(srvc, impl)); ListBuffer<Name> impls = new ListBuffer<>();
for (int i = 0; i < nimpls; i++) {
impls.append(readClassName(nextChar()));
provides.add(new InterimProvidesDirective(srvc, impls.toList()));
}
} }
interimProvides = provides.toList(); interimProvides = provides.toList();
} }
} }
}, },
new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) { new AttributeReader(names.ModuleVersion, V53, CLASS_ATTRIBUTE) {
@Override @Override
protected boolean accepts(AttributeKind kind) { protected boolean accepts(AttributeKind kind) {
return super.accepts(kind) && allowModules; return super.accepts(kind) && allowModules;
@ -1480,7 +1571,7 @@ public class ClassReader {
} else if (proxy.type.tsym == syms.repeatableType.tsym) { } else if (proxy.type.tsym == syms.repeatableType.tsym) {
repeatable = proxy; repeatable = proxy;
} else if (proxy.type.tsym == syms.deprecatedType.tsym) { } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
sym.flags_field |= DEPRECATED; sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
for (Pair<Name, Attribute> v : proxy.values) { for (Pair<Name, Attribute> v : proxy.values) {
if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) { if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) {
Attribute.Constant c = (Attribute.Constant) v.snd; Attribute.Constant c = (Attribute.Constant) v.snd;
@ -1547,7 +1638,7 @@ public class ClassReader {
// support preliminary jsr175-format class files // support preliminary jsr175-format class files
if (buf[poolIdx[i]] == CONSTANT_Class) if (buf[poolIdx[i]] == CONSTANT_Class)
return readClassSymbol(i).type; return readClassSymbol(i).type;
return readType(i); return readTypeToProxy(i);
} }
Type readEnumType(int i) { Type readEnumType(int i) {
// support preliminary jsr175-format class files // support preliminary jsr175-format class files
@ -1555,11 +1646,25 @@ public class ClassReader {
int length = getChar(index + 1); int length = getChar(index + 1);
if (buf[index + length + 2] != ';') if (buf[index + length + 2] != ';')
return enterClass(readName(i)).type; return enterClass(readName(i)).type;
return readType(i); return readTypeToProxy(i);
}
Type readTypeToProxy(int i) {
if (currentModule.module_info == currentOwner) {
int index = poolIdx[i];
return new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
} else {
return readType(i);
}
} }
CompoundAnnotationProxy readCompoundAnnotation() { CompoundAnnotationProxy readCompoundAnnotation() {
Type t = readTypeOrClassSymbol(nextChar()); Type t;
if (currentModule.module_info == currentOwner) {
int index = poolIdx[nextChar()];
t = new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
} else {
t = readTypeOrClassSymbol(nextChar());
}
int numFields = nextChar(); int numFields = nextChar();
ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>(); ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
for (int i=0; i<numFields; i++) { for (int i=0; i<numFields; i++) {
@ -1800,7 +1905,7 @@ public class ClassReader {
case 'e': case 'e':
return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar())); return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
case 'c': case 'c':
return new Attribute.Class(types, readTypeOrClassSymbol(nextChar())); return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
case '[': { case '[': {
int n = nextChar(); int n = nextChar();
ListBuffer<Attribute> l = new ListBuffer<>(); ListBuffer<Attribute> l = new ListBuffer<>();
@ -1817,6 +1922,7 @@ public class ClassReader {
interface ProxyVisitor extends Attribute.Visitor { interface ProxyVisitor extends Attribute.Visitor {
void visitEnumAttributeProxy(EnumAttributeProxy proxy); void visitEnumAttributeProxy(EnumAttributeProxy proxy);
void visitClassAttributeProxy(ClassAttributeProxy proxy);
void visitArrayAttributeProxy(ArrayAttributeProxy proxy); void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy); void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
} }
@ -1836,6 +1942,19 @@ public class ClassReader {
} }
} }
static class ClassAttributeProxy extends Attribute {
Type classType;
public ClassAttributeProxy(Type classType) {
super(null);
this.classType = classType;
}
public void accept(Visitor v) { ((ProxyVisitor)v).visitClassAttributeProxy(this); }
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public String toString() {
return "/*proxy class*/" + classType + ".class";
}
}
static class ArrayAttributeProxy extends Attribute { static class ArrayAttributeProxy extends Attribute {
List<Attribute> values; List<Attribute> values;
ArrayAttributeProxy(List<Attribute> values) { ArrayAttributeProxy(List<Attribute> values) {
@ -1909,14 +2028,15 @@ public class ClassReader {
} }
Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) { Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
Type annotationType = resolvePossibleProxyType(a.type);
ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>(); ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
for (List<Pair<Name,Attribute>> l = a.values; for (List<Pair<Name,Attribute>> l = a.values;
l.nonEmpty(); l.nonEmpty();
l = l.tail) { l = l.tail) {
MethodSymbol meth = findAccessMethod(a.type, l.head.fst); MethodSymbol meth = findAccessMethod(annotationType, l.head.fst);
buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd))); buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
} }
return new Attribute.Compound(a.type, buf.toList()); return new Attribute.Compound(annotationType, buf.toList());
} }
MethodSymbol findAccessMethod(Type container, Name name) { MethodSymbol findAccessMethod(Type container, Name name) {
@ -2000,7 +2120,8 @@ public class ClassReader {
public void visitEnumAttributeProxy(EnumAttributeProxy proxy) { public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
// type.tsym.flatName() should == proxy.enumFlatName // type.tsym.flatName() should == proxy.enumFlatName
TypeSymbol enumTypeSym = proxy.enumType.tsym; Type enumType = resolvePossibleProxyType(proxy.enumType);
TypeSymbol enumTypeSym = enumType.tsym;
VarSymbol enumerator = null; VarSymbol enumerator = null;
CompletionFailure failure = null; CompletionFailure failure = null;
try { try {
@ -2030,6 +2151,12 @@ public class ClassReader {
} }
} }
@Override
public void visitClassAttributeProxy(ClassAttributeProxy proxy) {
Type classType = resolvePossibleProxyType(proxy.classType);
result = new Attribute.Class(types, classType);
}
public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) { public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
int length = proxy.values.length(); int length = proxy.values.length();
Attribute[] ats = new Attribute[length]; Attribute[] ats = new Attribute[length];
@ -2044,6 +2171,21 @@ public class ClassReader {
public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) { public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
result = deproxyCompound(proxy); result = deproxyCompound(proxy);
} }
Type resolvePossibleProxyType(Type t) {
if (t instanceof ProxyType) {
Assert.check(requestingOwner.owner.kind == MDL);
ModuleSymbol prevCurrentModule = currentModule;
currentModule = (ModuleSymbol) requestingOwner.owner;
try {
return ((ProxyType) t).resolve();
} finally {
currentModule = prevCurrentModule;
}
} else {
return t;
}
}
} }
class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable { class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable {
@ -2086,7 +2228,11 @@ public class ClassReader {
AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) { AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
super(currentOwner.kind == MTH super(currentOwner.kind == MTH
? currentOwner.enclClass() : (ClassSymbol)currentOwner); ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
this.sym = sym; if (sym.kind == TYP && sym.owner.kind == MDL) {
this.sym = sym.owner;
} else {
this.sym = sym;
}
this.l = l; this.l = l;
this.classFile = currentClassFile; this.classFile = currentClassFile;
} }
@ -2097,6 +2243,18 @@ public class ClassReader {
try { try {
currentClassFile = classFile; currentClassFile = classFile;
List<Attribute.Compound> newList = deproxyCompoundList(l); List<Attribute.Compound> newList = deproxyCompoundList(l);
for (Attribute.Compound attr : newList) {
if (attr.type.tsym == syms.deprecatedType.tsym) {
sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
Attribute forRemoval = attr.member(names.forRemoval);
if (forRemoval instanceof Attribute.Constant) {
Attribute.Constant c = (Attribute.Constant) forRemoval;
if (c.type == syms.booleanType && ((Integer) c.value) != 0) {
sym.flags_field |= DEPRECATED_REMOVAL;
}
}
}
}
if (sym.annotationsPendingCompletion()) { if (sym.annotationsPendingCompletion()) {
sym.setDeclarationAttributes(newList); sym.setDeclarationAttributes(newList);
} else { } else {
@ -2407,15 +2565,22 @@ public class ClassReader {
} }
} else { } else {
c.flags_field = flags; c.flags_field = flags;
Name modInfoName = readModuleInfoName(nextChar());
currentModule = (ModuleSymbol) c.owner; currentModule = (ModuleSymbol) c.owner;
if (currentModule.name.append('.', names.module_info) != modInfoName) { int this_class = nextChar();
//strip trailing .module-info, if exists: // FIXME: temporary compatibility code
int modInfoStart = modInfoName.length() - names.module_info.length(); if (this_class == 0) {
modInfoName = modInfoName.subName(modInfoStart, modInfoName.length()) == names.module_info && readNewModuleAttribute = true;
modInfoName.charAt(modInfoStart - 1) == '.' ? } else {
modInfoName.subName(0, modInfoStart - 1) : modInfoName; Name modInfoName = readModuleInfoName(this_class);
throw badClassFile("module.name.mismatch", modInfoName, currentModule.name); if (currentModule.name.append('.', names.module_info) != modInfoName) {
//strip trailing .module-info, if exists:
int modInfoStart = modInfoName.length() - names.module_info.length();
modInfoName = modInfoName.subName(modInfoStart, modInfoName.length()) == names.module_info &&
modInfoName.charAt(modInfoStart - 1) == '.' ?
modInfoName.subName(0, modInfoStart - 1) : modInfoName;
throw badClassFile("module.name.mismatch", modInfoName, currentModule.name);
}
readNewModuleAttribute = false;
} }
} }
@ -2500,7 +2665,7 @@ public class ClassReader {
minorVersion = nextChar(); minorVersion = nextChar();
majorVersion = nextChar(); majorVersion = nextChar();
int maxMajor = Version.MAX().major; int maxMajor = 53; // Version.MAX().major; //******* TEMPORARY *******
int maxMinor = Version.MAX().minor; int maxMinor = Version.MAX().minor;
if (majorVersion > maxMajor || if (majorVersion > maxMajor ||
majorVersion * 1000 + minorVersion < majorVersion * 1000 + minorVersion <
@ -2542,6 +2707,8 @@ public class ClassReader {
List<Type> found = foundTypeVariables; List<Type> found = foundTypeVariables;
missingTypeVariables = List.nil(); missingTypeVariables = List.nil();
foundTypeVariables = List.nil(); foundTypeVariables = List.nil();
interimUses = List.nil();
interimProvides = List.nil();
filling = false; filling = false;
ClassType ct = (ClassType)currentOwner.type; ClassType ct = (ClassType)currentOwner.type;
ct.supertype_field = ct.supertype_field =
@ -2808,6 +2975,36 @@ public class ClassReader {
} }
} }
private class ProxyType extends Type {
private final byte[] content;
public ProxyType(byte[] content) {
super(syms.noSymbol, TypeMetadata.EMPTY);
this.content = content;
}
@Override
public TypeTag getTag() {
return TypeTag.NONE;
}
@Override
public Type cloneWithMetadata(TypeMetadata metadata) {
throw new UnsupportedOperationException();
}
public Type resolve() {
return sigToType(content, 0, content.length);
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public String toString() {
return "<ProxyType>";
}
}
private static final class InterimUsesDirective { private static final class InterimUsesDirective {
public final Name service; public final Name service;
@ -2819,11 +3016,11 @@ public class ClassReader {
private static final class InterimProvidesDirective { private static final class InterimProvidesDirective {
public final Name service; public final Name service;
public final Name impl; public final List<Name> impls;
public InterimProvidesDirective(Name service, Name impl) { public InterimProvidesDirective(Name service, List<Name> impls) {
this.service = service; this.service = service;
this.impl = impl; this.impls = impls;
} }
} }
@ -2852,8 +3049,12 @@ public class ClassReader {
currentModule.uses = uses.toList(); currentModule.uses = uses.toList();
ListBuffer<ProvidesDirective> provides = new ListBuffer<>(); ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
for (InterimProvidesDirective interim : interimProvidesCopy) { for (InterimProvidesDirective interim : interimProvidesCopy) {
ListBuffer<ClassSymbol> impls = new ListBuffer<>();
for (Name impl : interim.impls) {
impls.append(syms.enterClass(currentModule, impl));
}
ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service), ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
syms.enterClass(currentModule, interim.impl)); impls.toList());
provides.add(d); provides.add(d);
directives.add(d); directives.add(d);
} }

View file

@ -30,6 +30,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet;
import javax.tools.JavaFileManager; import javax.tools.JavaFileManager;
import javax.tools.FileObject; import javax.tools.FileObject;
@ -952,6 +953,10 @@ public class ClassWriter extends ClassFile {
ModuleSymbol m = (ModuleSymbol) c.owner; ModuleSymbol m = (ModuleSymbol) c.owner;
int alenIdx = writeAttr(names.Module); int alenIdx = writeAttr(names.Module);
databuf.appendChar(pool.put(names.fromUtf(externalize(m.name))));
databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
ListBuffer<RequiresDirective> requires = new ListBuffer<>(); ListBuffer<RequiresDirective> requires = new ListBuffer<>();
for (RequiresDirective r: m.requires) { for (RequiresDirective r: m.requires) {
if (!r.flags.contains(RequiresFlag.EXTRA)) if (!r.flags.contains(RequiresFlag.EXTRA))
@ -959,7 +964,7 @@ public class ClassWriter extends ClassFile {
} }
databuf.appendChar(requires.size()); databuf.appendChar(requires.size());
for (RequiresDirective r: requires) { for (RequiresDirective r: requires) {
databuf.appendChar(pool.put(r.module.name)); databuf.appendChar(pool.put(names.fromUtf(externalize(r.module.name))));
databuf.appendChar(RequiresFlag.value(r.flags)); databuf.appendChar(RequiresFlag.value(r.flags));
} }
@ -967,12 +972,29 @@ public class ClassWriter extends ClassFile {
databuf.appendChar(exports.size()); databuf.appendChar(exports.size());
for (ExportsDirective e: exports) { for (ExportsDirective e: exports) {
databuf.appendChar(pool.put(names.fromUtf(externalize(e.packge.flatName())))); databuf.appendChar(pool.put(names.fromUtf(externalize(e.packge.flatName()))));
databuf.appendChar(ExportsFlag.value(e.flags));
if (e.modules == null) { if (e.modules == null) {
databuf.appendChar(0); databuf.appendChar(0);
} else { } else {
databuf.appendChar(e.modules.size()); databuf.appendChar(e.modules.size());
for (ModuleSymbol msym: e.modules) for (ModuleSymbol msym: e.modules) {
databuf.appendChar(pool.put(msym.name)); databuf.appendChar(pool.put(names.fromUtf(externalize(msym.name))));
}
}
}
List<OpensDirective> opens = m.opens;
databuf.appendChar(opens.size());
for (OpensDirective o: opens) {
databuf.appendChar(pool.put(names.fromUtf(externalize(o.packge.flatName()))));
databuf.appendChar(OpensFlag.value(o.flags));
if (o.modules == null) {
databuf.appendChar(0);
} else {
databuf.appendChar(o.modules.size());
for (ModuleSymbol msym: o.modules) {
databuf.appendChar(pool.put(names.fromUtf(externalize(msym.name))));
}
} }
} }
@ -982,12 +1004,19 @@ public class ClassWriter extends ClassFile {
databuf.appendChar(pool.put(s.service)); databuf.appendChar(pool.put(s.service));
} }
List<ProvidesDirective> services = m.provides; // temporary fix to merge repeated provides clause for same service;
databuf.appendChar(services.size()); // eventually this should be disallowed when analyzing the module,
for (ProvidesDirective s: services) { // so that each service type only appears once.
databuf.appendChar(pool.put(s.service)); Map<ClassSymbol, Set<ClassSymbol>> mergedProvides = new LinkedHashMap<>();
databuf.appendChar(pool.put(s.impl)); for (ProvidesDirective p : m.provides) {
mergedProvides.computeIfAbsent(p.service, s -> new LinkedHashSet<>()).addAll(p.impls);
} }
databuf.appendChar(mergedProvides.size());
mergedProvides.forEach((srvc, impls) -> {
databuf.appendChar(pool.put(srvc));
databuf.appendChar(impls.size());
impls.forEach(impl -> databuf.appendChar(pool.put(impl)));
});
endAttr(alenIdx); endAttr(alenIdx);
return 1; return 1;
@ -1688,7 +1717,11 @@ public class ClassWriter extends ClassFile {
} }
databuf.appendChar(flags); databuf.appendChar(flags);
databuf.appendChar(pool.put(c)); if (c.owner.kind == MDL) {
databuf.appendChar(0);
} else {
databuf.appendChar(pool.put(c));
}
databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0); databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0);
databuf.appendChar(interfaces.length()); databuf.appendChar(interfaces.length());
for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail) for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
@ -1766,12 +1799,20 @@ public class ClassWriter extends ClassFile {
acount += writeEnclosingMethodAttribute(c); acount += writeEnclosingMethodAttribute(c);
if (c.owner.kind == MDL) { if (c.owner.kind == MDL) {
acount += writeModuleAttribute(c); acount += writeModuleAttribute(c);
acount += writeFlagAttrs(c.owner.flags());
} }
acount += writeExtraClassAttributes(c); acount += writeExtraClassAttributes(c);
poolbuf.appendInt(JAVA_MAGIC); poolbuf.appendInt(JAVA_MAGIC);
poolbuf.appendChar(target.minorVersion);
poolbuf.appendChar(target.majorVersion); if (c.owner.kind == MDL) {
// temporarily overide to force use of v53 for module-info.class
poolbuf.appendChar(0);
poolbuf.appendChar(53);
} else {
poolbuf.appendChar(target.minorVersion);
poolbuf.appendChar(target.majorVersion);
}
writePool(c.pool); writePool(c.pool);

View file

@ -31,8 +31,6 @@ import java.nio.file.Path;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import com.sun.tools.javac.jvm.ClassFile;
import static com.sun.tools.javac.jvm.ClassFile.*; import static com.sun.tools.javac.jvm.ClassFile.*;
@ -93,11 +91,44 @@ public class ModuleNameReader {
int minorVersion = nextChar(); int minorVersion = nextChar();
int majorVersion = nextChar(); int majorVersion = nextChar();
if (majorVersion < 53)
throw new BadClassFile("bad major version number for module: " + majorVersion);
indexPool(); indexPool();
int accessflags = nextChar(); int access_flags = nextChar();
return readModuleInfoName(nextChar()); if (access_flags != 0x8000)
throw new BadClassFile("invalid access flags for module: 0x" + Integer.toHexString(access_flags));
// FIXME: temporary compatibility code
int this_class = nextChar();
if (this_class == 0) {
// new form
checkZero(nextChar(), "super_class");
checkZero(nextChar(), "interface_count");
checkZero(nextChar(), "fields_count");
checkZero(nextChar(), "methods_count");
int attributes_count = nextChar();
for (int i = 0; i < attributes_count; i++) {
int attr_name = nextChar();
int attr_length = nextInt();
if (getUtf8Value(attr_name, false).equals("Module") && attr_length > 2) {
return getUtf8Value(nextChar(), true);
} else {
// skip over unknown attributes
bp += attr_length;
}
}
throw new BadClassFile("no Module attribute");
} else {
// old form
return readModuleInfoName(this_class);
}
}
void checkZero(int count, String name) throws BadClassFile {
if (count != 0)
throw new BadClassFile("invalid " + name + " for module: " + count);
} }
/** Extract a character at position bp from buf. /** Extract a character at position bp from buf.
@ -166,6 +197,20 @@ public class ModuleNameReader {
} }
} }
String getUtf8Value(int index, boolean internalize) throws BadClassFile {
int utf8Index = poolIdx[index];
if (buf[utf8Index] == CONSTANT_Utf8) {
int len = getChar(utf8Index + 1);
int start = utf8Index + 3;
if (internalize) {
return new String(ClassFile.internalize(buf, start, len));
} else {
return new String(buf, start, len);
}
}
throw new BadClassFile("bad name at index " + index);
}
/** Read the class name of a module-info.class file. /** Read the class name of a module-info.class file.
* The name is stored in a CONSTANT_Class entry, where the * The name is stored in a CONSTANT_Class entry, where the
* class name is of the form module-name/module-info. * class name is of the form module-name/module-info.

View file

@ -608,8 +608,9 @@ public class Arguments {
log.error(Errors.ProcessorpathNoProcessormodulepath); log.error(Errors.ProcessorpathNoProcessormodulepath);
} }
if (obsoleteOptionFound) if (obsoleteOptionFound && lintOptions) {
log.warning(LintCategory.OPTIONS, "option.obsolete.suppression"); log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
}
SourceVersion sv = Source.toSourceVersion(source); SourceVersion sv = Source.toSourceVersion(source);
validateAddExports(sv); validateAddExports(sv);
@ -617,6 +618,10 @@ public class Arguments {
validateAddReads(sv); validateAddReads(sv);
validateLimitModules(sv); validateLimitModules(sv);
if (lintOptions && options.isSet(Option.ADD_OPENS)) {
log.warning(LintCategory.OPTIONS, Warnings.AddopensIgnored);
}
return !errors && (log.nerrors == 0); return !errors && (log.nerrors == 0);
} }

View file

@ -584,6 +584,8 @@ public enum Option {
} }
}, },
ADD_OPENS("--add-opens", null, null, HIDDEN, BASIC),
ADD_READS("--add-reads", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) { ADD_READS("--add-reads", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) {
@Override @Override
public boolean process(OptionHelper helper, String option, String arg) { public boolean process(OptionHelper helper, String option, String arg) {

View file

@ -375,7 +375,8 @@ public class JavacElements implements Elements {
@DefinedBy(Api.LANGUAGE_MODEL) @DefinedBy(Api.LANGUAGE_MODEL)
public boolean isDeprecated(Element e) { public boolean isDeprecated(Element e) {
Symbol sym = cast(Symbol.class, e); Symbol sym = cast(Symbol.class, e);
return (sym.flags() & Flags.DEPRECATED) != 0; sym.complete();
return sym.isDeprecated();
} }
@DefinedBy(Api.LANGUAGE_MODEL) @DefinedBy(Api.LANGUAGE_MODEL)

View file

@ -29,6 +29,7 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.parser.Tokens.*; import com.sun.tools.javac.parser.Tokens.*;
@ -51,7 +52,6 @@ import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
import static com.sun.tools.javac.parser.Tokens.TokenKind.LT; import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
import static com.sun.tools.javac.tree.JCTree.Tag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*;
import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
/** The parser maps a token sequence into an abstract syntax /** The parser maps a token sequence into an abstract syntax
* tree. It operates by recursive descent, with code derived * tree. It operates by recursive descent, with code derived
@ -3105,65 +3105,78 @@ public class JavacParser implements Parser {
Token firstToken = token; Token firstToken = token;
JCModifiers mods = null; JCModifiers mods = null;
boolean consumedToplevelDoc = false; boolean consumedToplevelDoc = false;
boolean seenImport = false;
boolean seenPackage = false;
ListBuffer<JCTree> defs = new ListBuffer<>(); ListBuffer<JCTree> defs = new ListBuffer<>();
if (token.kind == MONKEYS_AT)
mods = modifiersOpt();
if (token.kind == IDENTIFIER && token.name() == names.module) { if (token.kind == PACKAGE) {
defs.append(moduleDecl(token.comment(CommentStyle.JAVADOC))); int packagePos = token.pos;
List<JCAnnotation> annotations = List.nil();
seenPackage = true;
if (mods != null) {
checkNoMods(mods.flags);
annotations = mods.annotations;
mods = null;
}
nextToken();
JCExpression pid = qualident(false);
accept(SEMI);
JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
attach(pd, firstToken.comment(CommentStyle.JAVADOC));
consumedToplevelDoc = true; consumedToplevelDoc = true;
} else { storeEnd(pd, token.pos);
boolean seenImport = false; defs.append(pd);
boolean seenPackage = false;
if (token.kind == MONKEYS_AT)
mods = modifiersOpt();
if (token.kind == PACKAGE) {
int packagePos = token.pos;
List<JCAnnotation> annotations = List.nil();
seenPackage = true;
if (mods != null) {
checkNoMods(mods.flags);
annotations = mods.annotations;
mods = null;
}
nextToken();
JCExpression pid = qualident(false);
accept(SEMI);
JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
attach(pd, firstToken.comment(CommentStyle.JAVADOC));
consumedToplevelDoc = true;
storeEnd(pd, token.pos);
defs.append(pd);
}
boolean checkForImports = true;
boolean firstTypeDecl = true;
while (token.kind != EOF) {
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(checkForImports, false, false, false);
if (token.kind == EOF)
break;
}
if (checkForImports && mods == null && token.kind == IMPORT) {
seenImport = true;
defs.append(importDeclaration());
} else {
Comment docComment = token.comment(CommentStyle.JAVADOC);
if (firstTypeDecl && !seenImport && !seenPackage) {
docComment = firstToken.comment(CommentStyle.JAVADOC);
consumedToplevelDoc = true;
}
JCTree def = typeDeclaration(mods, docComment);
if (def instanceof JCExpressionStatement)
def = ((JCExpressionStatement)def).expr;
defs.append(def);
if (def instanceof JCClassDecl)
checkForImports = false;
mods = null;
firstTypeDecl = false;
}
}
} }
boolean checkForImports = true;
boolean firstTypeDecl = true;
while (token.kind != EOF) {
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(checkForImports, false, false, false);
if (token.kind == EOF)
break;
}
if (checkForImports && mods == null && token.kind == IMPORT) {
seenImport = true;
defs.append(importDeclaration());
} else {
Comment docComment = token.comment(CommentStyle.JAVADOC);
if (firstTypeDecl && !seenImport && !seenPackage) {
docComment = firstToken.comment(CommentStyle.JAVADOC);
consumedToplevelDoc = true;
}
if (mods != null || token.kind != SEMI)
mods = modifiersOpt(mods);
if (firstTypeDecl && token.kind == IDENTIFIER) {
ModuleKind kind = ModuleKind.STRONG;
if (token.name() == names.open) {
kind = ModuleKind.OPEN;
nextToken();
}
if (token.kind == IDENTIFIER && token.name() == names.module) {
if (mods != null) {
checkNoMods(mods.flags & ~Flags.DEPRECATED);
}
defs.append(moduleDecl(mods, kind, docComment));
consumedToplevelDoc = true;
break;
} else if (kind != ModuleKind.STRONG) {
reportSyntaxError(token.pos, "expected.module");
}
}
JCTree def = typeDeclaration(mods, docComment);
if (def instanceof JCExpressionStatement)
def = ((JCExpressionStatement)def).expr;
defs.append(def);
if (def instanceof JCClassDecl)
checkForImports = false;
mods = null;
firstTypeDecl = false;
}
}
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList()); JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList());
if (!consumedToplevelDoc) if (!consumedToplevelDoc)
attach(toplevel, firstToken.comment(CommentStyle.JAVADOC)); attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
@ -3178,7 +3191,7 @@ public class JavacParser implements Parser {
return toplevel; return toplevel;
} }
JCModuleDecl moduleDecl(Comment dc) { JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
int pos = token.pos; int pos = token.pos;
if (!allowModules) { if (!allowModules) {
log.error(pos, Errors.ModulesNotSupportedInSource(source.name)); log.error(pos, Errors.ModulesNotSupportedInSource(source.name));
@ -3194,7 +3207,7 @@ public class JavacParser implements Parser {
accept(RBRACE); accept(RBRACE);
accept(EOF); accept(EOF);
JCModuleDecl result = toP(F.at(pos).ModuleDef(name, directives)); JCModuleDecl result = toP(F.at(pos).ModuleDef(mods, kind, name, directives));
attach(result, dc); attach(result, dc);
return result; return result;
} }
@ -3205,15 +3218,38 @@ public class JavacParser implements Parser {
int pos = token.pos; int pos = token.pos;
if (token.name() == names.requires) { if (token.name() == names.requires) {
nextToken(); nextToken();
boolean isPublic = false; boolean isTransitive = false;
if (token.kind == PUBLIC) { boolean isStaticPhase = false;
isPublic = true; loop:
while (true) {
switch (token.kind) {
case IDENTIFIER:
if (token.name() == names.transitive && !isTransitive) {
Token t1 = S.token(1);
if (t1.kind == SEMI || t1.kind == DOT) {
break loop;
}
isTransitive = true;
break;
} else {
break loop;
}
case STATIC:
if (isStaticPhase) {
error(token.pos, "repeated.modifier");
}
isStaticPhase = true;
break;
default:
break loop;
}
nextToken(); nextToken();
} }
JCExpression moduleName = qualident(false); JCExpression moduleName = qualident(false);
accept(SEMI); accept(SEMI);
defs.append(toP(F.at(pos).Requires(isPublic, moduleName))); defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
} else if (token.name() == names.exports) { } else if (token.name() == names.exports || token.name() == names.opens) {
boolean exports = token.name() == names.exports;
nextToken(); nextToken();
JCExpression pkgName = qualident(false); JCExpression pkgName = qualident(false);
List<JCExpression> moduleNames = null; List<JCExpression> moduleNames = null;
@ -3222,15 +3258,21 @@ public class JavacParser implements Parser {
moduleNames = qualidentList(false); moduleNames = qualidentList(false);
} }
accept(SEMI); accept(SEMI);
defs.append(toP(F.at(pos).Exports(pkgName, moduleNames))); JCDirective d;
if (exports) {
d = F.at(pos).Exports(pkgName, moduleNames);
} else {
d = F.at(pos).Opens(pkgName, moduleNames);
}
defs.append(toP(d));
} else if (token.name() == names.provides) { } else if (token.name() == names.provides) {
nextToken(); nextToken();
JCExpression serviceName = qualident(false); JCExpression serviceName = qualident(false);
if (token.kind == IDENTIFIER && token.name() == names.with) { if (token.kind == IDENTIFIER && token.name() == names.with) {
nextToken(); nextToken();
JCExpression implName = qualident(false); List<JCExpression> implNames = qualidentList(false);
accept(SEMI); accept(SEMI);
defs.append(toP(F.at(pos).Provides(serviceName, implName))); defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
} else { } else {
error(token.pos, "expected", "'" + names.with + "'"); error(token.pos, "expected", "'" + names.with + "'");
skip(false, false, false, false); skip(false, false, false, false);

View file

@ -872,6 +872,9 @@ compiler.err.operator.cant.be.applied.1=\
compiler.err.pkg.annotations.sb.in.package-info.java=\ compiler.err.pkg.annotations.sb.in.package-info.java=\
package annotations should be in file package-info.java package annotations should be in file package-info.java
compiler.err.no.pkg.in.module-info.java=\
package clauses should not be in file module-info.java
# 0: symbol # 0: symbol
compiler.err.pkg.clashes.with.class.of.same.name=\ compiler.err.pkg.clashes.with.class.of.same.name=\
package {0} clashes with class of same name package {0} clashes with class of same name
@ -1462,6 +1465,14 @@ compiler.warn.has.been.deprecated=\
compiler.warn.has.been.deprecated.for.removal=\ compiler.warn.has.been.deprecated.for.removal=\
{0} in {1} has been deprecated and marked for removal {0} in {1} has been deprecated and marked for removal
# 0: symbol
compiler.warn.has.been.deprecated.module=\
module {0} has been deprecated
# 0: symbol
compiler.warn.has.been.deprecated.for.removal.module=\
module {0} has been deprecated and marked for removal
# 0: symbol # 0: symbol
compiler.warn.sun.proprietary=\ compiler.warn.sun.proprietary=\
{0} is internal proprietary API and may be removed in a future release {0} is internal proprietary API and may be removed in a future release
@ -1796,6 +1807,9 @@ compiler.err.premature.eof=\
reached end of file while parsing reached end of file while parsing
## The following are related in form, but do not easily fit the above paradigm. ## The following are related in form, but do not easily fit the above paradigm.
compiler.err.expected.module=\
''module'' expected
compiler.err.dot.class.expected=\ compiler.err.dot.class.expected=\
''.class'' expected ''.class'' expected
@ -2747,8 +2761,23 @@ compiler.err.duplicate.requires=\
duplicate requires: {0} duplicate requires: {0}
# 0: symbol # 0: symbol
compiler.err.duplicate.exports=\ compiler.err.conflicting.exports=\
duplicate export: {0} duplicate or conflicting exports: {0}
# 0: symbol
compiler.err.conflicting.opens=\
duplicate or conflicting opens: {0}
# 0: symbol
compiler.err.conflicting.exports.to.module=\
duplicate or conflicting exports to module: {0}
# 0: symbol
compiler.err.conflicting.opens.to.module=\
duplicate or conflicting opens to module: {0}
compiler.err.no.opens.unless.strong=\
''opens'' only allowed in strong modules
# 0: symbol, 1: symbol # 0: symbol, 1: symbol
compiler.err.duplicate.provides=\ compiler.err.duplicate.provides=\
@ -2763,7 +2792,11 @@ compiler.err.service.implementation.is.abstract=\
the service implementation is an abstract class: {0} the service implementation is an abstract class: {0}
compiler.err.service.implementation.must.be.subtype.of.service.interface=\ compiler.err.service.implementation.must.be.subtype.of.service.interface=\
the service implementation type must be a subtype of the service interface type the service implementation type must be a subtype of the service interface type, or \
have a public static no-args method named "provider" returning the service implementation
compiler.err.service.implementation.provider.return.must.be.subtype.of.service.interface=\
the "provider" method return type must be a subtype of the service interface type
# 0: symbol # 0: symbol
compiler.err.service.implementation.is.inner=\ compiler.err.service.implementation.is.inner=\
@ -2799,6 +2832,14 @@ compiler.err.module.name.mismatch=\
compiler.misc.module.name.mismatch=\ compiler.misc.module.name.mismatch=\
module name {0} does not match expected name {1} module name {0} does not match expected name {1}
# 0: name
compiler.err.module.non.zero.opens=\
open module {0} has non-zero opens_count
# 0: name
compiler.misc.module.non.zero.opens=\
open module {0} has non-zero opens_count
compiler.err.module.decl.sb.in.module-info.java=\ compiler.err.module.decl.sb.in.module-info.java=\
module declarations should be in a file named module-info.java module declarations should be in a file named module-info.java
@ -2855,6 +2896,9 @@ compiler.warn.module.for.option.not.found=\
compiler.err.addmods.all.module.path.invalid=\ compiler.err.addmods.all.module.path.invalid=\
--add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module --add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module
compiler.warn.addopens.ignored=\
--add-opens has no effect at compile time
compiler.misc.locn.module_source_path=\ compiler.misc.locn.module_source_path=\
module source path module source path
@ -2885,8 +2929,8 @@ compiler.warn.leaks.not.accessible=\
compiler.warn.leaks.not.accessible.unexported=\ compiler.warn.leaks.not.accessible.unexported=\
{0} {1} in module {2} is not exported {0} {1} in module {2} is not exported
# 0: kind name, 1: symbol, 2: symbol # 0: kind name, 1: symbol, 2: symbol
compiler.warn.leaks.not.accessible.not.required.public=\ compiler.warn.leaks.not.accessible.not.required.transitive=\
{0} {1} in module {2} is not indirectly exported using 'requires public' {0} {1} in module {2} is not indirectly exported using 'requires transitive'
# 0: kind name, 1: symbol, 2: symbol # 0: kind name, 1: symbol, 2: symbol
compiler.warn.leaks.not.accessible.unexported.qualified=\ compiler.warn.leaks.not.accessible.unexported.qualified=\
{0} {1} in module {2} may not be visible to all clients that require this module {0} {1} in module {2} may not be visible to all clients that require this module

View file

@ -841,7 +841,7 @@ compiler.err.class.public.should.be.in.file=\u30AF\u30E9\u30B9{0}\u306Fpublic\u3
## All errors which do not refer to a particular line in the source code are ## All errors which do not refer to a particular line in the source code are
## preceded by this string. ## preceded by this string.
compiler.err.error=\u30A8\u30E9\u30FC: compiler.err.error=\u30A8\u30E9\u30FC:
# The following error messages do not refer to a line in the source code. # The following error messages do not refer to a line in the source code.
compiler.err.cant.read.file={0}\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093 compiler.err.cant.read.file={0}\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093
@ -1021,7 +1021,7 @@ compiler.warn.warning=\u8B66\u544A:
## Warning messages may also include the following prefix to identify a ## Warning messages may also include the following prefix to identify a
## lint option ## lint option
# 0: option name # 0: option name
compiler.warn.lintOption=[{0}] compiler.warn.lintOption=[{0}]
# 0: symbol # 0: symbol
compiler.warn.constant.SVUID=serialVersionUID\u306F\u30AF\u30E9\u30B9{0}\u306E\u5B9A\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 compiler.warn.constant.SVUID=serialVersionUID\u306F\u30AF\u30E9\u30B9{0}\u306E\u5B9A\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059

View file

@ -841,7 +841,7 @@ compiler.err.class.public.should.be.in.file=\u7C7B{0}\u662F\u516C\u5171\u7684, \
## All errors which do not refer to a particular line in the source code are ## All errors which do not refer to a particular line in the source code are
## preceded by this string. ## preceded by this string.
compiler.err.error=\u9519\u8BEF: compiler.err.error=\u9519\u8BEF:
# The following error messages do not refer to a line in the source code. # The following error messages do not refer to a line in the source code.
compiler.err.cant.read.file=\u65E0\u6CD5\u8BFB\u53D6: {0} compiler.err.cant.read.file=\u65E0\u6CD5\u8BFB\u53D6: {0}
@ -927,7 +927,7 @@ compiler.note.mref.stat=\u8F6C\u6362\u65B9\u6CD5\u5F15\u7528\n\u66FF\u4EE3 metaf
# 0: boolean, 1: symbol # 0: boolean, 1: symbol
compiler.note.mref.stat.1=\u8F6C\u6362\u65B9\u6CD5\u5F15\u7528\n\u66FF\u4EE3 metafactory = {0}\nbridge \u65B9\u6CD5 = {1} compiler.note.mref.stat.1=\u8F6C\u6362\u65B9\u6CD5\u5F15\u7528\n\u66FF\u4EE3 metafactory = {0}\nbridge \u65B9\u6CD5 = {1}
compiler.note.note=\u6CE8: compiler.note.note=\u6CE8:
# 0: file name # 0: file name
compiler.note.deprecated.filename={0}\u4F7F\u7528\u6216\u8986\u76D6\u4E86\u5DF2\u8FC7\u65F6\u7684 API\u3002 compiler.note.deprecated.filename={0}\u4F7F\u7528\u6216\u8986\u76D6\u4E86\u5DF2\u8FC7\u65F6\u7684 API\u3002
@ -1016,12 +1016,12 @@ compiler.misc.resume.abort=\u7EE7\u7EED(R), \u653E\u5F03(A)>
## ##
## All warning messages are preceded by the following string. ## All warning messages are preceded by the following string.
compiler.warn.warning=\u8B66\u544A: compiler.warn.warning=\u8B66\u544A:
## Warning messages may also include the following prefix to identify a ## Warning messages may also include the following prefix to identify a
## lint option ## lint option
# 0: option name # 0: option name
compiler.warn.lintOption=[{0}] compiler.warn.lintOption=[{0}]
# 0: symbol # 0: symbol
compiler.warn.constant.SVUID=serialVersionUID \u5728\u7C7B{0}\u4E2D\u5FC5\u987B\u662F\u5E38\u91CF compiler.warn.constant.SVUID=serialVersionUID \u5728\u7C7B{0}\u4E2D\u5FC5\u987B\u662F\u5E38\u91CF

View file

@ -47,7 +47,10 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*;
import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileManager.Location;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.tools.javac.code.Directive.ExportsDirective; import com.sun.tools.javac.code.Directive.ExportsDirective;
import com.sun.tools.javac.code.Directive.OpensDirective;
import com.sun.tools.javac.code.Type.ModuleType;
/** /**
* Root class for abstract syntax tree nodes. It provides definitions * Root class for abstract syntax tree nodes. It provides definitions
@ -352,6 +355,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
MODULEDEF, MODULEDEF,
EXPORTS, EXPORTS,
OPENS,
PROVIDES, PROVIDES,
REQUIRES, REQUIRES,
USES, USES,
@ -527,6 +531,16 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
@DefinedBy(Api.COMPILER_TREE) @DefinedBy(Api.COMPILER_TREE)
public Kind getKind() { return Kind.COMPILATION_UNIT; } public Kind getKind() { return Kind.COMPILATION_UNIT; }
public JCModuleDecl getModuleDecl() {
for (JCTree tree : defs) {
if (tree.hasTag(MODULEDEF)) {
return (JCModuleDecl) tree;
}
}
return null;
}
@DefinedBy(Api.COMPILER_TREE) @DefinedBy(Api.COMPILER_TREE)
public JCPackageDecl getPackage() { public JCPackageDecl getPackage() {
// PackageDecl must be the first entry if it exists // PackageDecl must be the first entry if it exists
@ -2619,11 +2633,17 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
} }
public static class JCModuleDecl extends JCTree implements ModuleTree { public static class JCModuleDecl extends JCTree implements ModuleTree {
public JCModifiers mods;
public ModuleType type;
private final ModuleKind kind;
public JCExpression qualId; public JCExpression qualId;
public List<JCDirective> directives; public List<JCDirective> directives;
public ModuleSymbol sym; public ModuleSymbol sym;
protected JCModuleDecl(JCExpression qualId, List<JCDirective> directives) { protected JCModuleDecl(JCModifiers mods, ModuleKind kind,
JCExpression qualId, List<JCDirective> directives) {
this.mods = mods;
this.kind = kind;
this.qualId = qualId; this.qualId = qualId;
this.directives = directives; this.directives = directives;
} }
@ -2636,6 +2656,16 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
return Kind.MODULE; return Kind.MODULE;
} }
@Override @DefinedBy(Api.COMPILER_TREE)
public List<? extends AnnotationTree> getAnnotations() {
return mods.annotations;
}
@Override @DefinedBy(Api.COMPILER_TREE)
public ModuleKind getModuleType() {
return kind;
}
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public JCExpression getName() { public JCExpression getName() {
return qualId; return qualId;
@ -2677,7 +2707,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public JCExpression getExportName() { public JCExpression getPackageName() {
return qualid; return qualid;
} }
@ -2693,18 +2723,58 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
@Override @Override
public Tag getTag() { public Tag getTag() {
return EXPORTS; return Tag.EXPORTS;
}
}
public static class JCOpens extends JCDirective
implements OpensTree {
public JCExpression qualid;
public List<JCExpression> moduleNames;
public OpensDirective directive;
protected JCOpens(JCExpression qualId, List<JCExpression> moduleNames) {
this.qualid = qualId;
this.moduleNames = moduleNames;
}
@Override
public void accept(Visitor v) { v.visitOpens(this); }
@Override @DefinedBy(Api.COMPILER_TREE)
public Kind getKind() {
return Kind.OPENS;
}
@Override @DefinedBy(Api.COMPILER_TREE)
public JCExpression getPackageName() {
return qualid;
}
@Override @DefinedBy(Api.COMPILER_TREE)
public List<JCExpression> getModuleNames() {
return moduleNames;
}
@Override @DefinedBy(Api.COMPILER_TREE)
public <R, D> R accept(TreeVisitor<R, D> v, D d) {
return v.visitOpens(this, d);
}
@Override
public Tag getTag() {
return Tag.OPENS;
} }
} }
public static class JCProvides extends JCDirective public static class JCProvides extends JCDirective
implements ProvidesTree { implements ProvidesTree {
public JCExpression serviceName; public JCExpression serviceName;
public JCExpression implName; public List<JCExpression> implNames;
protected JCProvides(JCExpression serviceName, JCExpression implName) { protected JCProvides(JCExpression serviceName, List<JCExpression> implNames) {
this.serviceName = serviceName; this.serviceName = serviceName;
this.implName = implName; this.implNames = implNames;
} }
@Override @Override
@ -2726,8 +2796,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public JCExpression getImplementationName() { public List<JCExpression> getImplementationNames() {
return implName; return implNames;
} }
@Override @Override
@ -2738,12 +2808,14 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public static class JCRequires extends JCDirective public static class JCRequires extends JCDirective
implements RequiresTree { implements RequiresTree {
public boolean isPublic; public boolean isTransitive;
public boolean isStaticPhase;
public JCExpression moduleName; public JCExpression moduleName;
public RequiresDirective directive; public RequiresDirective directive;
protected JCRequires(boolean isPublic, JCExpression moduleName) { protected JCRequires(boolean isTransitive, boolean isStaticPhase, JCExpression moduleName) {
this.isPublic = isPublic; this.isTransitive = isTransitive;
this.isStaticPhase = isStaticPhase;
this.moduleName = moduleName; this.moduleName = moduleName;
} }
@ -2761,8 +2833,13 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public boolean isPublic() { public boolean isTransitive() {
return isPublic; return isTransitive;
}
@Override @DefinedBy(Api.COMPILER_TREE)
public boolean isStatic() {
return isStaticPhase;
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
@ -2946,10 +3023,11 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args); JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args);
JCModifiers Modifiers(long flags, List<JCAnnotation> annotations); JCModifiers Modifiers(long flags, List<JCAnnotation> annotations);
JCErroneous Erroneous(List<? extends JCTree> errs); JCErroneous Erroneous(List<? extends JCTree> errs);
JCModuleDecl ModuleDef(JCExpression qualId, List<JCDirective> directives); JCModuleDecl ModuleDef(JCModifiers mods, ModuleKind kind, JCExpression qualId, List<JCDirective> directives);
JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames); JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames);
JCProvides Provides(JCExpression serviceName, JCExpression implName); JCOpens Opens(JCExpression qualId, List<JCExpression> moduleNames);
JCRequires Requires(boolean isPublic, JCExpression qualId); JCProvides Provides(JCExpression serviceName, List<JCExpression> implNames);
JCRequires Requires(boolean isTransitive, boolean isStaticPhase, JCExpression qualId);
JCUses Uses(JCExpression qualId); JCUses Uses(JCExpression qualId);
LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr); LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr);
} }
@ -3013,6 +3091,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitErroneous(JCErroneous that) { visitTree(that); } public void visitErroneous(JCErroneous that) { visitTree(that); }
public void visitModuleDef(JCModuleDecl that) { visitTree(that); } public void visitModuleDef(JCModuleDecl that) { visitTree(that); }
public void visitExports(JCExports that) { visitTree(that); } public void visitExports(JCExports that) { visitTree(that); }
public void visitOpens(JCOpens that) { visitTree(that); }
public void visitProvides(JCProvides that) { visitTree(that); } public void visitProvides(JCProvides that) { visitTree(that); }
public void visitRequires(JCRequires that) { visitTree(that); } public void visitRequires(JCRequires that) { visitTree(that); }
public void visitUses(JCUses that) { visitTree(that); } public void visitUses(JCUses that) { visitTree(that); }

View file

@ -28,6 +28,7 @@ package com.sun.tools.javac.tree;
import java.io.*; import java.io.*;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
@ -441,6 +442,10 @@ public class Pretty extends JCTree.Visitor {
@Override @Override
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {
try { try {
printAnnotations(tree.mods.annotations);
if (tree.getModuleType() == ModuleKind.OPEN) {
print("open ");
}
print("module "); print("module ");
printExpr(tree.qualId); printExpr(tree.qualId);
if (tree.directives == null) { if (tree.directives == null) {
@ -457,7 +462,11 @@ public class Pretty extends JCTree.Visitor {
@Override @Override
public void visitExports(JCExports tree) { public void visitExports(JCExports tree) {
try { try {
print("exports "); if (tree.hasTag(EXPORTS)) {
print("exports ");
} else {
print("opens ");
}
printExpr(tree.qualid); printExpr(tree.qualid);
if (tree.moduleNames != null) { if (tree.moduleNames != null) {
print(" to "); print(" to ");
@ -475,7 +484,7 @@ public class Pretty extends JCTree.Visitor {
print("provides "); print("provides ");
printExpr(tree.serviceName); printExpr(tree.serviceName);
print(" with "); print(" with ");
printExpr(tree.implName); printExprs(tree.implNames);
print(";"); print(";");
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
@ -486,8 +495,10 @@ public class Pretty extends JCTree.Visitor {
public void visitRequires(JCRequires tree) { public void visitRequires(JCRequires tree) {
try { try {
print("requires "); print("requires ");
if (tree.isPublic) if (tree.isStaticPhase)
print("public "); print("static ");
if (tree.isTransitive)
print("transitive ");
printExpr(tree.moduleName); printExpr(tree.moduleName);
print(";"); print(";");
} catch (IOException e) { } catch (IOException e) {

View file

@ -26,6 +26,7 @@
package com.sun.tools.javac.tree; package com.sun.tools.javac.tree;
import com.sun.source.tree.*; import com.sun.source.tree.*;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.DefinedBy.Api;
@ -508,9 +509,10 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public JCTree visitModule(ModuleTree node, P p) { public JCTree visitModule(ModuleTree node, P p) {
JCModuleDecl t = (JCModuleDecl) node; JCModuleDecl t = (JCModuleDecl) node;
JCModifiers mods = copy(t.mods, p);
JCExpression qualId = copy(t.qualId); JCExpression qualId = copy(t.qualId);
List<JCDirective> directives = copy(t.directives); List<JCDirective> directives = copy(t.directives);
return M.at(t.pos).ModuleDef(qualId, directives); return M.at(t.pos).ModuleDef(mods, t.getModuleType(), qualId, directives);
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
@ -521,19 +523,27 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
return M.at(t.pos).Exports(qualId, moduleNames); return M.at(t.pos).Exports(qualId, moduleNames);
} }
@Override @DefinedBy(Api.COMPILER_TREE)
public JCOpens visitOpens(OpensTree node, P p) {
JCOpens t = (JCOpens) node;
JCExpression qualId = copy(t.qualid, p);
List<JCExpression> moduleNames = copy(t.moduleNames, p);
return M.at(t.pos).Opens(qualId, moduleNames);
}
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public JCProvides visitProvides(ProvidesTree node, P p) { public JCProvides visitProvides(ProvidesTree node, P p) {
JCProvides t = (JCProvides) node; JCProvides t = (JCProvides) node;
JCExpression serviceName = copy(t.serviceName, p); JCExpression serviceName = copy(t.serviceName, p);
JCExpression implName = copy(t.implName, p); List<JCExpression> implNames = copy(t.implNames, p);
return M.at(t.pos).Provides(serviceName, implName); return M.at(t.pos).Provides(serviceName, implNames);
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public JCRequires visitRequires(RequiresTree node, P p) { public JCRequires visitRequires(RequiresTree node, P p) {
JCRequires t = (JCRequires) node; JCRequires t = (JCRequires) node;
JCExpression moduleName = copy(t.moduleName, p); JCExpression moduleName = copy(t.moduleName, p);
return M.at(t.pos).Requires(t.isPublic, moduleName); return M.at(t.pos).Requires(t.isTransitive, t.isStaticPhase, moduleName);
} }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)

View file

@ -378,6 +378,11 @@ public class TreeInfo {
return Position.NOPOS; return Position.NOPOS;
switch(tree.getTag()) { switch(tree.getTag()) {
case MODULEDEF: {
JCModuleDecl md = (JCModuleDecl)tree;
return md.mods.annotations.isEmpty() ? md.pos :
md.mods.annotations.head.pos;
}
case PACKAGEDEF: { case PACKAGEDEF: {
JCPackageDecl pd = (JCPackageDecl)tree; JCPackageDecl pd = (JCPackageDecl)tree;
return pd.annotations.isEmpty() ? pd.pos : return pd.annotations.isEmpty() ? pd.pos :
@ -769,8 +774,9 @@ public class TreeInfo {
switch (node.getTag()) { switch (node.getTag()) {
case TOPLEVEL: case TOPLEVEL:
JCCompilationUnit cut = (JCCompilationUnit) node; JCCompilationUnit cut = (JCCompilationUnit) node;
if (isModuleInfo(cut) && cut.defs.nonEmpty() && cut.defs.head.hasTag(MODULEDEF)) JCModuleDecl moduleDecl = cut.getModuleDecl();
return symbolFor(cut.defs.head); if (isModuleInfo(cut) && moduleDecl != null)
return symbolFor(moduleDecl);
return cut.packge; return cut.packge;
case MODULEDEF: case MODULEDEF:
return ((JCModuleDecl) node).sym; return ((JCModuleDecl) node).sym;
@ -1076,6 +1082,11 @@ public class TreeInfo {
case TYPE_ANNOTATION: case TYPE_ANNOTATION:
return Tree.Kind.TYPE_ANNOTATION; return Tree.Kind.TYPE_ANNOTATION;
case EXPORTS:
return Tree.Kind.EXPORTS;
case OPENS:
return Tree.Kind.OPENS;
default: default:
return null; return null;
} }
@ -1158,7 +1169,7 @@ public class TreeInfo {
public static boolean isModuleInfo(JCCompilationUnit tree) { public static boolean isModuleInfo(JCCompilationUnit tree) {
return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE) return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE)
&& tree.defs.nonEmpty() && tree.defs.head.hasTag(MODULEDEF); && tree.getModuleDecl() != null;
} }
public static JCModuleDecl getModule(JCCompilationUnit t) { public static JCModuleDecl getModule(JCCompilationUnit t) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,8 @@ package com.sun.tools.javac.tree;
import java.util.Iterator; import java.util.Iterator;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Type.*;
@ -538,8 +540,9 @@ public class TreeMaker implements JCTree.Factory {
} }
@Override @Override
public JCModuleDecl ModuleDef(JCExpression qualid, List<JCDirective> directives) { public JCModuleDecl ModuleDef(JCModifiers mods, ModuleKind kind,
JCModuleDecl tree = new JCModuleDecl(qualid, directives); JCExpression qualid, List<JCDirective> directives) {
JCModuleDecl tree = new JCModuleDecl(mods, kind, qualid, directives);
tree.pos = pos; tree.pos = pos;
return tree; return tree;
} }
@ -552,15 +555,22 @@ public class TreeMaker implements JCTree.Factory {
} }
@Override @Override
public JCProvides Provides(JCExpression serviceName, JCExpression implName) { public JCOpens Opens(JCExpression qualId, List<JCExpression> moduleNames) {
JCProvides tree = new JCProvides(serviceName, implName); JCOpens tree = new JCOpens(qualId, moduleNames);
tree.pos = pos; tree.pos = pos;
return tree; return tree;
} }
@Override @Override
public JCRequires Requires(boolean isPublic, JCExpression qualId) { public JCProvides Provides(JCExpression serviceName, List<JCExpression> implNames) {
JCRequires tree = new JCRequires(isPublic, qualId); JCProvides tree = new JCProvides(serviceName, implNames);
tree.pos = pos;
return tree;
}
@Override
public JCRequires Requires(boolean isTransitive, boolean isStaticPhase, JCExpression qualId) {
JCRequires tree = new JCRequires(isTransitive, isStaticPhase, qualId);
tree.pos = pos; tree.pos = pos;
return tree; return tree;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -73,6 +73,7 @@ public class TreeScanner extends Visitor {
@Override @Override
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {
scan(tree.mods);
scan(tree.qualId); scan(tree.qualId);
scan(tree.directives); scan(tree.directives);
} }
@ -83,10 +84,16 @@ public class TreeScanner extends Visitor {
scan(tree.moduleNames); scan(tree.moduleNames);
} }
@Override
public void visitOpens(JCOpens tree) {
scan(tree.qualid);
scan(tree.moduleNames);
}
@Override @Override
public void visitProvides(JCProvides tree) { public void visitProvides(JCProvides tree) {
scan(tree.serviceName); scan(tree.serviceName);
scan(tree.implName); scan(tree.implNames);
} }
@Override @Override

View file

@ -51,4 +51,5 @@ public class ModuleHelper {
from.addExports(pack, to); from.addExports(pack, to);
} }
} }
} }

View file

@ -64,11 +64,14 @@ public class Names {
public final Name _super; public final Name _super;
public final Name _this; public final Name _this;
public final Name exports; public final Name exports;
public final Name opens;
public final Name module; public final Name module;
public final Name provides; public final Name provides;
public final Name requires; public final Name requires;
public final Name to; public final Name to;
public final Name transitive;
public final Name uses; public final Name uses;
public final Name open;
public final Name with; public final Name with;
// field and method names // field and method names
@ -101,6 +104,7 @@ public class Names {
public final Name length; public final Name length;
public final Name next; public final Name next;
public final Name ordinal; public final Name ordinal;
public final Name provider;
public final Name serialVersionUID; public final Name serialVersionUID;
public final Name toString; public final Name toString;
public final Name value; public final Name value;
@ -146,6 +150,7 @@ public class Names {
public final Name LocalVariableTypeTable; public final Name LocalVariableTypeTable;
public final Name MethodParameters; public final Name MethodParameters;
public final Name Module; public final Name Module;
public final Name ModuleVersion;
public final Name RuntimeInvisibleAnnotations; public final Name RuntimeInvisibleAnnotations;
public final Name RuntimeInvisibleParameterAnnotations; public final Name RuntimeInvisibleParameterAnnotations;
public final Name RuntimeInvisibleTypeAnnotations; public final Name RuntimeInvisibleTypeAnnotations;
@ -160,7 +165,6 @@ public class Names {
public final Name Synthetic; public final Name Synthetic;
public final Name Value; public final Name Value;
public final Name Varargs; public final Name Varargs;
public final Name Version;
// members of java.lang.annotation.ElementType // members of java.lang.annotation.ElementType
public final Name ANNOTATION_TYPE; public final Name ANNOTATION_TYPE;
@ -168,6 +172,7 @@ public class Names {
public final Name FIELD; public final Name FIELD;
public final Name LOCAL_VARIABLE; public final Name LOCAL_VARIABLE;
public final Name METHOD; public final Name METHOD;
public final Name MODULE;
public final Name PACKAGE; public final Name PACKAGE;
public final Name PARAMETER; public final Name PARAMETER;
public final Name TYPE; public final Name TYPE;
@ -220,11 +225,14 @@ public class Names {
_super = fromString("super"); _super = fromString("super");
_this = fromString("this"); _this = fromString("this");
exports = fromString("exports"); exports = fromString("exports");
opens = fromString("opens");
module = fromString("module"); module = fromString("module");
provides = fromString("provides"); provides = fromString("provides");
requires = fromString("requires"); requires = fromString("requires");
to = fromString("to"); to = fromString("to");
transitive = fromString("transitive");
uses = fromString("uses"); uses = fromString("uses");
open = fromString("open");
with = fromString("with"); with = fromString("with");
// field and method names // field and method names
@ -257,6 +265,7 @@ public class Names {
length = fromString("length"); length = fromString("length");
next = fromString("next"); next = fromString("next");
ordinal = fromString("ordinal"); ordinal = fromString("ordinal");
provider = fromString("provider");
serialVersionUID = fromString("serialVersionUID"); serialVersionUID = fromString("serialVersionUID");
toString = fromString("toString"); toString = fromString("toString");
value = fromString("value"); value = fromString("value");
@ -303,6 +312,7 @@ public class Names {
LocalVariableTypeTable = fromString("LocalVariableTypeTable"); LocalVariableTypeTable = fromString("LocalVariableTypeTable");
MethodParameters = fromString("MethodParameters"); MethodParameters = fromString("MethodParameters");
Module = fromString("Module"); Module = fromString("Module");
ModuleVersion = fromString("ModuleVersion");
RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations"); RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations"); RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations"); RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
@ -317,7 +327,6 @@ public class Names {
Synthetic = fromString("Synthetic"); Synthetic = fromString("Synthetic");
Value = fromString("Value"); Value = fromString("Value");
Varargs = fromString("Varargs"); Varargs = fromString("Varargs");
Version = fromString("Version");
// members of java.lang.annotation.ElementType // members of java.lang.annotation.ElementType
ANNOTATION_TYPE = fromString("ANNOTATION_TYPE"); ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
@ -325,6 +334,7 @@ public class Names {
FIELD = fromString("FIELD"); FIELD = fromString("FIELD");
LOCAL_VARIABLE = fromString("LOCAL_VARIABLE"); LOCAL_VARIABLE = fromString("LOCAL_VARIABLE");
METHOD = fromString("METHOD"); METHOD = fromString("METHOD");
MODULE = fromString("MODULE");
PACKAGE = fromString("PACKAGE"); PACKAGE = fromString("PACKAGE");
PARAMETER = fromString("PARAMETER"); PARAMETER = fromString("PARAMETER");
TYPE = fromString("TYPE"); TYPE = fromString("TYPE");

View file

@ -28,7 +28,7 @@
* and its command line equivalent, <em>javac</em>, as well as <em>javah</em>. * and its command line equivalent, <em>javac</em>, as well as <em>javah</em>.
*/ */
module jdk.compiler { module jdk.compiler {
requires public java.compiler; requires transitive java.compiler;
exports com.sun.source.doctree; exports com.sun.source.doctree;
exports com.sun.source.tree; exports com.sun.source.tree;

View file

@ -79,7 +79,7 @@
* module declaration, to create a module set to considered for documentation * module declaration, to create a module set to considered for documentation
* as follows: * as follows:
* <ul> * <ul>
* <li> public -- follows and expands all "requires public" edges in the module graph * <li> transitive -- follows and expands all "requires transitive" edges in the module graph
* <li> all -- follows and expands all "requires" edges in the module graph. * <li> all -- follows and expands all "requires" edges in the module graph.
* By default, only the specified modules will be considered, without expansion * By default, only the specified modules will be considered, without expansion
* of the module dependencies. * of the module dependencies.

View file

@ -28,11 +28,18 @@ package jdk.javadoc.internal.doclets.formats.html;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.SortedSet;
import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder; import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder.DeprElementKind; import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder.DeprElementKind;
@ -57,6 +64,8 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
private String getAnchorName(DeprElementKind kind) { private String getAnchorName(DeprElementKind kind) {
switch (kind) { switch (kind) {
case MODULE:
return "module";
case PACKAGE: case PACKAGE:
return "package"; return "package";
case INTERFACE: case INTERFACE:
@ -88,6 +97,8 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
private String getHeadingKey(DeprElementKind kind) { private String getHeadingKey(DeprElementKind kind) {
switch (kind) { switch (kind) {
case MODULE:
return "doclet.Deprecated_Modules";
case PACKAGE: case PACKAGE:
return "doclet.Deprecated_Packages"; return "doclet.Deprecated_Packages";
case INTERFACE: case INTERFACE:
@ -119,6 +130,8 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
private String getSummaryKey(DeprElementKind kind) { private String getSummaryKey(DeprElementKind kind) {
switch (kind) { switch (kind) {
case MODULE:
return "doclet.deprecated_modules";
case PACKAGE: case PACKAGE:
return "doclet.deprecated_packages"; return "doclet.deprecated_packages";
case INTERFACE: case INTERFACE:
@ -150,6 +163,8 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
private String getHeaderKey(DeprElementKind kind) { private String getHeaderKey(DeprElementKind kind) {
switch (kind) { switch (kind) {
case MODULE:
return "doclet.Module";
case PACKAGE: case PACKAGE:
return "doclet.Package"; return "doclet.Package";
case INTERFACE: case INTERFACE:
@ -197,6 +212,7 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
writerMap = new EnumMap<>(DeprElementKind.class); writerMap = new EnumMap<>(DeprElementKind.class);
for (DeprElementKind kind : DeprElementKind.values()) { for (DeprElementKind kind : DeprElementKind.values()) {
switch (kind) { switch (kind) {
case MODULE:
case PACKAGE: case PACKAGE:
case INTERFACE: case INTERFACE:
case CLASS: case CLASS:
@ -268,12 +284,16 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
List<String> memberTableHeader = new ArrayList<>(); List<String> memberTableHeader = new ArrayList<>();
memberTableHeader.add(resources.getText(getHeaderKey(kind))); memberTableHeader.add(resources.getText(getHeaderKey(kind)));
memberTableHeader.add(resources.getText("doclet.Description")); memberTableHeader.add(resources.getText("doclet.Description"));
if (kind == DeprElementKind.PACKAGE) if (kind == DeprElementKind.MODULE) {
addModuleDeprecatedAPI(deprapi.getSet(kind),
getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
} else if (kind == DeprElementKind.PACKAGE) {
addPackageDeprecatedAPI(deprapi.getSet(kind), addPackageDeprecatedAPI(deprapi.getSet(kind),
getHeadingKey(kind), memberTableSummary, memberTableHeader, div); getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
else } else {
writerMap.get(kind).addDeprecatedAPI(deprapi.getSet(kind), writerMap.get(kind).addDeprecatedAPI(deprapi.getSet(kind),
getHeadingKey(kind), memberTableSummary, memberTableHeader, div); getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
}
} }
} }
if (configuration.allowTag(HtmlTag.MAIN)) { if (configuration.allowTag(HtmlTag.MAIN)) {
@ -373,4 +393,88 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.deprecatedLabel); Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.deprecatedLabel);
return li; return li;
} }
/**
* Add module deprecation information to the documentation tree
*
* @param deprMdles list of deprecated modules
* @param headingKey the caption for the deprecated module table
* @param tableSummary the summary for the deprecated module table
* @param tableHeader table headers for the deprecated module table
* @param contentTree the content tree to which the deprecated module table will be added
*/
protected void addModuleDeprecatedAPI(SortedSet<Element> deprMdles, String headingKey,
String tableSummary, List<String> tableHeader, Content contentTree) {
if (deprMdles.size() > 0) {
Content caption = getTableCaption(configuration.getContent(headingKey));
Content table = (configuration.isOutputHtml5())
? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
: HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
table.addContent(getSummaryTableHeader(tableHeader, "col"));
Content tbody = new HtmlTree(HtmlTag.TBODY);
boolean altColor = true;
for (Element e : deprMdles) {
ModuleElement mdle = (ModuleElement) e;
HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getModuleLink(mdle, new StringContent(mdle.getQualifiedName())));
HtmlTree tr = HtmlTree.TR(thRow);
HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
tdDesc.addStyle(HtmlStyle.colLast);
List<? extends DocTree> tags = utils.getDeprecatedTrees(mdle);
if (!tags.isEmpty()) {
addInlineDeprecatedComment(mdle, tags.get(0), tdDesc);
}
tr.addContent(tdDesc);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
tbody.addContent(tr);
}
table.addContent(tbody);
Content li = HtmlTree.LI(HtmlStyle.blockList, table);
Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
contentTree.addContent(ul);
}
}
/**
* Add package deprecation information to the documentation tree
*
* @param deprPkgs list of deprecated packages
* @param headingKey the caption for the deprecated package table
* @param tableSummary the summary for the deprecated package table
* @param tableHeader table headers for the deprecated package table
* @param contentTree the content tree to which the deprecated package table will be added
*/
protected void addPackageDeprecatedAPI(SortedSet<Element> deprPkgs, String headingKey,
String tableSummary, List<String> tableHeader, Content contentTree) {
if (deprPkgs.size() > 0) {
Content caption = getTableCaption(configuration.getContent(headingKey));
Content table = (configuration.isOutputHtml5())
? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
: HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
table.addContent(getSummaryTableHeader(tableHeader, "col"));
Content tbody = new HtmlTree(HtmlTag.TBODY);
boolean altColor = true;
for (Element e : deprPkgs) {
PackageElement pkg = (PackageElement) e;
HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getPackageLink(pkg, getPackageName(pkg)));
HtmlTree tr = HtmlTree.TR(thRow);
HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
tdDesc.addStyle(HtmlStyle.colLast);
List<? extends DocTree> tags = utils.getDeprecatedTrees(pkg);
if (!tags.isEmpty()) {
addInlineDeprecatedComment(pkg, tags.get(0), tdDesc);
}
tr.addContent(tdDesc);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
tbody.addContent(tr);
}
table.addContent(tbody);
Content li = HtmlTree.LI(HtmlStyle.blockList, table);
Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
contentTree.addContent(ul);
}
}
} }

View file

@ -1045,48 +1045,6 @@ public class HtmlDocletWriter extends HtmlDocWriter {
return new StringContent(packageName); return new StringContent(packageName);
} }
/**
* Add package deprecation information to the documentation tree
*
* @param deprPkgs list of deprecated packages
* @param headingKey the caption for the deprecated package table
* @param tableSummary the summary for the deprecated package table
* @param tableHeader table headers for the deprecated package table
* @param contentTree the content tree to which the deprecated package table will be added
*/
protected void addPackageDeprecatedAPI(SortedSet<Element> deprPkgs, String headingKey,
String tableSummary, List<String> tableHeader, Content contentTree) {
if (deprPkgs.size() > 0) {
Content caption = getTableCaption(configuration.getContent(headingKey));
Content table = (configuration.isOutputHtml5())
? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
: HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
table.addContent(getSummaryTableHeader(tableHeader, "col"));
Content tbody = new HtmlTree(HtmlTag.TBODY);
boolean altColor = true;
for (Element e : deprPkgs) {
PackageElement pkg = (PackageElement) e;
HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getPackageLink(pkg, getPackageName(pkg)));
HtmlTree tr = HtmlTree.TR(thRow);
HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
tdDesc.addStyle(HtmlStyle.colLast);
List<? extends DocTree> tags = utils.getDeprecatedTrees(pkg);
if (!tags.isEmpty()) {
addInlineDeprecatedComment(pkg, tags.get(0), tdDesc);
}
tr.addContent(tdDesc);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
tbody.addContent(tr);
}
table.addContent(tbody);
Content li = HtmlTree.LI(HtmlStyle.blockList, table);
Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
contentTree.addContent(ul);
}
}
/** /**
* Return the path to the class page for a typeElement. * Return the path to the class page for a typeElement.
* *

View file

@ -114,6 +114,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* *
* @param heading the heading for the section * @param heading the heading for the section
*/ */
@Override
public Content getModuleHeader(String heading) { public Content getModuleHeader(String heading) {
HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString())); HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString()));
HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
@ -126,6 +127,9 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
} }
HtmlTree div = new HtmlTree(HtmlTag.DIV); HtmlTree div = new HtmlTree(HtmlTag.DIV);
div.addStyle(HtmlStyle.header); div.addStyle(HtmlStyle.header);
Content annotationContent = new HtmlTree(HtmlTag.P);
addAnnotationInfo(mdle, annotationContent);
div.addContent(annotationContent);
Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
HtmlStyle.title, contents.moduleLabel); HtmlStyle.title, contents.moduleLabel);
tHeading.addContent(Contents.SPACE); tHeading.addContent(Contents.SPACE);
@ -143,6 +147,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* Get the content header. * Get the content header.
*/ */
@Override
public Content getContentHeader() { public Content getContentHeader() {
HtmlTree div = new HtmlTree(HtmlTag.DIV); HtmlTree div = new HtmlTree(HtmlTag.DIV);
div.addStyle(HtmlStyle.contentContainer); div.addStyle(HtmlStyle.contentContainer);
@ -152,6 +157,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* Get the summary section header. * Get the summary section header.
*/ */
@Override
public Content getSummaryHeader() { public Content getSummaryHeader() {
HtmlTree li = new HtmlTree(HtmlTag.LI); HtmlTree li = new HtmlTree(HtmlTag.LI);
li.addStyle(HtmlStyle.blockList); li.addStyle(HtmlStyle.blockList);
@ -163,6 +169,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* *
* @param summaryContentTree the content tree to be added to the summary tree. * @param summaryContentTree the content tree to be added to the summary tree.
*/ */
@Override
public Content getSummaryTree(Content summaryContentTree) { public Content getSummaryTree(Content summaryContentTree) {
HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree); HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
return ul; return ul;
@ -225,7 +232,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* Add the list of directives for the module. * Add the list of directives for the module.
* *
* @param dirs the list of module directives * @param dirs the list of module directives
* @params tbody the content tree to which the list is added * @param tbody the content tree to which the list is added
*/ */
public void addList(List<ModuleElement.Directive> dirs, Content tbody) { public void addList(List<ModuleElement.Directive> dirs, Content tbody) {
boolean altColor = true; boolean altColor = true;
@ -238,6 +245,9 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
case EXPORTS: case EXPORTS:
addExportedPackagesList((ModuleElement.ExportsDirective) direct, tbody, altColor); addExportedPackagesList((ModuleElement.ExportsDirective) direct, tbody, altColor);
break; break;
case OPENS:
//XXX ignore for now
break;
case USES: case USES:
addUsesList((ModuleElement.UsesDirective) direct, tbody, altColor); addUsesList((ModuleElement.UsesDirective) direct, tbody, altColor);
break; break;
@ -254,6 +264,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addModulesSummary(Content summaryContentTree) { public void addModulesSummary(Content summaryContentTree) {
List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.REQUIRES); List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.REQUIRES);
if (dirs != null && !dirs.isEmpty()) { if (dirs != null && !dirs.isEmpty()) {
@ -307,6 +318,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addPackagesSummary(Content summaryContentTree) { public void addPackagesSummary(Content summaryContentTree) {
List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.EXPORTS); List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.EXPORTS);
if (dirs != null && !dirs.isEmpty()) { if (dirs != null && !dirs.isEmpty()) {
@ -376,6 +388,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addServicesSummary(Content summaryContentTree) { public void addServicesSummary(Content summaryContentTree) {
List<ModuleElement.Directive> usesDirs = directiveMap.get(DirectiveKind.USES); List<ModuleElement.Directive> usesDirs = directiveMap.get(DirectiveKind.USES);
List<ModuleElement.Directive> providesDirs = directiveMap.get(DirectiveKind.PROVIDES); List<ModuleElement.Directive> providesDirs = directiveMap.get(DirectiveKind.PROVIDES);
@ -459,33 +472,60 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* @param altColor true if altColor style should be used or false if rowColor style should be used * @param altColor true if altColor style should be used or false if rowColor style should be used
*/ */
public void addProvidesList(ModuleElement.ProvidesDirective direct, Content tbody, boolean altColor) { public void addProvidesList(ModuleElement.ProvidesDirective direct, Content tbody, boolean altColor) {
TypeElement impl = direct.getImplementation(); List<? extends TypeElement> impls = direct.getImplementations();
TypeElement srv = direct.getService(); for (TypeElement impl : impls) {
Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl)); TypeElement srv = direct.getService();
Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv)); Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl));
HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent); Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
thType.addContent(new HtmlTree(HtmlTag.BR)); HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
thType.addContent("("); thType.addContent(new HtmlTree(HtmlTag.BR));
HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation); thType.addContent("(");
thType.addContent(implSpan); HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
thType.addContent(Contents.SPACE); thType.addContent(implSpan);
thType.addContent(implLinkContent); thType.addContent(Contents.SPACE);
thType.addContent(")"); thType.addContent(implLinkContent);
HtmlTree tdDesc = new HtmlTree(HtmlTag.TD); thType.addContent(")");
tdDesc.addStyle(HtmlStyle.colLast); HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
addSummaryComment(srv, tdDesc); tdDesc.addStyle(HtmlStyle.colLast);
HtmlTree tr = HtmlTree.TR(thType); addSummaryComment(srv, tdDesc);
tr.addContent(tdDesc); HtmlTree tr = HtmlTree.TR(thType);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); tr.addContent(tdDesc);
tbody.addContent(tr); tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
}
}
/**
* Add the module deprecation information to the documentation tree.
*
* @param div the content tree to which the deprecation information will be added
*/
public void addDeprecationInfo(Content div) {
List<? extends DocTree> deprs = utils.getBlockTags(mdle, DocTree.Kind.DEPRECATED);
if (utils.isDeprecated(mdle)) {
CommentHelper ch = utils.getCommentHelper(mdle);
HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
deprDiv.addStyle(HtmlStyle.deprecatedContent);
Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, contents.deprecatedPhrase);
deprDiv.addContent(deprPhrase);
if (!deprs.isEmpty()) {
List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
if (!commentTags.isEmpty()) {
addInlineDeprecatedComment(mdle, deprs.get(0), deprDiv);
}
}
div.addContent(deprDiv);
}
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addModuleDescription(Content moduleContentTree) { public void addModuleDescription(Content moduleContentTree) {
if (!utils.getFullBody(mdle).isEmpty()) { if (!utils.getFullBody(mdle).isEmpty()) {
Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree; Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree;
addDeprecationInfo(tree);
tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION); tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION);
tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION)); tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION));
addInlineComment(mdle, tree); addInlineComment(mdle, tree);
@ -498,6 +538,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addModuleTags(Content moduleContentTree) { public void addModuleTags(Content moduleContentTree) {
Content tree = (configuration.allowTag(HtmlTag.SECTION)) Content tree = (configuration.allowTag(HtmlTag.SECTION))
? HtmlTree.SECTION() ? HtmlTree.SECTION()
@ -513,6 +554,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* *
* @param subDiv the content tree to which the summary detail links will be added * @param subDiv the content tree to which the summary detail links will be added
*/ */
@Override
protected void addSummaryDetailLinks(Content subDiv) { protected void addSummaryDetailLinks(Content subDiv) {
Content div = HtmlTree.DIV(getNavSummaryLinks()); Content div = HtmlTree.DIV(getNavSummaryLinks());
subDiv.addContent(div); subDiv.addContent(div);
@ -560,6 +602,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addModuleContent(Content contentTree, Content moduleContentTree) { public void addModuleContent(Content contentTree, Content moduleContentTree) {
if (configuration.allowTag(HtmlTag.MAIN)) { if (configuration.allowTag(HtmlTag.MAIN)) {
mainTree.addContent(moduleContentTree); mainTree.addContent(moduleContentTree);
@ -572,6 +615,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void addModuleFooter(Content contentTree) { public void addModuleFooter(Content contentTree) {
Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
? HtmlTree.FOOTER() ? HtmlTree.FOOTER()
@ -633,6 +677,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* *
* @return a content tree for the previous link * @return a content tree for the previous link
*/ */
@Override
public Content getNavLinkPrevious() { public Content getNavLinkPrevious() {
Content li; Content li;
if (prevModule == null) { if (prevModule == null) {
@ -649,6 +694,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
* *
* @return a content tree for the next link * @return a content tree for the next link
*/ */
@Override
public Content getNavLinkNext() { public Content getNavLinkNext() {
Content li; Content li;
if (nextModule == null) { if (nextModule == null) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View file

@ -71,6 +71,7 @@ doclet.see.class_or_package_not_found=Tag {0}: reference not found: {1}
doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1} doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1}
doclet.tag.invalid_usage=invalid usage of tag {0} doclet.tag.invalid_usage=invalid usage of tag {0}
doclet.Deprecated_API=Deprecated API doclet.Deprecated_API=Deprecated API
doclet.Deprecated_Modules=Deprecated Modules
doclet.Deprecated_Packages=Deprecated Packages doclet.Deprecated_Packages=Deprecated Packages
doclet.Deprecated_Classes=Deprecated Classes doclet.Deprecated_Classes=Deprecated Classes
doclet.Deprecated_Enums=Deprecated Enums doclet.Deprecated_Enums=Deprecated Enums
@ -83,6 +84,7 @@ doclet.Deprecated_Constructors=Deprecated Constructors
doclet.Deprecated_Methods=Deprecated Methods doclet.Deprecated_Methods=Deprecated Methods
doclet.Deprecated_Enum_Constants=Deprecated Enum Constants doclet.Deprecated_Enum_Constants=Deprecated Enum Constants
doclet.Deprecated_Annotation_Type_Members=Deprecated Annotation Type Elements doclet.Deprecated_Annotation_Type_Members=Deprecated Annotation Type Elements
doclet.deprecated_modules=deprecated modules
doclet.deprecated_packages=deprecated packages doclet.deprecated_packages=deprecated packages
doclet.deprecated_classes=deprecated classes doclet.deprecated_classes=deprecated classes
doclet.deprecated_enums=deprecated enums doclet.deprecated_enums=deprecated enums

View file

@ -99,7 +99,7 @@ doclet.Subclasses=\u76F4\u7CFB\u306E\u65E2\u77E5\u306E\u30B5\u30D6\u30AF\u30E9\u
doclet.Subinterfaces=\u65E2\u77E5\u306E\u30B5\u30D6\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30EA\u30B9\u30C8: doclet.Subinterfaces=\u65E2\u77E5\u306E\u30B5\u30D6\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30EA\u30B9\u30C8:
doclet.Implementing_Classes=\u65E2\u77E5\u306E\u5B9F\u88C5\u30AF\u30E9\u30B9\u306E\u30EA\u30B9\u30C8: doclet.Implementing_Classes=\u65E2\u77E5\u306E\u5B9F\u88C5\u30AF\u30E9\u30B9\u306E\u30EA\u30B9\u30C8:
doclet.Functional_Interface=\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9 doclet.Functional_Interface=\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9
doclet.Functional_Interface_Message=\u3053\u308C\u306F\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306A\u306E\u3067\u3001\u30E9\u30E0\u30C0\u5F0F\u307E\u305F\u306F\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u306E\u5272\u5F53\u3066\u30BF\u30FC\u30B2\u30C3\u30C8\u3068\u3057\u3066\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002 doclet.Functional_Interface_Message=\u3053\u308C\u306F\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306A\u306E\u3067\u3001\u30E9\u30E0\u30C0\u5F0F\u307E\u305F\u306F\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u306E\u5272\u5F53\u3066\u30BF\u30FC\u30B2\u30C3\u30C8\u3068\u3057\u3066\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
doclet.also=\u540C\u69D8\u306B doclet.also=\u540C\u69D8\u306B
doclet.Frames=\u30D5\u30EC\u30FC\u30E0 doclet.Frames=\u30D5\u30EC\u30FC\u30E0
doclet.No_Frames=\u30D5\u30EC\u30FC\u30E0\u306A\u3057 doclet.No_Frames=\u30D5\u30EC\u30FC\u30E0\u306A\u3057

View file

@ -28,6 +28,7 @@ package jdk.javadoc.internal.doclets.toolkit.util;
import java.util.*; import java.util.*;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement; import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
@ -51,6 +52,7 @@ public class DeprecatedAPIListBuilder {
private final Configuration configuration; private final Configuration configuration;
private final Utils utils; private final Utils utils;
public static enum DeprElementKind { public static enum DeprElementKind {
MODULE,
PACKAGE, PACKAGE,
INTERFACE, INTERFACE,
CLASS, CLASS,
@ -82,12 +84,19 @@ public class DeprecatedAPIListBuilder {
/** /**
* Build the sorted list of all the deprecated APIs in this run. * Build the sorted list of all the deprecated APIs in this run.
* Build separate lists for deprecated packages, classes, constructors, * Build separate lists for deprecated modules, packages, classes, constructors,
* methods and fields. * methods and fields.
* *
* @param configuration the current configuration of the doclet. * @param configuration the current configuration of the doclet.
*/ */
private void buildDeprecatedAPIInfo() { private void buildDeprecatedAPIInfo() {
SortedSet<ModuleElement> modules = configuration.modules;
SortedSet<Element> mset = deprecatedMap.get(DeprElementKind.MODULE);
for (Element me : modules) {
if (utils.isDeprecated(me)) {
mset.add(me);
}
}
SortedSet<PackageElement> packages = configuration.packages; SortedSet<PackageElement> packages = configuration.packages;
SortedSet<Element> pset = deprecatedMap.get(DeprElementKind.PACKAGE); SortedSet<Element> pset = deprecatedMap.get(DeprElementKind.PACKAGE);
for (Element pe : packages) { for (Element pe : packages) {
@ -95,7 +104,6 @@ public class DeprecatedAPIListBuilder {
pset.add(pe); pset.add(pe);
} }
} }
deprecatedMap.put(DeprElementKind.PACKAGE, pset);
for (Element e : configuration.docEnv.getIncludedTypeElements()) { for (Element e : configuration.docEnv.getIncludedTypeElements()) {
TypeElement te = (TypeElement)e; TypeElement te = (TypeElement)e;
SortedSet<Element> eset; SortedSet<Element> eset;

View file

@ -516,10 +516,10 @@ public class ElementsTable {
private Set<ModuleElement> getModuleRequires(ModuleElement mdle, boolean isPublic) { private Set<ModuleElement> getModuleRequires(ModuleElement mdle, boolean isPublic) {
Set<ModuleElement> result = new HashSet<>(); Set<ModuleElement> result = new HashSet<>();
for (RequiresDirective rd : ElementFilter.requiresIn(mdle.getDirectives())) { for (RequiresDirective rd : ElementFilter.requiresIn(mdle.getDirectives())) {
if (isPublic && rd.isPublic()) { if (isPublic && rd.isTransitive()) {
result.add(rd.getDependency()); result.add(rd.getDependency());
} }
if (!isPublic && !rd.isPublic()) { if (!isPublic && !rd.isTransitive()) {
result.add(rd.getDependency()); result.add(rd.getDependency());
} }
} }

View file

@ -479,7 +479,7 @@ public enum ToolOption {
void setExpandRequires(ToolOption opt, String arg) throws OptionException { void setExpandRequires(ToolOption opt, String arg) throws OptionException {
switch (arg) { switch (arg) {
case "public": case "transitive":
jdtoolOpts.put(opt, AccessKind.PUBLIC); jdtoolOpts.put(opt, AccessKind.PUBLIC);
break; break;
case "all": case "all":

View file

@ -81,8 +81,8 @@ main.opt.expand.requires.arg=\
main.opt.expand.requires.desc=\ main.opt.expand.requires.desc=\
Instructs the tool to expand the set of modules to be\n\ Instructs the tool to expand the set of modules to be\n\
documented. By default, only the modules given explicitly on\n\ documented. By default, only the modules given explicitly on\n\
the command line will be documented. A value of "public" will\n\ the command line will be documented. A value of "transitive" will\n\
additionally include all "requires public" dependencies of\n\ additionally include all "requires transitive" dependencies of\n\
those modules. A value of "all" will include all dependencies\n\ those modules. A value of "all" will include all dependencies\n\
of those modules. of those modules.

View file

@ -28,8 +28,8 @@
* and its command line equivalent, <em>javadoc</em>. * and its command line equivalent, <em>javadoc</em>.
*/ */
module jdk.javadoc { module jdk.javadoc {
requires public java.compiler; requires transitive java.compiler;
requires public jdk.compiler; requires transitive jdk.compiler;
requires java.xml; requires java.xml;
exports com.sun.javadoc; exports com.sun.javadoc;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,20 +42,22 @@ public abstract class Attribute {
public static final String BootstrapMethods = "BootstrapMethods"; public static final String BootstrapMethods = "BootstrapMethods";
public static final String CharacterRangeTable = "CharacterRangeTable"; public static final String CharacterRangeTable = "CharacterRangeTable";
public static final String Code = "Code"; public static final String Code = "Code";
public static final String ConcealedPackages = "ConcealedPackages";
public static final String ConstantValue = "ConstantValue"; public static final String ConstantValue = "ConstantValue";
public static final String CompilationID = "CompilationID"; public static final String CompilationID = "CompilationID";
public static final String Deprecated = "Deprecated"; public static final String Deprecated = "Deprecated";
public static final String EnclosingMethod = "EnclosingMethod"; public static final String EnclosingMethod = "EnclosingMethod";
public static final String Exceptions = "Exceptions"; public static final String Exceptions = "Exceptions";
public static final String Hashes = "Hashes";
public static final String InnerClasses = "InnerClasses"; public static final String InnerClasses = "InnerClasses";
public static final String LineNumberTable = "LineNumberTable"; public static final String LineNumberTable = "LineNumberTable";
public static final String LocalVariableTable = "LocalVariableTable"; public static final String LocalVariableTable = "LocalVariableTable";
public static final String LocalVariableTypeTable = "LocalVariableTypeTable"; public static final String LocalVariableTypeTable = "LocalVariableTypeTable";
public static final String MainClass = "MainClass";
public static final String MethodParameters = "MethodParameters"; public static final String MethodParameters = "MethodParameters";
public static final String Module = "Module"; public static final String Module = "Module";
public static final String ModuleHashes = "ModuleHashes";
public static final String ModuleMainClass = "ModuleMainClass";
public static final String ModulePackages = "ModulePackages";
public static final String ModuleTarget = "ModuleTarget";
public static final String ModuleVersion = "ModuleVersion";
public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations"; public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations"; public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations"; public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@ -69,8 +71,6 @@ public abstract class Attribute {
public static final String StackMap = "StackMap"; public static final String StackMap = "StackMap";
public static final String StackMapTable = "StackMapTable"; public static final String StackMapTable = "StackMapTable";
public static final String Synthetic = "Synthetic"; public static final String Synthetic = "Synthetic";
public static final String TargetPlatform = "TargetPlatform";
public static final String Version = "Version";
public static class Factory { public static class Factory {
public Factory() { public Factory() {
@ -115,19 +115,21 @@ public abstract class Attribute {
standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class); standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class);
standardAttributes.put(Code, Code_attribute.class); standardAttributes.put(Code, Code_attribute.class);
standardAttributes.put(CompilationID, CompilationID_attribute.class); standardAttributes.put(CompilationID, CompilationID_attribute.class);
standardAttributes.put(ConcealedPackages, ConcealedPackages_attribute.class);
standardAttributes.put(ConstantValue, ConstantValue_attribute.class); standardAttributes.put(ConstantValue, ConstantValue_attribute.class);
standardAttributes.put(Deprecated, Deprecated_attribute.class); standardAttributes.put(Deprecated, Deprecated_attribute.class);
standardAttributes.put(EnclosingMethod, EnclosingMethod_attribute.class); standardAttributes.put(EnclosingMethod, EnclosingMethod_attribute.class);
standardAttributes.put(Exceptions, Exceptions_attribute.class); standardAttributes.put(Exceptions, Exceptions_attribute.class);
standardAttributes.put(Hashes, Hashes_attribute.class);
standardAttributes.put(InnerClasses, InnerClasses_attribute.class); standardAttributes.put(InnerClasses, InnerClasses_attribute.class);
standardAttributes.put(LineNumberTable, LineNumberTable_attribute.class); standardAttributes.put(LineNumberTable, LineNumberTable_attribute.class);
standardAttributes.put(LocalVariableTable, LocalVariableTable_attribute.class); standardAttributes.put(LocalVariableTable, LocalVariableTable_attribute.class);
standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class); standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class);
standardAttributes.put(MainClass, MainClass_attribute.class);
standardAttributes.put(MethodParameters, MethodParameters_attribute.class); standardAttributes.put(MethodParameters, MethodParameters_attribute.class);
standardAttributes.put(Module, Module_attribute.class); standardAttributes.put(Module, Module_attribute.class);
standardAttributes.put(ModuleHashes, ModuleHashes_attribute.class);
standardAttributes.put(ModuleMainClass, ModuleMainClass_attribute.class);
standardAttributes.put(ModulePackages, ModulePackages_attribute.class);
standardAttributes.put(ModuleTarget, ModuleTarget_attribute.class);
standardAttributes.put(ModuleVersion, ModuleVersion_attribute.class);
standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class); standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class); standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class); standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
@ -141,8 +143,6 @@ public abstract class Attribute {
standardAttributes.put(StackMap, StackMap_attribute.class); standardAttributes.put(StackMap, StackMap_attribute.class);
standardAttributes.put(StackMapTable, StackMapTable_attribute.class); standardAttributes.put(StackMapTable, StackMapTable_attribute.class);
standardAttributes.put(Synthetic, Synthetic_attribute.class); standardAttributes.put(Synthetic, Synthetic_attribute.class);
standardAttributes.put(TargetPlatform, TargetPlatform_attribute.class);
standardAttributes.put(Version, Version_attribute.class);
} }
private Map<String,Class<? extends Attribute>> standardAttributes; private Map<String,Class<? extends Attribute>> standardAttributes;
@ -178,19 +178,21 @@ public abstract class Attribute {
R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p); R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p);
R visitCode(Code_attribute attr, P p); R visitCode(Code_attribute attr, P p);
R visitCompilationID(CompilationID_attribute attr, P p); R visitCompilationID(CompilationID_attribute attr, P p);
R visitConcealedPackages(ConcealedPackages_attribute attr, P p);
R visitConstantValue(ConstantValue_attribute attr, P p); R visitConstantValue(ConstantValue_attribute attr, P p);
R visitDeprecated(Deprecated_attribute attr, P p); R visitDeprecated(Deprecated_attribute attr, P p);
R visitEnclosingMethod(EnclosingMethod_attribute attr, P p); R visitEnclosingMethod(EnclosingMethod_attribute attr, P p);
R visitExceptions(Exceptions_attribute attr, P p); R visitExceptions(Exceptions_attribute attr, P p);
R visitHashes(Hashes_attribute attr, P p);
R visitInnerClasses(InnerClasses_attribute attr, P p); R visitInnerClasses(InnerClasses_attribute attr, P p);
R visitLineNumberTable(LineNumberTable_attribute attr, P p); R visitLineNumberTable(LineNumberTable_attribute attr, P p);
R visitLocalVariableTable(LocalVariableTable_attribute attr, P p); R visitLocalVariableTable(LocalVariableTable_attribute attr, P p);
R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p); R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p);
R visitMainClass(MainClass_attribute attr, P p);
R visitMethodParameters(MethodParameters_attribute attr, P p); R visitMethodParameters(MethodParameters_attribute attr, P p);
R visitModule(Module_attribute attr, P p); R visitModule(Module_attribute attr, P p);
R visitModuleHashes(ModuleHashes_attribute attr, P p);
R visitModuleMainClass(ModuleMainClass_attribute attr, P p);
R visitModulePackages(ModulePackages_attribute attr, P p);
R visitModuleTarget(ModuleTarget_attribute attr, P p);
R visitModuleVersion(ModuleVersion_attribute attr, P p);
R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p); R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p); R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p); R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
@ -204,7 +206,5 @@ public abstract class Attribute {
R visitStackMap(StackMap_attribute attr, P p); R visitStackMap(StackMap_attribute attr, P p);
R visitStackMapTable(StackMapTable_attribute attr, P p); R visitStackMapTable(StackMapTable_attribute attr, P p);
R visitSynthetic(Synthetic_attribute attr, P p); R visitSynthetic(Synthetic_attribute attr, P p);
R visitTargetPlatform(TargetPlatform_attribute attr, P p);
R visitVersion(Version_attribute attr, P p);
} }
} }

View file

@ -55,6 +55,9 @@ public class ClassWriter {
/** /**
* Write a ClassFile data structure to a file. * Write a ClassFile data structure to a file.
* @param classFile the classfile object to be written
* @param f the file
* @throws IOException if an error occurs while writing the file
*/ */
public void write(ClassFile classFile, File f) throws IOException { public void write(ClassFile classFile, File f) throws IOException {
try (FileOutputStream f_out = new FileOutputStream(f)) { try (FileOutputStream f_out = new FileOutputStream(f)) {
@ -64,6 +67,9 @@ public class ClassWriter {
/** /**
* Write a ClassFile data structure to a stream. * Write a ClassFile data structure to a stream.
* @param classFile the classfile object to be written
* @param s the stream
* @throws IOException if an error occurs while writing the file
*/ */
public void write(ClassFile classFile, OutputStream s) throws IOException { public void write(ClassFile classFile, OutputStream s) throws IOException {
this.classFile = classFile; this.classFile = classFile;
@ -419,7 +425,7 @@ public class ClassWriter {
} }
@Override @Override
public Void visitConcealedPackages(ConcealedPackages_attribute attr, ClassOutputStream out) { public Void visitModulePackages(ModulePackages_attribute attr, ClassOutputStream out) {
out.writeShort(attr.packages_count); out.writeShort(attr.packages_count);
for (int i: attr.packages_index) for (int i: attr.packages_index)
out.writeShort(i); out.writeShort(i);
@ -461,12 +467,15 @@ public class ClassWriter {
} }
@Override @Override
public Void visitHashes(Hashes_attribute attr, ClassOutputStream out) { public Void visitModuleHashes(ModuleHashes_attribute attr, ClassOutputStream out) {
out.writeShort(attr.algorithm_index); out.writeShort(attr.algorithm_index);
out.writeShort(attr.hashes_table.length); out.writeShort(attr.hashes_table.length);
for (Hashes_attribute.Entry e: attr.hashes_table) { for (ModuleHashes_attribute.Entry e: attr.hashes_table) {
out.writeShort(e.requires_index); out.writeShort(e.module_name_index);
out.writeShort(e.hash_index); out.writeShort(e.hash.length);
for (byte b: e.hash) {
out.writeByte(b);
}
} }
return null; return null;
} }
@ -534,33 +543,54 @@ public class ClassWriter {
} }
@Override @Override
public Void visitMainClass(MainClass_attribute attr, ClassOutputStream out) { public Void visitModuleMainClass(ModuleMainClass_attribute attr, ClassOutputStream out) {
out.writeShort(attr.main_class_index); out.writeShort(attr.main_class_index);
return null; return null;
} }
@Override @Override
public Void visitModule(Module_attribute attr, ClassOutputStream out) { public Void visitModule(Module_attribute attr, ClassOutputStream out) {
out.writeShort(attr.module_name);
out.writeShort(attr.module_flags);
out.writeShort(attr.requires.length); out.writeShort(attr.requires.length);
for (Module_attribute.RequiresEntry e: attr.requires) { for (Module_attribute.RequiresEntry e: attr.requires) {
out.writeShort(e.requires_index); out.writeShort(e.requires_index);
out.writeShort(e.requires_flags); out.writeShort(e.requires_flags);
} }
out.writeShort(attr.exports.length); out.writeShort(attr.exports.length);
for (Module_attribute.ExportsEntry e: attr.exports) { for (Module_attribute.ExportsEntry e: attr.exports) {
out.writeShort(e.exports_index); out.writeShort(e.exports_index);
out.writeShort(e.exports_flags);
out.writeShort(e.exports_to_index.length); out.writeShort(e.exports_to_index.length);
for (int index: e.exports_to_index) for (int index: e.exports_to_index)
out.writeShort(index); out.writeShort(index);
} }
out.writeShort(attr.opens.length);
for (Module_attribute.OpensEntry e: attr.opens) {
out.writeShort(e.opens_index);
out.writeShort(e.opens_flags);
out.writeShort(e.opens_to_index.length);
for (int index: e.opens_to_index)
out.writeShort(index);
}
out.writeShort(attr.uses_index.length); out.writeShort(attr.uses_index.length);
for (int index: attr.uses_index) for (int index: attr.uses_index) {
out.writeShort(index); out.writeShort(index);
}
out.writeShort(attr.provides.length); out.writeShort(attr.provides.length);
for (Module_attribute.ProvidesEntry e: attr.provides) { for (Module_attribute.ProvidesEntry e: attr.provides) {
out.writeShort(e.provides_index); out.writeShort(e.provides_index);
out.writeShort(e.with_index); out.writeShort(e.with_count);
for (int with : e.with_index) {
out.writeShort(with);
}
} }
return null; return null;
} }
@ -656,7 +686,7 @@ public class ClassWriter {
} }
@Override @Override
public Void visitTargetPlatform(TargetPlatform_attribute attr, ClassOutputStream out) { public Void visitModuleTarget(ModuleTarget_attribute attr, ClassOutputStream out) {
out.writeShort(attr.os_name_index); out.writeShort(attr.os_name_index);
out.writeShort(attr.os_arch_index); out.writeShort(attr.os_arch_index);
out.writeShort(attr.os_version_index); out.writeShort(attr.os_version_index);
@ -668,7 +698,7 @@ public class ClassWriter {
} }
@Override @Override
public Void visitVersion(Version_attribute attr, ClassOutputStream out) { public Void visitModuleVersion(ModuleVersion_attribute attr, ClassOutputStream out) {
out.writeShort(attr.version_index); out.writeShort(attr.version_index);
return null; return null;
} }

View file

@ -35,8 +35,8 @@ import java.io.IOException;
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class Hashes_attribute extends Attribute { public class ModuleHashes_attribute extends Attribute {
Hashes_attribute(ClassReader cr, int name_index, int length) throws IOException { ModuleHashes_attribute(ClassReader cr, int name_index, int length) throws IOException {
super(name_index, length); super(name_index, length);
algorithm_index = cr.readUnsignedShort(); algorithm_index = cr.readUnsignedShort();
hashes_table_length = cr.readUnsignedShort(); hashes_table_length = cr.readUnsignedShort();
@ -45,13 +45,13 @@ public class Hashes_attribute extends Attribute {
hashes_table[i] = new Entry(cr); hashes_table[i] = new Entry(cr);
} }
public Hashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table) public ModuleHashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table)
throws ConstantPoolException { throws ConstantPoolException {
this(constant_pool.getUTF8Index(Attribute.Hashes), algorithm_index, hashes_table); this(constant_pool.getUTF8Index(Attribute.ModuleHashes), algorithm_index, hashes_table);
} }
public Hashes_attribute(int name_index, int algorithm_index, Entry[] hashes_table) { public ModuleHashes_attribute(int name_index, int algorithm_index, Entry[] hashes_table) {
super(name_index, 4 + hashes_table.length * Entry.length()); super(name_index, 2 + 2 + length(hashes_table));
this.algorithm_index = algorithm_index; this.algorithm_index = algorithm_index;
this.hashes_table_length = hashes_table.length; this.hashes_table_length = hashes_table.length;
this.hashes_table = hashes_table; this.hashes_table = hashes_table;
@ -59,7 +59,15 @@ public class Hashes_attribute extends Attribute {
@Override @Override
public <R, D> R accept(Visitor<R, D> visitor, D data) { public <R, D> R accept(Visitor<R, D> visitor, D data) {
return visitor.visitHashes(this, data); return visitor.visitModuleHashes(this, data);
}
private static int length(Entry[] hashes_table) {
int len = 0;
for (Entry e: hashes_table) {
len += e.length();
}
return len;
} }
public final int algorithm_index; public final int algorithm_index;
@ -68,16 +76,20 @@ public class Hashes_attribute extends Attribute {
public static class Entry { public static class Entry {
Entry(ClassReader cr) throws IOException { Entry(ClassReader cr) throws IOException {
requires_index = cr.readUnsignedShort(); module_name_index = cr.readUnsignedShort();
hash_index = cr.readUnsignedShort(); int hash_length = cr.readUnsignedShort();
hash = new byte[hash_length];
for (int i=0; i<hash_length; i++) {
hash[i] = (byte) cr.readUnsignedByte();
}
} }
public static int length() { public int length() {
return 4; return 4 + hash.length;
} }
public final int requires_index; public final int module_name_index;
public final int hash_index; public final byte[] hash;
} }
} }

View file

@ -35,18 +35,18 @@ import java.io.IOException;
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class MainClass_attribute extends Attribute { public class ModuleMainClass_attribute extends Attribute {
MainClass_attribute(ClassReader cr, int name_index, int length) throws IOException { ModuleMainClass_attribute(ClassReader cr, int name_index, int length) throws IOException {
super(name_index, length); super(name_index, length);
main_class_index = cr.readUnsignedShort(); main_class_index = cr.readUnsignedShort();
} }
public MainClass_attribute(ConstantPool constant_pool, int mainClass_index) public ModuleMainClass_attribute(ConstantPool constant_pool, int mainClass_index)
throws ConstantPoolException { throws ConstantPoolException {
this(constant_pool.getUTF8Index(Attribute.Version), mainClass_index); this(constant_pool.getUTF8Index(Attribute.ModuleMainClass), mainClass_index);
} }
public MainClass_attribute(int name_index, int mainClass_index) { public ModuleMainClass_attribute(int name_index, int mainClass_index) {
super(name_index, 2); super(name_index, 2);
this.main_class_index = mainClass_index; this.main_class_index = mainClass_index;
} }
@ -57,7 +57,7 @@ public class MainClass_attribute extends Attribute {
@Override @Override
public <R, D> R accept(Visitor<R, D> visitor, D data) { public <R, D> R accept(Visitor<R, D> visitor, D data) {
return visitor.visitMainClass(this, data); return visitor.visitModuleMainClass(this, data);
} }
public final int main_class_index; public final int main_class_index;

View file

@ -35,8 +35,8 @@ import java.io.IOException;
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class ConcealedPackages_attribute extends Attribute { public class ModulePackages_attribute extends Attribute {
ConcealedPackages_attribute(ClassReader cr, int name_index, int length) ModulePackages_attribute(ClassReader cr, int name_index, int length)
throws IOException { throws IOException {
super(name_index, length); super(name_index, length);
packages_count = cr.readUnsignedShort(); packages_count = cr.readUnsignedShort();
@ -45,15 +45,15 @@ public class ConcealedPackages_attribute extends Attribute {
packages_index[i] = cr.readUnsignedShort(); packages_index[i] = cr.readUnsignedShort();
} }
public ConcealedPackages_attribute(ConstantPool constant_pool, public ModulePackages_attribute(ConstantPool constant_pool,
int[] packages_index) int[] packages_index)
throws ConstantPoolException { throws ConstantPoolException {
this(constant_pool.getUTF8Index(Attribute.ConcealedPackages), this(constant_pool.getUTF8Index(Attribute.ModulePackages),
packages_index); packages_index);
} }
public ConcealedPackages_attribute(int name_index, public ModulePackages_attribute(int name_index,
int[] packages_index) { int[] packages_index) {
super(name_index, 2 + packages_index.length * 2); super(name_index, 2 + packages_index.length * 2);
this.packages_count = packages_index.length; this.packages_count = packages_index.length;
this.packages_index = packages_index; this.packages_index = packages_index;
@ -66,7 +66,7 @@ public class ConcealedPackages_attribute extends Attribute {
@Override @Override
public <R, D> R accept(Visitor<R, D> visitor, D data) { public <R, D> R accept(Visitor<R, D> visitor, D data) {
return visitor.visitConcealedPackages(this, data); return visitor.visitModulePackages(this, data);
} }
public final int packages_count; public final int packages_count;

View file

@ -35,8 +35,8 @@ import java.io.IOException;
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class TargetPlatform_attribute extends Attribute { public class ModuleTarget_attribute extends Attribute {
TargetPlatform_attribute(ClassReader cr, int name_index, int length) throws IOException { ModuleTarget_attribute(ClassReader cr, int name_index, int length) throws IOException {
super(name_index, length); super(name_index, length);
os_name_index = cr.readUnsignedShort(); os_name_index = cr.readUnsignedShort();
os_arch_index = cr.readUnsignedShort(); os_arch_index = cr.readUnsignedShort();
@ -45,7 +45,7 @@ public class TargetPlatform_attribute extends Attribute {
@Override @Override
public <R, D> R accept(Visitor<R, D> visitor, D data) { public <R, D> R accept(Visitor<R, D> visitor, D data) {
return visitor.visitTargetPlatform(this, data); return visitor.visitModuleTarget(this, data);
} }
public final int os_name_index; public final int os_name_index;

View file

@ -35,25 +35,25 @@ import java.io.IOException;
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class Version_attribute extends Attribute { public class ModuleVersion_attribute extends Attribute {
Version_attribute(ClassReader cr, int name_index, int length) throws IOException { ModuleVersion_attribute(ClassReader cr, int name_index, int length) throws IOException {
super(name_index, length); super(name_index, length);
version_index = cr.readUnsignedShort(); version_index = cr.readUnsignedShort();
} }
public Version_attribute(ConstantPool constant_pool, int version_index) public ModuleVersion_attribute(ConstantPool constant_pool, int version_index)
throws ConstantPoolException { throws ConstantPoolException {
this(constant_pool.getUTF8Index(Attribute.Version), version_index); this(constant_pool.getUTF8Index(Attribute.ModuleVersion), version_index);
} }
public Version_attribute(int name_index, int version_index) { public ModuleVersion_attribute(int name_index, int version_index) {
super(name_index, 2); super(name_index, 2);
this.version_index = version_index; this.version_index = version_index;
} }
@Override @Override
public <R, D> R accept(Visitor<R, D> visitor, D data) { public <R, D> R accept(Visitor<R, D> visitor, D data) {
return visitor.visitVersion(this, data); return visitor.visitModuleVersion(this, data);
} }
public final int version_index; public final int version_index;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,24 +36,38 @@ import java.io.IOException;
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class Module_attribute extends Attribute { public class Module_attribute extends Attribute {
public static final int ACC_PUBLIC = 0x20; public static final int ACC_TRANSITIVE = 0x10;
public static final int ACC_SYNTHETIC = 0x1000; public static final int ACC_STATIC_PHASE = 0x20;
public static final int ACC_MANDATED = 0x8000; public static final int ACC_OPEN = 0x20;
public static final int ACC_SYNTHETIC = 0x1000;
public static final int ACC_MANDATED = 0x8000;
Module_attribute(ClassReader cr, int name_index, int length) throws IOException { Module_attribute(ClassReader cr, int name_index, int length) throws IOException {
super(name_index, length); super(name_index, length);
module_name = cr.readUnsignedShort();
module_flags = cr.readUnsignedShort();
requires_count = cr.readUnsignedShort(); requires_count = cr.readUnsignedShort();
requires = new RequiresEntry[requires_count]; requires = new RequiresEntry[requires_count];
for (int i = 0; i < requires_count; i++) for (int i = 0; i < requires_count; i++)
requires[i] = new RequiresEntry(cr); requires[i] = new RequiresEntry(cr);
exports_count = cr.readUnsignedShort(); exports_count = cr.readUnsignedShort();
exports = new ExportsEntry[exports_count]; exports = new ExportsEntry[exports_count];
for (int i = 0; i < exports_count; i++) for (int i = 0; i < exports_count; i++)
exports[i] = new ExportsEntry(cr); exports[i] = new ExportsEntry(cr);
opens_count = cr.readUnsignedShort();
opens = new OpensEntry[opens_count];
for (int i = 0; i < opens_count; i++)
opens[i] = new OpensEntry(cr);
uses_count = cr.readUnsignedShort(); uses_count = cr.readUnsignedShort();
uses_index = new int[uses_count]; uses_index = new int[uses_count];
for (int i = 0; i < uses_count; i++) for (int i = 0; i < uses_count; i++)
uses_index[i] = cr.readUnsignedShort(); uses_index[i] = cr.readUnsignedShort();
provides_count = cr.readUnsignedShort(); provides_count = cr.readUnsignedShort();
provides = new ProvidesEntry[provides_count]; provides = new ProvidesEntry[provides_count];
for (int i = 0; i < provides_count; i++) for (int i = 0; i < provides_count; i++)
@ -61,20 +75,26 @@ public class Module_attribute extends Attribute {
} }
public Module_attribute(int name_index, public Module_attribute(int name_index,
int module_name,
int module_flags,
RequiresEntry[] requires, RequiresEntry[] requires,
ExportsEntry[] exports, ExportsEntry[] exports,
OpensEntry[] opens,
int[] uses, int[] uses,
ProvidesEntry[] provides) { ProvidesEntry[] provides) {
super(name_index, 2); super(name_index, 2);
this.module_name = module_name;
this.module_flags = module_flags;
requires_count = requires.length; requires_count = requires.length;
this.requires = requires; this.requires = requires;
exports_count = exports.length; exports_count = exports.length;
this.exports = exports; this.exports = exports;
opens_count = opens.length;
this.opens = opens;
uses_count = uses.length; uses_count = uses.length;
this.uses_index = uses; this.uses_index = uses;
provides_count = provides.length; provides_count = provides.length;
this.provides = provides; this.provides = provides;
} }
public String getUses(int index, ConstantPool constant_pool) throws ConstantPoolException { public String getUses(int index, ConstantPool constant_pool) throws ConstantPoolException {
@ -87,10 +107,14 @@ public class Module_attribute extends Attribute {
return visitor.visitModule(this, data); return visitor.visitModule(this, data);
} }
public final int module_name;
public final int module_flags;
public final int requires_count; public final int requires_count;
public final RequiresEntry[] requires; public final RequiresEntry[] requires;
public final int exports_count; public final int exports_count;
public final ExportsEntry[] exports; public final ExportsEntry[] exports;
public final int opens_count;
public final OpensEntry[] opens;
public final int uses_count; public final int uses_count;
public final int[] uses_index; public final int[] uses_index;
public final int provides_count; public final int provides_count;
@ -120,14 +144,16 @@ public class Module_attribute extends Attribute {
public static class ExportsEntry { public static class ExportsEntry {
ExportsEntry(ClassReader cr) throws IOException { ExportsEntry(ClassReader cr) throws IOException {
exports_index = cr.readUnsignedShort(); exports_index = cr.readUnsignedShort();
exports_flags = cr.readUnsignedShort();
exports_to_count = cr.readUnsignedShort(); exports_to_count = cr.readUnsignedShort();
exports_to_index = new int[exports_to_count]; exports_to_index = new int[exports_to_count];
for (int i = 0; i < exports_to_count; i++) for (int i = 0; i < exports_to_count; i++)
exports_to_index[i] = cr.readUnsignedShort(); exports_to_index[i] = cr.readUnsignedShort();
} }
public ExportsEntry(int index, int[] to) { public ExportsEntry(int index, int flags, int[] to) {
this.exports_index = index; this.exports_index = index;
this.exports_flags = flags;
this.exports_to_count = to.length; this.exports_to_count = to.length;
this.exports_to_index = to; this.exports_to_index = to;
} }
@ -137,24 +163,57 @@ public class Module_attribute extends Attribute {
} }
public final int exports_index; public final int exports_index;
public final int exports_flags;
public final int exports_to_count; public final int exports_to_count;
public final int[] exports_to_index; public final int[] exports_to_index;
} }
public static class OpensEntry {
OpensEntry(ClassReader cr) throws IOException {
opens_index = cr.readUnsignedShort();
opens_flags = cr.readUnsignedShort();
opens_to_count = cr.readUnsignedShort();
opens_to_index = new int[opens_to_count];
for (int i = 0; i < opens_to_count; i++)
opens_to_index[i] = cr.readUnsignedShort();
}
public OpensEntry(int index, int flags, int[] to) {
this.opens_index = index;
this.opens_flags = flags;
this.opens_to_count = to.length;
this.opens_to_index = to;
}
public int length() {
return 4 + 2 * opens_to_index.length;
}
public final int opens_index;
public final int opens_flags;
public final int opens_to_count;
public final int[] opens_to_index;
}
public static class ProvidesEntry { public static class ProvidesEntry {
ProvidesEntry(ClassReader cr) throws IOException { ProvidesEntry(ClassReader cr) throws IOException {
provides_index = cr.readUnsignedShort(); provides_index = cr.readUnsignedShort();
with_index = cr.readUnsignedShort(); with_count = cr.readUnsignedShort();
with_index = new int[with_count];
for (int i = 0; i < with_count; i++)
with_index[i] = cr.readUnsignedShort();
} }
public ProvidesEntry(int provides, int with) { public ProvidesEntry(int provides, int[] with) {
this.provides_index = provides; this.provides_index = provides;
this.with_count = with.length;
this.with_index = with; this.with_index = with;
} }
public static final int length = 4; public static final int length = 4;
public final int provides_index; public final int provides_index;
public final int with_index; public final int with_count;
public final int[] with_index;
} }
} }

View file

@ -34,7 +34,6 @@ import com.sun.tools.classfile.CharacterRangeTable_attribute;
import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry; import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry;
import com.sun.tools.classfile.Code_attribute; import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.CompilationID_attribute; import com.sun.tools.classfile.CompilationID_attribute;
import com.sun.tools.classfile.ConcealedPackages_attribute;
import com.sun.tools.classfile.ConstantPool; import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.ConstantValue_attribute; import com.sun.tools.classfile.ConstantValue_attribute;
@ -42,15 +41,18 @@ import com.sun.tools.classfile.DefaultAttribute;
import com.sun.tools.classfile.Deprecated_attribute; import com.sun.tools.classfile.Deprecated_attribute;
import com.sun.tools.classfile.EnclosingMethod_attribute; import com.sun.tools.classfile.EnclosingMethod_attribute;
import com.sun.tools.classfile.Exceptions_attribute; import com.sun.tools.classfile.Exceptions_attribute;
import com.sun.tools.classfile.Hashes_attribute;
import com.sun.tools.classfile.InnerClasses_attribute; import com.sun.tools.classfile.InnerClasses_attribute;
import com.sun.tools.classfile.InnerClasses_attribute.Info; import com.sun.tools.classfile.InnerClasses_attribute.Info;
import com.sun.tools.classfile.LineNumberTable_attribute; import com.sun.tools.classfile.LineNumberTable_attribute;
import com.sun.tools.classfile.LocalVariableTable_attribute; import com.sun.tools.classfile.LocalVariableTable_attribute;
import com.sun.tools.classfile.LocalVariableTypeTable_attribute; import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
import com.sun.tools.classfile.MainClass_attribute;
import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.MethodParameters_attribute;
import com.sun.tools.classfile.Module_attribute; import com.sun.tools.classfile.Module_attribute;
import com.sun.tools.classfile.ModuleHashes_attribute;
import com.sun.tools.classfile.ModuleMainClass_attribute;
import com.sun.tools.classfile.ModulePackages_attribute;
import com.sun.tools.classfile.ModuleTarget_attribute;
import com.sun.tools.classfile.ModuleVersion_attribute;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
@ -64,8 +66,6 @@ import com.sun.tools.classfile.SourceID_attribute;
import com.sun.tools.classfile.StackMapTable_attribute; import com.sun.tools.classfile.StackMapTable_attribute;
import com.sun.tools.classfile.StackMap_attribute; import com.sun.tools.classfile.StackMap_attribute;
import com.sun.tools.classfile.Synthetic_attribute; import com.sun.tools.classfile.Synthetic_attribute;
import com.sun.tools.classfile.TargetPlatform_attribute;
import com.sun.tools.classfile.Version_attribute;
import static com.sun.tools.classfile.AccessFlags.*; import static com.sun.tools.classfile.AccessFlags.*;
@ -237,7 +237,7 @@ public class AttributeWriter extends BasicWriter
return null; return null;
} }
private String getJavaPackage(ConcealedPackages_attribute attr, int index) { private String getJavaPackage(ModulePackages_attribute attr, int index) {
try { try {
return getJavaName(attr.getPackage(index, constant_pool)); return getJavaName(attr.getPackage(index, constant_pool));
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -246,8 +246,8 @@ public class AttributeWriter extends BasicWriter
} }
@Override @Override
public Void visitConcealedPackages(ConcealedPackages_attribute attr, Void ignore) { public Void visitModulePackages(ModulePackages_attribute attr, Void ignore) {
println("ConcealedPackages: "); println("ModulePackages: ");
indent(+1); indent(+1);
for (int i = 0; i < attr.packages_count; i++) { for (int i = 0; i < attr.packages_count; i++) {
print("#" + attr.packages_index[i]); print("#" + attr.packages_index[i]);
@ -323,22 +323,24 @@ public class AttributeWriter extends BasicWriter
} }
@Override @Override
public Void visitHashes(Hashes_attribute attr, Void ignore) { public Void visitModuleHashes(ModuleHashes_attribute attr, Void ignore) {
println("Hashes:"); println("ModuleHashes:");
indent(+1); indent(+1);
print("algorithm #" + attr.algorithm_index); print("algorithm #" + attr.algorithm_index);
tab(); tab();
println("// " + getAlgorithm(attr)); println("// " + getAlgorithm(attr));
for (Hashes_attribute.Entry e : attr.hashes_table) { for (ModuleHashes_attribute.Entry e : attr.hashes_table) {
print("#" + e.requires_index + ", #" + e.hash_index); print("#" + e.module_name_index);
tab(); tab();
println("// " + getRequires(e) + ": " + getHash(e)); println("// " + getModuleName(e));
println("hash_length: " + e.hash.length);
println("hash: [" + toHex(e.hash) + "]");
} }
indent(-1); indent(-1);
return null; return null;
} }
private String getAlgorithm(Hashes_attribute attr) { private String getAlgorithm(ModuleHashes_attribute attr) {
try { try {
return constant_pool.getUTF8Value(attr.algorithm_index); return constant_pool.getUTF8Value(attr.algorithm_index);
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -346,17 +348,9 @@ public class AttributeWriter extends BasicWriter
} }
} }
private String getRequires(Hashes_attribute.Entry entry) { private String getModuleName(ModuleHashes_attribute.Entry entry) {
try { try {
return constant_pool.getUTF8Value(entry.requires_index); return constant_pool.getUTF8Value(entry.module_name_index);
} catch (ConstantPoolException e) {
return report(e);
}
}
private String getHash(Hashes_attribute.Entry entry) {
try {
return constant_pool.getUTF8Value(entry.hash_index);
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
return report(e); return report(e);
} }
@ -456,15 +450,15 @@ public class AttributeWriter extends BasicWriter
} }
@Override @Override
public Void visitMainClass(MainClass_attribute attr, Void ignore) { public Void visitModuleMainClass(ModuleMainClass_attribute attr, Void ignore) {
print("MainClass: #" + attr.main_class_index); print("ModuleMainClass: #" + attr.main_class_index);
tab(); tab();
print("// " + getJavaClassName(attr)); print("// " + getJavaClassName(attr));
println(); println();
return null; return null;
} }
private String getJavaClassName(MainClass_attribute a) { private String getJavaClassName(ModuleMainClass_attribute a) {
try { try {
return getJavaName(a.getMainClassName(constant_pool)); return getJavaName(a.getMainClassName(constant_pool));
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -477,7 +471,6 @@ public class AttributeWriter extends BasicWriter
@Override @Override
public Void visitMethodParameters(MethodParameters_attribute attr, public Void visitMethodParameters(MethodParameters_attribute attr,
Void ignore) { Void ignore) {
final String header = String.format(format, "Name", "Flags"); final String header = String.format(format, "Name", "Flags");
println("MethodParameters:"); println("MethodParameters:");
indent(+1); indent(+1);
@ -501,8 +494,25 @@ public class AttributeWriter extends BasicWriter
public Void visitModule(Module_attribute attr, Void ignore) { public Void visitModule(Module_attribute attr, Void ignore) {
println("Module:"); println("Module:");
indent(+1); indent(+1);
print(attr.module_name);
tab();
println("// " + constantWriter.stringValue(attr.module_name));
print(String.format("%x", attr.module_flags));
tab();
print("// ");
if ((attr.module_flags & Module_attribute.ACC_OPEN) != 0)
print(" ACC_OPEN");
if ((attr.module_flags & Module_attribute.ACC_MANDATED) != 0)
print(" ACC_MANDATED");
if ((attr.module_flags & Module_attribute.ACC_SYNTHETIC) != 0)
print(" ACC_SYNTHETIC");
println();
printRequiresTable(attr); printRequiresTable(attr);
printExportsTable(attr); printExportsTable(attr);
printOpensTable(attr);
printUsesTable(attr); printUsesTable(attr);
printProvidesTable(attr); printProvidesTable(attr);
indent(-1); indent(-1);
@ -511,63 +521,107 @@ public class AttributeWriter extends BasicWriter
protected void printRequiresTable(Module_attribute attr) { protected void printRequiresTable(Module_attribute attr) {
Module_attribute.RequiresEntry[] entries = attr.requires; Module_attribute.RequiresEntry[] entries = attr.requires;
println(entries.length + "\t// " + "requires"); print(entries.length);
tab();
println("// " + "requires");
indent(+1); indent(+1);
for (Module_attribute.RequiresEntry e: entries) { for (Module_attribute.RequiresEntry e: entries) {
print("#" + e.requires_index + "," + print("#" + e.requires_index + "," + String.format("%x", e.requires_flags));
String.format("%x", e.requires_flags)+ "\t// requires"); tab();
if ((e.requires_flags & Module_attribute.ACC_PUBLIC) != 0) print("// " + constantWriter.stringValue(e.requires_index));
print(" public"); if ((e.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0)
print(" ACC_TRANSITIVE");
if ((e.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0)
print(" ACC_STATIC_PHASE");
if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0) if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0)
print(" synthetic"); print(" ACC_SYNTHETIC");
if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0) if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0)
print(" mandated"); print(" ACC_MANDATED");
println(" " + constantWriter.stringValue(e.requires_index)); println();
} }
indent(-1); indent(-1);
} }
protected void printExportsTable(Module_attribute attr) { protected void printExportsTable(Module_attribute attr) {
Module_attribute.ExportsEntry[] entries = attr.exports; Module_attribute.ExportsEntry[] entries = attr.exports;
println(entries.length + "\t// " + "exports"); print(entries.length);
tab();
println("// exports");
indent(+1); indent(+1);
for (Module_attribute.ExportsEntry e: entries) { for (Module_attribute.ExportsEntry e: entries) {
print("#" + e.exports_index + "\t// exports"); printExportOpenEntry(e.exports_index, e.exports_flags, e.exports_to_index);
print(" " + constantWriter.stringValue(e.exports_index));
if (e.exports_to_index.length == 0) {
println();
} else {
println(" to ... " + e.exports_to_index.length);
indent(+1);
for (int to: e.exports_to_index) {
println("#" + to + "\t// ... to " + constantWriter.stringValue(to));
}
indent(-1);
}
} }
indent(-1); indent(-1);
} }
protected void printOpensTable(Module_attribute attr) {
Module_attribute.OpensEntry[] entries = attr.opens;
print(entries.length);
tab();
println("// opens");
indent(+1);
for (Module_attribute.OpensEntry e: entries) {
printExportOpenEntry(e.opens_index, e.opens_flags, e.opens_to_index);
}
indent(-1);
}
protected void printExportOpenEntry(int index, int flags, int[] to_index) {
print("#" + index + "," + String.format("%x", flags));
tab();
print("// ");
print(constantWriter.stringValue(index));
if ((flags & Module_attribute.ACC_MANDATED) != 0)
print(" ACC_MANDATED");
if ((flags & Module_attribute.ACC_SYNTHETIC) != 0)
print(" ACC_SYNTHETIC");
if (to_index.length == 0) {
println();
} else {
println(" to ... " + to_index.length);
indent(+1);
for (int to: to_index) {
print("#" + to);
tab();
println("// ... to " + constantWriter.stringValue(to));
}
indent(-1);
}
}
protected void printUsesTable(Module_attribute attr) { protected void printUsesTable(Module_attribute attr) {
int[] entries = attr.uses_index; int[] entries = attr.uses_index;
println(entries.length + "\t// " + "uses services"); print(entries.length);
tab();
println("// " + "uses");
indent(+1); indent(+1);
for (int e: entries) { for (int e: entries) {
println("#" + e + "\t// uses " + constantWriter.stringValue(e)); print("#" + e);
tab();
println("// " + constantWriter.stringValue(e));
} }
indent(-1); indent(-1);
} }
protected void printProvidesTable(Module_attribute attr) { protected void printProvidesTable(Module_attribute attr) {
Module_attribute.ProvidesEntry[] entries = attr.provides; Module_attribute.ProvidesEntry[] entries = attr.provides;
println(entries.length + "\t// " + "provides services"); print(entries.length);
tab();
println("// " + "provides");
indent(+1); indent(+1);
for (Module_attribute.ProvidesEntry e: entries) { for (Module_attribute.ProvidesEntry e: entries) {
print("#" + e.provides_index + ",#" + print("#" + e.provides_index);
e.with_index + "\t// provides "); tab();
print("// ");
print(constantWriter.stringValue(e.provides_index)); print(constantWriter.stringValue(e.provides_index));
print (" with "); println(" with ... " + e.with_count);
println(constantWriter.stringValue(e.with_index)); indent(+1);
for (int with : e.with_index) {
print("#" + with);
tab();
println("// ... with " + constantWriter.stringValue(with));
}
indent(-1);
} }
indent(-1); indent(-1);
} }
@ -876,8 +930,8 @@ public class AttributeWriter extends BasicWriter
} }
@Override @Override
public Void visitTargetPlatform(TargetPlatform_attribute attr, Void ignore) { public Void visitModuleTarget(ModuleTarget_attribute attr, Void ignore) {
println("TargetPlatform:"); println("ModuleTarget:");
indent(+1); indent(+1);
print("os_name: #" + attr.os_name_index); print("os_name: #" + attr.os_name_index);
if (attr.os_name_index != 0) { if (attr.os_name_index != 0) {
@ -901,7 +955,7 @@ public class AttributeWriter extends BasicWriter
return null; return null;
} }
private String getOSName(TargetPlatform_attribute attr) { private String getOSName(ModuleTarget_attribute attr) {
try { try {
return constant_pool.getUTF8Value(attr.os_name_index); return constant_pool.getUTF8Value(attr.os_name_index);
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -909,7 +963,7 @@ public class AttributeWriter extends BasicWriter
} }
} }
private String getOSArch(TargetPlatform_attribute attr) { private String getOSArch(ModuleTarget_attribute attr) {
try { try {
return constant_pool.getUTF8Value(attr.os_arch_index); return constant_pool.getUTF8Value(attr.os_arch_index);
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -917,7 +971,7 @@ public class AttributeWriter extends BasicWriter
} }
} }
private String getOSVersion(TargetPlatform_attribute attr) { private String getOSVersion(ModuleTarget_attribute attr) {
try { try {
return constant_pool.getUTF8Value(attr.os_version_index); return constant_pool.getUTF8Value(attr.os_version_index);
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -926,8 +980,8 @@ public class AttributeWriter extends BasicWriter
} }
@Override @Override
public Void visitVersion(Version_attribute attr, Void ignore) { public Void visitModuleVersion(ModuleVersion_attribute attr, Void ignore) {
print("Version: #" + attr.version_index); print("ModuleVersion: #" + attr.version_index);
indent(+1); indent(+1);
tab(); tab();
println("// " + getVersion(attr)); println("// " + getVersion(attr));
@ -935,7 +989,7 @@ public class AttributeWriter extends BasicWriter
return null; return null;
} }
private String getVersion(Version_attribute attr) { private String getVersion(ModuleVersion_attribute attr) {
try { try {
return constant_pool.getUTF8Value(attr.version_index); return constant_pool.getUTF8Value(attr.version_index);
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
@ -962,6 +1016,14 @@ public class AttributeWriter extends BasicWriter
return StringUtils.toUpperCase(s); return StringUtils.toUpperCase(s);
} }
static String toHex(byte[] ba) {
StringBuilder sb = new StringBuilder(ba.length);
for (byte b: ba) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
private final AnnotationWriter annotationWriter; private final AnnotationWriter annotationWriter;
private final CodeWriter codeWriter; private final CodeWriter codeWriter;
private final ConstantWriter constantWriter; private final ConstantWriter constantWriter;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -40,7 +40,7 @@ import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.ConstantValue_attribute; import com.sun.tools.classfile.ConstantValue_attribute;
import com.sun.tools.classfile.Descriptor; import com.sun.tools.classfile.Descriptor;
import com.sun.tools.classfile.DescriptorException; import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
import com.sun.tools.classfile.Exceptions_attribute; import com.sun.tools.classfile.Exceptions_attribute;
import com.sun.tools.classfile.Field; import com.sun.tools.classfile.Field;
import com.sun.tools.classfile.Method; import com.sun.tools.classfile.Method;
@ -157,21 +157,36 @@ public class ClassWriter extends BasicWriter {
indent(-1); indent(-1);
} }
String name = getJavaName(classFile);
AccessFlags flags = cf.access_flags; AccessFlags flags = cf.access_flags;
writeModifiers(flags.getClassModifiers()); writeModifiers(flags.getClassModifiers());
if (classFile.access_flags.is(AccessFlags.ACC_MODULE) && name.endsWith(".module-info")) { if (classFile.access_flags.is(AccessFlags.ACC_MODULE)) {
print("module "); Attribute attr = classFile.attributes.get(Attribute.Module);
print(name.replace(".module-info", "")); if (attr instanceof Module_attribute) {
Module_attribute modAttr = (Module_attribute) attr;
String name;
try {
name = getJavaName(constant_pool.getUTF8Value(modAttr.module_name));
} catch (ConstantPoolException e) {
name = report(e);
}
if ((modAttr.module_flags & Module_attribute.ACC_OPEN) != 0) {
print("open ");
}
print("module ");
print(name);
} else {
// fallback for malformed class files
print("class ");
print(getJavaName(classFile));
}
} else { } else {
if (classFile.isClass()) if (classFile.isClass())
print("class "); print("class ");
else if (classFile.isInterface()) else if (classFile.isInterface())
print("interface "); print("interface ");
print(name); print(getJavaName(classFile));
} }
Signature_attribute sigAttr = getSignature(cf.attributes); Signature_attribute sigAttr = getSignature(cf.attributes);
@ -210,7 +225,23 @@ public class ClassWriter extends BasicWriter {
indent(+1); indent(+1);
println("minor version: " + cf.minor_version); println("minor version: " + cf.minor_version);
println("major version: " + cf.major_version); println("major version: " + cf.major_version);
writeList("flags: ", flags.getClassFlags(), "\n"); writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getClassFlags(), "\n");
print("this_class: #" + cf.this_class);
if (cf.this_class != 0) {
tab();
print("// " + constantWriter.stringValue(cf.this_class));
}
println();
print("super_class: #" + cf.super_class);
if (cf.super_class != 0) {
tab();
print("// " + constantWriter.stringValue(cf.super_class));
}
println();
print("interfaces: " + cf.interfaces.length);
print(", fields: " + cf.fields.length);
print(", methods: " + cf.methods.length);
println(", attributes: " + cf.attributes.attrs.length);
indent(-1); indent(-1);
constantWriter.writeConstantPool(); constantWriter.writeConstantPool();
} else { } else {
@ -249,17 +280,20 @@ public class ClassWriter extends BasicWriter {
return builder.toString(); return builder.toString();
} }
@Override
public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) { public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) {
sb.append(getJavaName(type.name)); sb.append(getJavaName(type.name));
return sb; return sb;
} }
@Override
public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) { public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) {
append(sb, type.elemType); append(sb, type.elemType);
sb.append("[]"); sb.append("[]");
return sb; return sb;
} }
@Override
public StringBuilder visitMethodType(MethodType type, StringBuilder sb) { public StringBuilder visitMethodType(MethodType type, StringBuilder sb) {
appendIfNotEmpty(sb, "<", type.typeParamTypes, "> "); appendIfNotEmpty(sb, "<", type.typeParamTypes, "> ");
append(sb, type.returnType); append(sb, type.returnType);
@ -268,6 +302,7 @@ public class ClassWriter extends BasicWriter {
return sb; return sb;
} }
@Override
public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) { public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) {
appendIfNotEmpty(sb, "<", type.typeParamTypes, ">"); appendIfNotEmpty(sb, "<", type.typeParamTypes, ">");
if (isInterface) { if (isInterface) {
@ -283,6 +318,7 @@ public class ClassWriter extends BasicWriter {
return sb; return sb;
} }
@Override
public StringBuilder visitClassType(ClassType type, StringBuilder sb) { public StringBuilder visitClassType(ClassType type, StringBuilder sb) {
if (type.outerType != null) { if (type.outerType != null) {
append(sb, type.outerType); append(sb, type.outerType);
@ -293,6 +329,7 @@ public class ClassWriter extends BasicWriter {
return sb; return sb;
} }
@Override
public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) { public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) {
sb.append(type.name); sb.append(type.name);
String sep = " extends "; String sep = " extends ";
@ -312,6 +349,7 @@ public class ClassWriter extends BasicWriter {
return sb; return sb;
} }
@Override
public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) { public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) {
switch (type.kind) { switch (type.kind) {
case UNBOUNDED: case UNBOUNDED:
@ -402,7 +440,7 @@ public class ClassWriter extends BasicWriter {
println("descriptor: " + getValue(f.descriptor)); println("descriptor: " + getValue(f.descriptor));
if (options.verbose) if (options.verbose)
writeList("flags: ", flags.getFieldFlags(), "\n"); writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getFieldFlags(), "\n");
if (options.showAllAttrs) { if (options.showAllAttrs) {
for (Attribute attr: f.attributes) for (Attribute attr: f.attributes)
@ -459,16 +497,20 @@ public class ClassWriter extends BasicWriter {
if (methodType != null) { if (methodType != null) {
print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes)); print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes));
} }
if (getName(m).equals("<init>")) { switch (getName(m)) {
print(getJavaName(classFile)); case "<init>":
print(getJavaParameterTypes(d, flags)); print(getJavaName(classFile));
} else if (getName(m).equals("<clinit>")) { print(getJavaParameterTypes(d, flags));
print("{}"); break;
} else { case "<clinit>":
print(getJavaReturnType(d)); print("{}");
print(" "); break;
print(getName(m)); default:
print(getJavaParameterTypes(d, flags)); print(getJavaReturnType(d));
print(" ");
print(getName(m));
print(getJavaParameterTypes(d, flags));
break;
} }
Attribute e_attr = m.attributes.get(Attribute.Exceptions); Attribute e_attr = m.attributes.get(Attribute.Exceptions);
@ -499,7 +541,7 @@ public class ClassWriter extends BasicWriter {
} }
if (options.verbose) { if (options.verbose) {
writeList("flags: ", flags.getMethodFlags(), "\n"); writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getMethodFlags(), "\n");
} }
Code_attribute code = null; Code_attribute code = null;
@ -555,15 +597,18 @@ public class ClassWriter extends BasicWriter {
Module_attribute m = (Module_attribute) attr; Module_attribute m = (Module_attribute) attr;
for (Module_attribute.RequiresEntry entry: m.requires) { for (Module_attribute.RequiresEntry entry: m.requires) {
print("requires"); print("requires");
if ((entry.requires_flags & Module_attribute.ACC_PUBLIC) != 0) if ((entry.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0)
print(" public"); print(" static");
if ((entry.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0)
print(" transitive");
print(" "); print(" ");
print(getUTF8Value(entry.requires_index).replace('/', '.')); print(getUTF8Value(entry.requires_index).replace('/', '.'));
println(";"); println(";");
} }
for (Module_attribute.ExportsEntry entry: m.exports) { for (Module_attribute.ExportsEntry entry: m.exports) {
print("exports "); print("exports");
print(" ");
print(getUTF8Value(entry.exports_index).replace('/', '.')); print(getUTF8Value(entry.exports_index).replace('/', '.'));
boolean first = true; boolean first = true;
for (int i: entry.exports_to_index) { for (int i: entry.exports_to_index) {
@ -587,6 +632,32 @@ public class ClassWriter extends BasicWriter {
indent(-1); indent(-1);
} }
for (Module_attribute.OpensEntry entry: m.opens) {
print("opens");
print(" ");
print(getUTF8Value(entry.opens_index).replace('/', '.'));
boolean first = true;
for (int i: entry.opens_to_index) {
String mname;
try {
mname = classFile.constant_pool.getUTF8Value(i).replace('/', '.');
} catch (ConstantPoolException e) {
mname = report(e);
}
if (first) {
println(" to");
indent(+1);
first = false;
} else {
println(",");
}
print(mname);
}
println(";");
if (!first)
indent(-1);
}
for (int entry: m.uses_index) { for (int entry: m.uses_index) {
print("uses "); print("uses ");
print(getClassName(entry).replace('/', '.')); print(getClassName(entry).replace('/', '.'));
@ -594,13 +665,22 @@ public class ClassWriter extends BasicWriter {
} }
for (Module_attribute.ProvidesEntry entry: m.provides) { for (Module_attribute.ProvidesEntry entry: m.provides) {
print("provides "); print("provides ");
print(getClassName(entry.provides_index).replace('/', '.')); print(getClassName(entry.provides_index).replace('/', '.'));
println(" with"); boolean first = true;
indent(+1); for (int i: entry.with_index) {
print(getClassName(entry.with_index).replace('/', '.')); if (first) {
println(" with");
indent(+1);
first = false;
} else {
println(",");
}
print(getClassName(i).replace('/', '.'));
}
println(";"); println(";");
indent(-1); if (!first)
indent(-1);
} }
} }
@ -679,7 +759,7 @@ public class ClassWriter extends BasicWriter {
return getJavaName(d.getFieldType(constant_pool)); return getJavaName(d.getFieldType(constant_pool));
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
return report(e); return report(e);
} catch (DescriptorException e) { } catch (InvalidDescriptor e) {
return report(e); return report(e);
} }
} }
@ -689,7 +769,7 @@ public class ClassWriter extends BasicWriter {
return getJavaName(d.getReturnType(constant_pool)); return getJavaName(d.getReturnType(constant_pool));
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
return report(e); return report(e);
} catch (DescriptorException e) { } catch (InvalidDescriptor e) {
return report(e); return report(e);
} }
} }
@ -699,7 +779,7 @@ public class ClassWriter extends BasicWriter {
return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool))); return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool)));
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
return report(e); return report(e);
} catch (DescriptorException e) { } catch (InvalidDescriptor e) {
return report(e); return report(e);
} }
} }
@ -766,12 +846,16 @@ public class ClassWriter extends BasicWriter {
ConstantPool.CONSTANT_Integer_info info = ConstantPool.CONSTANT_Integer_info info =
(ConstantPool.CONSTANT_Integer_info) cpInfo; (ConstantPool.CONSTANT_Integer_info) cpInfo;
String t = d.getValue(constant_pool); String t = d.getValue(constant_pool);
if (t.equals("C")) { // character switch (t) {
return getConstantCharValue((char) info.value); case "C":
} else if (t.equals("Z")) { // boolean // character
return String.valueOf(info.value == 1); return getConstantCharValue((char) info.value);
} else { // other: assume integer case "Z":
return String.valueOf(info.value); // boolean
return String.valueOf(info.value == 1);
default:
// other: assume integer
return String.valueOf(info.value);
} }
} }
@ -823,10 +907,10 @@ public class ClassWriter extends BasicWriter {
} }
} }
private Options options; private final Options options;
private AttributeWriter attrWriter; private final AttributeWriter attrWriter;
private CodeWriter codeWriter; private final CodeWriter codeWriter;
private ConstantWriter constantWriter; private final ConstantWriter constantWriter;
private ClassFile classFile; private ClassFile classFile;
private URI uri; private URI uri;
private long lastModified; private long lastModified;

View file

@ -136,7 +136,7 @@ public class TraverseProc extends AbstractProcessor {
Set<PackageElement> set = new HashSet<>(); Set<PackageElement> set = new HashSet<>();
for (ModuleElement m : mods) { for (ModuleElement m : mods) {
for (ModuleElement.Directive dir : m.getDirectives()) { for (ModuleElement.Directive dir : m.getDirectives()) {
if (dir.getKind() == ModuleElement.DirectiveKind.EXPORTS) { if (dir.getKind() == ModuleElement.DirectiveKind.EXPORTS) { //XXX
ModuleElement.ExportsDirective exp = (ModuleElement.ExportsDirective)dir; ModuleElement.ExportsDirective exp = (ModuleElement.ExportsDirective)dir;
if (exp.getTargetModules() == null) { if (exp.getTargetModules() == null) {
set.add(exp.getPackage()); set.add(exp.getPackage());

View file

@ -25,6 +25,7 @@
package com.sun.tools.jdeps; package com.sun.tools.jdeps;
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Dependencies.ClassFileError; import com.sun.tools.classfile.Dependencies.ClassFileError;
@ -170,7 +171,9 @@ public class ClassFileReader implements Closeable {
protected Set<String> scan() { protected Set<String> scan() {
try { try {
ClassFile cf = ClassFile.read(path); ClassFile cf = ClassFile.read(path);
return Collections.singleton(cf.getName()); String name = cf.access_flags.is(AccessFlags.ACC_MODULE)
? "module-info" : cf.getName();
return Collections.singleton(name);
} catch (ConstantPoolException|IOException e) { } catch (ConstantPoolException|IOException e) {
throw new ClassFileError(e); throw new ClassFileError(e);
} }

View file

@ -37,6 +37,7 @@ import com.sun.tools.classfile.Dependency.Location;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -175,6 +176,9 @@ class DependencyFinder {
public Set<Location> call() throws Exception { public Set<Location> call() throws Exception {
Set<Location> targets = new HashSet<>(); Set<Location> targets = new HashSet<>();
for (ClassFile cf : archive.reader().getClassFiles()) { for (ClassFile cf : archive.reader().getClassFiles()) {
if (cf.access_flags.is(AccessFlags.ACC_MODULE))
continue;
String classFileName; String classFileName;
try { try {
classFileName = cf.getName(); classFileName = cf.getName();
@ -216,9 +220,13 @@ class DependencyFinder {
{ {
ClassFile cf = archive.reader().getClassFile(name); ClassFile cf = archive.reader().getClassFile(name);
if (cf == null) { if (cf == null) {
throw new IllegalArgumentException(archive.getName() + " does not contain " + name); throw new IllegalArgumentException(archive.getName() +
" does not contain " + name);
} }
if (cf.access_flags.is(AccessFlags.ACC_MODULE))
return Collections.emptySet();
Set<Location> targets = new HashSet<>(); Set<Location> targets = new HashSet<>();
String cn; String cn;
try { try {

View file

@ -29,11 +29,9 @@ import com.sun.tools.classfile.Dependency.Location;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque; import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
@ -263,7 +261,7 @@ public class DepsAnalyzer {
public static enum Info { public static enum Info {
REQUIRES, REQUIRES,
REQUIRES_PUBLIC, REQUIRES_TRANSITIVE,
EXPORTED_API, EXPORTED_API,
MODULE_PRIVATE, MODULE_PRIVATE,
QUALIFIED_EXPORTED_API, QUALIFIED_EXPORTED_API,
@ -288,7 +286,7 @@ public class DepsAnalyzer {
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (info != Info.REQUIRES && info != Info.REQUIRES_PUBLIC) if (info != Info.REQUIRES && info != Info.REQUIRES_TRANSITIVE)
sb.append(source).append("/"); sb.append(source).append("/");
sb.append(name); sb.append(name);
@ -325,7 +323,7 @@ public class DepsAnalyzer {
* Returns a graph of module dependences. * Returns a graph of module dependences.
* *
* Each Node represents a module and each edge is a dependence. * Each Node represents a module and each edge is a dependence.
* No analysis on "requires public". * No analysis on "requires transitive".
*/ */
public Graph<Node> moduleGraph() { public Graph<Node> moduleGraph() {
Graph.Builder<Node> builder = new Graph.Builder<>(); Graph.Builder<Node> builder = new Graph.Builder<>();

View file

@ -388,10 +388,10 @@ public final class Graph<T> {
} }
static void printEdges(PrintWriter out, Graph<String> graph, static void printEdges(PrintWriter out, Graph<String> graph,
String node, Set<String> requiresPublic) { String node, Set<String> requiresTransitive) {
graph.adjacentNodes(node).forEach(dn -> { graph.adjacentNodes(node).forEach(dn -> {
String attr = dn.equals("java.base") ? REQUIRES_BASE String attr = dn.equals("java.base") ? REQUIRES_BASE
: (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES); : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
out.format(" \"%s\" -> \"%s\" [%s];%n", node, dn, attr); out.format(" \"%s\" -> \"%s\" [%s];%n", node, dn, attr);
}); });
} }

View file

@ -38,6 +38,8 @@ import java.io.InputStream;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.lang.module.Configuration; import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleFinder; import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader; import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference; import java.lang.module.ModuleReference;
@ -408,7 +410,7 @@ public class JdepsConfiguration implements AutoCloseable {
} }
@Override @Override
public void close() throws IOException { public void close() {
} }
}; };
} }
@ -421,12 +423,18 @@ public class JdepsConfiguration implements AutoCloseable {
} }
private ModuleDescriptor dropHashes(ModuleDescriptor md) { private ModuleDescriptor dropHashes(ModuleDescriptor md) {
ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name()); ModuleDescriptor.Builder builder = ModuleDescriptor.module(md.name());
md.requires().forEach(builder::requires); md.requires().forEach(builder::requires);
md.exports().forEach(builder::exports); md.exports().forEach(builder::exports);
md.provides().values().stream().forEach(builder::provides); md.opens().forEach(builder::opens);
md.provides().stream().forEach(builder::provides);
md.uses().stream().forEach(builder::uses); md.uses().stream().forEach(builder::uses);
builder.conceals(md.conceals());
Set<String> concealed = new HashSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
concealed.forEach(builder::contains);
return builder.build(); return builder.build();
} }

View file

@ -154,6 +154,7 @@ class JdepsTask {
ANALYZE_DEPS(""), ANALYZE_DEPS(""),
GENERATE_DOT_FILE("-dotoutput", "--dot-output"), GENERATE_DOT_FILE("-dotoutput", "--dot-output"),
GENERATE_MODULE_INFO("--generate-module-info"), GENERATE_MODULE_INFO("--generate-module-info"),
GENERATE_OPEN_MODULE("--generate-open-module"),
LIST_DEPS("--list-deps"), LIST_DEPS("--list-deps"),
LIST_REDUCED_DEPS("--list-reduced-deps"), LIST_REDUCED_DEPS("--list-reduced-deps"),
CHECK_MODULES("--check"); CHECK_MODULES("--check");
@ -248,7 +249,15 @@ class JdepsTask {
if (task.command != null) { if (task.command != null) {
throw new BadArgs("err.command.set", task.command, opt); throw new BadArgs("err.command.set", task.command, opt);
} }
task.command = task.genModuleInfo(Paths.get(arg)); task.command = task.genModuleInfo(Paths.get(arg), false);
}
},
new Option(true, CommandOption.GENERATE_OPEN_MODULE) {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
if (task.command != null) {
throw new BadArgs("err.command.set", task.command, opt);
}
task.command = task.genModuleInfo(Paths.get(arg), true);
} }
}, },
new Option(false, CommandOption.LIST_DEPS) { new Option(false, CommandOption.LIST_DEPS) {
@ -596,11 +605,11 @@ class JdepsTask {
return new GenDotFile(dir); return new GenDotFile(dir);
} }
private GenModuleInfo genModuleInfo(Path dir) throws BadArgs { private GenModuleInfo genModuleInfo(Path dir, boolean openModule) throws BadArgs {
if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) { if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
throw new BadArgs("err.invalid.path", dir.toString()); throw new BadArgs("err.invalid.path", dir.toString());
} }
return new GenModuleInfo(dir); return new GenModuleInfo(dir, openModule);
} }
private ListModuleDeps listModuleDeps(boolean reduced) throws BadArgs { private ListModuleDeps listModuleDeps(boolean reduced) throws BadArgs {
@ -823,9 +832,11 @@ class JdepsTask {
class GenModuleInfo extends Command { class GenModuleInfo extends Command {
final Path dir; final Path dir;
GenModuleInfo(Path dir) { final boolean openModule;
GenModuleInfo(Path dir, boolean openModule) {
super(CommandOption.GENERATE_MODULE_INFO); super(CommandOption.GENERATE_MODULE_INFO);
this.dir = dir; this.dir = dir;
this.openModule = openModule;
} }
@Override @Override
@ -866,7 +877,7 @@ class JdepsTask {
} }
ModuleInfoBuilder builder ModuleInfoBuilder builder
= new ModuleInfoBuilder(config, inputArgs, dir); = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
boolean ok = builder.run(); boolean ok = builder.run();
if (!ok && !options.nowarning) { if (!ok && !options.nowarning) {

View file

@ -26,6 +26,8 @@
package com.sun.tools.jdeps; package com.sun.tools.jdeps;
import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.net.URI; import java.net.URI;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -240,18 +242,24 @@ class Module extends Archive {
private StrictModule(Module m, Map<String, Boolean> requires) { private StrictModule(Module m, Map<String, Boolean> requires) {
super(m.name(), m.location, m.descriptor, m.exports, m.isSystem, m.reader()); super(m.name(), m.location, m.descriptor, m.exports, m.isSystem, m.reader());
ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(m.name()); ModuleDescriptor.Builder builder = ModuleDescriptor.module(m.name());
requires.keySet().forEach(mn -> { requires.keySet().forEach(mn -> {
if (requires.get(mn).equals(Boolean.TRUE)) { if (requires.get(mn).equals(Boolean.TRUE)) {
builder.requires(ModuleDescriptor.Requires.Modifier.PUBLIC, mn); builder.requires(Set.of(ModuleDescriptor.Requires.Modifier.TRANSITIVE), mn);
} else { } else {
builder.requires(mn); builder.requires(mn);
} }
}); });
m.descriptor.exports().forEach(e -> builder.exports(e)); m.descriptor.exports().forEach(e -> builder.exports(e));
m.descriptor.opens().forEach(o -> builder.opens(o));
m.descriptor.uses().forEach(s -> builder.uses(s)); m.descriptor.uses().forEach(s -> builder.uses(s));
m.descriptor.provides().values().forEach(p -> builder.provides(p)); m.descriptor.provides().forEach(p -> builder.provides(p));
builder.conceals(m.descriptor.conceals());
Set<String> concealed = new HashSet<>(m.descriptor.packages());
m.descriptor.exports().stream().map(Exports::source).forEach(concealed::remove);
m.descriptor.opens().stream().map(Opens::source).forEach(concealed::remove);
concealed.forEach(builder::contains);
this.md = builder.build(); this.md = builder.build();
} }

View file

@ -87,8 +87,8 @@ public class ModuleAnalyzer {
public boolean run() throws IOException { public boolean run() throws IOException {
try { try {
// compute "requires public" dependences // compute "requires transitive" dependences
modules.values().forEach(ModuleDeps::computeRequiresPublic); modules.values().forEach(ModuleDeps::computeRequiresTransitive);
modules.values().forEach(md -> { modules.values().forEach(md -> {
// compute "requires" dependences // compute "requires" dependences
@ -104,7 +104,7 @@ public class ModuleAnalyzer {
class ModuleDeps { class ModuleDeps {
final Module root; final Module root;
Set<Module> requiresPublic; Set<Module> requiresTransitive;
Set<Module> requires; Set<Module> requires;
Map<String, Set<String>> unusedQualifiedExports; Map<String, Set<String>> unusedQualifiedExports;
@ -113,15 +113,15 @@ public class ModuleAnalyzer {
} }
/** /**
* Compute 'requires public' dependences by analyzing API dependencies * Compute 'requires transitive' dependences by analyzing API dependencies
*/ */
private void computeRequiresPublic() { private void computeRequiresTransitive() {
// record requires public // record requires transitive
this.requiresPublic = computeRequires(true) this.requiresTransitive = computeRequires(true)
.filter(m -> !m.name().equals(JAVA_BASE)) .filter(m -> !m.name().equals(JAVA_BASE))
.collect(toSet()); .collect(toSet());
trace("requires public: %s%n", requiresPublic); trace("requires transitive: %s%n", requiresTransitive);
} }
private void computeRequires() { private void computeRequires() {
@ -144,24 +144,24 @@ public class ModuleAnalyzer {
} }
ModuleDescriptor descriptor() { ModuleDescriptor descriptor() {
return descriptor(requiresPublic, requires); return descriptor(requiresTransitive, requires);
} }
private ModuleDescriptor descriptor(Set<Module> requiresPublic, private ModuleDescriptor descriptor(Set<Module> requiresTransitive,
Set<Module> requires) { Set<Module> requires) {
ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(root.name()); ModuleDescriptor.Builder builder = ModuleDescriptor.module(root.name());
if (!root.name().equals(JAVA_BASE)) if (!root.name().equals(JAVA_BASE))
builder.requires(MANDATED, JAVA_BASE); builder.requires(Set.of(MANDATED), JAVA_BASE);
requiresPublic.stream() requiresTransitive.stream()
.filter(m -> !m.name().equals(JAVA_BASE)) .filter(m -> !m.name().equals(JAVA_BASE))
.map(Module::name) .map(Module::name)
.forEach(mn -> builder.requires(PUBLIC, mn)); .forEach(mn -> builder.requires(Set.of(TRANSITIVE), mn));
requires.stream() requires.stream()
.filter(m -> !requiresPublic.contains(m)) .filter(m -> !requiresTransitive.contains(m))
.filter(m -> !m.name().equals(JAVA_BASE)) .filter(m -> !m.name().equals(JAVA_BASE))
.map(Module::name) .map(Module::name)
.forEach(mn -> builder.requires(mn)); .forEach(mn -> builder.requires(mn));
@ -172,10 +172,10 @@ public class ModuleAnalyzer {
private Graph<Module> buildReducedGraph() { private Graph<Module> buildReducedGraph() {
ModuleGraphBuilder rpBuilder = new ModuleGraphBuilder(configuration); ModuleGraphBuilder rpBuilder = new ModuleGraphBuilder(configuration);
rpBuilder.addModule(root); rpBuilder.addModule(root);
requiresPublic.stream() requiresTransitive.stream()
.forEach(m -> rpBuilder.addEdge(root, m)); .forEach(m -> rpBuilder.addEdge(root, m));
// requires public graph // requires transitive graph
Graph<Module> rbg = rpBuilder.build().reduce(); Graph<Module> rbg = rpBuilder.build().reduce();
ModuleGraphBuilder gb = new ModuleGraphBuilder(configuration); ModuleGraphBuilder gb = new ModuleGraphBuilder(configuration);
@ -198,7 +198,7 @@ public class ModuleAnalyzer {
*/ */
ModuleDescriptor reduced() { ModuleDescriptor reduced() {
Graph<Module> g = buildReducedGraph(); Graph<Module> g = buildReducedGraph();
return descriptor(requiresPublic, g.adjacentNodes(root)); return descriptor(requiresTransitive, g.adjacentNodes(root));
} }
/** /**
@ -309,16 +309,16 @@ public class ModuleAnalyzer {
} }
private boolean matches(ModuleDescriptor md, ModuleDescriptor other) { private boolean matches(ModuleDescriptor md, ModuleDescriptor other) {
// build requires public from ModuleDescriptor // build requires transitive from ModuleDescriptor
Set<ModuleDescriptor.Requires> reqPublic = md.requires().stream() Set<ModuleDescriptor.Requires> reqTransitive = md.requires().stream()
.filter(req -> req.modifiers().contains(PUBLIC)) .filter(req -> req.modifiers().contains(TRANSITIVE))
.collect(toSet()); .collect(toSet());
Set<ModuleDescriptor.Requires> otherReqPublic = other.requires().stream() Set<ModuleDescriptor.Requires> otherReqTransitive = other.requires().stream()
.filter(req -> req.modifiers().contains(PUBLIC)) .filter(req -> req.modifiers().contains(TRANSITIVE))
.collect(toSet()); .collect(toSet());
if (!reqPublic.equals(otherReqPublic)) { if (!reqTransitive.equals(otherReqTransitive)) {
trace("mismatch requires public: %s%n", reqPublic); trace("mismatch requires transitive: %s%n", reqTransitive);
return false; return false;
} }
@ -365,12 +365,12 @@ public class ModuleAnalyzer {
.sorted(Comparator.comparing(ModuleDescriptor::name)) .sorted(Comparator.comparing(ModuleDescriptor::name))
.forEach(md -> { .forEach(md -> {
String mn = md.name(); String mn = md.name();
Set<String> requiresPublic = md.requires().stream() Set<String> requiresTransitive = md.requires().stream()
.filter(d -> d.modifiers().contains(PUBLIC)) .filter(d -> d.modifiers().contains(TRANSITIVE))
.map(d -> d.name()) .map(d -> d.name())
.collect(toSet()); .collect(toSet());
DotGraph.printEdges(out, graph, mn, requiresPublic); DotGraph.printEdges(out, graph, mn, requiresTransitive);
}); });
out.println("}"); out.println("}");
@ -380,20 +380,20 @@ public class ModuleAnalyzer {
/** /**
* Returns a Graph of the given Configuration after transitive reduction. * Returns a Graph of the given Configuration after transitive reduction.
* *
* Transitive reduction of requires public edge and requires edge have * Transitive reduction of requires transitive edge and requires edge have
* to be applied separately to prevent the requires public edges * to be applied separately to prevent the requires transitive edges
* (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V) * (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V)
* in which V would not be re-exported from U. * in which V would not be re-exported from U.
*/ */
private Graph<String> gengraph(Set<Module> modules) { private Graph<String> gengraph(Set<Module> modules) {
// build a Graph containing only requires public edges // build a Graph containing only requires transitive edges
// with transitive reduction. // with transitive reduction.
Graph.Builder<String> rpgbuilder = new Graph.Builder<>(); Graph.Builder<String> rpgbuilder = new Graph.Builder<>();
for (Module module : modules) { for (Module module : modules) {
ModuleDescriptor md = module.descriptor(); ModuleDescriptor md = module.descriptor();
String mn = md.name(); String mn = md.name();
md.requires().stream() md.requires().stream()
.filter(d -> d.modifiers().contains(PUBLIC)) .filter(d -> d.modifiers().contains(TRANSITIVE))
.map(d -> d.name()) .map(d -> d.name())
.forEach(d -> rpgbuilder.addEdge(mn, d)); .forEach(d -> rpgbuilder.addEdge(mn, d));
} }

View file

@ -178,7 +178,7 @@ public class ModuleExportsAnalyzer extends DepsAnalyzer {
RootModule(String name) { RootModule(String name) {
super(name); super(name);
ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(name); ModuleDescriptor.Builder builder = ModuleDescriptor.module(name);
this.descriptor = builder.build(); this.descriptor = builder.build();
} }

View file

@ -98,7 +98,7 @@ public class ModuleGraphBuilder extends Graph.Builder<Module> {
}); });
}); });
// read requires public from ModuleDescriptor // read requires transitive from ModuleDescriptor
Module source; Module source;
while ((source = deque.poll()) != null) { while ((source = deque.poll()) != null) {
if (visited.contains(source)) if (visited.contains(source))
@ -107,7 +107,7 @@ public class ModuleGraphBuilder extends Graph.Builder<Module> {
visited.add(source); visited.add(source);
builder.addNode(source); builder.addNode(source);
Module from = source; Module from = source;
requiresPublic(from).forEach(m -> { requiresTransitive(from).forEach(m -> {
deque.add(m); deque.add(m);
builder.addEdge(from, m); builder.addEdge(from, m);
}); });
@ -116,13 +116,13 @@ public class ModuleGraphBuilder extends Graph.Builder<Module> {
} }
/* /*
* Returns a stream of modules upon which the given module `requires public` * Returns a stream of modules upon which the given module `requires transitive`
*/ */
public Stream<Module> requiresPublic(Module m) { public Stream<Module> requiresTransitive(Module m) {
// find requires public // find requires transitive
return m.descriptor() return m.descriptor()
.requires().stream() .requires().stream()
.filter(req -> req.modifiers().contains(PUBLIC)) .filter(req -> req.modifiers().contains(TRANSITIVE))
.map(ModuleDescriptor.Requires::name) .map(ModuleDescriptor.Requires::name)
.map(config::findModule) .map(config::findModule)
.flatMap(Optional::stream); .flatMap(Optional::stream);

View file

@ -47,13 +47,14 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
public class ModuleInfoBuilder { public class ModuleInfoBuilder {
final JdepsConfiguration configuration; final JdepsConfiguration configuration;
final Path outputdir; final Path outputdir;
final boolean open;
final DependencyFinder dependencyFinder; final DependencyFinder dependencyFinder;
final Analyzer analyzer; final Analyzer analyzer;
@ -63,9 +64,11 @@ public class ModuleInfoBuilder {
final Map<Module, Module> automaticToExplicitModule; final Map<Module, Module> automaticToExplicitModule;
public ModuleInfoBuilder(JdepsConfiguration configuration, public ModuleInfoBuilder(JdepsConfiguration configuration,
List<String> args, List<String> args,
Path outputdir) { Path outputdir,
boolean open) {
this.configuration = configuration; this.configuration = configuration;
this.outputdir = outputdir; this.outputdir = outputdir;
this.open = open;
this.dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER); this.dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER);
this.analyzer = new Analyzer(configuration, Type.CLASS, DEFAULT_FILTER); this.analyzer = new Analyzer(configuration, Type.CLASS, DEFAULT_FILTER);
@ -73,13 +76,13 @@ public class ModuleInfoBuilder {
// add targets to modulepath if it has module-info.class // add targets to modulepath if it has module-info.class
List<Path> paths = args.stream() List<Path> paths = args.stream()
.map(fn -> Paths.get(fn)) .map(fn -> Paths.get(fn))
.collect(Collectors.toList()); .collect(toList());
// automatic module to convert to explicit module // automatic module to convert to explicit module
this.automaticToExplicitModule = ModuleFinder.of(paths.toArray(new Path[0])) this.automaticToExplicitModule = ModuleFinder.of(paths.toArray(new Path[0]))
.findAll().stream() .findAll().stream()
.map(configuration::toModule) .map(configuration::toModule)
.collect(Collectors.toMap(Function.identity(), Function.identity())); .collect(toMap(Function.identity(), Function.identity()));
Optional<Module> om = automaticToExplicitModule.keySet().stream() Optional<Module> om = automaticToExplicitModule.keySet().stream()
.filter(m -> !m.descriptor().isAutomatic()) .filter(m -> !m.descriptor().isAutomatic())
@ -96,7 +99,7 @@ public class ModuleInfoBuilder {
public boolean run() throws IOException { public boolean run() throws IOException {
try { try {
// pass 1: find API dependencies // pass 1: find API dependencies
Map<Archive, Set<Archive>> requiresPublic = computeRequiresPublic(); Map<Archive, Set<Archive>> requiresTransitive = computeRequiresTransitive();
// pass 2: analyze all class dependences // pass 2: analyze all class dependences
dependencyFinder.parse(automaticModules().stream()); dependencyFinder.parse(automaticModules().stream());
@ -105,13 +108,13 @@ public class ModuleInfoBuilder {
boolean missingDeps = false; boolean missingDeps = false;
for (Module m : automaticModules()) { for (Module m : automaticModules()) {
Set<Archive> apiDeps = requiresPublic.containsKey(m) Set<Archive> apiDeps = requiresTransitive.containsKey(m)
? requiresPublic.get(m) ? requiresTransitive.get(m)
: Collections.emptySet(); : Collections.emptySet();
Path file = outputdir.resolve(m.name()).resolve("module-info.java"); Path file = outputdir.resolve(m.name()).resolve("module-info.java");
// computes requires and requires public // computes requires and requires transitive
Module explicitModule = toExplicitModule(m, apiDeps); Module explicitModule = toExplicitModule(m, apiDeps);
if (explicitModule != null) { if (explicitModule != null) {
automaticToExplicitModule.put(m, explicitModule); automaticToExplicitModule.put(m, explicitModule);
@ -136,7 +139,7 @@ public class ModuleInfoBuilder {
return m == NOT_FOUND || m == REMOVED_JDK_INTERNALS; return m == NOT_FOUND || m == REMOVED_JDK_INTERNALS;
} }
private Module toExplicitModule(Module module, Set<Archive> requiresPublic) private Module toExplicitModule(Module module, Set<Archive> requiresTransitive)
throws IOException throws IOException
{ {
// done analysis // done analysis
@ -148,7 +151,7 @@ public class ModuleInfoBuilder {
} }
Map<String, Boolean> requires = new HashMap<>(); Map<String, Boolean> requires = new HashMap<>();
requiresPublic.stream() requiresTransitive.stream()
.map(Archive::getModule) .map(Archive::getModule)
.forEach(m -> requires.put(m.name(), Boolean.TRUE)); .forEach(m -> requires.put(m.name(), Boolean.TRUE));
@ -183,53 +186,60 @@ public class ModuleInfoBuilder {
}); });
} }
void writeModuleInfo(Path file, ModuleDescriptor descriptor) { void writeModuleInfo(Path file, ModuleDescriptor md) {
try { try {
Files.createDirectories(file.getParent()); Files.createDirectories(file.getParent());
try (PrintWriter pw = new PrintWriter(Files.newOutputStream(file))) { try (PrintWriter pw = new PrintWriter(Files.newOutputStream(file))) {
printModuleInfo(pw, descriptor); printModuleInfo(pw, md);
} }
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
} }
} }
private void printModuleInfo(PrintWriter writer, ModuleDescriptor descriptor) { private void printModuleInfo(PrintWriter writer, ModuleDescriptor md) {
writer.format("module %s {%n", descriptor.name()); writer.format("%smodule %s {%n", open ? "open " : "", md.name());
Map<String, Module> modules = configuration.getModules(); Map<String, Module> modules = configuration.getModules();
// first print the JDK modules // first print the JDK modules
descriptor.requires().stream() md.requires().stream()
.filter(req -> !req.name().equals("java.base")) // implicit requires .filter(req -> !req.name().equals("java.base")) // implicit requires
.sorted(Comparator.comparing(Requires::name)) .sorted(Comparator.comparing(Requires::name))
.forEach(req -> writer.format(" requires %s;%n", req)); .forEach(req -> writer.format(" requires %s;%n", req));
descriptor.exports().stream() if (!open) {
.peek(exp -> { md.exports().stream()
if (exp.targets().size() > 0) .peek(exp -> {
throw new InternalError(descriptor.name() + " qualified exports: " + exp); if (exp.targets().size() > 0)
}) throw new InternalError(md.name() + " qualified exports: " + exp);
.sorted(Comparator.comparing(Exports::source)) })
.forEach(exp -> writer.format(" exports %s;%n", exp.source())); .sorted(Comparator.comparing(Exports::source))
.forEach(exp -> writer.format(" exports %s;%n", exp.source()));
}
descriptor.provides().values().stream() md.provides().stream()
.sorted(Comparator.comparing(Provides::service)) .sorted(Comparator.comparing(Provides::service))
.forEach(p -> p.providers().stream() .map(p -> p.providers().stream()
.sorted() .map(impl -> " " + impl.replace('$', '.'))
.forEach(impl -> writer.format(" provides %s with %s;%n", p.service(), impl))); .collect(joining(",\n",
String.format(" provides %s with%n",
p.service().replace('$', '.')),
";")))
.forEach(writer::println);
writer.println("}"); writer.println("}");
} }
private Set<Module> automaticModules() { private Set<Module> automaticModules() {
return automaticToExplicitModule.keySet(); return automaticToExplicitModule.keySet();
} }
/** /**
* Compute 'requires public' dependences by analyzing API dependencies * Compute 'requires transitive' dependences by analyzing API dependencies
*/ */
private Map<Archive, Set<Archive>> computeRequiresPublic() throws IOException { private Map<Archive, Set<Archive>> computeRequiresTransitive()
throws IOException
{
// parse the input modules // parse the input modules
dependencyFinder.parseExportedAPIs(automaticModules().stream()); dependencyFinder.parseExportedAPIs(automaticModules().stream());

View file

@ -125,6 +125,13 @@ main.opt.generate-module-info=\
\ --generate-module-info <dir> Generate module-info.java under the specified\n\ \ --generate-module-info <dir> Generate module-info.java under the specified\n\
\ directory. The specified JAR files will be\n\ \ directory. The specified JAR files will be\n\
\ analyzed. This option cannot be used with\n\ \ analyzed. This option cannot be used with\n\
\ --dot-output or --class-path. Use \n\
\ --generate-open-module option for open modules.
main.opt.generate-open-module=\
\ --generate-open-module <dir> Generate module-info.java for the specified\n\
\ JAR files under the specified directory as\n\
\ open modules. This option cannot be used with\n\
\ --dot-output or --class-path. \ --dot-output or --class-path.
main.opt.check=\ main.opt.check=\

View file

@ -33,9 +33,7 @@ module jdk.jdeps {
exports com.sun.tools.classfile to exports com.sun.tools.classfile to
jdk.jlink; jdk.jlink;
provides java.util.spi.ToolProvider provides java.util.spi.ToolProvider with
with com.sun.tools.javap.Main.JavapToolProvider; com.sun.tools.javap.Main.JavapToolProvider,
com.sun.tools.jdeps.Main.JDepsToolProvider;
provides java.util.spi.ToolProvider
with com.sun.tools.jdeps.Main.JDepsToolProvider;
} }

View file

@ -126,7 +126,7 @@ jshell.err.retained.mode.failure = \u4FDD\u6301\u3055\u308C\u305F\u30E2\u30FC\u3
jshell.console.see.more = <\u8A73\u7D30\u306F\u3001\u30BF\u30D6\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044> jshell.console.see.more = <\u8A73\u7D30\u306F\u3001\u30BF\u30D6\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044>
jshell.console.do.nothing = \u4F55\u3082\u3057\u306A\u3044 jshell.console.do.nothing = \u4F55\u3082\u3057\u306A\u3044
jshell.console.choice = \u9078\u629E: jshell.console.choice = \u9078\u629E:
jshell.console.create.variable = \u5909\u6570\u306E\u4F5C\u6210 jshell.console.create.variable = \u5909\u6570\u306E\u4F5C\u6210
jshell.console.resolvable = \n\u8B58\u5225\u5B50\u306F\u3053\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3067\u89E3\u6C7A\u3067\u304D\u307E\u3059\u3002 jshell.console.resolvable = \n\u8B58\u5225\u5B50\u306F\u3053\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3067\u89E3\u6C7A\u3067\u304D\u307E\u3059\u3002
jshell.console.no.candidate = \n\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u5019\u88DC\u306E\u5B8C\u5168\u4FEE\u98FE\u3055\u308C\u305F\u540D\u524D\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 jshell.console.no.candidate = \n\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u5019\u88DC\u306E\u5B8C\u5168\u4FEE\u98FE\u3055\u308C\u305F\u540D\u524D\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002

View file

@ -29,7 +29,7 @@
* Read-Eval-Print Loops (REPLs). * Read-Eval-Print Loops (REPLs).
*/ */
module jdk.jshell { module jdk.jshell {
requires public java.compiler; requires transitive java.compiler;
requires java.prefs; requires java.prefs;
requires jdk.compiler; requires jdk.compiler;
requires jdk.internal.le; requires jdk.internal.le;

View file

@ -14,8 +14,8 @@ keys=intermittent randomness
# Group definitions # Group definitions
groups=TEST.groups groups=TEST.groups
# Tests using jtreg 4.2 b03 features # Tests using jtreg 4.2 b04 features
requiredVersion=4.2 b03 requiredVersion=4.2 b04
# Use new module options # Use new module options
useNewOptions=true useNewOptions=true

View file

@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363 * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363 8168766
* @summary Test modules support in javadoc. * @summary Test modules support in javadoc.
* @author bpatel * @author bpatel
* @library ../lib * @library ../lib
@ -181,6 +181,34 @@ public class TestModules extends JavadocTester {
checkModuleFilesAndLinks(true); checkModuleFilesAndLinks(true);
} }
/**
* Test generated module pages for a deprecated module.
*/
@Test
void testModuleDeprecation() {
javadoc("-d", "out-moduledepr",
"-tag", "regular:a:Regular Tag:",
"-tag", "moduletag:s:Module Tag:",
"--module-source-path", testSrc,
"--module", "module1,module2,moduletags",
"testpkgmdl1", "testpkgmdl2", "testpkgmdltags");
checkExit(Exit.OK);
checkModuleDeprecation(true);
}
/**
* Test annotations on modules.
*/
@Test
void testModuleAnnotation() {
javadoc("-d", "out-moduleanno",
"--module-source-path", testSrc,
"--module", "module1,module2",
"testpkgmdl1", "testpkgmdl2");
checkExit(Exit.OK);
checkModuleAnnotation();
}
void checkDescription(boolean found) { void checkDescription(boolean found) {
checkOutput("module1-summary.html", found, checkOutput("module1-summary.html", found,
"<!-- ============ MODULE DESCRIPTION =========== -->\n" "<!-- ============ MODULE DESCRIPTION =========== -->\n"
@ -218,6 +246,9 @@ public class TestModules extends JavadocTester {
void checkHtml5Description(boolean found) { void checkHtml5Description(boolean found) {
checkOutput("module1-summary.html", found, checkOutput("module1-summary.html", found,
"<section role=\"region\">\n" "<section role=\"region\">\n"
+ "<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
+ "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated.</span></div>\n"
+ "</div>\n"
+ "<!-- ============ MODULE DESCRIPTION =========== -->\n" + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+ "<a id=\"module.description\">\n" + "<a id=\"module.description\">\n"
+ "<!-- -->\n" + "<!-- -->\n"
@ -556,4 +587,37 @@ public class TestModules extends JavadocTester {
+ "<dd>&nbsp;</dd>\n" + "<dd>&nbsp;</dd>\n"
+ "</dl>"); + "</dl>");
} }
void checkModuleDeprecation(boolean found) {
checkOutput("module1-summary.html", found,
"<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
+ "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated.</span></div>\n"
+ "</div>");
checkOutput("deprecated-list.html", found,
"<ul>\n"
+ "<li><a href=\"#module\">Deprecated Modules</a></li>\n"
+ "</ul>",
"<tr class=\"altColor\">\n"
+ "<th class=\"colFirst\" scope=\"row\"><a href=\"module1-summary.html\">module1</a></th>\n"
+ "<td class=\"colLast\">\n"
+ "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated.</span></div>\n"
+ "</td>\n"
+ "</tr>");
checkOutput("module2-summary.html", !found,
"<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
+ "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated using just the javadoc tag.</span></div>");
checkOutput("moduletags-summary.html", found,
"<p>@Deprecated\n"
+ "</p>",
"<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span></div>");
}
void checkModuleAnnotation() {
checkOutput("module2-summary.html", true,
"<p><a href=\"testpkgmdl2/AnnotationType.html\" title=\"annotation in testpkgmdl2\">@AnnotationType</a>(<a href=\"testpkgmdl2/AnnotationType.html#optional--\">optional</a>=\"Module Annotation\",\n"
+ " <a href=\"testpkgmdl2/AnnotationType.html#required--\">required</a>=2016)\n"
+ "</p>");
checkOutput("module2-summary.html", false,
"@AnnotationTypeUndocumented");
}
} }

View file

@ -25,7 +25,10 @@
/** /**
* This is a test description for the module1 module. Search phrase {@index "search phrase" with description}. * This is a test description for the module1 module. Search phrase {@index "search phrase" with description}.
*
* @deprecated This module is deprecated.
*/ */
@Deprecated
module module1 { module module1 {
requires module2; requires module2;

View file

@ -25,7 +25,11 @@
/** /**
* This is a test description for the module2 module. Search word {@index search_word} with no description. * This is a test description for the module2 module. Search word {@index search_word} with no description.
*
* @deprecated This module is deprecated using just the javadoc tag.
*/ */
@testpkgmdl2.AnnotationType(optional="Module Annotation", required=2016)
@testpkgmdl2.AnnotationTypeUndocumented(optional="Module Annotation", required=2016)
module module2 { module module2 {
exports testpkgmdl2; exports testpkgmdl2;

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package testpkgmdl2;
import java.lang.annotation.*;
/**
* This is a test annotation type.
*/
@Documented public @interface AnnotationType {
/**
* The copyright holder.
*
* @return a string.
*/
String optional() default "unknown";
/**
* The year of the copyright.
*
* @return an int.
*/
int required();
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package testpkgmdl2;
import java.lang.annotation.*;
/**
* This is a test annotation type this is not documented because it
* is missing the @Documented tag.
*/
public @interface AnnotationTypeUndocumented {
/**
* The copyright holder.
*
* @return a string.
*/
String optional() default "unknown";
/**
* The year of the copyright.
*
* @return an int.
*/
int required();
}

View file

@ -37,6 +37,7 @@
* @moduletag Just a simple module tag. * @moduletag Just a simple module tag.
* @version 1.0 * @version 1.0
*/ */
@Deprecated
module moduletags { module moduletags {
requires module2; requires module2;

View file

@ -393,14 +393,14 @@ public class Modules extends ModuleTestBase {
* Module M : test module, with variable requires * Module M : test module, with variable requires
* *
* Module N : * Module N :
* requires public O ---> Module O: * requires transitive O ---> Module O:
* requires J ----> Module J: * requires J ----> Module J:
* exports openO exports openJ * exports openO exports openJ
* *
* *
* Module L : * Module L :
* requires public P ---> Module P: * requires transitive P ---> Module P:
* exports openP * exports openP
* *
* *
*/ */
@ -431,14 +431,14 @@ public class Modules extends ModuleTestBase {
} }
@Test @Test
public void testExpandRequiresPublic(Path base) throws Exception { public void testExpandRequiresTransitive(Path base) throws Exception {
Path src = base.resolve("src"); Path src = base.resolve("src");
createAuxiliaryModules(src); createAuxiliaryModules(src);
new ModuleBuilder(tb, "M") new ModuleBuilder(tb, "M")
.comment("The M module.") .comment("The M module.")
.requiresPublic("N", src) .requiresTransitive("N", src)
.requires("L", src) .requires("L", src)
.exports("p") .exports("p")
.classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
@ -446,7 +446,7 @@ public class Modules extends ModuleTestBase {
execTask("--module-source-path", src.toString(), execTask("--module-source-path", src.toString(),
"--module", "M", "--module", "M",
"--expand-requires", "public"); "--expand-requires", "transitive");
checkModulesSpecified("M", "N", "O"); checkModulesSpecified("M", "N", "O");
checkModulesIncluded("M", "N", "O"); checkModulesIncluded("M", "N", "O");
@ -462,7 +462,7 @@ public class Modules extends ModuleTestBase {
new ModuleBuilder(tb, "M") new ModuleBuilder(tb, "M")
.comment("The M module.") .comment("The M module.")
.requiresPublic("N", src) .requiresTransitive("N", src)
.requires("L", src) .requires("L", src)
.requires("O", src) .requires("O", src)
.exports("p") .exports("p")
@ -490,7 +490,7 @@ public class Modules extends ModuleTestBase {
new ModuleBuilder(tb, "M") new ModuleBuilder(tb, "M")
.comment("The M module.") .comment("The M module.")
.requiresPublic("N", src) .requiresTransitive("N", src)
.requires("L", src) .requires("L", src)
.requires("O", src) .requires("O", src)
.exports("p") .exports("p")
@ -512,7 +512,7 @@ public class Modules extends ModuleTestBase {
new ModuleBuilder(tb, "M") new ModuleBuilder(tb, "M")
.comment("The M module.") .comment("The M module.")
.requiresPublic("N", src) .requiresTransitive("N", src)
.requires("L", src) .requires("L", src)
.requires("O", src) .requires("O", src)
.exports("p") .exports("p")
@ -538,7 +538,7 @@ public class Modules extends ModuleTestBase {
new ModuleBuilder(tb, "L") new ModuleBuilder(tb, "L")
.comment("The L module.") .comment("The L module.")
.exports("openL") .exports("openL")
.requiresPublic("P") . requiresTransitive("P")
.classes("package openL; /** Class L open */ public class L { }") .classes("package openL; /** Class L open */ public class L { }")
.classes("package closedL; /** Class L closed */ public class L { }") .classes("package closedL; /** Class L closed */ public class L { }")
.write(src); .write(src);
@ -546,7 +546,7 @@ public class Modules extends ModuleTestBase {
new ModuleBuilder(tb, "N") new ModuleBuilder(tb, "N")
.comment("The N module.") .comment("The N module.")
.exports("openN") .exports("openN")
.requiresPublic("O") .requiresTransitive("O")
.classes("package openN; /** Class N open */ public class N { }") .classes("package openN; /** Class N open */ public class N { }")
.classes("package closedN; /** Class N closed */ public class N { }") .classes("package closedN; /** Class N closed */ public class N { }")
.write(src); .write(src);

View file

@ -29,6 +29,7 @@
* @modules jdk.compiler/com.sun.tools.javac.api * @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.main
* jdk.jdeps/com.sun.tools.javap * jdk.jdeps/com.sun.tools.javap
* jdk.jshell/jdk.jshell:open
* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
* @build KullaTesting TestingInputStream Compiler * @build KullaTesting TestingInputStream Compiler
* @run testng CompletionSuggestionTest * @run testng CompletionSuggestionTest

View file

@ -28,6 +28,7 @@
* @library /tools/lib * @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api * @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.main
* jdk.jshell/jdk.jshell:open
* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
* @build KullaTesting TestingInputStream Compiler * @build KullaTesting TestingInputStream Compiler
* @run testng ComputeFQNsTest * @run testng ComputeFQNsTest

View file

@ -26,7 +26,7 @@
* @bug 8166744 * @bug 8166744
* @summary Test Completion * @summary Test Completion
* @modules jdk.internal.le/jdk.internal.jline.extra * @modules jdk.internal.le/jdk.internal.jline.extra
* jdk.jshell/jdk.internal.jshell.tool * jdk.jshell/jdk.internal.jshell.tool:+open
* @build HistoryTest * @build HistoryTest
* @run testng HistoryTest * @run testng HistoryTest
*/ */

View file

@ -28,7 +28,7 @@
* @library /tools/lib * @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api * @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.main
* jdk.jshell * jdk.jshell/jdk.jshell:open
* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
* @build KullaTesting TestingInputStream Compiler * @build KullaTesting TestingInputStream Compiler
* @run testng JavadocTest * @run testng JavadocTest

View file

@ -25,7 +25,7 @@
* @test 8167461 * @test 8167461
* @summary Verify PipeInputStream works. * @summary Verify PipeInputStream works.
* @modules jdk.compiler/com.sun.tools.javac.util * @modules jdk.compiler/com.sun.tools.javac.util
* jdk.jshell * jdk.jshell/jdk.jshell.execution:open
* @run testng PipeInputStreamTest * @run testng PipeInputStreamTest
*/ */

View file

@ -1188,7 +1188,7 @@ public class ClassfileInspector {
} }
@Override @Override
public Void visitConcealedPackages(ConcealedPackages_attribute attr, T p) { public Void visitModulePackages(ModulePackages_attribute attr, T p) {
return null; return null;
} }
@ -1238,7 +1238,7 @@ public class ClassfileInspector {
} }
@Override @Override
public Void visitHashes(Hashes_attribute attr, T p) { public Void visitModuleHashes(ModuleHashes_attribute attr, T p) {
return null; return null;
} }
@ -1263,7 +1263,7 @@ public class ClassfileInspector {
} }
@Override @Override
public Void visitMainClass(MainClass_attribute attr, T p) { public Void visitModuleMainClass(ModuleMainClass_attribute attr, T p) {
return null; return null;
} }
@ -1343,12 +1343,12 @@ public class ClassfileInspector {
} }
@Override @Override
public Void visitTargetPlatform(TargetPlatform_attribute attr, T p) { public Void visitModuleTarget(ModuleTarget_attribute attr, T p) {
return null; return null;
} }
@Override @Override
public Void visitVersion(Version_attribute attr, T p) { public Void visitModuleVersion(ModuleVersion_attribute attr, T p) {
return null; return null;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,7 @@
* @modules jdk.compiler/com.sun.tools.javac.file * @modules jdk.compiler/com.sun.tools.javac.file
* jdk.compiler/com.sun.tools.javac.parser * jdk.compiler/com.sun.tools.javac.parser
* jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util * jdk.compiler/com.sun.tools.javac.util:+open
*/ */
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.io.InputStream; import java.io.InputStream;

View file

@ -27,7 +27,7 @@
* @summary REGRESSION: javac crashes if -d or -s argument is a file * @summary REGRESSION: javac crashes if -d or -s argument is a file
* @author Peter von der Ah\u00e9 * @author Peter von der Ah\u00e9
* @modules java.compiler * @modules java.compiler
* jdk.compiler/com.sun.tools.javac.util * jdk.compiler/com.sun.tools.javac.util:open
*/ */
import java.lang.reflect.Field; import java.lang.reflect.Field;

View file

@ -26,7 +26,7 @@
* @bug 8006582 * @bug 8006582
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @modules jdk.jdeps/com.sun.tools.classfile * @modules jdk.jdeps/com.sun.tools.classfile
* @build MethodParametersTester * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
* @compile -parameters AnnotationTest.java * @compile -parameters AnnotationTest.java
* @run main MethodParametersTester AnnotationTest AnnotationTest.out * @run main MethodParametersTester AnnotationTest AnnotationTest.out
*/ */

Some files were not shown because too many files have changed in this diff Show more