feat: Gutter launch buttons
This commit is contained in:
parent
d6afb01d08
commit
c3145edc5c
11 changed files with 386 additions and 17 deletions
|
@ -23,6 +23,12 @@ Changelog structure reference:
|
|||
- Toolchain
|
||||
- Debugging Support
|
||||
|
||||
- Editor
|
||||
- Gutter icons for:
|
||||
- Launching a file with a `main` top level function
|
||||
- Launching a file with tests in it
|
||||
- Running `zig build` from a build.zig file
|
||||
|
||||
### Fixed
|
||||
|
||||
- Toolchain
|
||||
|
|
30
README.md
30
README.md
|
@ -28,10 +28,11 @@ and the Eclipse LSP4J project
|
|||
A multifunctional Zig Programming Language plugin for the IDEA platform.
|
||||
|
||||
Core features:
|
||||
- Uses ZLS (Zig Language Server) for code assistance, syntax highlighting, and anything to do with smart coding
|
||||
- Uses ZLS (Zig Language Server) for code assistance, syntax highlighting, and anything to do with coding assistance
|
||||
- Supports build.zig.zon files with autocomplete
|
||||
- Per-project Zig toolchain integration
|
||||
- Debugging support for CLion (builtin), and IDEA Ultimate [With this plugin](https://plugins.jetbrains.com/plugin/12775-native-debugging-support)
|
||||
- Gutter icon for running main(), tests, and build
|
||||
|
||||
|
||||
## Setting up the language server
|
||||
|
@ -60,19 +61,20 @@ Currently, the debugger only works with the bundled LLDB debugger, so make sure
|
|||
## Feature tracker:
|
||||
|
||||
### .zig files:
|
||||
- Working:
|
||||
- Code completion
|
||||
- Code folding
|
||||
- Syntax highlighting
|
||||
- Inlay hints
|
||||
- Basic error diagnostics
|
||||
- Go to definition
|
||||
- Rename symbol
|
||||
- Hover documentation
|
||||
- Go to implementations / find usages
|
||||
- Brace/Parenthesis/Bracket matching
|
||||
- Breakpoints (CLion/IDEA Ultimate)
|
||||
- File creation prompt
|
||||
- Code completion
|
||||
- Code folding
|
||||
- Syntax highlighting
|
||||
- Inlay hints
|
||||
- Basic error diagnostics
|
||||
- Go to definition
|
||||
- Rename symbol
|
||||
- Hover documentation
|
||||
- Go to implementations / find usages
|
||||
- Brace/Parenthesis/Bracket matching
|
||||
- Breakpoints (CLion/IDEA Ultimate)
|
||||
- File creation prompt
|
||||
- Gutter launch buttons
|
||||
|
||||
- TODO:
|
||||
- Workspace Symbols
|
||||
|
||||
|
|
|
@ -19,11 +19,15 @@ package com.falsepattern.zigbrains.project.execution.actions;
|
|||
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration;
|
||||
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationType;
|
||||
import com.falsepattern.zigbrains.zig.parser.ZigFile;
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
|
||||
import com.falsepattern.zigbrains.zig.util.PsiUtil;
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.actions.ConfigurationFromContext;
|
||||
import com.intellij.execution.configurations.ConfigurationFactory;
|
||||
import com.intellij.execution.configurations.ConfigurationTypeUtil;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -38,6 +42,27 @@ public class ZigRunExecutionConfigurationProducer extends AbstractZigRunExecutio
|
|||
|
||||
@Override
|
||||
protected boolean setupConfigurationFromContext(@NotNull ZigRunExecutionConfiguration configuration, @NotNull ConfigurationContext context, @NotNull Ref<PsiElement> sourceElement) {
|
||||
var loc = context.getLocation();
|
||||
if (loc == null) {
|
||||
return false;
|
||||
}
|
||||
var element = loc.getPsiElement();
|
||||
var psiFile = element.getContainingFile();
|
||||
if (psiFile == null) {
|
||||
return false;
|
||||
}
|
||||
var theFile = psiFile.getVirtualFile();
|
||||
var filePath = theFile.getPath();
|
||||
if (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) {
|
||||
configuration.command = "test " + filePath;
|
||||
configuration.setName("Test " + theFile.getPresentableName());
|
||||
} else if ("build.zig".equals(theFile.getName())) {
|
||||
configuration.command = "build";
|
||||
configuration.setName("Build");
|
||||
} else {
|
||||
configuration.command = "run " + filePath;
|
||||
configuration.setName(theFile.getPresentableName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -46,10 +71,24 @@ public class ZigRunExecutionConfigurationProducer extends AbstractZigRunExecutio
|
|||
if (context.getLocation() == null) {
|
||||
return false;
|
||||
}
|
||||
var element = context.getLocation().getPsiElement();
|
||||
if (element.getContainingFile() == null) {
|
||||
val element = context.getLocation().getPsiElement();
|
||||
val file = element.getContainingFile();
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
return element.getContainingFile() instanceof ZigFile;
|
||||
if (!(file instanceof ZigFile)) {
|
||||
return false;
|
||||
}
|
||||
val vFile = file.getVirtualFile();
|
||||
val filePath = vFile.getPath();
|
||||
if (!configuration.command.contains(filePath)) {
|
||||
return configuration.command.startsWith("build") && vFile.getName().equals("build.zig");
|
||||
}
|
||||
return (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) == configuration.command.startsWith("test ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReplace(@NotNull ConfigurationFromContext self, @NotNull ConfigurationFromContext other) {
|
||||
return self.getConfigurationType() instanceof ZigRunExecutionConfigurationType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2023 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.execution.linemarker;
|
||||
|
||||
import com.intellij.execution.lineMarker.RunLineMarkerContributor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ZigAggregateLineMarkerContributor extends RunLineMarkerContributor {
|
||||
private final List<RunLineMarkerContributor> contributors = List.of(
|
||||
new ZigExecutableRunLineMarkerContributor(),
|
||||
new ZigTestLineMarkerContributor(),
|
||||
new ZigBuildLineMarkerContributor()
|
||||
);
|
||||
@Override
|
||||
public @Nullable Info getInfo(@NotNull PsiElement element) {
|
||||
for (var contributor: contributors) {
|
||||
var info = contributor.getInfo(element);
|
||||
if (info != null) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2023 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.execution.linemarker;
|
||||
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
|
||||
import com.falsepattern.zigbrains.zig.util.PsiUtil;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public class ZigBuildLineMarkerContributor extends ZigTopLevelDeclarationLineMarkerContributorBase {
|
||||
@Override
|
||||
protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) {
|
||||
if (PsiUtil.getElementType(element) != ZigTypes.IDENTIFIER) {
|
||||
return null;
|
||||
}
|
||||
if (!element.textMatches("build")) {
|
||||
return null;
|
||||
}
|
||||
var parent = element.getParent();
|
||||
if (PsiUtil.getElementType(parent) != ZigTypes.FN_PROTO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var file = element.getContainingFile();
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
var fileName = file.getVirtualFile().getName();
|
||||
if (!"build.zig".equals(fileName)) {
|
||||
return null;
|
||||
}
|
||||
return parent.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Icon getIcon(@NotNull PsiElement element) {
|
||||
return AllIcons.RunConfigurations.TestState.Run;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2023 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.execution.linemarker;
|
||||
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
|
||||
import com.falsepattern.zigbrains.zig.util.PsiUtil;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public class ZigExecutableRunLineMarkerContributor extends ZigTopLevelDeclarationLineMarkerContributorBase {
|
||||
@Override
|
||||
protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) {
|
||||
if (PsiUtil.getElementType(element) != ZigTypes.IDENTIFIER) {
|
||||
return null;
|
||||
}
|
||||
if (!element.textMatches("main")) {
|
||||
return null;
|
||||
}
|
||||
var parent = element.getParent();
|
||||
if (PsiUtil.getElementType(parent) != ZigTypes.FN_PROTO) {
|
||||
return null;
|
||||
}
|
||||
return parent.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Icon getIcon(@NotNull PsiElement element) {
|
||||
return AllIcons.RunConfigurations.TestState.Run;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2023 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.execution.linemarker;
|
||||
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
|
||||
import com.falsepattern.zigbrains.zig.util.PsiUtil;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public class ZigTestLineMarkerContributor extends ZigTopLevelDeclarationLineMarkerContributorBase {
|
||||
@Override
|
||||
protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) {
|
||||
if (PsiUtil.getElementType(element) != ZigTypes.KEYWORD_TEST) {
|
||||
return null;
|
||||
}
|
||||
var parent = element.getParent();
|
||||
if (PsiUtil.getElementType(parent) != ZigTypes.TEST_DECL) {
|
||||
return null;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Icon getIcon(@NotNull PsiElement element) {
|
||||
return AllIcons.RunConfigurations.TestState.Run;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2023 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.execution.linemarker;
|
||||
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
|
||||
import com.falsepattern.zigbrains.zig.util.PsiUtil;
|
||||
import com.intellij.execution.lineMarker.ExecutorAction;
|
||||
import com.intellij.execution.lineMarker.RunLineMarkerContributor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public abstract class ZigTopLevelDeclarationLineMarkerContributorBase extends RunLineMarkerContributor {
|
||||
@Override
|
||||
public @Nullable Info getInfo(@NotNull PsiElement element) {
|
||||
PsiElement parent = getDeclaration(element);
|
||||
|
||||
int nestingLevel = 0;
|
||||
while (parent != null && !(parent instanceof PsiFile)) {
|
||||
if (PsiUtil.getElementType(parent) == ZigTypes.CONTAINER_DECLARATION) {
|
||||
nestingLevel++;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
if (nestingLevel != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
val actions = ExecutorAction.getActions(0);
|
||||
return new Info(getIcon(element), actions, null);
|
||||
}
|
||||
|
||||
protected abstract @Nullable PsiElement getDeclaration(@NotNull PsiElement element);
|
||||
|
||||
protected abstract @NotNull Icon getIcon(@NotNull PsiElement element);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2023 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.runconfig;
|
||||
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ZigRegularRunner extends ZigExecutableRunner{
|
||||
public ZigRegularRunner() {
|
||||
super(DefaultRunExecutor.EXECUTOR_ID, "Unable to run zig");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull @NonNls String getRunnerId() {
|
||||
return "ZigRegularRunner";
|
||||
}
|
||||
}
|
|
@ -11,6 +11,12 @@
|
|||
instance="com.falsepattern.zigbrains.project.ide.project.ZigProjectConfigurable"
|
||||
id="com.falsepattern.zigbrains.project.ide.project.ZigProjectConfigurable"
|
||||
displayName="Zig"/>
|
||||
|
||||
<runLineMarkerContributor language="Zig"
|
||||
implementationClass="com.falsepattern.zigbrains.project.execution.linemarker.ZigAggregateLineMarkerContributor"/>
|
||||
|
||||
<programRunner implementation="com.falsepattern.zigbrains.project.runconfig.ZigRegularRunner"
|
||||
id="ZigDebugRunner"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2023 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.zig.util;
|
||||
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigFnProto;
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PsiUtil {
|
||||
@Contract("null -> null")
|
||||
public static @Nullable IElementType getElementType(@Nullable PsiElement element) {
|
||||
if (element instanceof ASTWrapperPsiElement ast) {
|
||||
return ast.getNode().getElementType();
|
||||
} else if (element instanceof ASTNode ast) {
|
||||
return ast.getElementType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue