Skip to content

Commit

Permalink
Merge pull request #34 from ingwarsw/add-commenter
Browse files Browse the repository at this point in the history
Add extra features to plugin
  • Loading branch information
idelvall authored Jul 5, 2024
2 parents d6a37a5 + 8eab843 commit dcc2cd2
Show file tree
Hide file tree
Showing 31 changed files with 1,176 additions and 92 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
on:
pull_request:
push:

jobs:
test:
runs-on: ubuntu-latest
env:
FORCE_COLOR: 1
EARTHLY_CONVERSION_PARALLELISM: "5"
steps:
- uses: actions/checkout@v2
- uses: earthly/actions/setup-earthly@v1
- name: test
run: earthly +test
14 changes: 5 additions & 9 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@ VERSION --pass-args --global-cache --use-function-keyword 0.7
PROJECT earthly-technologies/core
IMPORT github.com/earthly/lib/gradle:0a891b93330eced8fe57f48397a1109d829cb7d4 AS gradle
ARG --global gradle_version=8.2.1
ARG --global bundle="github.com/earthly/earthfile-grammar+export/"
FROM gradle:${gradle_version}-jdk17

GET_BUNDLE:
FUNCTION
COPY $bundle build/
RUN scripts/bundle.sh build/earthfile-syntax-highlighting

install:
RUN apt-get update && apt-get install -y \
zip \
Expand All @@ -21,11 +15,14 @@ install:
src:
FROM +install
COPY src src
COPY scripts scripts
DO +GET_BUNDLE
ARG --required version
RUN sed -i 's^0.0.0^'"$version"'^g' ./build.gradle.kts

test:
ARG version="0.0.0"
FROM +src --version=$version
RUN --mount=$EARTHLY_GRADLE_USER_HOME_CACHE --mount=$EARTHLY_GRADLE_PROJECT_CACHE gradle --no-daemon test

# dist builds the plugin and saves the artifact locally
dist:
ARG version="0.0.0"
Expand Down Expand Up @@ -66,5 +63,4 @@ generate-gradle-wrapper:
# ide opens an IntelliJ IDE with the plugin installed. Requires ./gradlew (see +generate-gradle-wrapper)
ide:
LOCALLY
DO +GET_BUNDLE
RUN ./gradlew runIde
18 changes: 7 additions & 11 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
plugins {
id("java")
id("org.jetbrains.intellij") version "1.16.1"
id("org.jetbrains.intellij") version "1.17.3"
}

dependencies {
implementation("org.apache.commons:commons-collections4:4.4")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.1")
testImplementation("junit:junit:4.13.2")
}

sourceSets["main"].java.srcDirs("src/main/gen")

group = "dev.earthly"
version = "0.0.0"

