feat: add TypeHints for Methods

This commit is contained in:
Ruben 2024-12-12 21:03:31 +01:00
parent 2f25c64dc6
commit 32a7a6e015
8 changed files with 114 additions and 39 deletions

View File

@ -32,7 +32,8 @@ export function activate(context: vscode.ExtensionContext) {
documentSelector: [{ scheme: 'file', language: 'java' }],
synchronize: {
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.java')
}
},
revealOutputChannelOn: 4
};
// Language Client erstellen und starten

View File

@ -34,6 +34,7 @@ public class JavaTXLanguageServer implements LanguageServer {
capabilities.setDocumentFormattingProvider(true);
capabilities.setTextDocumentSync(TextDocumentSyncKind.Full);
capabilities.setHoverProvider(true);
capabilities.setInlayHintProvider(true);
capabilities.setTextDocumentSync(TextDocumentSyncKind.Full);
capabilities.setCompletionProvider(new CompletionOptions(true, List.of()));

View File

@ -5,6 +5,8 @@ import org.antlr.v4.runtime.Token;
import org.eclipse.lsp4j.launch.LSPLauncher;
import org.eclipse.lsp4j.services.LanguageClient;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.HashSet;
/**

View File

@ -1,5 +1,6 @@
package de.dhbw;
import de.dhbw.compiler.languageServerInterface.LanguageServerInterface;
import de.dhbw.helper.CodeSnippetOptions;
import de.dhbw.helper.TypeFinder;
import de.dhbw.model.ParseError.DiagnoseErrorListener;
@ -58,11 +59,12 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
item.setInsertTextFormat(InsertTextFormat.Snippet);
completions.add(item);
}
client.showMessage(new MessageParams(MessageType.Info, "Returning completion suggestions: " + completions));
return CompletableFuture.completedFuture(Either.forLeft(completions));
}
/**
*
* Handles didOpen Events
@ -71,7 +73,7 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
* */
@Override
public void didOpen(DidOpenTextDocumentParams params) {
client.showMessage(new MessageParams(MessageType.Info, "Datei geöffnet: " + params.getTextDocument().getUri()));
}
/**
@ -103,7 +105,6 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
Java17ParserBaseListener listener = new Java17ParserBaseListener();
walker.walk(listener, tree);
client.showMessage(new MessageParams(MessageType.Info, " " + errorListener.getErrorMessages().size()));
PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(params.getTextDocument().getUri(), errorListener.getErrorMessages());
client.publishDiagnostics(diagnosticsParams);
@ -142,9 +143,35 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
@Override
public void didSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {
//Irgendwie so machen das man nur dan inlayHints bekommt wenn man das DOkument speichert.
}
@Override
public CompletableFuture<List<InlayHint>> inlayHint(InlayHintParams params) {
TypeFinder typeFinder = new TypeFinder();
try {
//TODO: change to get current Textdocument String
var languageServer = new LanguageServerInterface();
var typesOfMethods = typeFinder.infereMethodType(currentTextDocument);
List<InlayHint> typeHint = new ArrayList<>();
for (var typeOfMethod : typesOfMethods) {
InlayHint inlayHint = new InlayHint();
inlayHint.setLabel(":" + typeOfMethod.getType());
inlayHint.setPosition(new Position(typeOfMethod.getLine()-1, typeOfMethod.getCharPosition()+1));
inlayHint.setKind(InlayHintKind.Type);
typeHint.add(inlayHint);
}
return CompletableFuture.completedFuture(typeHint);
} catch (Exception e) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
}
@Override
public void willSave(WillSaveTextDocumentParams params) {
TextDocumentService.super.willSave(params);
@ -268,7 +295,6 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
String hoverText = getWordOfLineAndCharacter(params.getPosition().getLine(), params.getPosition().getCharacter(), currentTextDocument);
MarkupContent markupContent = new MarkupContent();
markupContent.setKind("markdown");
markupContent.setValue(hoverText);

View File

@ -5,10 +5,7 @@ import de.dhbw.compiler.syntaxtree.visual.ASTTypePrinter;
import de.dhbw.compiler.typeinference.result.ResultSet;
import de.dhbw.compiler.core.JavaTXCompiler;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.*;
import java.util.List;
/**
@ -20,7 +17,9 @@ public class LanguageServerInterface {
* get final Result Set
* */
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String input) throws IOException, ClassNotFoundException {
File tempSourcefile = File.createTempFile("pattern", ".java");
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
File tempSourcefile = File.createTempFile("temp", ".java");
tempSourcefile.deleteOnExit();
BufferedWriter out = new BufferedWriter(new FileWriter(tempSourcefile));
@ -28,6 +27,8 @@ public class LanguageServerInterface {
out.close();
JavaTXCompiler tx = new JavaTXCompiler(tempSourcefile);
return tx.getResultSetAndAbstractSyntax(tempSourcefile);
var test = tx.getResultSetAndAbstractSyntax(tempSourcefile);
System.setOut(System.out);
return test;
}
}

