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

Add VirtualFile / VirtualFileRef #712

Merged
merged 3 commits into from
Feb 26, 2020
Merged

Conversation

eed3si9n
Copy link
Member

This uses rootPaths to encode VirtualFileRef id. As a relatively simple method of abstracting out absolute paths, VirtualFileUtil.mapSources takes a list of root paths, and substitutes them with positional index like ${0}.

@stephenjudkins
Copy link

Is there any way I could help here? I could definitely assist with any rote conversions from java.io.File to xsbti.VirtualFile

@eed3si9n
Copy link
Member Author

@stephenjudkins I guess you could help test it or port it to Bazel once it's ready.

@stephenjudkins
Copy link

Any expectations on when this might land in a release?

@eed3si9n
Copy link
Member Author

I'm still working on other parts, so maybe in a month or so?

@stephenjudkins
Copy link

Great, thanks for the estimate. Really appreciate your work on this.

@@ -11,6 +11,9 @@

package xsbti;

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

public class BasicVirtualFileRef implements VirtualFileRef {
private String parent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Could parent and name be marked final and possibly annotated @NotNull? Below it isn't obvious to me in the names method that a null check isn't necessary on parent.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds like a good idea.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is there a NotNull that's standard in JDK 8 and 11?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, good point. There might not be.

if (parent == "") {
return new String[] { name };
}
ArrayList<String> xs = new ArrayList<String>(Arrays.asList(parent.split("/")));
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a big deal at all, but I kinda prefer an imperative approach here just to minimize the extra copying (it also isn't obvious from the code alone that you need to wrap the result of Arrays.asList because otherwise xs.add will throw an unsupported operation exception). Maybe that's a premature optimization though:

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;
return results;  

@eed3si9n eed3si9n force-pushed the wip/machine_vf branch 3 times, most recently from d5ca70b to 0e941b5 Compare January 16, 2020 23:39
@eed3si9n eed3si9n marked this pull request as ready for review January 16, 2020 23:40
@eed3si9n
Copy link
Member Author

About 90% of the scripted tests are passing.

At least one of the failure is related to the virtual file position vs concrete position.

[error] (run-main-0) sbt.internal.inc.ScriptedRunnerImpl$ScriptedFailure$1: 11 (out of 143) scripted tests failed:
[error] 
[error] 	source-dependencies / check-products
[error] 	source-dependencies / compactify
[error] 	source-dependencies / default-arguments-separate-compilation
[error] 	source-dependencies / empty-package
[error] 	source-dependencies / java-basic
[error] 	source-dependencies / java-inner
[error] 	source-dependencies / recorded-products
[error] 	source-dependencies / remove-test-b
[error] 	source-dependencies / restore-classes
[error] 	source-dependencies / typeref-only
[error] 	reporter / warnings-reported

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools

This comment has been minimized.

@typesafe-tools
Copy link

A validation involving this pull request is in progress...

@typesafe-tools
Copy link

The validator has checked the following projects, tested using sources.sh.

Project Reference Commit
sbt pull/5417/head sbt/sbt@bd98dcc
zinc pull/712/head e732a05
io develop sbt/io@fcedb90
librarymanagement develop sbt/librarymanagement@3132a3e
util develop sbt/util@098796c

✅ The result is: SUCCESS
(restart)

@eed3si9n
Copy link
Member Author

For the interest of review and/or porting, squashed all the commits into one.

build.sbt Outdated Show resolved Hide resolved
eed3si9n added a commit to eed3si9n/compiler-interface that referenced this pull request Feb 19, 2020
Currently this repo lacks validation beyond compilation. This improves the situation slightly by adding a "dummy-bridge" implementation, which is an actual bridge proposed in sbt/zinc#712.

The test currently tests that the bridge is capable of building an in-memory VirtualFile.
@eed3si9n
Copy link
Member Author

For the record, I've started to move xsbti data types in this PR including VirtualFile to https://github.com/scala/compiler-interface/, which likely will be under some other package like scala.tools.sci.

package xsbti;

/*
* Represents a reference to a file-like object.
Copy link
Member

Choose a reason for hiding this comment

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

How does one dereference to get to the underlying content or the underlying physical file? Why is a reference required? Some of these design notes could live here.

How are VirtualFileRef-s expected to behave for equality -- is it just based on .id?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added docs in 5137b10

* Returns unique identifier for the file.
* For Java compilation
* it needs to contain the path structure matching
* the package name.
Copy link
Member

@retronym retronym Feb 25, 2020

Choose a reason for hiding this comment

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

"... for example com/acme/Foo.java." (?)

Copy link
Member Author

Choose a reason for hiding this comment

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

👍

Copy link
Member

@retronym retronym left a comment

Choose a reason for hiding this comment

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

I'm happy with this direction.

@eed3si9n eed3si9n merged commit fc58a39 into sbt:develop Feb 26, 2020
@eed3si9n eed3si9n deleted the wip/machine_vf branch February 26, 2020 16:21
eed3si9n added a commit to eed3si9n/sbt that referenced this pull request Apr 19, 2020
eed3si9n added a commit to eed3si9n/sbt that referenced this pull request Apr 24, 2020
* Given the sequence of Scala and Java source files,
* <code>MappedFileConverter</code> will create a sequence of
* <code>MappedVirtualFile</code> whose <code>id</code> would look like
* <code>${0}/src/main/example/A.scala</code>.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't undestand what this ${0} thing is. Why isn't the id src/main/example/A.scala ?

Copy link
Member Author

Choose a reason for hiding this comment

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

MappedFileConverter can calculate the id based on multiple root paths, including for example Coursier cache directory.

Copy link

@bishabosha bishabosha May 26, 2020

Choose a reason for hiding this comment

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

if toPath on a MappedVirtualFile does not resolve the id what should you substitute?

* Java files must end with ".java",
* and Scala files must end with ".scala".
*/
public String[] names();
Copy link
Contributor

Choose a reason for hiding this comment

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

This has the exact same documentation as name, but I guess it does something different? How can a file have multiple names?

Copy link
Member Author

Choose a reason for hiding this comment

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

Names return the path elements like id.split("/").

Comment on lines +49 to +53
if (u.startsWith("file:///var/folders/"))
Seq(
idx -> u,
idx -> u.replaceAllLiterally("file:///var/folders/", "file:///private/var/folders/")
)
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this special case for? It's missing documentation

Copy link
Member Author

Choose a reason for hiding this comment

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

On macOS /tmp/ and /var/ seems to be symlinks to /private/tmp/ and /private/var/ respectively.

lrwxr-xr-x@   1 root  wheel    20xx tmp@ -> private/tmp
lrwxr-xr-x@   1 root  wheel    20xx var@ -> private/var

When temporary directories are created under /var/folders/ Zinc and compilers sometimes end up reporting different paths for *.scala, *.java, *.class etc. Maybe there's a better solution than this, but the above is a workaround for that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest using getCanonicalPath.

Copy link
Contributor

@smarter smarter May 3, 2020

Choose a reason for hiding this comment

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

(or Path#toRealPath which seems to be the equivalent for Path, though this one will throw an exception if the file doesn't actually exist on disk)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yea. I have to figure out the right point to dealias symlinks so that a build can be created under /tmp/ (or compiler bridge can be compiled in temp etc) and things continue to work.

if (classpathEntry.id.endsWith(".jar") &&
(converter.toPath(classpathEntry).toString != converter.toPath(file).toString))
invalidateBinary(s"${className} is now provided by ${classpathEntry}")
else compareStamps(file, classpathEntry)
Copy link

@mernst-github mernst-github Oct 24, 2022

Choose a reason for hiding this comment

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

This line seems to contain a bug: if classpathEntry turns out to be a directory, this comparison unsurprisingly always fails:

Invalidating '.../build/classes/scala/main/.../Foo.class' because
 .../build/classes/scala/main/....class (farm(77c283a23fed88f2)) != .../build/classes/scala/main (absent)
                                                                         ^^^ RHS is a ***directory***.

The resolve step was completely dropped in this PR.

Copy link
Member

Choose a reason for hiding this comment

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

I've just found out this bug and I am going to fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.