Skip to content

Commit

Permalink
Cleanup parts of the VirtualFile-related code
Browse files Browse the repository at this point in the history
* Rename VirtualFileWrap/XsbtPlainFile/XsbtVirtualFile to
  AbstractZincFile/ZincPlainFile/ZincVirtualFil;
* Default FileConverter#toVirtualFile(VirtualFileRef): VirtualFile
* Rework BasicVirtualDirectory & BasicMemoryFile to avoid needless
  Option and BasicVirtualDirectory boxing, & use structural sharing;
* Cleanup some of VirtualFile's docs.
  • Loading branch information
dwijnand committed Jul 9, 2020
1 parent db1039b commit 2c0e4e0
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 188 deletions.
8 changes: 2 additions & 6 deletions internal/compiler-bridge/src/main/scala/xsbt/API.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ final class API(val global: CallbackGlobal) extends Compat with GlobalHelpers wi
}

private def processScalaUnit(unit: CompilationUnit): Unit = {
val sourceFile: VirtualFile = unit.source.file match {
case v: VirtualFileWrap => v.underlying
}
val sourceFile: VirtualFile = unit.source.file match { case AbstractZincFile(vf) => vf }
debuglog("Traversing " + sourceFile)
callback.startSource(sourceFile)
val extractApi = new ExtractAPI[global.type](global, sourceFile)
Expand Down Expand Up @@ -137,9 +135,7 @@ final class API(val global: CallbackGlobal) extends Compat with GlobalHelpers wi
val sourceJavaFile0 =
if (sourceFile == null) symbol.enclosingTopLevelClass.sourceFile
else sourceFile
val sourceJavaFile: VirtualFile = sourceJavaFile0 match {
case v: VirtualFileWrap => v.underlying
}
val sourceJavaFile: VirtualFile = sourceJavaFile0 match { case AbstractZincFile(vf) => vf }

def registerProductNames(names: FlattenedNames): Unit = {
// Guard against a local class in case it surreptitiously leaks here
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Zinc - The incremental compiler for Scala.
* Copyright Lightbend, Inc. and Mark Harrah
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package xsbt

import xsbti.{ PathBasedFile, VirtualFile }
import scala.reflect.io.Streamable

private trait AbstractZincFile extends scala.reflect.io.AbstractFile {
def underlying: VirtualFile
}

private final class ZincPlainFile private[xsbt] (val underlying: PathBasedFile)
extends scala.reflect.io.PlainFile(scala.reflect.io.Path(underlying.toPath.toFile))
with AbstractZincFile

private final class ZincVirtualFile private[xsbt] (val underlying: VirtualFile)
extends scala.reflect.io.VirtualFile(underlying.name, underlying.id)
with AbstractZincFile {
Streamable.closing(output)(_.write(Streamable.bytes(underlying.input))) // fill in the content
}

private object AbstractZincFile {
def apply(virtualFile: VirtualFile): AbstractZincFile = virtualFile match {
case file: PathBasedFile => new ZincPlainFile(file)
case _ => new ZincVirtualFile(virtualFile)
}

def unapply(file: scala.reflect.io.AbstractFile): Option[VirtualFile] = file match {
case wrapper: AbstractZincFile => Some(wrapper.underlying)
case _ => None
}
}
4 changes: 1 addition & 3 deletions internal/compiler-bridge/src/main/scala/xsbt/Analyzer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ final class Analyzer(val global: CallbackGlobal) extends LocateClassFile {

def apply(unit: CompilationUnit): Unit = {
if (!unit.isJava) {
val sourceFile0: VirtualFileWrap = unit.source.file match {
case v: VirtualFileWrap => v
}
val sourceFile0: AbstractZincFile = unit.source.file match { case v: AbstractZincFile => v }
val sourceFile: VirtualFile = sourceFile0.underlying
lazy val outputDir = settings.outputDirs.outputDirFor(sourceFile0).file
for (iclass <- unit.icode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private final class CachedCompiler0(args: Array[String], output: Output, initial
compiler.set(callback, underlyingReporter)
val run = new compiler.ZincRun(compileProgress)

val wrappedFiles = sources.map(VirtualFileWrap(_))
val wrappedFiles = sources.map(AbstractZincFile(_))
val sortedSourceFiles: List[AbstractFile] =
wrappedFiles.sortWith(_.underlying.id < _.underlying.id)
run.compileFiles(sortedSourceFiles)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ private object DelegatingReporter {

def makePosition(pos: Position): xsbti.Position = {
val src = pos.source
val sourcePath = src.file match {
case VirtualFileWrap(virtualFile) => virtualFile.id
}
val sourcePath = src.file match { case AbstractZincFile(virtualFile) => virtualFile.id }
val sourceFile = new File(src.file.path)
val line = pos.line
val lineContent = pos.lineContent.stripLineEnd
Expand Down
7 changes: 2 additions & 5 deletions internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with
None
}

private val sourceFile: VirtualFile = unit.source.file match {
case v: VirtualFileWrap => v.underlying
}
private val sourceFile: VirtualFile = unit.source.file match { case AbstractZincFile(vf) => vf }
private val responsibleOfImports = firstClassOrModuleClass(unit.body)
private var orphanImportsReported = false

Expand Down Expand Up @@ -158,8 +156,7 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with
val targetSymbol = dep.to
val onSource = targetSymbol.sourceFile
onSource match {
case v: VirtualFileWrap =>
val onSourceFile: VirtualFile = v.underlying
case AbstractZincFile(onSourceFile) =>
if (onSourceFile != sourceFile || allowLocal) {
// We cannot ignore dependencies coming from the same source file because
// the dependency info needs to propagate. See source-dependencies/trait-trait-211.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private class Runner(
def document(ignore: Seq[String]): Unit = {
import compiler._
val run = new Run
val wrappedFiles = sources.toList.map(VirtualFileWrap(_))
val wrappedFiles = sources.toList.map(AbstractZincFile(_))
val sortedSourceFiles: List[AbstractFile] =
wrappedFiles.sortWith(_.underlying.id < _.underlying.id)
run.compileFiles(sortedSourceFiles)
Expand Down
54 changes: 0 additions & 54 deletions internal/compiler-bridge/src/main/scala/xsbt/VirtualFileWrap.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,65 +11,48 @@

package xsbti;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Objects;

public class BasicVirtualFileRef implements VirtualFileRef {
final private String id;
final private String parent;
final private String name;
private final String id;
private final String parent;
private final String name;

protected BasicVirtualFileRef(String _id) {
this.id = _id;
int idx = _id.lastIndexOf('/');
if (idx >= 0) {
parent = _id.substring(0, idx + 1);
} else {
parent = "";
}
name = _id.substring(idx + 1);
}

public String id() {
// https://github.com/sbt/zinc/issues/768
// keep the whole id as val
return this.id;
}

public String name() {
return name;
this.id = _id.replace('\\', '/');
int idx = id.lastIndexOf('/');
parent = idx == -1 ? "" : id.substring(0, idx + 1);
name = id.substring(idx + 1);
}

public String[] names() {
if (parent == null || parent == "") {
if (Objects.equals(parent, "")) {
return new String[] { name };
}
String[] parts = parent.split("/");
String[] results = new String[parts.length + 1];
int i = 0;
for (i = 0; i < parts.length; i++) results[i] = parts[i];
results[i] = name;
System.arraycopy(parts, 0, results, 0, parts.length);
results[parts.length] = name;
return results;
}

public BasicVirtualFileRef withId(String id) {
return new BasicVirtualFileRef(id);
}
public BasicVirtualFileRef withId(String id) { return new BasicVirtualFileRef(id); }

public String id() { return id; } // keep the whole id as val sbt/zinc#768
public String name() { return name; }
public String toString() { return id; }

public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof VirtualFileRef)) {
return false;
} else {
VirtualFileRef o = (VirtualFileRef)obj;
return this.id().equals(o.id());
return Objects.equals(id(), ((VirtualFileRef) obj).id());
}
}

public int hashCode() {
return 37 * (37 * (17 + "xsbti.VirtualFileRef".hashCode()) + id().hashCode());
}
public String toString() {
return id();
return 37 * (37 * (17 + "xsbti.VirtualFileRef".hashCode()) + id.hashCode());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

public interface FileConverter {
Path toPath(VirtualFileRef ref);
VirtualFile toVirtualFile(VirtualFileRef ref);

default VirtualFile toVirtualFile(VirtualFileRef ref) {
return ref instanceof VirtualFile ? ((VirtualFile) ref) : toVirtualFile(toPath(ref));
}

VirtualFile toVirtualFile(Path path);
}
28 changes: 14 additions & 14 deletions internal/compiler-interface/src/main/java/xsbti/VirtualFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,27 @@
* and content hashing.
* See also {@link VirtualFileRef}
*
* <p>One of the goals of this <i>virtual</i> file (as opposed to concrete file)
* is abtraction from the machine and user specifics.
* Previous <code>Analysis</code> file that records the relationships among
* the incremental compilation stored the file names using <code>java.io.File</code>.
* This prevented the <code>Analysis</code> information to be shared across machines
* without manipulating the absolute paths in the file names.
* <p>One of the goals of this <i>virtual</i> file (as opposed to a concrete file)
* is to abstract from the machine and user specifics.
* Previous Zinc's <code>Analysis</code> metadata files
* stored file paths using <code>java.io.File</code>.
* This impeded them from being shared across machines
* without pre- and post-processing them appropriately.
* </p>
* <p>To create a <code>VirtualFile</code>, one way of doing so is creating
* an instance of {@link FileConverter}, such as <code>MappedFileConverter</code>.
* <p>To create a <code>VirtualFile</code> you may use a {@link FileConverter},
* such as <code>MappedFileConverter</code>.
* <code>MappedFileConverter</code> internally stores the root paths to the working directory,
* Coursier cache etc, and it will create a <code>VirtualFile</code> with an <code>id</code>
* Coursier's cache, etc..., and it will create a <code>VirtualFile</code> with an <code>id</code>
* that looks like <code>${BASE}/src/main/example/A.scala</code>.
* </p>
* <p>Note that <code>VirtualFile</code> can also be implemented with just plain Java objects
* using <code>String</code> to represent the content, without "real" files.
* <p>A <code>VirtualFile</code> can also be created with plain <code>String</code>s
* to represent the content, without any "real" files.
* </p>
* <h3>ok, so how would the compiler compile this?</h3>
* See <code>IncrementalCompile.scala</code>.
* <h3>OK, but how does the compiler compile these?</h3>
* See <code>IncrementalCompiler.java</code>.
* At the top layer of Zinc, we are passing in the source files as a
* sequence of {@link VirtualFile}s.
* The files then gets wrapped by a datatype called <code>VirtualFileWrap</code>,
* The files then gets wrapped by a datatype called <code>AbstractZincFile</code>,
* which extends <code>scala.reflect.io.AbstractFile</code>,
* which the compiler is able to compile.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
* See <code>IncrementalCompile.scala</code>.
* At the top layer of Zinc, we are passing in the source files as a
* sequence of {@link VirtualFile}s.
* The files then gets wrapped by a datatype called <code>VirtualFileWrap</code>,
* The files then gets wrapped by a datatype called <code>AbstractZincFile</code>,
* which extends <code>scala.reflect.io.AbstractFile</code>,
* which the compiler is able to compile.
*/
Expand Down Expand Up @@ -104,10 +104,5 @@ public static VirtualFileRef of(String id) {
*/
public String name();

/*
* Returns "file name" for the file.
* Java files must end with ".java",
* and Scala files must end with ".scala".
*/
public String[] names();
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,16 @@ import java.nio.file.{ Files, Path }
import sbt.io.IO
import sbt.internal.util.ConsoleLogger
import xsbti.api.DependencyContext._
import xsbti.{ AnalysisCallback, TestCallback, VirtualFile, VirtualFileRef }
import xsbti.{ AnalysisCallback, BasicVirtualFileRef, TestCallback, VirtualFile, VirtualFileRef }
import xsbti.TestCallback.ExtractedClassDependencies
import xsbti.compile.SingleOutput

import scala.collection.JavaConverters._

object JavaCompilerForUnitTesting {
private class TestVirtualFile(underlying: Path) extends VirtualFile {
override def contentHash(): Long = sbt.io.Hash(underlying.toFile).hashCode.toLong
override def id(): String = underlying.toString
override def name(): String = underlying.getFileName.toString
override def names(): Array[String] = id.split("/")
override def input(): InputStream = Files.newInputStream(underlying)
private class TestVirtualFile(p: Path) extends BasicVirtualFileRef(p.toString) with VirtualFile {
override def contentHash(): Long = sbt.io.Hash(p.toFile).hashCode.toLong
override def input(): InputStream = Files.newInputStream(p)
}

def extractDependenciesFromSrcs(srcs: (String, String)*): ExtractedClassDependencies = {
Expand Down
Loading

0 comments on commit 2c0e4e0

Please sign in to comment.