Skip to content

Commit

Permalink
support aspect template for Python (bazelbuild#7011)
Browse files Browse the repository at this point in the history
  • Loading branch information
xuansontrinh authored and Tomasz Pasternak committed Nov 25, 2024
1 parent c312307 commit 05d4f57
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
10 changes: 6 additions & 4 deletions aspect/intellij_info_impl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ load(":flag_hack.bzl", "FlagHackInfo")

load("@intellij_aspect_template//:java_info.bzl", "get_java_info", "java_info_in_target", "java_info_reference")

load("@intellij_aspect_template//:python_info.bzl", "get_py_info", "py_info_in_target")

load("@intellij_aspect_template//:code_generator_info.bzl", "CODE_GENERATOR_RULE_NAMES")

load(
Expand Down Expand Up @@ -341,7 +343,7 @@ def _do_starlark_string_expansion(ctx, name, strings, extra_targets = []):

def collect_py_info(target, ctx, semantics, ide_info, ide_info_file, output_groups):
"""Updates Python-specific output groups, returns false if not a Python target."""
if not PyInfo in target or _is_language_specific_proto_library(ctx, target, semantics):
if not py_info_in_target(target) or _is_language_specific_proto_library(ctx, target, semantics):
return False

py_semantics = getattr(semantics, "py", None)
Expand All @@ -351,7 +353,7 @@ def collect_py_info(target, ctx, semantics, ide_info, ide_info_file, output_grou
py_launcher = None

sources = sources_from_target(ctx)
to_build = target[PyInfo].transitive_sources
to_build = get_py_info(target).transitive_sources
args = getattr(ctx.rule.attr, "args", [])
data_deps = getattr(ctx.rule.attr, "data", [])
args = _do_starlark_string_expansion(ctx, "args", args, data_deps)
Expand Down Expand Up @@ -397,14 +399,14 @@ def collect_py_info(target, ctx, semantics, ide_info, ide_info_file, output_grou
def provider_imports_to_attr_imports():
result = []

for provider_import in target[PyInfo].imports.to_list():
for provider_import in get_py_info(target).imports.to_list():
attr_import = provider_import_to_attr_import(provider_import)
if attr_import:
result.append(attr_import)

return result

if target[PyInfo].imports:
if get_py_info(target).imports:
imports.extend(provider_imports_to_attr_imports())

runfiles = target[DefaultInfo].default_runfiles
Expand Down
9 changes: 9 additions & 0 deletions aspect_template/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ filegroup(
"code_generator_info.template.bzl",
"java_info.bzl",
"java_info.template.bzl",
"python_info.bzl",
"python_info.template.bzl"
],
visibility = ["//visibility:public"],
)
Expand All @@ -23,6 +25,13 @@ genrule(
cmd = STRIP_TEMPLATE_SCRIPT,
)

genrule(
name = "generate_py_info_template",
srcs = ["python_info.bzl"],
outs = ["python_info.template.bzl"],
cmd = STRIP_TEMPLATE_SCRIPT,
)

genrule(
name = "generate_code_generator_info_template",
srcs = ["code_generator_info.bzl"],
Expand Down
37 changes: 37 additions & 0 deletions aspect_template/python_info.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# TEMPLATE-INCLUDE-BEGIN
###if( $isPythonEnabled == "true" && $bazel8OrAbove == "true" )
##load("@rules_python//python:defs.bzl", "PyInfo")
###end
# TEMPLATE-INCLUDE-END

def py_info_in_target(target):
# TEMPLATE-IGNORE-BEGIN
return PyInfo in target
# TEMPLATE-IGNORE-END

# TEMPLATE-INCLUDE-BEGIN
## #if( $isPythonEnabled == "true" )
## return PyInfo in target
## #else
## return None
## #end
# TEMPLATE-INCLUDE-END

def get_py_info(target):
# TEMPLATE-IGNORE-BEGIN
if PyInfo in target:
return target[PyInfo]
else:
return None
# TEMPLATE-IGNORE-END

# TEMPLATE-INCLUDE-BEGIN
## #if( $isPythonEnabled == "true" )
## if PyInfo in target:
## return target[PyInfo]
## else:
## return None
## #else
## return None
## #end
# TEMPLATE-INCLUDE-END
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class SyncAspectTemplateProvider implements SyncListener {

private final static String TEMPLATE_JAVA = "java_info.template.bzl";
private final static String REALIZED_JAVA = "java_info.bzl";
private final static String TEMPLATE_PYTHON = "python_info.template.bzl";
private final static String REALIZED_PYTHON = "python_info.bzl";
private final static String TEMPLATE_CODE_GENERATOR = "code_generator_info.template.bzl";
private final static String REALIZED_CODE_GENERATOR = "code_generator_info.bzl";

Expand Down Expand Up @@ -77,7 +79,7 @@ private void prepareProjectAspect(Project project) throws SyncFailedException {
final var templateAspects = AspectRepositoryProvider.findAspectTemplateDirectory()
.orElseThrow(() -> new SyncFailedException("Couldn't find aspect template directory"));

writeJavaInfo(manager, realizedAspectsPath, templateAspects, project);
writeLanguageInfos(manager, realizedAspectsPath, templateAspects, project);
writeCodeGeneratorInfo(manager, project, realizedAspectsPath, templateAspects);
}

Expand Down Expand Up @@ -105,29 +107,45 @@ private void writeCodeGeneratorInfo(
}
}

private void writeJavaInfo(
private void writeLanguageInfos(
BlazeProjectDataManager manager,
Path realizedAspectsPath,
File templateAspects, Project project) throws SyncFailedException {
var realizedFile = realizedAspectsPath.resolve(REALIZED_JAVA);
File templateAspects,
Project project) throws SyncFailedException {
var templateLanguageStringMap = getLanguageStringMap(manager, project);
writeLanguageInfo(manager, realizedAspectsPath, templateAspects, TEMPLATE_JAVA, REALIZED_JAVA, templateLanguageStringMap);
writeLanguageInfo(manager, realizedAspectsPath, templateAspects, TEMPLATE_PYTHON, REALIZED_PYTHON, templateLanguageStringMap);
}

private void writeLanguageInfo(
BlazeProjectDataManager manager,
Path realizedAspectsPath,
File templateAspects,
String templateFileName,
String realizedFileName,
Map<String, String> templateLanguageStringMap) throws SyncFailedException {
var realizedFile = realizedAspectsPath.resolve(realizedFileName);
var templateWriter = new TemplateWriter(templateAspects.toPath());
var templateVariableMap = getJavaStringStringMap(manager, project);
if (!templateWriter.writeToFile(TEMPLATE_JAVA, realizedFile, templateVariableMap)) {
throw new SyncFailedException("Could not create template for: " + REALIZED_JAVA);
if (!templateWriter.writeToFile(templateFileName, realizedFile, templateLanguageStringMap)) {
throw new SyncFailedException("Could not create template for: " + realizedFileName);
}
}

private static @NotNull Map<String, String> getJavaStringStringMap(BlazeProjectDataManager manager, Project project) throws SyncFailedException {
private static @NotNull Map<String, String> getLanguageStringMap(BlazeProjectDataManager manager, Project project) {
var projectData = Optional.ofNullable(manager.getBlazeProjectData()); // It can be empty on intial sync. Fall back to no lauguage support
var blazeProjectData = BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
var activeLanguages = projectData.map(it -> it.getWorkspaceLanguageSettings().getActiveLanguages()).orElse(ImmutableSet.of());
var isJavaEnabled = activeLanguages.contains(LanguageClass.JAVA)
&& blazeProjectData != null
&& blazeProjectData.getExternalWorkspaceData().getByRepoName("rules_java") != null;
var isPythonEnabled = activeLanguages.contains(LanguageClass.PYTHON)
&& blazeProjectData != null
&& blazeProjectData.getExternalWorkspaceData().getByRepoName("rules_python") != null;
var isAtLeastBazel8 = projectData.map(it -> it.getBlazeVersionData().bazelIsAtLeastVersion(8, 0, 0)).orElse(false);
return Map.of(
"bazel8OrAbove", isAtLeastBazel8 ? "true" : "false",
"isJavaEnabled", isJavaEnabled ? "true" : "false"
"isJavaEnabled", isJavaEnabled ? "true" : "false",
"isPythonEnabled", isPythonEnabled ? "true" : "false"
);
}

Expand Down

0 comments on commit 05d4f57

Please sign in to comment.