Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement goto definition with low CPU and memory overhead #332

Merged
merged 30 commits into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
280ffb9
Remove everything
olafurpg Oct 8, 2018
c18495b
Refactor the build
olafurpg Oct 8, 2018
ec15dcf
Update docs to reflect latest scala version
olafurpg Oct 8, 2018
2c327bb
Add utility object to map LegacyScanner tokens to readable names
olafurpg Oct 8, 2018
f6c4366
Add useful extension methods.
olafurpg Oct 8, 2018
f2e3d82
Implement "toplevel symbol" parser for Scala sources
olafurpg Oct 8, 2018
5e0a941
Expose helper method to change the scribe logging format
olafurpg Oct 8, 2018
599425c
Create mtags module with a complete solution for navigation.
olafurpg Oct 8, 2018
ae09098
Add coursier utilities to fetch sources of libraries
olafurpg Oct 8, 2018
667510d
Add testing utilities
olafurpg Oct 8, 2018
4132081
Write test cases.
olafurpg Oct 8, 2018
17e30c9
Add ToplevelSuite to test toplevel symbol extraction
olafurpg Oct 8, 2018
07fdb8d
Add SemanticdbSuite as a baseline for other test suites
olafurpg Oct 8, 2018
6f9acc4
Add MtagsSuite to test JavaMtags and ScalaMtags
olafurpg Oct 8, 2018
c94ea7a
Add ScalaToplevelSuite to assert that it's a subset of Mtags.
olafurpg Oct 8, 2018
628d766
Add DefinitionSuite to stress e2e "goto definition" handling
olafurpg Oct 8, 2018
75ac015
Add SaveExpect class to save expect test outputs.
olafurpg Oct 8, 2018
4dcb2e9
Ignore generated expect files from scalafmt
olafurpg Oct 8, 2018
7d085df
Add benchmarking infrastructure
olafurpg Oct 8, 2018
2566691
Reformat sources
olafurpg Oct 8, 2018
f91e7d8
Remove dead imports with Scalafix
olafurpg Oct 8, 2018
fa1351e
Refine benchmarkd for toplevel symbols and memory usage
olafurpg Oct 8, 2018
59bda2a
s/IndexBench/MetalsBench/
olafurpg Oct 8, 2018
a2bb282
Fix scripted tests
olafurpg Oct 8, 2018
6f4192b
Add readme with results for benchmarks
olafurpg Oct 8, 2018
6519b46
Simplify GlobalSymbolIndex
olafurpg Oct 9, 2018
3579a69
Reproduce bug for in-project Java symbols referenced from Scala
olafurpg Oct 9, 2018
53cd1dd
Fix bug in handling of Java source files on disk.
olafurpg Oct 9, 2018
44b0f4c
Address review comments
olafurpg Oct 13, 2018
889b282
Address review comments
olafurpg Oct 17, 2018
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
3 changes: 3 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
rules = [
RemoveUnused
]
1 change: 1 addition & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ To fix this problem:

project.excludeFilters = [
test-workspace
tests/unit/src/test/resources
sbt-metals/src/sbt-test
]
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ stages:
jobs:
include:
# default stage is test
- env: TEST="scalafmt"
script: ./bin/scalafmt --test
- env: TEST="scalafmt+scalafix"
script:
- ./bin/scalafmt --test
- sbt scalafixCheck
- env: TEST="sbt test"
script:
- sbt startServer metalsSetup test
Expand Down
155 changes: 78 additions & 77 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import java.io.File
inThisBuild(
List(
version ~= { dynVer =>
if (sys.env.contains("CI")) dynVer
else "SNAPSHOT" // only for local publishng
},
scalaVersion := V.scala212,
crossScalaVersions := List(V.scala212),
scalacOptions ++= List(
"-Yrangepos",
"-deprecation",
// -Xlint is unusable because of
// https://github.com/scala/bug/issues/10448
"-Ywarn-unused-import"
),
addCompilerPlugin(MetalsPlugin.semanticdbScalac),
organization := "org.scalameta",
licenses := Seq(
"Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")
),
testFrameworks := List(new TestFramework("utest.runner.Framework")),
libraryDependencies += "com.lihaoyi" %% "utest" % "0.6.0" % Test,
homepage := Some(url("https://github.com/scalameta/metals")),
developers := List(
Developer(
Expand Down Expand Up @@ -50,70 +52,50 @@ inThisBuild(
url("http://delmore.io")
)
),
testFrameworks := List(),
resolvers += Resolver.sonatypeRepo("releases"),
// faster publishLocal:
publishArtifact in packageDoc := sys.env.contains("CI"),
publishArtifact in packageSrc := sys.env.contains("CI"),
addCompilerPlugin(
"org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full
)
publishArtifact in packageSrc := sys.env.contains("CI")
)
)

