Skip to content

Commit 078cbcd

Browse files
authored
Merge pull request #112 from olafurpg/documentation-website
2 parents 756563f + fe6bfdb commit 078cbcd

File tree

28 files changed

+944
-200
lines changed

28 files changed

+944
-200
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- uses: olafurpg/setup-scala@v10
1313
- uses: actions/setup-go@v2
1414
with:
15-
go-version: '^1.13.1'
15+
go-version: "^1.13.1"
1616
- run: go get github.com/sourcegraph/lsif-semanticdb/cmd/lsif-semanticdb
1717
- run: sbt test
1818
check:

.github/workflows/mdoc.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: Website
2+
on:
3+
push:
4+
branches: [master, documentation-website]
5+
tags: ["*"]
6+
jobs:
7+
publish:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- uses: olafurpg/setup-scala@v10
12+
- run: sbt docs/docusaurusPublishGhpages
13+
env:
14+
GIT_DEPLOY_KEY: ${{ secrets.GIT_DEPLOY_KEY }}

.github/workflows/native.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
- name: sbt nativeImage
3131
shell: bash
3232
run: |
33-
sbt cli/nativeImage "cli/nativeImageRun --cwd tests/gradle-example"
33+
sbt cli/nativeImage "cli/nativeImageRun --cwd tests/gradle-example index"
3434
- uses: actions/upload-artifact@master
3535
with:
3636
path: ${{ matrix.local_path }}

CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Contributing guide
2+
3+
See https://sourcegraph.github.io/lsif-java/docs/contributing.html

README.md

