feat: External Libraries and some toolchain perf tweaks
This commit is contained in:
parent
cac455b460
commit
6514f65980
9 changed files with 253 additions and 9 deletions
|
@ -17,6 +17,11 @@ Changelog structure reference:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Zig
|
||||||
|
- External Libraries support for zig stdlib
|
||||||
|
|
||||||
## [14.1.0]
|
## [14.1.0]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023-2024 FalsePattern
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.falsepattern.zigbrains.common.util;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Lazy<T> {
|
||||||
|
private T value;
|
||||||
|
|
||||||
|
private final Supplier<T> initializer;
|
||||||
|
|
||||||
|
public T get() {
|
||||||
|
if (value != null)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
if (value != null)
|
||||||
|
return value;
|
||||||
|
return value = initializer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettings;
|
||||||
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
|
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
|
||||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainProvider;
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainProvider;
|
||||||
|
import com.falsepattern.zigbrains.project.toolchain.tools.ZigCompilerTool;
|
||||||
import com.intellij.openapi.project.ProjectManager;
|
import com.intellij.openapi.project.ProjectManager;
|
||||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||||
import com.intellij.openapi.util.Disposer;
|
import com.intellij.openapi.util.Disposer;
|
||||||
|
@ -114,8 +115,8 @@ public class ZigProjectSettingsPanel implements MyDisposable {
|
||||||
() -> {
|
() -> {
|
||||||
val toolchain = Optional.ofNullable(pathToToolchain).map(ZigToolchainProvider::findToolchain).orElse(null);
|
val toolchain = Optional.ofNullable(pathToToolchain).map(ZigToolchainProvider::findToolchain).orElse(null);
|
||||||
val zig = Optional.ofNullable(toolchain).map(AbstractZigToolchain::zig).orElse(null);
|
val zig = Optional.ofNullable(toolchain).map(AbstractZigToolchain::zig).orElse(null);
|
||||||
val version = Optional.ofNullable(zig).flatMap(z -> z.queryVersion(Path.of("."))).orElse(null);
|
val version = Optional.ofNullable(zig).flatMap(ZigCompilerTool::queryVersion).orElse(null);
|
||||||
val stdPath = Optional.ofNullable(zig).flatMap(z -> z.getStdPath(Path.of("."))).orElse(null);
|
val stdPath = Optional.ofNullable(zig).flatMap(ZigCompilerTool::getStdPath).orElse(null);
|
||||||
|
|
||||||
return new Pair<>(version, stdPath);
|
return new Pair<>(version, stdPath);
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.toolchain;
|
package com.falsepattern.zigbrains.project.toolchain;
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.common.util.Lazy;
|
||||||
import com.falsepattern.zigbrains.project.toolchain.flavours.AbstractZigToolchainFlavour;
|
import com.falsepattern.zigbrains.project.toolchain.flavours.AbstractZigToolchainFlavour;
|
||||||
import com.falsepattern.zigbrains.project.toolchain.tools.ZigCompilerTool;
|
import com.falsepattern.zigbrains.project.toolchain.tools.ZigCompilerTool;
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||||
|
@ -31,6 +32,8 @@ import java.util.Objects;
|
||||||
public abstract class AbstractZigToolchain {
|
public abstract class AbstractZigToolchain {
|
||||||
private final Path location;
|
private final Path location;
|
||||||
|
|
||||||
|
private final Lazy<ZigCompilerTool> zig = new Lazy<>(() -> new ZigCompilerTool(this));
|
||||||
|
|
||||||
public static @Nullable AbstractZigToolchain suggest() {
|
public static @Nullable AbstractZigToolchain suggest() {
|
||||||
return suggest(null);
|
return suggest(null);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +49,7 @@ public abstract class AbstractZigToolchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZigCompilerTool zig() {
|
public ZigCompilerTool zig() {
|
||||||
return new ZigCompilerTool(this);
|
return zig.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract int executionTimeoutInMilliseconds();
|
public abstract int executionTimeoutInMilliseconds();
|
||||||
|
|
|
@ -18,17 +18,23 @@ package com.falsepattern.zigbrains.project.toolchain;
|
||||||
|
|
||||||
import com.intellij.execution.wsl.WslPath;
|
import com.intellij.execution.wsl.WslPath;
|
||||||
import com.intellij.openapi.util.SystemInfo;
|
import com.intellij.openapi.util.SystemInfo;
|
||||||
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
public class LocalZigToolchainProvider implements ZigToolchainProvider {
|
public class LocalZigToolchainProvider implements ZigToolchainProvider {
|
||||||
|
private static final Map<Path, LocalZigToolchain> tcCache = ContainerUtil.createWeakKeyWeakValueMap();
|
||||||
@Override
|
@Override
|
||||||
public @Nullable AbstractZigToolchain getToolchain(Path homePath) {
|
public @Nullable AbstractZigToolchain getToolchain(Path homePath) {
|
||||||
if (SystemInfo.isWindows && WslPath.isWslUncPath(homePath.toString())) {
|
if (SystemInfo.isWindows && WslPath.isWslUncPath(homePath.toString())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LocalZigToolchain(homePath);
|
return tcCache.computeIfAbsent(homePath, LocalZigToolchain::new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023-2024 FalsePattern
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.falsepattern.zigbrains.project.toolchain.stdlib;
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.roots.AdditionalLibraryRootsProvider;
|
||||||
|
import com.intellij.openapi.roots.SyntheticLibrary;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class ZigLibraryRootProvider extends AdditionalLibraryRootsProvider {
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<SyntheticLibrary> getAdditionalProjectLibraries(@NotNull Project project) {
|
||||||
|
return Collections.singleton(new ZigSyntheticLibrary(project));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023-2024 FalsePattern
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.falsepattern.zigbrains.project.toolchain.stdlib;
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.common.util.ApplicationUtil;
|
||||||
|
import com.falsepattern.zigbrains.common.util.PathUtil;
|
||||||
|
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
|
||||||
|
import com.falsepattern.zigbrains.zig.Icons;
|
||||||
|
import com.falsepattern.zigbrains.zig.parser.ZigFile;
|
||||||
|
import com.intellij.navigation.ItemPresentation;
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.project.ProjectUtil;
|
||||||
|
import com.intellij.openapi.roots.SyntheticLibrary;
|
||||||
|
import com.intellij.openapi.util.NlsSafe;
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.val;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ZigSyntheticLibrary extends SyntheticLibrary implements ItemPresentation {
|
||||||
|
private final Future<Collection<VirtualFile>> roots;
|
||||||
|
private final Future<String> name;
|
||||||
|
public ZigSyntheticLibrary(Project project) {
|
||||||
|
val service = ZigProjectSettingsService.getInstance(project);
|
||||||
|
val state = service.getState();
|
||||||
|
this.roots = ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||||
|
var roots = pathToVFS(state.getExplicitPathToStd());
|
||||||
|
if (roots != null) {
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
val toolchain = state.getToolchain();
|
||||||
|
if (toolchain != null) {
|
||||||
|
val stdPath =
|
||||||
|
toolchain.zig().getStdPath().orElse(null);
|
||||||
|
return pathToVFS(stdPath);
|
||||||
|
}
|
||||||
|
return Collections.emptySet();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.name = ApplicationManager.getApplication()
|
||||||
|
.executeOnPooledThread(() -> Optional.ofNullable(state.getToolchain())
|
||||||
|
.flatMap(tc -> tc.zig().queryVersion())
|
||||||
|
.map(version -> "Zig " + version)
|
||||||
|
.orElse("Zig"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @Nullable Collection<VirtualFile> pathToVFS(String path) {
|
||||||
|
if (path != null && !path.isEmpty()) {
|
||||||
|
val thePath = PathUtil.pathFromString(path);
|
||||||
|
if (thePath != null) {
|
||||||
|
val file = VfsUtil.findFile(thePath, true);
|
||||||
|
if (file != null) {
|
||||||
|
val children = file.getChildren();
|
||||||
|
if (children != null && children.length > 0)
|
||||||
|
return Arrays.asList(children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<VirtualFile> getSourceRoots() {
|
||||||
|
try {
|
||||||
|
return roots.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<VirtualFile> getBinaryRoots() {
|
||||||
|
return super.getBinaryRoots();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof ZigSyntheticLibrary other && Objects.equals(roots.get(), other.roots.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(roots.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NlsSafe @Nullable String getPresentableText() {
|
||||||
|
try {
|
||||||
|
return name.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "Zig";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Icon getIcon(boolean unused) {
|
||||||
|
return Icons.ZIG;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,20 +16,45 @@
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.toolchain.tools;
|
package com.falsepattern.zigbrains.project.toolchain.tools;
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.common.util.Lazy;
|
||||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainEnvironmentSerializable;
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainEnvironmentSerializable;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.intellij.execution.process.ProcessOutput;
|
import com.intellij.execution.process.ProcessOutput;
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
|
import lombok.val;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
|
||||||
public class ZigCompilerTool extends AbstractZigTool{
|
public class ZigCompilerTool extends AbstractZigTool{
|
||||||
public static final String TOOL_NAME = "zig";
|
public static final String TOOL_NAME = "zig";
|
||||||
|
private final Lazy<Optional<String>> version;
|
||||||
|
private final Lazy<Optional<String>> stdPath;
|
||||||
|
|
||||||
public ZigCompilerTool(AbstractZigToolchain toolchain) {
|
public ZigCompilerTool(AbstractZigToolchain toolchain) {
|
||||||
super(toolchain, TOOL_NAME);
|
super(toolchain, TOOL_NAME);
|
||||||
|
val app = ApplicationManager.getApplication();
|
||||||
|
val baseFuture = app.executeOnPooledThread(() -> getEnv(null));
|
||||||
|
version = new Lazy<>(() -> {
|
||||||
|
try {
|
||||||
|
return baseFuture.get().map(ZigToolchainEnvironmentSerializable::version);
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stdPath = new Lazy<>(() -> {
|
||||||
|
try {
|
||||||
|
return baseFuture.get().map(ZigToolchainEnvironmentSerializable::stdDirectory);
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ZigToolchainEnvironmentSerializable> getEnv(@Nullable Path workingDirectory) {
|
public Optional<ZigToolchainEnvironmentSerializable> getEnv(@Nullable Path workingDirectory) {
|
||||||
|
@ -39,11 +64,11 @@ public class ZigCompilerTool extends AbstractZigTool{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> getStdPath(@Nullable Path workingDirectory) {
|
public Optional<String> getStdPath() {
|
||||||
return getEnv(workingDirectory).map(ZigToolchainEnvironmentSerializable::stdDirectory);
|
return stdPath.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> queryVersion(@Nullable Path workingDirectory) {
|
public Optional<String> queryVersion() {
|
||||||
return getEnv(workingDirectory).map(ZigToolchainEnvironmentSerializable::version);
|
return version.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,8 @@
|
||||||
|
|
||||||
<consoleFilterProvider implementation="com.falsepattern.zigbrains.project.console.ZigConsoleFilterProvider"/>
|
<consoleFilterProvider implementation="com.falsepattern.zigbrains.project.console.ZigConsoleFilterProvider"/>
|
||||||
<analyzeStacktraceFilter implementation="com.falsepattern.zigbrains.project.console.ZigSourceFileFilter"/>
|
<analyzeStacktraceFilter implementation="com.falsepattern.zigbrains.project.console.ZigSourceFileFilter"/>
|
||||||
|
|
||||||
|
<additionalLibraryRootsProvider implementation="com.falsepattern.zigbrains.project.toolchain.stdlib.ZigLibraryRootProvider"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
||||||
|
|
Loading…
Add table
Reference in a new issue