addCommandAlias("scalafixAll", "all compile:scalafix test:scalafix")
addCommandAlias("scalafixCheck", "; scalafix --check ; test:scalafix --check")

commands += Command.command("save-expect") { s =>
"unit/test:runMain tests.SaveExpect" ::
s
}

lazy val V = new {
val scala210 = "2.10.7"
val scala212 = MetalsPlugin.scala212
val scalameta = MetalsPlugin.semanticdbVersion
val scalafix = "0.5.7"
val circe = "0.9.0"
val enumeratum = "1.5.12"
}

lazy val legacyScala212 = List(
addCompilerPlugin(MetalsPlugin.semanticdbScalac),
scalaVersion := V.scala212,
crossScalaVersions := List(V.scala212),
)
skip.in(publish) := true

skip in publish := true
legacyScala212
lazy val mtags = project
.settings(
libraryDependencies ++= List(
"com.thoughtworks.qdox" % "qdox" % "2.0-M9", // for java mtags
"org.scalameta" %% "scalameta" % V.scalameta
)
)

lazy val metals = project
.enablePlugins(BuildInfoPlugin)
.settings(
legacyScala212,
fork in Test := true, // required for jni interrop with leveldb.
buildInfoKeys := Seq[BuildInfoKey](
"testWorkspaceBaseDirectory" ->
baseDirectory.in(testWorkspace).value,
version,
),
buildInfoPackage := "scala.meta.metals.internal",
libraryDependencies ++= List(
"com.thoughtworks.qdox" % "qdox" % "2.0-M9", // for java mtags
"com.lihaoyi" %% "pprint" % "0.5.3", // for pretty formatting of log values
"org.scala-sbt.ipcsocket" % "ipcsocket" % "1.0.0", // for sbt server
"ch.epfl.scala" % "scalafix-reflect" % V.scalafix cross CrossVersion.full,
"com.googlecode.java-diff-utils" % "diffutils" % "1.3.0", // for edit-distance
"com.thoughtworks.qdox" % "qdox" % "2.0-M7", // for java mtags
"io.get-coursier" %% "coursier" % coursier.util.Properties.version, // for jars
"io.get-coursier" %% "coursier-cache" % coursier.util.Properties.version,
"io.github.soc" % "directories" % "5", // for cache location
"me.xdrop" % "fuzzywuzzy" % "1.1.9", // for workspace/symbol
"org.fusesource.leveldbjni" % "leveldbjni-all" % "1.8", // for caching classpath index
"org.scalameta" %% "lsp4s" % "0.2.1",
"org.scalameta" %% "semanticdb-scalac" % V.scalameta cross CrossVersion.full,
"io.circe" %% "circe-core" % V.circe,
"io.circe" %% "circe-generic" % V.circe,
"io.circe" %% "circe-generic-extras" % V.circe,
"io.circe" %% "circe-parser" % V.circe,
"com.beachape" %% "enumeratum" % V.enumeratum,
"com.beachape" %% "enumeratum-circe" % "1.5.15",
"org.scalameta" %% "testkit" % V.scalameta % Test,
"org.scalameta" %% "scalameta" % V.scalameta,
"org.scalameta" %% "symtab" % V.scalameta,
"org.scalameta" % "interactive" % V.scalameta cross CrossVersion.full,
Copy link
Member

Choose a reason for hiding this comment

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

is this still in use?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, ls4ps is not strictly used either because the metals project has 2 source files at the moment. I will clean up the metals project once we add language server stuff.

Copy link
Member

Choose a reason for hiding this comment

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

I meant the interactive part specifically, but there's no rush to clean this up now, I agree

"org.scalameta" %% "lsp4s" % "0.2.1"
)
)
.dependsOn(
testWorkspace % "test->test"
)
.dependsOn(mtags)

lazy val `sbt-metals` = project
.settings(
Expand All @@ -135,54 +117,73 @@ lazy val `sbt-metals` = project
),
)
.enablePlugins(ScriptedPlugin)
.disablePlugins(ScalafixPlugin)