Expand All @@ -20,7 +17,7 @@ repositories {

// Configure Gradle IntelliJ Plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
intellij {
version.set("2021.2")
version.set("2023.2.6")
type.set("IU") // Target IDE Platform
plugins.set(listOf("org.jetbrains.plugins.textmate"))
}
Expand All @@ -29,12 +26,12 @@ intellij {
tasks {
// Set the JVM compatibility versions
withType<JavaCompile> {
sourceCompatibility = "11"
targetCompatibility = "11"
sourceCompatibility = "17"
targetCompatibility = "17"
}

patchPluginXml {
sinceBuild.set("212")
sinceBuild.set("232")
untilBuild.set("241.*")
}

Expand All @@ -49,7 +46,6 @@ tasks {
}

test {
useJUnitPlatform()
include("dev/earthly/plugin/lexer/**")
useJUnit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.util.ProcessingContext;
import dev.earthly.plugin.language.syntax.psi.EarthlyPsiElement;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class EarthlyCompletionContributor extends CompletionContributor {
EarthlyCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement().withParent(EarthlyPsiElement.class),
new CompletionProvider<>() {
public void addCompletions(@NotNull CompletionParameters parameters,
@NotNull ProcessingContext context,
@NotNull CompletionResultSet resultSet) {
final PsiElement element = parameters.getPosition().getParent();
final Project project = element.getProject();

String key = element.getText().replace(CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED, "");
if (StringUtils.isEmpty(key))
return;
List<PsiElement> matched = EarthlyUtil.findAllFunctions(project, (EarthlyPsiElement) element);
for (PsiElement potential : matched) {
if (potential.getText().startsWith(key))
resultSet.addElement(LookupElementBuilder.create(potential.getText()));
}
}
}
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.lang.cacheBuilder.DefaultWordsScanner;
import com.intellij.lang.cacheBuilder.WordsScanner;
import com.intellij.lang.findUsages.FindUsagesProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.TokenSet;
import dev.earthly.plugin.language.syntax.highlighting.EarthlyHighlightingLexer;
import dev.earthly.plugin.language.syntax.highlighting.EarthlyTokenSets;
import dev.earthly.plugin.language.syntax.psi.EarthlyPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class EarthlyFindUsagesProvider implements FindUsagesProvider {

@Override
public WordsScanner getWordsScanner() {
return new DefaultWordsScanner(new EarthlyHighlightingLexer(),
EarthlyTokenSets.IDENTIFIERS,
EarthlyTokenSets.COMMENTS,
TokenSet.EMPTY);
}

@Override
public boolean canFindUsagesFor(@NotNull PsiElement psiElement) {
return psiElement instanceof EarthlyPsiElement;
}

@Nullable
@Override
public String getHelpId(@NotNull PsiElement psiElement) {
return null;
}

@NotNull
@Override
public String getType(@NotNull PsiElement element) {
if (element instanceof EarthlyPsiElement) {
return "earthly target";
}
return "";
}

@NotNull
@Override
public String getDescriptiveName(@NotNull PsiElement element) {
if (element instanceof EarthlyPsiElement) {
return "Earthly: " + element.getText();
}
return "";
}

@NotNull
@Override
public String getNodeText(@NotNull PsiElement element, boolean useFullName) {
if (element instanceof EarthlyPsiElement) {
return element.getText();
}
return "";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import dev.earthly.plugin.language.syntax.psi.EarthlyPsiElement;
import dev.earthly.plugin.metadata.EarthlyIcons;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.List;

final class EarthlyLineMarkerProvider extends RelatedItemLineMarkerProvider {

@Override
protected void collectNavigationMarkers(@NotNull PsiElement element,
@NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result) {
if (!(element instanceof EarthlyPsiElement eapsi)) {
return;
}

Project project = element.getProject();
final List<PsiElement> functions = EarthlyUtil.findFunctionsByName(project, eapsi);

if (!functions.isEmpty()) {
NavigationGutterIconBuilder<PsiElement> builder =
NavigationGutterIconBuilder.create(EarthlyIcons.FILE)
.setTargets(functions)
.setTooltipText("Navigate to Earthly language property");
result.add(builder.createLineMarkerInfo(element));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.lang.refactoring.NamesValidator;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;

public class EarthlyNamesValidator implements NamesValidator {
private static final Predicate<String> TARGET_PATTERN = Pattern.compile("^[a-z][a-zA-Z0-9.\\-]*$").asMatchPredicate();
private static final Predicate<String> FUNCTION_PATTERN = Pattern.compile("^[A-Z][a-zA-Z0-9._]*$").asMatchPredicate();
@Override
public boolean isKeyword(@NotNull String name, Project project) {
List<String> keywords = List.of("base");
return keywords.contains(name);
}

@Override
public boolean isIdentifier(@NotNull String name, Project project) {
final int len = name.length();
if (len == 0) return false;
if (isKeyword(name, project))
return false;
return TARGET_PATTERN.test(name) || FUNCTION_PATTERN.test(name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.psi.PsiElement;
import dev.earthly.plugin.language.syntax.psi.EarthlyPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class EarthlyRefactoringSupportProvider extends RefactoringSupportProvider {
@Override
public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement elementToRename, @Nullable PsiElement context) {
return (elementToRename instanceof EarthlyPsiElement);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import dev.earthly.plugin.language.syntax.psi.EarthlyPsiElement;
import dev.earthly.plugin.metadata.EarthlyIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

final class EarthlyReference extends PsiReferenceBase<EarthlyPsiElement> implements PsiPolyVariantReference {

EarthlyReference(@NotNull EarthlyPsiElement element) {
super(element, new TextRange(0, element.getTextLength()));
}

@Override
public ResolveResult @NotNull [] multiResolve(boolean incompleteCode) {
Project project = myElement.getProject();
final List<PsiElement> properties = EarthlyUtil.findFunctionsByName(project, myElement);
List<ResolveResult> results = new ArrayList<>();
for (PsiElement property : properties) {
if (property != myElement)
results.add(new PsiElementResolveResult(property));
}
return results.toArray(new ResolveResult[0]);
}

@Nullable
@Override
public PsiElement resolve() {
ResolveResult[] resolveResults = multiResolve(false);
return resolveResults.length == 1 ? resolveResults[0].getElement() : null;
}

@Override
public Object @NotNull [] getVariants() {
Project project = myElement.getProject();
final List<PsiElement> properties = EarthlyUtil.findFunctionsByName(project, myElement);
List<LookupElement> variants = new ArrayList<>();
for (final PsiElement property : properties) {
if (property != myElement) {
variants.add(LookupElementBuilder
.create(property).withIcon(EarthlyIcons.FILE)
.withTypeText(property.getContainingFile().getName())
);
}
}
return variants.toArray();
}

@Override
public PsiElement handleElementRename(@NotNull String newElementName) throws IncorrectOperationException {
return myElement.setName(newElementName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.earthly.plugin.language.syntax;

import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
import dev.earthly.plugin.language.syntax.psi.EarthlyPsiElement;
import org.jetbrains.annotations.NotNull;

import static com.intellij.patterns.PlatformPatterns.psiElement;

final class EarthlyReferenceContributor extends PsiReferenceContributor {

@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(psiElement(EarthlyPsiElement.class),
new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element,
@NotNull ProcessingContext context) {
return new PsiReference[]{new EarthlyReference((EarthlyPsiElement) element)};
}
});
}
}
Loading

0 comments on commit dcc2cd2

Please sign in to comment.