Lines changed: 9 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,9 @@
1-
# Java LSIF indexer ![](https://img.shields.io/badge/status-development-yellow?style=flat)
2-
3-
Visit https://lsif.dev/ to learn about LSIF.
4-
5-
## Usage
6-
7-
⚠️ This project is under development so there is nothing to try out at the
8-
moment.
9-
10-
### Supported tools and versions
11-
12-
Currently, only Java 8 with the build tool sbt is supported. We hope to increase
13-
compatibility with more Java language versions and build tools as the project
14-
evolves.
15-
16-
| Language version | Support |
17-
| ---------------- | --------------------------------- |
18-
| Java 7 ||
19-
| Java 8 ||
20-
| Java 11 ||
21-
| Java 12 | Not tested in CI, but should work |
22-
| Java 13 | Not tested in CI, but should work |
23-
| Java 14 | Not tested in CI, but should work |
24-
| Java 15 ||
25-
| Java 16 | Not tested in CI, but should work |
26-
| Java 17 | Not tested in CI, but should work |
27-
28-
| Build tool | Support |
29-
| ---------- | ------- |
30-
| Gradle ||
31-
| Maven ||
32-
| Bazel ||
33-
| Buck ||
34-
| sbt ||
35-
36-
## Overview
37-
38-
This project is implemented as a
39-
[Java compiler plugin](https://docs.oracle.com/en/java/javase/11/docs/api/jdk.compiler/com/sun/source/util/Plugin.html)
40-
that generates one
41-
[SemanticDB](https://scalameta.org/docs/semanticdb/specification.html) file for
42-
every `*.java` source file. After compilation completes, the SemanticDB files
43-
are processed to produce LSIF.
44-
45-
![A three stage pipeline that starts with a list of Java sources, creates a list of SemanticDB files that then become a single LSIF index.](docs/img/semanticdb-javac-pipeline.svg)
46-
47-
### Why Java compiler plugin?
48-
49-
There are several benefits to implementing lsif-java as a compiler plugin:
50-
51-
- **Simple installation**: compiler plugins are enabled with the `-Xplugin`
52-
compiler option. All Java build tools support a way to customize compiler
53-
options, simplifying installation.
54-
- **Language fidelity**: by using the Java compiler to produce semantic
55-
information, we ensure that the produced LSIF data is accurate even as new
56-
Java language versions with new language features are released.
57-
- **Environment fidelity**: by hooking into the compilation process of the build
58-
tool, we minimize the risk of diverging from the CI build environment such as
59-
installed system dependencies, custom compiler options and custom annotation
60-
processors.
61-
62-
### Why SemanticDB?
63-
64-
SemanticDB is Protobuf schema for information about symbols and types in Java
65-
programs, Scala programs and other languages. There are several benefits to
66-
using SemanticDB as an intermediary representation for LSIF:
67-
68-
- **Simplicity**: It's easy to translate a single Java source file into a single
69-
SemanticDB file inside a compiler plugin. It's more complicated to produce
70-
LSIF because compiler plugins does not have access to a project-wide context,
71-
which is necessary to produce accurate definitions and hovers in multi-module
72-
projects with external library dependencies.
73-
- **Performance**: SemanticDB is fast to write and read. Each compilation unit
74-
can be processed independently to keep memory usage low. The final conversion
75-
from SemanticDB to LSIF can be safely parallelized.
76-
- **Cross-language**: SemanticDB has a
77-
[spec](https://scalameta.org/docs/semanticdb/specification.html) for Java and
78-
Scala enabling cross-language navigation in hybrid Java/Scala codebases.
79-
- **Cross-repository**: Compiler plugins have access to both source code and the
80-
classpath (compiled bytecode of upstream dependencies). SemanticDB has been
81-
designed so that it's also possible to generate spec-compliant symbols from
82-
the classpath alone (no source code) and from the syntax tree of an individual
83-
source file (no classpath). This flexibility allows the
84-
[Metals](https://scalameta.org/metals/) language server to index codebases
85-
from a variety of different inputs, and will be helpful for lsif-java in the
86-
future to unblock cross-repository navigation.
87-
88-
## Contributing
89-
90-
The following sections provide tips on how to contribute to this codebase.
91-
92-
### System dependencies
93-
94-
- `java`: any version should work
95-
- `git`: any version should work
96-
- `lsif-semanticdb`:
97-
`go get github.com/sourcegraph/lsif-semanticdb/cmd/lsif-semanticdb`
98-
- `gradle`: `brew install gradle`, or see
99-
[general installation guide](https://gradle.org/install/).
100-
- `mvn`: `brew install maven`, or see
101-
[general installation guide](https://www.baeldung.com/install-maven-on-windows-linux-mac).
102-
103-
### Project structure
104-
105-
These are the main components of the project.
106-
107-
- `semanticdb-javac/src/main/java`: the Java compiler plugin that creates
108-
SemanticDB files.
109-
- `tests/minimized`: minimized Java source files that reproduce interesting test
110-
cases.
111-
- `tests/unit`: fast running unit tests that are helpful for local edit-and-test
112-
workflows.
113-
- `tests/snapshots`: slow running
114-
["snapshot tests"](https://jestjs.io/docs/en/snapshot-testing) that index a
115-
corpus of published Java libraries.
116-
- `build.sbt`: the sbt build definition.
117-
- `project/plugins.sbt`: plugins for the sbt build.
118-
119-
### Helpful commands
120-
121-
| Command | Where | Description |
122-
| ------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------- |
123-
| `./sbt` | terminal | Start interactive sbt shell with Java 11. Takes a while to load on the first run. |
124-
| `unit/test` | sbt | Run fast unit tests. |
125-
| `~unit/test` | sbt | Start watch mode to run tests on file save, good for local edit-and-test workflows. |
126-
| `buildTools/test` | sbt | Run slow build tool tests (Gradle, Maven). |
127-
| `snapshots/testOnly tests.MinimizedSnapshotSuite` | sbt | Runs fast snapshot tests. Indexes a small set of files under `tests/minimized`. |
128-
| `snapshots/testOnly tests.MinimizedSnapshotSuite -- *InnerClasses*` | sbt | Runs only individual tests cases matching the name "InnerClasses". |
129-
| `snapshots/testOnly tests.LibrarySnapshotSuite` | sbt | Runs slow snapshot tests. Indexes a corpus of external Java libraries. |
130-
| `snapshots/test` | sbt | Runs all snapshot tests. |
131-
| `snapshots/run` | sbt | Update snapshot tests. Use this command after you have fixed a bug. |
132-
| `cli/run --cwd DIRECTORY` | sbt | Run `lsif-java` command-line tool against a given Gradle/Maven build. |
133-
| `fixAll` | sbt | Run Scalafmt, Scalafix and Javafmt on all sources. Run this before opening a PR. |
134-
135-
### Import the project into IntelliJ
136-
137-
It's recommended to use IntelliJ when editing code in this codebase.
138-
139-
First, install the
140-
[IntelliJ Community Edition](https://www.jetbrains.com/idea/download/). The
141-
community edition is
142-
[open source](https://github.com/JetBrains/intellij-community) and free to use.
143-
144-
Next, install the IntelliJ Scala plugin.
145-
146-
Finally, run "File > Project From Existing Sources" to import the sbt build into
147-
IntelliJ. Select the "sbt" option if it asks you to choose between
148-
sbt/BSP/Bloop.
149-
150-
It's best to run tests from the sbt shell, not from the IntelliJ UI.
151-
152-
### Don't use VS Code/Vim/Sublime Text/Emacs
153-
154-
If you want to use completions and precise code navigation, it's not recommended
155-
to use other editors than IntelliJ. IntelliJ is the only IDE that properly
156-
supports hybrid Java/Scala codebases at the moment, although that may change
157-
soon thanks to lsif-java :)
158-
159-
### Tests are written in Scala
160-
161-
This codebases uses the Scala library [MUnit](https://scalameta.org/munit/) to
162-
write tests because:
163-
164-
- MUnit has built-in assertions that print readable multiline diffs in color.
165-
- MUnit makes it easy to implement
166-
[snapshot testing](https://jestjs.io/docs/en/snapshot-testing), which is a
167-
testing technique that's heavily used in this codebase.
168-
- Multiline literal strings in Scala make it easy to write unit tests for source
169-
code (which is always multiline). Modern versions of Java support multiline
170-
string literals, but they're not supported in Java 8, which is supported by
171-
lsif-java.
172-
173-
## Benchmarks
174-
175-
See [docs/benchmarks.md] for benchmark results.
1+
# Java indexer for the Language Server Index Format (LSIF) ![](https://img.shields.io/badge/status-development-yellow?style=flat)
2+
3+
| Documentation | Link |
4+
| -------------------- | ---------------------------------------------------------------------- |
5+
| Landing page | https://sourcegraph.github.io/lsif-java |
6+
| Getting started | https://sourcegraph.github.io/lsif-java/docs/getting-started.html |
7+
| Manual configuration | https://sourcegraph.github.io/lsif-java/docs/manual-configuration.html |
8+
| Contributing | https://sourcegraph.github.io/lsif-java/docs/contributing.html |
9+
| Design | https://sourcegraph.github.io/lsif-java/docs/design.html |

build.sbt

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import scala.xml.{Node => XmlNode, NodeSeq => XmlNodeSeq, _}
2+
import scala.xml.transform.{RewriteRule, RuleTransformer}
13
import java.io.File
24
import java.util.Properties
35
import scala.collection.mutable.ListBuffer
@@ -59,7 +61,7 @@ commands +=
5961
commands +=
6062
Command.command("checkAll") { s =>
6163
"scalafmtCheckAll" :: "scalafmtSbtCheck" :: "scalafixAll --check" ::
62-
"javafmtCheckAll" :: "publishLocal" :: s
64+
"javafmtCheckAll" :: "publishLocal" :: "docs/docusaurusCreateSite" :: s
6365
}
6466

6567
lazy val agent = project
@@ -97,6 +99,16 @@ lazy val plugin = project
9799
old.withEnabled(false)
98100
},
99101
fatjarPackageSettings,
102+
assemblyShadeRules.in(assembly) :=
103+
Seq(
104+
ShadeRule
105+
.rename(
106+
"com.google.**" -> "com.sourcegraph.shaded.com.google.@1",
107+
"google.**" -> "com.sourcegraph.shaded.google.@1",
108+
"org.relaxng.**" -> "com.sourcegraph.shaded.relaxng.@1"
109+
)
110+
.inAll
111+
),
100112
crossPaths := false,
101113
PB.targets.in(Compile) :=
102114
Seq(PB.gens.java -> (Compile / sourceManaged).value)
@@ -280,7 +292,7 @@ lazy val fatjarPackageSettings = List[Def.Setting[_]](
280292
case PathList("sun", _ @_*) =>
281293
MergeStrategy.discard
282294
case PathList("META-INF", "versions", "9", "module-info.class") =>
283-
MergeStrategy.first
295+
MergeStrategy.discard
284296
case x =>
285297
val oldStrategy = (assemblyMergeStrategy in assembly).value
286298
oldStrategy(x)
@@ -291,5 +303,48 @@ lazy val fatjarPackageSettings = List[Def.Setting[_]](
291303
val _ = assembly.value
292304
IO.copyFile(fatJar, slimJar, CopyOptions().withOverwrite(true))
293305
slimJar
306+
},
307+
packagedArtifact.in(Compile).in(packageBin) := {
308+
val (art, slimJar) = packagedArtifact.in(Compile).in(packageBin).value
309+
val fatJar =
310+
new File(crossTarget.value + "/" + assemblyJarName.in(assembly).value)
311+
val _ = assembly.value
312+
IO.copy(List(fatJar -> slimJar), CopyOptions().withOverwrite(true))
313+
(art, slimJar)
314+
},
315+
pomPostProcess := { node =>
316+
new RuleTransformer(
317+
new RewriteRule {
318+
private def isAbsorbedDependency(node: XmlNode): Boolean = {
319+
node.label == "dependency" &&
320+
node.child.exists(child => child.label == "artifactId")
321+
}
322+
override def transform(node: XmlNode): XmlNodeSeq =
323+
node match {
324+
case e: Elem if isAbsorbedDependency(node) =>
325+
Comment(
326+
"the dependency that was here has been absorbed via sbt-assembly"
327+
)
328+
case _ =>
329+
node
330+
}
331+
}
332+
).transform(node).head
294333
}
295334
)
335+
336+
lazy val docs = project
337+
.in(file("lsif-java-docs"))
338+
.settings(
339+
mdocOut :=
340+
baseDirectory.in(ThisBuild).value / "website" / "target" / "docs",
341+
fork := false,
342+
mdocVariables :=
343+
Map[String, String](
344+
"VERSION" -> version.value,
345+
"SCALA_VERSION" -> scalaVersion.value,
346+
"STABLE_VERSION" -> version.value.replaceFirst("\\-.*", "")
347+
)
348+
)
349+
.dependsOn(unit)
350+
.enablePlugins(DocusaurusPlugin)

cli/src/main/scala/com/sourcegraph/lsif_java/IndexCommand.scala

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import java.nio.file.Paths
66

77
import com.sourcegraph.lsif_java.buildtools.BuildTool
88
import moped.annotations.Description
9+
import moped.annotations.ExampleUsage
910
import moped.annotations.ExampleValue
1011
import moped.annotations.Inline
1112
import moped.annotations.TrailingArguments
13+
import moped.annotations.Usage
1214
import moped.cli.Application
1315
import moped.cli.Command
1416
import moped.cli.CommandParser
@@ -18,7 +20,12 @@ import os.Inherit
1820
import os.Shellable
1921

2022
@Description(
21-
"Generates an LSIF index for the Java build of a provided workspace directory."
23+
"Automatically generate an LSIF index in the current working directory."
24+
)
25+
@Usage("lsif-java index [OPTIONS ...] -- [TRAILING_ARGUMENTS ...]")
26+
@ExampleUsage(
27+
"""|# Running the `index` command with no flags should work most of the time.
28+
|$ lsif-java index""".stripMargin
2229
)
2330
case class IndexCommand(
2431
@Description("The path where to generate the LSIF index.") output: Path =
@@ -41,12 +48,12 @@ case class IndexCommand(
4148
)
4249
@ExampleValue("Gradle") buildTool: Option[String] = None,
4350
@Description(
44-
"Whether to enable remove generated temporary files on exit."
51+
"Whether to remove generated temporary files on exit."
4552
) cleanup: Boolean = true,
4653
@Description(
47-
"The build command to use to compile all sources. " +
54+
"Optional. The build command to use to compile all sources. " +
4855
"Defaults to a build-specific command. For example, the default command for Maven command is 'clean verify -DskipTests'." +
49-
"To override the default, pass in the build command after a double dash: 'lsif-java -- compile'"
56+
"To override the default, pass in the build command after a double dash: 'lsif-java index -- compile test:compile'"
5057
)
5158
@TrailingArguments() buildCommand: List[String] = Nil,
5259
@Inline
@@ -79,6 +86,7 @@ case class IndexCommand(
7986
def workingDirectory: Path = AbsolutePath.of(app.env.workingDirectory)
8087
def finalTargetroot(default: Path): Path =
8188
AbsolutePath.of(targetroot.getOrElse(default), workingDirectory)
89+
def finalOutput: Path = AbsolutePath.of(output, workingDirectory)
8290
def finalBuildCommand(default: List[String]): List[String] =
8391
if (buildCommand.isEmpty)
8492
default
@@ -142,8 +150,14 @@ case class IndexCommand(
142150
} else {
143151
val generateLsifResult = process(
144152
"lsif-semanticdb",
153+
s"--out=${finalOutput}",
145154
s"--semanticdbDir=${tool.targetroot}"
146155
)
156+
if (
157+
generateLsifResult.exitCode == 0 && Files.isRegularFile(finalOutput)
158+
) {
159+
app.info(finalOutput.toAbsolutePath().toString())
160+
}
147161
generateSemanticdbResult.exitCode + generateLsifResult.exitCode
148162
}
149163
case many =>

0 commit comments

Comments
 (0)