lazy val integration = project
.in(file("tests/integration"))
lazy val input = project
.in(file("tests/input"))
.settings(
legacyScala212,
skip in publish := true
skip.in(publish) := true,
libraryDependencies ++= List(
// these projects have macro annotations
"org.scalameta" %% "scalameta" % V.scalameta,
"io.circe" %% "circe-derivation-annotations" % "0.9.0-M5"
),
addCompilerPlugin(
"org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full
)
)
.dependsOn(metals % "compile->compile;test->test")

lazy val testWorkspace = project
.in(file("test-workspace"))
lazy val unit = project
.in(file("tests/unit"))
.settings(
legacyScala212,
skip in publish := true,
scalacOptions += {
// Need to fix source root so it matches the workspace folder.
s"-P:semanticdb:sourceroot:${baseDirectory.value}"
},
scalacOptions += "-Ywarn-unused-import",
scalacOptions -= "-Xlint"
skip.in(publish) := true,
testFrameworks := List(new TestFramework("utest.runner.Framework")),
libraryDependencies ++= List(
"io.get-coursier" %% "coursier" % coursier.util.Properties.version, // for jars
"io.get-coursier" %% "coursier-cache" % coursier.util.Properties.version,
"org.scalameta" % "metac" % V.scalameta cross CrossVersion.full,
"org.scalameta" %% "testkit" % V.scalameta,
"com.lihaoyi" %% "utest" % "0.6.0",
),
buildInfoPackage := "tests",
resourceGenerators.in(Compile) += InputProperties.resourceGenerator(input),
compile.in(Compile) :=
compile.in(Compile).dependsOn(compile.in(input, Test)).value,
buildInfoKeys := Seq[BuildInfoKey](
"testResourceDirectory" -> resourceDirectory.in(Test).value
)
)
.dependsOn(metals)
.enablePlugins(BuildInfoPlugin)

lazy val bench = project
.in(file("metals-bench"))
.settings(
fork.in(run) := true,
skip.in(publish) := true,
moduleName := "metals-bench",
libraryDependencies ++= List(
// for measuring memory usage
"org.spire-math" %% "clouseau" % "0.2.2",
"org.openjdk.jol" % "jol-core" % "0.9"
),
)
.dependsOn(unit)
.enablePlugins(JmhPlugin)

lazy val docs = project
.in(file("metals-docs"))
.settings(
skip in publish := true, // disabled until Scalameta v4 upgrade
skip.in(publish) := true,
moduleName := "metals-docs",
sources.in(Compile) += {
sourceDirectory.in(metals, Compile).value /
"scala/scala/meta/metals/Configuration.scala"
},
scalaVersion := "2.12.7",
crossScalaVersions := List("2.12.6"),
mainClass.in(Compile) := Some("docs.Docs"),
SettingKey[Boolean]("metalsEnabled") := false,
libraryDependencies ++= List(
"com.geirsson" % "mdoc" % "0.5.0" cross CrossVersion.full,
// Dependencies below can be removed after the upgrade to Scalameta v4.0
"io.circe" %% "circe-core" % V.circe,
"io.circe" %% "circe-generic" % V.circe,
"io.circe" %% "circe-generic-extras" % V.circe,
"io.circe" %% "circe-parser" % V.circe,
"com.beachape" %% "enumeratum" % V.enumeratum,
"com.beachape" %% "enumeratum-circe" % "1.5.15"
"com.geirsson" % "mdoc" % "0.5.1" cross CrossVersion.full
),
buildInfoKeys := Seq[BuildInfoKey](
version,
),
buildInfoPackage := "docs"
)
.dependsOn(metals)
.enablePlugins(DocusaurusPlugin, BuildInfoPlugin)
54 changes: 32 additions & 22 deletions docs/installation-contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ id: installation-contributors
title: Installation
---

> ⚠ ️ This project is very alpha stage. Expect bugs and incomplete documentation.
> ⚠ ️ This project is very alpha stage. Expect bugs and incomplete
> documentation.

The following instructions are intended for contributors who want to try Metals
and provide feedback. We do not provide support for day-to-day usage of Metals.

## Requirements

* Scala 2.12.4, down to the exact PATCH version. Note that Scala versions 2.11.x and
2.12.6 are not supported.
* Java 8. Note that Java 9 or higher has not been tested.
* macOS or Linux. Note that there have been reported issues on Windows.
- Scala 2.12.7, down to the exact PATCH version. Note that Scala versions 2.11.x
Copy link
Member

Choose a reason for hiding this comment

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

maybe make the Scala version dynamic using V.scala212?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, done.

Copy link
Member Author

Choose a reason for hiding this comment

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

The docs don't build actually at the moment because the Configuration object is now gone. We'll need to update the docs before there is a release.

