Open schowave opened 1 week ago
Thank you for reporting this @schowave.
Are you maybe using K2 mode in IntelliJ? There are currently problems with K2 and the way kte templates work (see https://github.com/casid/jte-intellij/issues/49)
Oh, you are right, then this issue is a duplicate. Sorry for the inconvenience!
No worries at all!
Claude-3.5-Sonnet says: (This is just a output of my question how to fix the import statements...)
1 Modify the KTE file parsing: You'll need to change how the plugin handles KTE files, especially the @import statements. The goal is to prevent these statements from being treated as regular Kotlin code fragments.
2 Update the KtePsiFile class: In the src/main/java/org/jusecase/jte/intellij/language/psi/KtePsiFile.java file, you might need to override methods that deal with imports. You may need to implement a custom way of handling imports that doesn't conflict with K2's expectations.
3 Implement a custom KteLanguageInjector: Create a new class that extends LanguageInjector to handle how Kotlin code is injected into KTE files. This injector should handle @import statements separately from the main code body.
4 Update the KteLanguage class: In src/main/java/org/jusecase/jte/intellij/language/KteLanguage.java, you might need to register your custom language injector.
5 Modify the KteElementType: In src/main/java/org/jusecase/jte/intellij/language/parsing/KteElementType.java, you might need to create a special element type for imports that won't be processed as regular Kotlin code.
1 First, let's modify the KtePsiFile class to handle imports differently:
public class KtePsiFile extends PsiFileBase {
private List<PsiElement> importStatements;
// ... existing constructor and methods ...
public List<PsiElement> getImportStatements() {
if (importStatements == null) {
importStatements = new ArrayList<>();
// Parse the file and collect @import statements
// This is a simplified example; you'll need to implement proper parsing
for (PsiElement child : getChildren()) {
if (child.getText().startsWith("@import")) {
importStatements.add(child);
}
}
}
return importStatements;
}
@Override
public void subtreeChanged() {
super.subtreeChanged();
importStatements = null; // Reset cache when file changes
}
}
2 Next, create a new KteKotlinLanguageInjector class:
package org.jusecase.jte.intellij.language;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinLanguage;
import org.jusecase.jte.intellij.language.psi.KtePsiFile;
import java.util.Collections;
import java.util.List;
public class KteKotlinLanguageInjector implements MultiHostInjector {
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
if (!(context instanceof KtePsiFile)) return;
KtePsiFile kteFile = (KtePsiFile) context;
List<PsiElement> imports = kteFile.getImportStatements();
// Inject Kotlin language for the main content, excluding imports
TextRange contentRange = getContentRange(kteFile, imports);
registrar.startInjecting(KotlinLanguage.INSTANCE)
.addPlace(null, null, (PsiLanguageInjectionHost) context, contentRange)
.doneInjecting();
// Handle imports separately (optional, depending on how you want to process them)
for (PsiElement importStatement : imports) {
registrar.startInjecting(KteLanguage.INSTANCE)
.addPlace(null, null, (PsiLanguageInjectionHost) context, importStatement.getTextRange())
.doneInjecting();
}
}
private TextRange getContentRange(KtePsiFile file, List<PsiElement> imports) {
int start = 0;
for (PsiElement importStmt : imports) {
start = Math.max(start, importStmt.getTextRange().getEndOffset());
}
return new TextRange(start, file.getTextLength());
}
@NotNull
@Override
public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return Collections.singletonList(KtePsiFile.class);
}
}
3 Update the plugin.xml file to register the new injector:
Add this line within the
<multiHostInjector implementation="org.jusecase.jte.intellij.language.KteKotlinLanguageInjector"/>
4 You might also need to update the KteLanguage class to ensure it's not treated as a regular Kotlin file:
public class KteLanguage extends Language implements TemplateLanguage {
// ... existing code ...
@Override
public boolean isCaseSensitive() {
return true;
}
@Override
public boolean isKindOf(Language another) {
return super.isKindOf(another) || another == KotlinLanguage.INSTANCE;
}
}
These changes should help address the K2 compiler issue by:
1 Separating the handling of @import statements from the main Kotlin code.
2 Injecting Kotlin language only for the main content, excluding imports.
3 Optionally handling imports separately within the KTE language context.
I am not sure if this is the right place for a bug report, but since updating to IntelliJ 2024.3, I have suddenly started receiving error messages regarding imports in the .kte files.
The error message reads: “Package directive and imports are forbidden in code fragments”
Is this an IntelliJ bug, or is it a syntax issue with JTE?
Thank you for your support!