mirror of
https://github.com/enso-org/enso.git
synced 2024-10-05 17:17:50 +03:00
IGV can jump to JMH sources & more (#4008)
Improvements to behavior and visual appearance of IGV Enso integration.
This commit is contained in:
parent
e6838bc90d
commit
0041b649eb
@ -494,6 +494,7 @@
|
||||
- [Add executionContext/interrupt API command][3952]
|
||||
- [Any.== is a builtin method][3956]
|
||||
- [Simplify exception handling for polyglot exceptions][3981]
|
||||
- [IGV can jump to JMH sources & more][4008]
|
||||
|
||||
[3227]: https://github.com/enso-org/enso/pull/3227
|
||||
[3248]: https://github.com/enso-org/enso/pull/3248
|
||||
@ -571,6 +572,7 @@
|
||||
[3952]: https://github.com/enso-org/enso/pull/3952
|
||||
[3956]: https://github.com/enso-org/enso/pull/3956
|
||||
[3981]: https://github.com/enso-org/enso/pull/3981
|
||||
[4008]: https://github.com/enso-org/enso/pull/4008
|
||||
|
||||
# Enso 2.0.0-alpha.18 (2021-10-12)
|
||||
|
||||
|
@ -349,7 +349,8 @@ However, as we don't want these things polluting our standard builds, we provide
|
||||
a helper SBT command `withDebug` to allow for passing these options. It supports
|
||||
the following flags:
|
||||
|
||||
- `--dumpGraphs`: This dumps the IGV (a Graal tool) graphs for the program to
|
||||
- `--dumpGraphs`: This dumps the IGV (read about
|
||||
[Enso tooling for IGV](../tools/enso4igv/README.md)) graphs for the program to
|
||||
allow for manual analysis and discovery of optimisation failures.
|
||||
- `--showCompilations`: Prints the truffle compilation trace information.
|
||||
- `--printAssembly`: Prints the assembly output from the HotSpot JIT tier.
|
||||
|
@ -36,7 +36,7 @@ E.g. in Chrome open: devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/W
|
||||
|
||||
copy the printed URL into chrome browser and you should see:
|
||||
|
||||
![Chrome Debugger](chrome-debugger.png)
|
||||
![Chrome Debugger](https://user-images.githubusercontent.com/26887752/209614265-684f530e-cf7e-45d5-9450-7ea1e4f65986.png)
|
||||
|
||||
Step in, step over, set breakpoints, watch values of the variables as well as
|
||||
evaluate arbitrary expressions in the console. Note that as of December 2022,
|
||||
@ -72,7 +72,7 @@ and then _Debug/Attach Debugger_. Once connected suspend the execution and (if
|
||||
the Enso language has already been started) choose the _Toggle Pause in GraalVM
|
||||
Script_ button in the toolbar:
|
||||
|
||||
![NetBeans Debugger](java-debugger.png)
|
||||
![NetBeans Debugger](https://user-images.githubusercontent.com/26887752/209614191-b0513635-819b-4c64-a6f9-9823b90a1513.png)
|
||||
|
||||
and your execution shall stop on the next `.enso` line of code. This mode allows
|
||||
to debug both - the Enso code as well as Java code. The stack traces shows a
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 205 KiB |
Binary file not shown.
Before Width: | Height: | Size: 139 KiB |
@ -96,7 +96,8 @@ order: 7
|
||||
something wrong.
|
||||
10. Avoid
|
||||
[deoptimizations](https://www.graalvm.org/22.2/graalvm-as-a-platform/language-implementation-framework/Optimizing/#debugging-deoptimizations).
|
||||
Understanding IGV graphs can be a very time-consuming and complex process.
|
||||
Understanding IGV graphs can be a very time-consuming and complex process
|
||||
(even with the help of [Enso tooling for IGV](../tools/enso4igv/README.md)).
|
||||
Sometimes it is sufficient to only look at the compilation traces to
|
||||
discover repeated or unnecessary deoptimizations which can significantly
|
||||
affect overall performance of your program. You can tell runner to generate
|
||||
|
@ -66,16 +66,15 @@ object FrgaalJavaCompiler {
|
||||
val sources = sources0 map {
|
||||
case x: PathBasedFile => x.toPath.toAbsolutePath.toString
|
||||
}
|
||||
val out = output.getSingleOutputAsPath().get()
|
||||
val shared = sources0.fold(out)((a, b) => {
|
||||
var ap = a match {
|
||||
|
||||
def asPath(a: Any) : Path = a match {
|
||||
case p: PathBasedFile => p.toPath
|
||||
case p: Path => p
|
||||
}
|
||||
val bp = b match {
|
||||
case p: PathBasedFile => p.toPath
|
||||
case p: Path => p
|
||||
}
|
||||
}
|
||||
|
||||
def asCommon(a: Any, b: Any): Path = {
|
||||
var ap = asPath(a)
|
||||
val bp = asPath(b)
|
||||
|
||||
var i = 0
|
||||
while (i < Math.min(ap.getNameCount(), bp.getNameCount()) && ap.getName(i) == bp.getName(i)) {
|
||||
@ -86,7 +85,45 @@ object FrgaalJavaCompiler {
|
||||
ap = ap.getParent()
|
||||
}
|
||||
ap
|
||||
}).asInstanceOf[Path]
|
||||
}
|
||||
|
||||
val out = output.getSingleOutputAsPath().get()
|
||||
val shared = sources0.fold(out)(asCommon).asInstanceOf[Path]
|
||||
|
||||
// searching for $shared/src/main/java or
|
||||
// $shared/src/test/java or
|
||||
// $shared/src/bench/java or etc.
|
||||
def findUnder(depth : Int, dir : Path): Path = {
|
||||
var d = dir
|
||||
while (d.getNameCount() > depth) {
|
||||
val threeUp = d.subpath(0, d.getNameCount() - depth)
|
||||
val relShare = shared.subpath(0, shared.getNameCount())
|
||||
if (relShare.equals(threeUp)) {
|
||||
return d
|
||||
} else {
|
||||
d = d.getParent()
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot findUnder for " + dir + " and " + shared +
|
||||
"\nout: " + out + "\nsources: " + sources
|
||||
)
|
||||
}
|
||||
def checkTarget(x : Any) = {
|
||||
val p = asPath(x)
|
||||
val namesCheck = for (i <- 0 until p.getNameCount)
|
||||
yield "target".equals(p.getName(i).toString())
|
||||
val inATargetDir = namesCheck.exists(x => x)
|
||||
inATargetDir
|
||||
}
|
||||
|
||||
val (withTarget, noTarget) = sources0.partition(checkTarget)
|
||||
val in = findUnder(3, noTarget.tail.fold(asPath(noTarget.head))(asCommon).asInstanceOf[Path])
|
||||
val generated = if (withTarget.isEmpty) {
|
||||
None
|
||||
} else {
|
||||
Some(findUnder(4, withTarget.tail.fold(asPath(withTarget.head))(asCommon).asInstanceOf[Path]))
|
||||
}
|
||||
|
||||
if (shared.toFile().exists()) {
|
||||
val ensoMarker = new File(shared.toFile(), ENSO_SOURCES)
|
||||
@ -97,6 +134,10 @@ object FrgaalJavaCompiler {
|
||||
values.zipWithIndex.foreach { case (value, idx) => ensoProperties.setProperty(s"$name.$idx", value) }
|
||||
}
|
||||
|
||||
ensoProperties.setProperty("input", in.toString())
|
||||
if (generated.isDefined) {
|
||||
ensoProperties.setProperty("generated", generated.get.toString())
|
||||
}
|
||||
ensoProperties.setProperty("output", out.toString())
|
||||
storeArray("options", options)
|
||||
source.foreach(v => ensoProperties.setProperty("source", v))
|
||||
|
@ -101,7 +101,10 @@ and open it as _"project"_ in IGV:
|
||||
|
||||
The project directories (not only `runtime`, but also other like
|
||||
`runtime-language-epb`, etc.) are recognized only if you have built the Enso
|
||||
engine sources with `sbt buildEngineDistribution`.
|
||||
engine sources with `sbt buildEngineDistribution`. Once the IGV opens the
|
||||
`runtime` & co. projects, it allows smooth navigation among the sources
|
||||
|
||||
![IGV Projects view](https://user-images.githubusercontent.com/26887752/209615348-8911af4c-4680-4e61-ac87-19a19738e2ca.png)
|
||||
|
||||
With such setup let's open graph for one of the top-most functions:
|
||||
`TruffleHotSpotCompilation*Primes*next*.bgv`. Choose compilation phase _"Before
|
||||
@ -142,7 +145,7 @@ environment. Switch to this directory and invoke:
|
||||
```bash
|
||||
enso/tools/enso4igv$ mvn clean install
|
||||
enso/tools/enso4igv$ ls target/*.nbm
|
||||
target/enso4igv-1.0-SNAPSHOT.nbm
|
||||
target/enso4igv-*-SNAPSHOT.nbm
|
||||
```
|
||||
|
||||
an NBM file is generated which can be installed into IGV, NetBeans or any other
|
||||
|
@ -5,7 +5,7 @@
|
||||
<artifactId>enso4igv</artifactId>
|
||||
<packaging>nbm</packaging>
|
||||
<name>Enso Language Support for NetBeans & Ideal Graph Visualizer</name>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<version>1.7-SNAPSHOT</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@ -69,6 +69,11 @@
|
||||
<artifactId>org-netbeans-modules-projectapi</artifactId>
|
||||
<version>${netbeans.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-modules-projectuiapi</artifactId>
|
||||
<version>${netbeans.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-api-templates</artifactId>
|
||||
@ -132,31 +137,37 @@
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-modules-projectuiapi-base</artifactId>
|
||||
<version>RELEASE113</version>
|
||||
<version>${netbeans.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-api-java-classpath</artifactId>
|
||||
<version>RELEASE113</version>
|
||||
<version>${netbeans.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-modules-java-project</artifactId>
|
||||
<version>RELEASE113</version>
|
||||
<version>${netbeans.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-modules-java-platform</artifactId>
|
||||
<version>RELEASE113</version>
|
||||
<version>${netbeans.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-api-java</artifactId>
|
||||
<version>RELEASE113</version>
|
||||
<version>${netbeans.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-netbeans-modules-java-project-ui</artifactId>
|
||||
<version>${netbeans.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -28,7 +28,7 @@ import org.openide.windows.TopComponent;
|
||||
@GrammarRegistration(mimeType = "application/x-enso", grammar = "enso.tmLanguage.json")
|
||||
@DataObject.Registration(
|
||||
mimeType = "application/x-enso",
|
||||
iconBase = "org/enso/tools/enso4igv/enso.png",
|
||||
iconBase = "org/enso/tools/enso4igv/enso.svg",
|
||||
displayName = "#LBL_Enso_LOADER",
|
||||
position = 300
|
||||
)
|
||||
@ -98,7 +98,7 @@ public class EnsoDataObject extends MultiDataObject {
|
||||
|
||||
@MultiViewElement.Registration(
|
||||
displayName = "#LBL_Enso_EDITOR",
|
||||
iconBase = "org/enso/tools/enso4igv/enso.png",
|
||||
iconBase = "org/enso/tools/enso4igv/enso.svg",
|
||||
mimeType = "application/x-enso",
|
||||
persistenceType = TopComponent.PERSISTENCE_ONLY_OPENED,
|
||||
preferredID = "Enso",
|
||||
|
@ -0,0 +1,119 @@
|
||||
package org.enso.tools.enso4igv;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.enso.tools.enso4igv.EnsoSbtClassPathProvider.EnsoSources;
|
||||
import org.netbeans.api.project.Project;
|
||||
import org.netbeans.api.project.ProjectUtils;
|
||||
import org.netbeans.api.project.SourceGroup;
|
||||
import org.netbeans.spi.java.project.support.ui.PackageView;
|
||||
import org.netbeans.spi.project.ui.LogicalViewProvider;
|
||||
import org.netbeans.spi.project.ui.support.CommonProjectActions;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
import org.openide.awt.ActionReferences;
|
||||
import org.openide.filesystems.*;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbCollections;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
|
||||
@ActionReferences({
|
||||
@ActionReference(position = 3100, id = @ActionID(category = "Project", id = "org-netbeans-modules-project-ui-CloseProject"), path = "Projects/ensosbtprj/Actions", separatorBefore = 3000),
|
||||
})
|
||||
final class EnsoLogicalView implements LogicalViewProvider {
|
||||
private final EnsoSbtProject p;
|
||||
|
||||
EnsoLogicalView(EnsoSbtProject p) {
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node createLogicalView() {
|
||||
return new EnsoSbtProjectNode(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node findPath(Node root, Object target) {
|
||||
Project prj = root.getLookup().lookup(Project.class);
|
||||
if (prj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (target instanceof FileObject) {
|
||||
FileObject fo = (FileObject) target;
|
||||
for (Node n : root.getChildren().getNodes(true)) {
|
||||
Node result = PackageView.findPath(n, target);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class EnsoSbtProjectNode extends AbstractNode {
|
||||
|
||||
private final EnsoSbtProject project;
|
||||
|
||||
public EnsoSbtProjectNode(EnsoSbtProject p) {
|
||||
super(Children.create(new EnsoRoots(p), true), Lookups.fixed(p));
|
||||
this.project = p;
|
||||
setDisplayName();
|
||||
setIconBaseWithExtension("org/enso/tools/enso4igv/enso.svg");
|
||||
}
|
||||
|
||||
private void setDisplayName() {
|
||||
setDisplayName(ProjectUtils.getInformation(project).getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHtmlDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action[] getActions(boolean context) {
|
||||
return CommonProjectActions.forType("ensosbtprj"); // NOI18N
|
||||
}
|
||||
}
|
||||
|
||||
private static final class EnsoRoots extends ChildFactory<SourceGroup> implements ChangeListener {
|
||||
private final EnsoSbtProject prj;
|
||||
|
||||
EnsoRoots(EnsoSbtProject project) {
|
||||
this.prj = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<SourceGroup> toPopulate) {
|
||||
var arr = Arrays.asList(ProjectUtils.getSources(prj).getSourceGroups(null));
|
||||
var enso = NbCollections.checkedListByCopy(arr, EnsoSources.class, true);
|
||||
for (var e : enso) {
|
||||
toPopulate.add(e);
|
||||
}
|
||||
for (var e : enso) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(SourceGroup key) {
|
||||
return PackageView.createPackageView(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
refresh(false);
|
||||
}
|
||||
|
||||
record Entry(String prefix, FileObject root) {
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +1,89 @@
|
||||
package org.enso.tools.enso4igv;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.netbeans.api.java.classpath.ClassPath;
|
||||
import org.netbeans.api.java.classpath.GlobalPathRegistry;
|
||||
import org.netbeans.api.java.platform.JavaPlatform;
|
||||
import org.netbeans.api.java.queries.SourceForBinaryQuery;
|
||||
import org.netbeans.api.project.SourceGroup;
|
||||
import org.netbeans.api.project.Sources;
|
||||
import org.netbeans.spi.java.classpath.ClassPathProvider;
|
||||
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
|
||||
import org.netbeans.spi.java.project.support.ProjectPlatform;
|
||||
import org.netbeans.spi.java.queries.BinaryForSourceQueryImplementation2;
|
||||
import org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation;
|
||||
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
|
||||
import org.netbeans.spi.java.queries.SourceLevelQueryImplementation2;
|
||||
import org.netbeans.spi.project.ui.ProjectOpenedHook;
|
||||
import org.openide.filesystems.FileObject;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.openide.filesystems.URLMapper;
|
||||
import org.openide.util.Exceptions;
|
||||
|
||||
final class EnsoSbtClassPathProvider extends ProjectOpenedHook
|
||||
implements ClassPathProvider, SourceLevelQueryImplementation2, CompilerOptionsQueryImplementation {
|
||||
implements ClassPathProvider, SourceLevelQueryImplementation2, CompilerOptionsQueryImplementation,
|
||||
Sources, BinaryForSourceQueryImplementation2<EnsoSbtClassPathProvider.EnsoSources>, SourceForBinaryQueryImplementation2 {
|
||||
private static final String BOOT = "classpath/boot";
|
||||
private static final String SOURCE = "classpath/source";
|
||||
private static final String COMPILE = "classpath/compile";
|
||||
private final EnsoSbtProject project;
|
||||
private final EnsoSources info;
|
||||
private final EnsoSources[] sources;
|
||||
|
||||
EnsoSbtClassPathProvider(EnsoSbtProject prj) {
|
||||
this.project = prj;
|
||||
this.info = computeSbtClassPath(prj);
|
||||
this.sources = computeSbtClassPath(prj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassPath findClassPath(FileObject file, String type) {
|
||||
if (FileUtil.isParentOf(project.getProjectDirectory(), file)) {
|
||||
return switch (type) {
|
||||
case SOURCE -> info.srcCp;
|
||||
case COMPILE -> info.cp;
|
||||
case BOOT -> info.platform.getBootstrapLibraries();
|
||||
default -> null;
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
for (var i : sources) {
|
||||
if (i.controlsSource(file)) {
|
||||
return switch (type) {
|
||||
case SOURCE -> i.srcCp;
|
||||
case COMPILE -> i.cp;
|
||||
case BOOT -> i.platform.getBootstrapLibraries();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectOpened() {
|
||||
GlobalPathRegistry.getDefault().register(COMPILE, new ClassPath[] { info.cp });
|
||||
GlobalPathRegistry.getDefault().register(SOURCE, new ClassPath[] { info.srcCp });
|
||||
for (var i : sources) {
|
||||
GlobalPathRegistry.getDefault().register(COMPILE, new ClassPath[] { i.cp });
|
||||
GlobalPathRegistry.getDefault().register(SOURCE, new ClassPath[] { i.srcCp });
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
GlobalPathRegistry.getDefault().unregister(COMPILE, new ClassPath[] { info.cp });
|
||||
GlobalPathRegistry.getDefault().unregister(SOURCE, new ClassPath[] { info.srcCp });
|
||||
for (var i : sources) {
|
||||
GlobalPathRegistry.getDefault().unregister(COMPILE, new ClassPath[] { i.cp });
|
||||
GlobalPathRegistry.getDefault().unregister(SOURCE, new ClassPath[] { i.srcCp });
|
||||
}
|
||||
}
|
||||
|
||||
private static EnsoSources computeSbtClassPath(EnsoSbtProject prj) {
|
||||
private static EnsoSources[] computeSbtClassPath(EnsoSbtProject prj) {
|
||||
var sources = new ArrayList<EnsoSources>();
|
||||
var platform = JavaPlatform.getDefault();
|
||||
var roots = new LinkedHashSet<>();
|
||||
var generatedSources = new LinkedHashSet<>();
|
||||
var source = "11";
|
||||
var source = "19";
|
||||
var options = new ArrayList<String>();
|
||||
for (FileObject ch : prj.getProjectDirectory().getChildren()) {
|
||||
if (ch.getNameExt().startsWith(".enso-sources")) {
|
||||
if (ch.getNameExt().startsWith(".enso-sources-")) {
|
||||
Properties p = new Properties();
|
||||
try (InputStream is = ch.getInputStream()) {
|
||||
p.load(is);
|
||||
@ -116,70 +132,238 @@ implements ClassPathProvider, SourceLevelQueryImplementation2, CompilerOptionsQu
|
||||
}
|
||||
options.add(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
var srcRoots = new LinkedHashSet<>();
|
||||
|
||||
var srcRoots = new LinkedHashSet<>();
|
||||
var srcDir = prj.getProjectDirectory().getFileObject("src");
|
||||
if (srcDir != null) {
|
||||
for (var group : srcDir.getChildren()) {
|
||||
if (group.isFolder()) {
|
||||
for (var ch : group.getChildren()) {
|
||||
if (ch.isFolder()) {
|
||||
srcRoots.add(ch);
|
||||
var inputSrc = p.getProperty("input");
|
||||
var inputDir = inputSrc != null ? FileUtil.toFileObject(new File(inputSrc)) : null;
|
||||
if (inputDir != null) {
|
||||
if (inputDir.getNameExt().equals("org")) {
|
||||
// lib/rust/parser doesn't follow typical project conventions
|
||||
inputDir = inputDir.getParent();
|
||||
}
|
||||
srcRoots.add(inputDir);
|
||||
}
|
||||
|
||||
var srcDir = prj.getProjectDirectory().getFileObject("src");
|
||||
if (srcDir != null) {
|
||||
for (var group : srcDir.getChildren()) {
|
||||
if (group.isFolder()) {
|
||||
for (var child : group.getChildren()) {
|
||||
if (child.isFolder()) {
|
||||
srcRoots.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
srcRoots.addAll(generatedSources);
|
||||
|
||||
var outputSrc = p.getProperty("output");
|
||||
var outputDir = outputSrc != null ? FileUtil.toFileObject(new File(outputSrc)) : null;
|
||||
|
||||
var generatedSrc = p.getProperty("generated");
|
||||
var generatedDir = generatedSrc != null ? FileUtil.toFileObject(new File(generatedSrc)) : null;
|
||||
if (generatedDir != null) {
|
||||
srcRoots.add(generatedDir);
|
||||
}
|
||||
|
||||
|
||||
var cp = ClassPathSupport.createClassPath(roots.toArray(new FileObject[0]));
|
||||
var srcCp = ClassPathSupport.createClassPath(srcRoots.toArray(new FileObject[0]));
|
||||
var s = new EnsoSources(cp, srcCp, platform, outputDir, source, options);
|
||||
if ("main".equals(s.getName())) {
|
||||
sources.add(0, s);
|
||||
} else {
|
||||
sources.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
srcRoots.addAll(generatedSources);
|
||||
var cp = ClassPathSupport.createClassPath(roots.toArray(new FileObject[0]));
|
||||
var srcCp = ClassPathSupport.createClassPath(srcRoots.toArray(new FileObject[0]));
|
||||
return new EnsoSources(cp, srcCp, platform, source, options);
|
||||
return sources.toArray(new EnsoSources[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceLevelQueryImplementation2.Result getSourceLevel(FileObject fo) {
|
||||
return new SourceLevelQueryImplementation2.Result() {
|
||||
@Override
|
||||
public String getSourceLevel() {
|
||||
return info.source;
|
||||
}
|
||||
for (var i : sources) {
|
||||
if (i.controlsSource(fo)) {
|
||||
return new SourceLevelQueryImplementation2.Result() {
|
||||
@Override
|
||||
public String getSourceLevel() {
|
||||
return i.source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener cl) {
|
||||
}
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener cl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener cl) {
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener cl) {
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerOptionsQueryImplementation.Result getOptions(FileObject fo) {
|
||||
return new CompilerOptionsQueryImplementation.Result() {
|
||||
@Override
|
||||
public List<? extends String> getArguments() {
|
||||
return info.options;
|
||||
}
|
||||
for (var i : sources) {
|
||||
if (i.controlsSource(fo)) {
|
||||
return new CompilerOptionsQueryImplementation.Result() {
|
||||
@Override
|
||||
public List<? extends String> getArguments() {
|
||||
return i.options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener cl) {
|
||||
}
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener cl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener cl) {
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener cl) {
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceGroup[] getSourceGroups(String string) {
|
||||
return sources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener cl) {
|
||||
}
|
||||
|
||||
private record EnsoSources(
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener cl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnsoSources findBinaryRoots2(URL url) {
|
||||
var fo = URLMapper.findFileObject(url);
|
||||
for (var i : sources) {
|
||||
if (i.outputsTo(fo) || i.controlsSource(fo)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL[] computeRoots(EnsoSources result) {
|
||||
return new URL[] { result.output().toURL() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean computePreferBinaries(EnsoSources result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeChangeListener(EnsoSources result, boolean bln, ChangeListener cl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceForBinaryQueryImplementation2.Result findSourceRoots2(URL url) {
|
||||
var fo = URLMapper.findFileObject(url);
|
||||
if (fo == null) {
|
||||
return null;
|
||||
}
|
||||
for (var i : sources) {
|
||||
if (i.outputsTo(fo) || i.controlsSource(fo)) {
|
||||
return new SourceForBinaryQueryImplementation2.Result() {
|
||||
@Override
|
||||
public boolean preferSources() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileObject[] getRoots() {
|
||||
return i.getRoots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener l) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
|
||||
return findSourceRoots2(binaryRoot);
|
||||
}
|
||||
|
||||
record EnsoSources(
|
||||
ClassPath cp, ClassPath srcCp,
|
||||
JavaPlatform platform,
|
||||
FileObject output,
|
||||
String source, List<String> options
|
||||
) {
|
||||
) implements SourceGroup {
|
||||
@Override
|
||||
public FileObject getRootFolder() {
|
||||
return srcCp.getRoots()[0];
|
||||
}
|
||||
|
||||
private FileObject[] getRoots() {
|
||||
return srcCp.getRoots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getRootFolder().getParent().getNameExt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon(boolean bln) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(FileObject fo) {
|
||||
if (getRootFolder().equals(fo)) {
|
||||
return true;
|
||||
}
|
||||
return FileUtil.isParentOf(getRootFolder(), fo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener pl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener pl) {
|
||||
}
|
||||
|
||||
private boolean controlsSource(FileObject fo) {
|
||||
return contains(fo) || srcCp.contains(fo);
|
||||
}
|
||||
|
||||
private boolean outputsTo(FileObject fo) {
|
||||
if (fo == null || output() == null) {
|
||||
return false;
|
||||
}
|
||||
if (fo.equals(output())) {
|
||||
return true;
|
||||
}
|
||||
return FileUtil.isParentOf(output(), fo);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "EnsoSources[name=" + getName() + ",root=" + getRootFolder() + ",output=" + output() + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,8 @@ public class EnsoSbtProject implements Project {
|
||||
this.ps = ps;
|
||||
this.lkp = Lookups.fixed(
|
||||
this,
|
||||
new EnsoSbtClassPathProvider(this)
|
||||
new EnsoSbtClassPathProvider(this),
|
||||
new EnsoLogicalView(this)
|
||||
);
|
||||
}
|
||||
|
||||
@ -59,7 +60,7 @@ public class EnsoSbtProject implements Project {
|
||||
@Override
|
||||
public ProjectManager.Result isProject2(FileObject fo) {
|
||||
if (isProject(fo)) {
|
||||
var img = ImageUtilities.loadImage("org/enso/tools/enso4igv/enso.png");
|
||||
var img = ImageUtilities.loadImage("org/enso/tools/enso4igv/enso.svg");
|
||||
return new ProjectManager.Result(ImageUtilities.image2Icon(img));
|
||||
}
|
||||
return null;
|
||||
|
@ -0,0 +1,85 @@
|
||||
package org.enso.tools.enso4igv;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.filesystems.FileObject;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.openide.filesystems.URLMapper;
|
||||
import org.netbeans.api.java.queries.SourceForBinaryQuery;
|
||||
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
|
||||
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
|
||||
import org.openide.util.Exceptions;
|
||||
|
||||
@org.openide.util.lookup.ServiceProvider(service = SourceForBinaryQueryImplementation.class, position = 100000)
|
||||
public class GraalVMSourceForBinaryQuery implements SourceForBinaryQueryImplementation2 {
|
||||
|
||||
public GraalVMSourceForBinaryQuery() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceForBinaryQueryImplementation2.Result findSourceRoots2(URL binaryRoot) {
|
||||
var binaryRootS = binaryRoot.toExternalForm();
|
||||
String srcZipS = null;
|
||||
String srcZipIn = null;
|
||||
if (binaryRootS.startsWith("nbjrt:")) {
|
||||
int end = binaryRootS.indexOf('!');
|
||||
if (end >= 0) {
|
||||
srcZipS = binaryRootS.substring(6, end) + "lib/src.zip";
|
||||
String reminder = binaryRootS.substring(end + 1);
|
||||
final String prefix = "/modules/";
|
||||
if (reminder.startsWith(prefix)) {
|
||||
srcZipIn = reminder.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (srcZipS != null) {
|
||||
try {
|
||||
URL srcZip = FileUtil.getArchiveRoot(new URL(srcZipS));
|
||||
FileObject fo = URLMapper.findFileObject(srcZip);
|
||||
if (fo != null) {
|
||||
if (srcZipIn != null) {
|
||||
fo = fo.getFileObject(srcZipIn);
|
||||
}
|
||||
if (fo != null) {
|
||||
return new R(fo);
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException mue) {
|
||||
Exceptions.printStackTrace(mue);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
|
||||
return this.findSourceRoots2(binaryRoot);
|
||||
}
|
||||
|
||||
private static class R implements SourceForBinaryQueryImplementation2.Result {
|
||||
private final FileObject root;
|
||||
|
||||
private R(FileObject fo) {
|
||||
root = fo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileObject[] getRoots() {
|
||||
return root.isValid() ? new FileObject[]{root} : new FileObject[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preferSources() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package org.enso.tools.enso4igv;
|
||||
|
||||
import java.net.URL;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.netbeans.api.java.queries.SourceForBinaryQuery;
|
||||
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
|
||||
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
|
||||
import org.openide.filesystems.FileObject;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.openide.filesystems.URLMapper;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
|
||||
@ServiceProvider(service = SourceForBinaryQueryImplementation.class)
|
||||
public final class NextToSourceForBinaryQueryImpl implements SourceForBinaryQueryImplementation {
|
||||
@Override
|
||||
public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
|
||||
var file = FileUtil.getArchiveFile(binaryRoot);
|
||||
if (file != null) {
|
||||
var fo = URLMapper.findFileObject(file);
|
||||
if (fo != null) {
|
||||
var src = fo.getParent().getFileObject(fo.getName() + "-sources", fo.getExt());
|
||||
if (src != null) {
|
||||
return new SourceForBinaryQueryImplementation2.Result() {
|
||||
@Override
|
||||
public boolean preferSources() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileObject[] getRoots() {
|
||||
return new FileObject[] { FileUtil.getArchiveRoot(src) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener l) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg x="0px" y="0px" width="16px" height="16px"
|
||||
viewBox="0 0 40 40"
|
||||
class="h-8 self-center mr-8 fill-current content-extrastrong"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g>
|
||||
<circle cx="20" cy="20" r="20" fill="white"></circle>
|
||||
<path d="M20.0519 0C8.93506 0 0 8.93506 0 20.0519C0 31.1688 8.93506 40.1039 20.0519 40.1039C31.0649 40.1039 40.1039 31.1688 40.1039 20.0519C40.1039 8.93506 31.0649 0 20.0519 0ZM20.0519 36.0519C11.1169 36.0519 3.94805 28.8831 3.94805 19.9481C3.94805 11.013 11.1169 3.84416 20.0519 3.84416C28.987 3.84416 36.1558 11.013 36.1558 19.9481C36.0519 28.8831 28.8831 36.0519 20.0519 36.0519Z"></path>
|
||||
<path d="M27.1169 17.7662C29.4026 18.8051 30.3377 21.4025 29.5065 23.6882C28.1558 27.6363 24.3117 30.5454 19.9481 30.5454C14.3377 30.5454 9.76623 25.974 9.76623 20.3636C9.76623 20.3636 11.3247 22.4415 14.3377 22.4415C17.3506 22.4415 18.7013 21.2986 19.9481 20.3636C21.1948 19.4285 22.026 17.3506 25.1429 17.3506C25.8701 17.3506 26.5974 17.5584 27.1169 17.7662Z"></path>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
Loading…
Reference in New Issue
Block a user