Compare commits

...
2 Commits
Author SHA1 Message Date
dholle ab5a6b06b1 Version bump 2026-07-16 14:07:35 +02:00
dholle ce2f9aae86 Fix duplicate insert points for Methods 2026-07-02 16:35:12 +02:00
13 changed files with 166 additions and 62 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "java-tx-language-extension",
"version": "0.0.21",
"version": "0.0.22",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "java-tx-language-extension",
"version": "0.0.21",
"version": "0.0.22",
"dependencies": {
"@vscode/vsce": "^3.6.1",
"vscode-languageclient": "^9.0.1"
+1 -1
View File
@@ -3,7 +3,7 @@
"name": "java-tx-language-extension",
"displayName": "Java-TX Language Extension",
"description": "The Language Extension for Java-TX with Typehints and Syntax Checks",
"version": "0.0.21",
"version": "0.0.22",
"engines": {
"vscode": "^1.94.0"
},
@@ -1,7 +1,5 @@
package de.dhbw;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
@@ -16,7 +14,6 @@ import java.util.concurrent.CompletableFuture;
*
* */
public class JavaTXLanguageServer implements LanguageServer {
private static final Logger logger = LogManager.getLogger(JavaTXLanguageServer.class);
public static ClientCapabilities capabilities;
private LanguageClient client;
@@ -25,7 +22,7 @@ public class JavaTXLanguageServer implements LanguageServer {
textDocumentService.setClient(client);
}
private final JavaTXTextDocumentService textDocumentService = new JavaTXTextDocumentService();
public final JavaTXTextDocumentService textDocumentService = new JavaTXTextDocumentService();
private final JavaTXWorkspaceService workspaceService = new JavaTXWorkspaceService();
@Override
@@ -13,11 +13,11 @@ import org.eclipse.lsp4j.services.LanguageClient;
* */
public class JavaTXLanguageServerLauncher {
private static final Logger logger = LogManager.getLogger(JavaTXLanguageServerLauncher.class);
public static JavaTXLanguageServer server;
public static void main(String[] args) {
try {
JavaTXLanguageServer server = new JavaTXLanguageServer();
server = new JavaTXLanguageServer();
var launcher = LSPLauncher.createServerLauncher(server, System.in, System.out);
LanguageClient client = launcher.getRemoteProxy();
@@ -30,7 +30,7 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
private final ParserService parserService;
private final TypeResolver typeResolver;
private final de.dhbw.service.TextDocumentService textDocumentService;
private final LogService logService;
public final LogService logService;
private final ClientService clientService;
private final CacheService cacheService;
private final ConversionHelper conversionHelper;
@@ -46,13 +46,13 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
Boolean singleFileOpened = false;
public JavaTXTextDocumentService() {
this.clientService = new ClientService(null);
this.logService = new LogService(clientService);
this.textHelper = new TextHelper();
this.cacheService = new CacheService();
this.clientService = new ClientService(null);
this.typeResolver = new TypeResolver();
this.textDocumentService = new de.dhbw.service.TextDocumentService();
this.conversionHelper = new ConversionHelper(textHelper, textDocumentService);
this.logService = new LogService(clientService);
this.formattingHandler = new FormattingHandler(textDocumentService);
this.parserService = new ParserService(conversionHelper, clientService, cacheService);
this.codeActionHandler = new CodeActionHandler(textHelper, textDocumentService, cacheService, typeResolver, logService, conversionHelper);
@@ -158,9 +158,10 @@ public class ChangeHandler {
sWatch.start();
try {
File tempFile2 = null;
try {
File tempDir2 = Path.of(new URI(params.getTextDocument().getUri())).getParent().toFile();
File tempFile2 = File.createTempFile("jtx_temp", ".tmp", tempDir2);
tempFile2 = File.createTempFile("jtx_temp", ".tmp", tempDir2);
FileWriter fileWriter = new FileWriter(tempFile2, true);
BufferedWriter bw = new BufferedWriter(fileWriter);
bw.write(input);
@@ -189,15 +190,15 @@ public class ChangeHandler {
clientService.showMessage(MessageType.Error, f.getMessage() == null ? "null" : f.getMessage());
cacheService.updateGlobalMaps(new ArrayList<>(), new ArrayList<>(), params.getTextDocument().getUri());
}
tempFile2.delete();
} catch (Exception e) {
logService.log("[didSave] Error trying to get Inlay-Hints and Diagnostics for Client: " + e.getMessage(), MessageType.Error);
clientService.showMessage(MessageType.Error, e.getMessage() == null ? "null" : e.getMessage());
cacheService.updateGlobalMaps(new ArrayList<>(), new ArrayList<>(), params.getTextDocument().getUri());
} finally {
sWatch.stop();
logService.log("[didSave] Finished Calculating in [" + sWatch.elapsed().toSeconds() + "s]", MessageType.Info);
if (tempFile2 != null) tempFile2.delete();
}
} catch (Exception e) {
@@ -3,6 +3,7 @@ package de.dhbw.helper;
import de.dhbw.model.PlaceholderPoint;
import de.dhbw.model.PlaceholderType;
import de.dhbw.model.PlaceholderVariable;
import de.dhbw.service.LogService;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
@@ -15,23 +16,28 @@ import de.dhbwstuttgart.typeinference.result.*;
import org.antlr.v4.runtime.Token;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class ASTTransformationHelper {
public static Set<PlaceholderVariable> createTypeInsertPoints(SourceFile forSourcefile, GenericsResult generics) {
public static Set<PlaceholderVariable> createTypeInsertPoints(SourceFile forSourcefile, List<GenericsResult> generics) {
return new PlaceholderPlacer(forSourcefile, generics).getTypeInserts();
}
public static PlaceholderVariable createInsertPoints(RefTypeOrTPHOrWildcardOrGeneric type, Token offset, ClassOrInterface cl, Method m,
ResultSet resultSet, GenericsResultSet constraints, GenericsResultSet classConstraints) {
ResolvedType resolvedType = resultSet.resolveType(type);
PlaceholderPoint insertPoint = new PlaceholderPoint(offset,
new PlaceholderToInsertString(resolvedType.resolvedType, constraints, classConstraints).insert, PlaceholderType.NORMAL_INSERT);
return new PlaceholderVariable(insertPoint, createGenericInsert(constraints, classConstraints, cl, m, offset), resolvedType.getResultPair(), constraints);
}
var resolvedType = constraints.getGenerics().getType(type);
if (resolvedType == null) {
resolvedType = classConstraints.getGenerics().getType(type);
}
PlaceholderPoint insertPoint = new PlaceholderPoint(offset,
new PlaceholderToInsertString(resolvedType, constraints, classConstraints).insert, PlaceholderType.NORMAL_INSERT);
return new PlaceholderVariable(insertPoint, createGenericInsert(constraints, classConstraints, cl, m, offset), type, constraints);
}
private static synchronized Set<PlaceholderPoint> createGenericInsert(GenericsResultSet methodConstraints, GenericsResultSet classConstraints, ClassOrInterface cl, Method m, Token mOffset){
Set<PlaceholderPoint> result = createGenericClassInserts(classConstraints, cl);
@@ -1,19 +1,24 @@
package de.dhbw.helper;
import de.dhbw.JavaTXLanguageServerLauncher;
import de.dhbw.model.PlaceholderVariable;
import de.dhbw.service.LogService;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PlaceholderPlacer extends AbstractASTWalker {
Set<PlaceholderVariable> inserts = new HashSet<>();
String pkgName;
private GenericsResult genericsResult;
private List<GenericsResult> genericsResult;
private SourceFile forSourceFile;
public PlaceholderPlacer(SourceFile forSourceFile, GenericsResult genericsResult) {
public PlaceholderPlacer(SourceFile forSourceFile, List<GenericsResult> genericsResult) {
this.forSourceFile = forSourceFile;
this.genericsResult = genericsResult;
this.pkgName = forSourceFile.getPkgName();
@@ -28,6 +33,10 @@ public class PlaceholderPlacer extends AbstractASTWalker {
@Override
public void visit(ClassOrInterface classOrInterface) {
var logService = JavaTXLanguageServerLauncher.server.textDocumentService.logService;
var text = ASTPrinter.print(forSourceFile);
logService.log(text);
de.dhbw.helper.PlaceholderPlacerClass cl = new de.dhbw.helper.PlaceholderPlacerClass(classOrInterface, genericsResult);
this.inserts.addAll(cl.inserts);
}
@@ -1,19 +1,39 @@
package de.dhbw.helper;
import de.dhbw.JavaTXLanguageServer;
import de.dhbw.JavaTXLanguageServerLauncher;
import de.dhbw.model.PlaceholderVariable;
import de.dhbw.service.ClientService;
import de.dhbw.service.LogService;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.generate.BoundsList;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.target.generate.GenericsResultSet;
import de.dhbwstuttgart.target.generate.ASTToTargetAST.Generics;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
class PlaceholderPlacerClass extends AbstractASTWalker{
protected final ResultSet results;
private GenericsResult generatedGenerics;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
class PlaceholderPlacerClass extends AbstractASTWalker {
private final LogService logger;
private List<GenericsResult> generatedGenerics;
private GenericsResult current;
protected final ClassOrInterface cl;
public final Set<PlaceholderVariable> inserts = new HashSet<>();
private Method method;
@@ -21,40 +41,114 @@ class PlaceholderPlacerClass extends AbstractASTWalker{
GenericsResultSet constraints;
GenericsResultSet classConstraints;
PlaceholderPlacerClass(ClassOrInterface forClass, GenericsResult generatedGenerics) {
PlaceholderPlacerClass(ClassOrInterface forClass, List<GenericsResult> generatedGenerics) {
this.logger = JavaTXLanguageServerLauncher.server.textDocumentService.logService;
this.cl = forClass;
this.method = null;
this.results = generatedGenerics.getGenerics().getResultSet();
this.generatedGenerics = generatedGenerics;
forClass.accept(this);
}
// TODO Should these be moved into the Compiler?
private static boolean isTypeEqual(RefTypeOrTPHOrWildcardOrGeneric a, RefTypeOrTPHOrWildcardOrGeneric b) {
if (a instanceof RefType ra && b instanceof RefType rb) {
if (!ra.getName().equals(rb.getName())) return false;
if (ra.getParaList().size() != rb.getParaList().size()) return false;
for (int i = 0; i < ra.getParaList().size(); i++) {
if (!isTypeEqual(ra.getParaList().get(i), rb.getParaList().get(i))) return false;
}
return true;
} else if (a instanceof TypePlaceholder && b instanceof TypePlaceholder) {
return true; // Type placeholders are considered equal regardless of their names
}
return Objects.equals(a, b);
}
private static class MethodBounds extends AbstractList<BoundsList> {
private final List<BoundsList> bounds;
MethodBounds(List<BoundsList> bounds) {
this.bounds = Collections.unmodifiableList(bounds);
}
@Override
public int size() { return bounds.size(); }
@Override
public BoundsList get(int index) { return bounds.get(index); }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodBounds that)) return false;
if (this.size() != that.size()) return false;
for (int i = 0; i < this.size(); i++) {
var a = this.get(i);
var b = that.get(i);
if (!isTypeEqual(a.base, b.base)) return false;
if (!a.equals(b)) return false;
}
return true;
}
}
private static MethodBounds boundsForParameters(ClassOrInterface clazz, Method method, GenericsResult result) {
var bounds = new ArrayList<BoundsList>();
bounds.add(result.getBounds(method.getReturnType(), clazz, method));
for (var para : method.getParameterList().getFormalparalist()) {
bounds.add(result.getBounds(para.getType(), clazz, method));
}
return new MethodBounds(bounds);
}
@Override
public void visit(Constructor constructor) {
this.visit((Method) constructor);
}
@Override
public void visit(Method method) {
this.method = method;
constraints = generatedGenerics.get(cl, method);
classConstraints = generatedGenerics.get(cl);
if(method.getReturnType() instanceof TypePlaceholder)
inserts.add(ASTTransformationHelper.createInsertPoints(
method.getReturnType(), method.getReturnType().getOffset(), cl, method, results, constraints, classConstraints));
super.visit(method);
var allMethodBounds = new HashSet<MethodBounds>();
for (var generics : generatedGenerics) {
current = generics;
var bounds = boundsForParameters(cl, method, generics);
if (allMethodBounds.contains(bounds)) continue;
allMethodBounds.add(bounds);
constraints = generics.get(cl, method);
classConstraints = generics.get(cl);
if (method.getReturnType() instanceof TypePlaceholder) {
if (!(method instanceof Constructor)) {
logger.log(generics.getGenerics().getResultSet().toString());
inserts.add(ASTTransformationHelper.createInsertPoints(
method.getReturnType(), method.getReturnType().getOffset(), cl, method, generics.getGenerics().getResultSet(), constraints, classConstraints));
}
super.visit(method);
}
}
}
@Override
public void visit(Field field) {
if(field.getType() instanceof TypePlaceholder){
classConstraints = generatedGenerics.get(cl);
if (field.getType() instanceof TypePlaceholder) {
for (var generics : generatedGenerics) {
classConstraints = generics.get(cl);
inserts.add(ASTTransformationHelper.createInsertPoints(
field.getType(), field.getType().getOffset(), cl, method, results, null, classConstraints));
field.getType(), field.getType().getOffset(), cl, method, generics.getGenerics().getResultSet(), null, classConstraints));
}
}
super.visit(field);
}
@Override
public void visit(FormalParameter param) {
if(param.getType() instanceof TypePlaceholder)
inserts.add(ASTTransformationHelper.createInsertPoints(
param.getType(), param.getType().getOffset(), cl, method, results, constraints, classConstraints));
if(param.getType() instanceof TypePlaceholder)
inserts.add(ASTTransformationHelper.createInsertPoints(
param.getType(), param.getType().getOffset(), cl, method, current.getGenerics().getResultSet(), constraints, classConstraints));
super.visit(param);
}
@@ -1,8 +1,9 @@
package de.dhbw.helper;
import de.dhbw.JavaTXLanguageServer;
import de.dhbw.JavaTXLanguageServerLauncher;
import de.dhbw.model.*;
import de.dhbw.model.PlaceholderVariable;
import de.dhbwstuttgart.exceptions.CompilerWarning;
import de.dhbwstuttgart.languageServerInterface.LanguageServerInterface;
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
@@ -30,7 +31,6 @@ public class TypeResolver {
private List<GenericsResult> generatedGenerics = null;
private HashMap<InsertPoint, List<PlaceholderVariable>> inserts;
public HashMap<InsertPoint, List<PlaceholderVariable>> getInserts() {
return inserts;
}
@@ -69,7 +69,7 @@ public class TypeResolver {
return true;
}
public void getCompilerInput(String path, String input) throws IOException, URISyntaxException, ClassNotFoundException {
/*public void getCompilerInput(String path, String input) throws IOException, URISyntaxException, ClassNotFoundException {
LanguageServerInterface languageServer = new LanguageServerInterface();
var transferObj = languageServer.getResultSetAndAbstractSyntax(path, RESET_TO_LETTER);
current = transferObj;
@@ -78,19 +78,17 @@ public class TypeResolver {
public LanguageServerTransferObject updateIfNotPresent(String path, String input) throws IOException, URISyntaxException, ClassNotFoundException {
if (current == null) {
LanguageServerInterface languageServer = new LanguageServerInterface();
LanguageServerTransferObject transferObj = languageServer.getResultSetAndAbstractSyntax(path);
LanguageServerTransferObject transferObj = languageServer.getResultSetAndAbstractSyntax(path, RESET_TO_LETTER);
return transferObj;
}
return current;
}
}*/
public ArrayList<LSPVariable> infereChangeInput() throws IOException, ClassNotFoundException, URISyntaxException {
Set<PlaceholderVariable> tips = new HashSet<>();
for (var results : generatedGenerics) {
tips.addAll(ASTTransformationHelper.createTypeInsertPoints(current.getAst(), results));
}
tips.addAll(ASTTransformationHelper.createTypeInsertPoints(current.getAst(), generatedGenerics));
HashMap<InsertPoint, List<PlaceholderVariable>> insertsOnLines = new HashMap<>();
@@ -115,7 +113,7 @@ public class TypeResolver {
v.point.point.getLine(),
v.point.point.getCharPositionInLine(),
v.point.point.getStopIndex(),
v.getResultPair().getLeft());
v.getType());
}
).toList()
);
@@ -147,15 +145,13 @@ public class TypeResolver {
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
LanguageServerInterface languageServerInterface = new LanguageServerInterface();
LanguageServerTransferObject lsTransfer = languageServerInterface.getResultSetAndAbstractSyntax(pathString);
LanguageServerTransferObject lsTransfer = languageServerInterface.getResultSetAndAbstractSyntax(pathString, RESET_TO_LETTER);
var parsedSource = lsTransfer.getAst();
Set<PlaceholderVariable> tips = new HashSet<>();
generatedGenerics = lsTransfer.getGeneratedGenerics().get(lsTransfer.getAst());
for (var generics : generatedGenerics) {
tips.addAll(ASTTransformationHelper.createTypeInsertPoints(parsedSource, generics));
}
tips.addAll(ASTTransformationHelper.createTypeInsertPoints(parsedSource, generatedGenerics));
System.setOut(System.out);
this.current = lsTransfer;
@@ -189,7 +185,7 @@ public class TypeResolver {
variable.point.point.getLine(),
variable.point.point.getCharPositionInLine(),
variable.point.point.getStopIndex(),
variable.getResultPair().getLeft()));
variable.getType()));
}
@@ -221,7 +217,7 @@ public class TypeResolver {
public void updateAst(String uri) throws IOException, URISyntaxException, ClassNotFoundException {
logger.info("Old AST:");
logger.info(ASTPrinter.print(this.current.getAst()));
this.current = new LanguageServerTransferObject(getNewAst(uri), "", current.getGeneratedGenerics(), current.getWarnings());
this.current = new LanguageServerTransferObject(getNewAst(uri), "", current.getConstraints(), current.getGeneratedGenerics(), current.getWarnings());
logger.info("NEW AST:");
logger.info(ASTPrinter.print(current.getAst()));
@@ -1,6 +1,7 @@
package de.dhbw.model;
import de.dhbw.helper.ConversionHelper;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.generate.GenericsResultSet;
import de.dhbwstuttgart.typeinference.result.ResultPair;
@@ -12,14 +13,14 @@ public class PlaceholderVariable {
*/
public final PlaceholderPoint point;
Set<PlaceholderPoint> inserts;
ResultPair<?, ?> resultPair;
RefTypeOrTPHOrWildcardOrGeneric type;
private final GenericsResultSet constraints;
public PlaceholderVariable(PlaceholderPoint point, Set<PlaceholderPoint> additionalPoints, ResultPair<?, ?> resultPair, GenericsResultSet constraints) {
public PlaceholderVariable(PlaceholderPoint point, Set<PlaceholderPoint> additionalPoints, RefTypeOrTPHOrWildcardOrGeneric type, GenericsResultSet constraints) {
this.point = point;
this.constraints = constraints;
inserts = additionalPoints;
this.resultPair = resultPair;
this.type = type;
}
public String insert(String intoSource) {
@@ -49,8 +50,8 @@ public class PlaceholderVariable {
point.setInsertString(ConversionHelper.cleanType(point.getInsertString()));
}
public ResultPair<?, ?> getResultPair() {
return this.resultPair;
public RefTypeOrTPHOrWildcardOrGeneric getType() {
return this.type;
}
public boolean equals(Object obj) {
@@ -36,7 +36,7 @@ public class CacheService {
this.typeInserts = typeInserts;
}
public void reset(){
public void reset() {
globalInlayHintMap = new HashMap<>();
lastSavedFiles = new HashMap<>();
currentlyCalculating = false;