View File

@ -1,11 +1,13 @@
package de.dhbw.helper;
import de.dhbw.compiler.languageServerInterface.LanguageServerInterface;
import de.dhbw.compiler.languageServerInterface.LanguageServerTransferObject;
import de.dhbw.model.MethodNameWithType;
import java.awt.desktop.SystemSleepEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
@ -20,29 +22,21 @@ public class TypeFinder {
}
/**
* find the Type of a specific Word, given by its line and character. The character must be any Part of the Word.
* <p>
* DOES NOT WORK RIGHT NOW
*
* @param line the line of the character
* @param character the character of the character or the char-Number of the String
* @param currentTextDocument the String of the Content of the current Document.
* find the concrete Type of all TPHs and return the outcome as Hashmap.
*/
public String findAvailableTypes(int line, int character, String currentTextDocument) throws IOException, ClassNotFoundException {
public HashMap<String, ArrayList<String>> findAvailableTypes(LanguageServerTransferObject resultSet) throws IOException, ClassNotFoundException {
HashMap<String, ArrayList<String>> typePlaceholderTypes = new HashMap<>();
var resultSet = languageServer.getResultSetAndAbstractSyntax(currentTextDocument);
resultSet.getResultSets().forEach(conSet -> {
for (var constraint : conSet.results) {
var typeNameString = constraint.getLeft().toString();
System.out.println(typeNameString);
ArrayList<String> finalTypes = new ArrayList<>();
Queue<String> queue = new LinkedList<>();
if (typeNameString.contains("TPH")) {
if (typeNameString.contains("TPH ")) {
queue.add(typeNameString);
} else {
finalTypes.add(typeNameString);
@ -69,11 +63,41 @@ public class TypeFinder {
}
);
typePlaceholderTypes.forEach((k, v) -> {
System.out.println(k + " : ");
v.forEach(System.out::println);
System.out.println("-----------");
});
return "";
return typePlaceholderTypes;
}
public String findTypeOfMethod(LanguageServerTransferObject transferObj, String methodName) throws IOException, ClassNotFoundException {
var typeHashMap = findAvailableTypes(transferObj);
for (var method : transferObj.getAst().getAllMethods()) {
if (method.name.equals(methodName)) {
if (method.getReturnType().toString().contains("TPH ")) {
return typeHashMap.get(method.getReturnType().toString()).getFirst();
}else{
return method.getReturnType().toString();
}
}
}
return "java.lang.Object";
}
public ArrayList<MethodNameWithType> infereMethodType(String input) throws IOException, ClassNotFoundException {
var transferObj = languageServer.getResultSetAndAbstractSyntax(input);
//Für RefTypes und so dann entsprechend InstanceOf durch den Syntaxbaum denke ich
ArrayList<MethodNameWithType> methodNameWithTypeList = new ArrayList<>();
for (var method : transferObj.getAst().getAllMethods()) {
var type = findTypeOfMethod(transferObj, method.name);
methodNameWithTypeList.add(new MethodNameWithType(method.name, type, method.getOffset().getLine(), method.getOffset().getStartIndex()));
}
return methodNameWithTypeList;
}
}

View File

@ -3,10 +3,14 @@ package de.dhbw.model;
public class MethodNameWithType {
String name;
String type;
int line;
int charPosition;
public MethodNameWithType(String name, String type) {
public MethodNameWithType(String name, String type, int line, int charPosition) {
this.name = name;
this.type = type;
this.line = line;
this.charPosition = charPosition;
}
public String getName() {
@ -24,4 +28,16 @@ public class MethodNameWithType {
public void setType(String type) {
this.type = type;
}
public int getLine() {
return line;
}
public void setLine(int line) {
this.line = line;
}
public int getCharPosition() {
return charPosition;
}
public void setCharPosition(int charPosition) {
this.charPosition = charPosition;
}
}

View File

@ -28,12 +28,16 @@ public class CompilerInterfaceTest {
@Test
public void testTypeFinder() throws IOException, ClassNotFoundException {
TypeFinder typeFinder = new TypeFinder();
typeFinder.findAvailableTypes(0,0, "import java.lang.Integer; public class test{\n" +
" \n" +
" public main( test){\n" +
" Integer i = test; " +
" return i;\n" +
" }\n" +
"}");
var inferedMethods = typeFinder.infereMethodType("import java.lang.Integer;" +
"public class test{"+
"public main(test){"+
"Integer i = 0;"+
"return i;"+
"}"+
"}"
);
inferedMethods.forEach(el -> System.out.println(el.getName() + ": " + el.getType()));
}
}