and 2.12.6 are not supported.
- Java 8. Note that Java 9 or higher has not been tested.
- macOS or Linux. Note that there have been reported issues on Windows.

## Global setup

Expand All @@ -30,57 +31,66 @@ You can install the plugin with:
addSbtPlugin("org.scalameta" % "sbt-metals" % "@VERSION@")
```

You can add the plugin to a specific project (adding it to `project/plugins.sbt`) or globally adding it to:
You can add the plugin to a specific project (adding it to
`project/plugins.sbt`) or globally adding it to:

- (sbt 1) `~/.sbt/1.0/plugins/plugins.sbt`
- (sbt 0.13) `~/.sbt/0.13/plugins/plugins.sbt`

### VSCode extension

> ***N.B.*** This project is still in development - right now you will need to run the VSCode plugin
> as described [here](getting-started-contributors.html#running-a-local-version-of-the-vscode-extension)
> **_N.B._** This project is still in development - right now you will need to
> run the VSCode plugin as described
> [here](getting-started-contributors.html#running-a-local-version-of-the-vscode-extension)

## Per-project setup

These steps are required on each project.

### Quick-start
The quickest way to get started with Metals is to use the `metalsSetup` command in sbt.

The quickest way to get started with Metals is to use the `metalsSetup` command
in sbt.

```
sbt
> metalsSetup
```

The command will create the necessary metadata in the `.metals` directory
(which you should not checkout into version control) and setup the `semanticdb-scalac` compiler
plugin for the current sbt session.
The command will create the necessary metadata in the `.metals` directory (which
you should not checkout into version control) and setup the `semanticdb-scalac`
compiler plugin for the current sbt session.

You should not checkout the `.metals` directory into version control. We recommend to add it to your
project's `.gitignore` or/and to your global `.gitignore`:
You should not checkout the `.metals` directory into version control. We
recommend to add it to your project's `.gitignore` or/and to your global
`.gitignore`:

```
echo ".metals/" >> .gitignore
```

Note that in sbt 0.13 you will need to invoke `metalsSetup` (or `semanticdbEnable`) whenever you close and
re-open sbt. For a more persistent setup, keep reading. In sbt 1 you don't need to do it because Metals will
automatically invoke `semanticdbEnable` every time it connects to the sbt server.
Note that in sbt 0.13 you will need to invoke `metalsSetup` (or
`semanticdbEnable`) whenever you close and re-open sbt. For a more persistent
setup, keep reading. In sbt 1 you don't need to do it because Metals will
automatically invoke `semanticdbEnable` every time it connects to the sbt
server.

### Persisting the semanticdb-scalac compiler plugin
Some features like definition/references/hover rely on artifacts produced by a compiler plugin
called `semanticdb-scalac`.

`metalsSetup` enables the plugin on the current session (by invoking `semanticdbEnable`), but you
can choose to enable it permanently on your project by adding these two settings in your sbt build
definition:
Some features like definition/references/hover rely on artifacts produced by a
compiler plugin called `semanticdb-scalac`.

`metalsSetup` enables the plugin on the current session (by invoking
`semanticdbEnable`), but you can choose to enable it permanently on your project
by adding these two settings in your sbt build definition:

```scala
addCompilerPlugin(MetalsPlugin.semanticdbScalac)
scalacOptions += "-Yrangepos"
```

### Start editing

Open your project in VSCode (`code .` from your terminal) and open a Scala file;
the server will now start.

Expand Down
19 changes: 19 additions & 0 deletions metals-bench/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Benchmarks

Date: 2018 October 8th, commit 59bda2ac81a497fa168677499bd1a9df60fec5ab
```
> bench/jmh:run -i 10 -wi 10 -f1 -t1
[info] Benchmark Mode Cnt Score Error Units
[info] MetalsBench.indexSources ss 10 0.620 ± 0.058 s/op
[info] MetalsBench.javaMtags ss 10 7.233 ± 0.017 s/op
[info] MetalsBench.scalaMtags ss 10 4.617 ± 0.034 s/op
[info] MetalsBench.scalaToplevels ss 10 0.361 ± 0.005 s/op
> bench/run
[info] info elapsed: 3265ms
[info] info java lines: 0
[info] info scala lines: 1263569
[info] bench.Memory.printFootprint:11 iterable.source: "index"
[info] bench.Memory.printFootprint:12 Units.approx(size): "16.9M"
[info] bench.Memory.printFootprint:24 count: 12L
[info] bench.Memory.printFootprint:25 Units.approx(elementSize): "1.41M"
```
Loading