Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions make/CompileJavaModules.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,28 @@ $(eval $(call SetupJavaCompilation, $(MODULE), \
TARGETS += $($(MODULE))

################################################################################
# Setup compilation for value classes in the module
# Setup compilation for preview classes in the module
# TBD: When $(DOCLINT) was included there was an NPE in JavacTypes.getOverriddenMethods

# Directory and file name suffix for jar file containing value classes
VALUECLASSES_STR := valueclasses
# Directory and file name suffix for jar file containing preview classes/resources.
PREVIEW_CLASSES_LABEL := preview
# Module relative path in which preview classes/resources are placed.
PREVIEW_PATH := META-INF/preview

ifneq ($(COMPILER), bootjdk)
MODULE_VALUECLASS_SRC_DIRS := $(call FindModuleValueClassSrcDirs, $(MODULE))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of this is unrelated to annotation processing per se, just renaming "value class" stuff when it's really just "preview" stuff more generally.

MODULE_VALUECLASS_SOURCEPATH := $(call GetModuleValueClassSrcPath)
ifneq ($(MODULE_VALUECLASS_SRC_DIRS),)
# Temporarily compile valueclasses into a separate directory, and then copy
# into the correct "META-INF/preview" path location.
MODULE_PREVIEW_SRC_DIRS := $(call FindModulePreviewSrcDirs, $(MODULE))
MODULE_PREVIEW_SOURCEPATH := $(call GetModulePreviewSrcPath)
ifneq ($(MODULE_PREVIEW_SRC_DIRS),)
# Temporarily compile preview classes into a separate directory, and then
# copy into the correct output path location.
# We cannot compile directly into the desired directory because it's the
# compiler which creates the original '<module>/<classpath>/...' hierarchy.
TEMP_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/$(VALUECLASSES_STR)
TEMP_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/$(PREVIEW_CLASSES_LABEL)

$(eval $(call SetupJavaCompilation, $(MODULE)-$(VALUECLASSES_STR), \
$(eval $(call SetupJavaCompilation, $(MODULE)-$(PREVIEW_CLASSES_LABEL), \
SMALL_JAVA := false, \
MODULE := $(MODULE), \
SRC := $(wildcard $(MODULE_VALUECLASS_SRC_DIRS)), \
SRC := $(wildcard $(MODULE_PREVIEW_SRC_DIRS)), \
INCLUDES := $(JDK_USER_DEFINED_FILTER), \
FAIL_NO_SRC := $(FAIL_NO_SRC), \
BIN := $(TEMP_OUTPUTDIR)/, \
Expand All @@ -160,32 +162,34 @@ ifneq ($(COMPILER), bootjdk)
EXCLUDE_FILES := $(EXCLUDE_FILES) \
KEEP_ALL_TRANSLATIONS := $(KEEP_ALL_TRANSLATIONS), \
DEPENDS := $($(MODULE)), \
PROCESSOR_PATH := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New argument to add to the default path containing /depend dir.

JAVAC_FLAGS := \
$(JAVAC_FLAGS) \
--module-source-path $(MODULE_VALUECLASS_SOURCEPATH) \
--module-source-path $(MODULE_PREVIEW_SOURCEPATH) \
--module-path $(JDK_OUTPUTDIR)/modules \
--system none \
--enable-preview -source $(JDK_SOURCE_TARGET_VERSION), \
--enable-preview -source $(JDK_SOURCE_TARGET_VERSION) \
-processor build.tools.valueclasses.GenValueClassList, \
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just this 1 line triggers the new (unwanted) warnings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding -Xlint:-removal \ on the line above this make compilation work.

))

# Don't add '$($(MODULE)-$(VALUECLASSES_STR))' to TARGETS (it's transient).
# The 'valueclasses' target below depends on it, and that's the non-transient
# Don't add '$($(MODULE)-$(PREVIEW_CLASSES_LABEL))' to TARGETS (it's transient).
# The 'preview' target below depends on it, and that's the non-transient
# result we care about.

# Copy compiled output from "$TEMP_OUTPUTDIR/$MODULE/<classpath>/..."
# to "$COMPILATION_OUTPUTDIR/$MODULE/META-INF/preview/<classpath>/...".
# to "$COMPILATION_OUTPUTDIR/$MODULE/$PREVIEW_PATH/<classpath>/...".
MOD_SRC := $(TEMP_OUTPUTDIR)/$(MODULE)
MOD_DST := $(COMPILATION_OUTPUTDIR)/$(MODULE)

# NOTE: We cannot use '$(CP) -R $(MOD_SRC)/*/ ...' to select sub-directories (it
# does not work on MacOS/BSD). Use 'filter-out' to explicitly exclude marker files.
$(MOD_DST)/_the.$(MODULE).valueclasses: $($(MODULE)-$(VALUECLASSES_STR))
$(RM) -r $(@D)/META-INF/preview
$(MKDIR) -p $(@D)/META-INF/preview
$(CP) -R $(filter-out $(MOD_SRC)/_%, $(wildcard $(MOD_SRC)/*)) $(@D)/META-INF/preview
$(MOD_DST)/_the.$(MODULE).preview: $($(MODULE)-$(PREVIEW_CLASSES_LABEL))
$(RM) -r $(@D)/$(PREVIEW_PATH)
$(MKDIR) -p $(@D)/$(PREVIEW_PATH)
$(CP) -R $(filter-out $(MOD_SRC)/_%, $(wildcard $(MOD_SRC)/*)) $(@D)/$(PREVIEW_PATH)
$(TOUCH) $@

TARGETS += $(MOD_DST)/_the.$(MODULE).valueclasses
TARGETS += $(MOD_DST)/_the.$(MODULE).preview
endif
endif

Expand Down
7 changes: 6 additions & 1 deletion make/common/JavaCompilation.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,18 @@ define SetupJavaCompilationBody
# including the compilation output on the classpath, so that incremental
# compilations in unnamed module can refer to other classes from the same
# source root, which are not being recompiled in this compilation:
$1_AUGMENTED_CLASSPATH += $$(BUILDTOOLS_OUTPUTDIR)/depend $$($1_BIN)
$1_AUGMENTED_CLASSPATH += $$($1_BIN)
$1_PROCESSOR_PATH += $$(BUILDTOOLS_OUTPUTDIR)/depend
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to work if the /depend dir is no longer also in the augmented classpath.
I don't think order matters here (the user path is first).

endif

ifneq ($$($1_AUGMENTED_CLASSPATH), )
$1_FLAGS += -cp $$(call PathList, $$($1_AUGMENTED_CLASSPATH))
endif

ifneq ($$($1_PROCESSOR_PATH), )
$1_FLAGS += --processor-path $$(call PathList, $$($1_PROCESSOR_PATH))
endif

# Make sure the dirs exist, or that one of the EXTRA_FILES, that may not
# exist yet, is in it.
$$(foreach d, $$($1_SRC), \
Expand Down
10 changes: 6 additions & 4 deletions make/common/Modules.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ FindModuleSrcDirs = \
$(addsuffix /$(strip $1), $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
$(foreach sub, $(SRC_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))

# Find value class source dirs for a particular module (only generated)
# Find preview class source dirs for a particular module.
# Currently this is restricted to generated value classes, but can be extended.
# $1 - Module to find source dirs for
FindModuleValueClassSrcDirs = \
FindModulePreviewSrcDirs = \
$(strip $(wildcard \
$(addsuffix /$(strip $1), $(GENERATED_VALUE_CLASS_SUBDIRS))))

Expand All @@ -176,8 +177,9 @@ GetModuleSrcPath = \
$(addsuffix /*, $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
$(foreach sub, $(SRC_SUBDIRS), $(addsuffix /*/$(sub), $(TOP_SRC_DIRS))))

# Construct the complete module source path for value classes
GetModuleValueClassSrcPath = \
# Construct the complete module source path for preview classes.
# Currently this is restricted to generated value classes, but can be extended.
GetModulePreviewSrcPath = \
$(call PathList, \
$(addsuffix /*, $(GENERATED_VALUE_CLASS_SUBDIRS) $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
$(foreach sub, $(SRC_SUBDIRS), $(addsuffix /*/$(sub), $(TOP_SRC_DIRS))))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package build.tools.valueclasses;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;

/**
* <ul>
* <li>{@code @jdk.internal.ValueBased} appears on concrete value classes.
* <li>{@code @jdk.internal.MigratedValueClass} appears on concrete and abstract value classes.
* </ul>
*/
@SupportedAnnotationTypes({"jdk.internal.*"})
public final class GenValueClassList extends AbstractProcessor {
/**
* Override to return latest version, since the runtime in which this is
* compiled doesn't know about development source versions.
*/
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
// We don't have direct access to ValueBased or MigratedValueClass
// classes here, but we can find the matching type elements.
Optional<? extends TypeElement> migratedValueClass =
getAnnotation(annotations, "jdk.internal.MigratedValueClass");
Optional<? extends TypeElement> valueBased =
getAnnotation(annotations, "jdk.internal.ValueBased");
if (migratedValueClass.isPresent() && valueBased.isPresent()) {
Set<String> valueClasses = getAnnotatedTypeNames(env, migratedValueClass.get());
Set<String> abstractClasses = getAnnotatedTypeNames(env, valueBased.get());
//valueClasses.forEach(n -> System.out.format("---> %s (%s)", n, abstractClasses.contains(n) ? "abstract" : "concrete"));
}
return true;
}

private static Optional<? extends TypeElement> getAnnotation(Set<? extends TypeElement> annotations, String name) {
return annotations.stream()
.filter(e -> e.getQualifiedName().toString().equals(name))
.findFirst();
}

private static Set<String> getAnnotatedTypeNames(RoundEnvironment env, TypeElement annotation) {
Set<String> typeNames = new TreeSet<>();
for (Element e : env.getElementsAnnotatedWith(annotation)) {
if (!e.getKind().isClass()) {
throw new IllegalStateException(
"Unexpected element kind (" + e.getKind() + ") for element: " + e);
}
Name fqn = ((TypeElement) e).getQualifiedName();
if (fqn.isEmpty()) {
throw new IllegalStateException(
"Unexpected empty name for element: " + e);
}
typeNames.add(fqn.toString());
}
return typeNames;
}
}