|
| 1 | +""" |
| 2 | +Bazel aspect to run scip-java against a Java Bazel codebase. |
| 3 | +
|
| 4 | +You can optionally commit this file into your git repository, gitignore it, or |
| 5 | +just delete it. When you run `scip-java index` in a Bazel codebase, this file |
| 6 | +will get re-created and the command will error if the file already exists but with |
| 7 | +different contents. |
| 8 | +
|
| 9 | +This aspect is needed for scip-java to inspect the structure of the Bazel build |
| 10 | +and register actions to index all java_library/java_test/java_binary targets. |
| 11 | +The result of running this aspect is that your bazel-bin/ directory will contain |
| 12 | +many *.scip (https://github.com/sourcegraph/scip) and |
| 13 | +*.semanticdb (https://scalameta.org/docs/semanticdb/specification.html) files. |
| 14 | +These files encode information about which symbols are referenced from which |
| 15 | +locations in your source code. |
| 16 | +
|
| 17 | +This aspect only works on Linux when using the `local` spawn strategy because |
| 18 | +the `run_shell` action writes SemanticDB and SCIP files to the provided |
| 19 | +--targetroot argument. It should be possible to avoid this requirement |
| 20 | +in the future if there's a strong desire to make the aspect work with the |
| 21 | +default (sandboxed) spawn strategy. |
| 22 | +
|
| 23 | +Use the command below to merge all of these SCIP files into a single index: |
| 24 | +
|
| 25 | + find bazel-bin/ -type f -name '*.scip' | xargs cat > index.scip |
| 26 | +
|
| 27 | +Use `src code-intel upload` to upload the unified SCIP file to Sourcegraph: |
| 28 | +
|
| 29 | + npm install -g @sourcegraph/src |
| 30 | + export SRC_ENDPOINT=SOURCEGRAPH_URL |
| 31 | + export SRC_ACCESS_TOKEN=TOKEN_VALUE |
| 32 | + src login # confirm you are correctly authenticated |
| 33 | + src code-intel upload -file=index.scip |
| 34 | +
|
| 35 | +Example command to run this aspect directly: |
| 36 | +
|
| 37 | + bazel build //... --spawn_strategy=local --aspects path/to/scip_java.bzl%scip_java_aspect --output_groups=scip --define=sourceroot=$(pwd) --define=scip_java_binary=$(which scip-java) --define=java_home=$JAVA_HOME |
| 38 | +
|
| 39 | +To learn more about aspects: https://bazel.build/extending/aspects |
| 40 | +""" |
| 41 | + |
| 42 | +def _scip_java(target, ctx): |
| 43 | + if JavaInfo not in target or not hasattr(ctx.rule.attr, "srcs"): |
| 44 | + return None |
| 45 | + |
| 46 | + javac_action = None |
| 47 | + for a in target.actions: |
| 48 | + if a.mnemonic == "Javac": |
| 49 | + javac_action = a |
| 50 | + break |
| 51 | + |
| 52 | + if not javac_action: |
| 53 | + return None |
| 54 | + |
| 55 | + info = target[JavaInfo] |
| 56 | + compilation = info.compilation_info |
| 57 | + annotations = info.annotation_processing |
| 58 | + |
| 59 | + source_files = [] |
| 60 | + for src in ctx.rule.files.srcs: |
| 61 | + source_files.append(src.path) |
| 62 | + if len(source_files) == 0: |
| 63 | + return None |
| 64 | + |
| 65 | + classpath = [j.path for j in compilation.compilation_classpath.to_list()] |
| 66 | + bootclasspath = [j.path for j in compilation.boot_classpath] |
| 67 | + |
| 68 | + processorpath = [] |
| 69 | + processors = [] |
| 70 | + if annotations and annotations.enabled: |
| 71 | + processorpath += [j.path for j in annotations.processor_classpath.to_list()] |
| 72 | + processors = annotations.processor_classnames |
| 73 | + |
| 74 | + build_config = struct(**{ |
| 75 | + "javaHome": ctx.var["java_home"], |
| 76 | + "classpath": classpath, |
| 77 | + "sourceFiles": source_files, |
| 78 | + "javacOptions": compilation.javac_options, |
| 79 | + "processors": processors, |
| 80 | + "processorpath": processorpath, |
| 81 | + "bootclasspath": bootclasspath, |
| 82 | + "reportWarningOnEmptyIndex": False, |
| 83 | + }) |
| 84 | + build_config_path = ctx.actions.declare_file(ctx.label.name + ".scip.json") |
| 85 | + |
| 86 | + scip_output = ctx.actions.declare_file(ctx.label.name + ".scip") |
| 87 | + targetroot = ctx.actions.declare_directory(ctx.label.name + ".semanticdb") |
| 88 | + ctx.actions.write( |
| 89 | + output = build_config_path, |
| 90 | + content = build_config.to_json(), |
| 91 | + ) |
| 92 | + |
| 93 | + deps = [javac_action.inputs, annotations.processor_classpath] |
| 94 | + ctx.actions.run_shell( |
| 95 | + command = "\"{}\" index --no-cleanup --index-semanticdb.allow-empty-index --cwd \"{}\" --targetroot {} --scip-config \"{}\" --output \"{}\"".format( |
| 96 | + ctx.var["scip_java_binary"], |
| 97 | + ctx.var["sourceroot"], |
| 98 | + targetroot.path, |
| 99 | + build_config_path.path, |
| 100 | + scip_output.path, |
| 101 | + ), |
| 102 | + env = { |
| 103 | + "JAVA_HOME": ctx.var["java_home"], |
| 104 | + "NO_PROGRESS_BAR": "true", |
| 105 | + }, |
| 106 | + inputs = depset([build_config_path], transitive = deps), |
| 107 | + outputs = [scip_output, targetroot], |
| 108 | + ) |
| 109 | + |
| 110 | + return scip_output |
| 111 | + |
| 112 | +def _scip_java_aspect(target, ctx): |
| 113 | + scip = _scip_java(target, ctx) |
| 114 | + if not scip: |
| 115 | + return struct() |
| 116 | + return [OutputGroupInfo(scip = [scip])] |
| 117 | + |
| 118 | +scip_java_aspect = aspect( |
| 119 | + _scip_java_aspect, |
| 120 | +) |
| 121 | + |
| 122 | +def _scip_java_impl(ctx): |
| 123 | + output = ctx.attr.compilation[OutputGroupInfo] |
| 124 | + return [ |
| 125 | + OutputGroupInfo(scip = output.scip), |
| 126 | + DefaultInfo(files = output.scip), |
| 127 | + ] |
| 128 | + |
| 129 | +scip_java = rule( |
| 130 | + implementation = _scip_java_impl, |
| 131 | + attrs = {"compilation": attr.label(aspects = [scip_java_aspect])}, |
| 132 | +) |
0 commit comments