37 Commits

Author SHA1 Message Date
Ruben
1e125407f1 feat: finally positions are handled correctly 2025-08-07 16:56:49 +02:00
Ruben
579d736efc feat: finally positions are handled correctly 2025-08-07 16:55:23 +02:00
Ruben
c5760210fe feat: add Compiler jar to git 2025-08-07 16:33:18 +02:00
Ruben
2e6be4079a feat: positionAdjustment 2025-08-07 16:18:26 +02:00
Ruben
bb9be2c319 feat: infere Lambdas in Methods 2025-07-12 11:55:59 +02:00
Ruben
57c82542f4 refactor: add Method instead of calculating directly 2025-07-12 11:35:43 +02:00
Ruben
cb54606a93 feat: add lambda inference for Field Variables 2025-07-12 11:15:34 +02:00
Ruben
31ed1f16b6 feat: import all generics when one is selected 2025-07-11 21:20:04 +02:00
Ruben
5569b6d0db feat: add Picture and Description to VSC Client 2025-07-09 16:15:47 +02:00
Ruben
2a87b85dc1 fix: display ParserErrors 2025-07-09 15:47:21 +02:00
Ruben
11fb843efe docs: add Doc for installation of LSP Client for Intellij 2025-07-09 15:25:15 +02:00
Ruben
701caab9cd fix: fix generic Display and enable them 2025-07-08 20:45:49 +02:00
Ruben
c2cbd0aa92 fix: reduction of ResultSet now also bases on last saved File 2025-07-08 19:54:35 +02:00
Ruben
e1b000b976 fix: fix position adjustment 2025-07-08 19:28:06 +02:00
RubenKraft
7de2b2764a Merge pull request 'refactor' (#37) from refactor into main
Reviewed-on: #37
2025-07-07 18:38:09 +00:00
Ruben
27282721bc refactor: type Algorithm 2025-07-07 20:36:13 +02:00
Ruben
144cb84c2c refactor: type Algorithm 2025-07-07 20:19:58 +02:00
Ruben
ae5f9a1771 refactor: add Change Handler 2025-07-07 17:36:00 +02:00
Ruben
c8fa373972 refactor: rename package 2025-07-07 16:28:17 +02:00
Ruben
f1f0fb8bf3 refactor: Handle Save with Services 2025-07-07 16:27:31 +02:00
Ruben
d6dd414aba #10: add initial support for Intellij 2025-07-06 21:27:21 +02:00
Ruben
2b6fc2fc91 feat: add Constructor to get inferred 2025-06-10 15:47:58 +02:00
Ruben
762b86be85 feat: add support for fields 2025-06-10 15:39:51 +02:00
RubenKraft
38166cf6f2 Merge pull request 'reduce-result-set' (#36) from reduce-result-set into main
Reviewed-on: #36
2025-06-05 14:55:53 +00:00
Ruben
c012471a22 feat: reduce Resultset when selecting a Type 2025-06-04 17:19:19 +02:00
Ruben
0091c9ef71 feat: reduce Resultset when selecting a Type 2025-06-02 17:58:49 +02:00
Ruben
f6ed883ddb feat: add boolean for enabling and disabling generics 2025-06-02 14:06:28 +02:00
Ruben
ae3b5e80d0 feat: add originalName Attribute 2025-06-02 13:38:08 +02:00
Ruben
4226623abc feat: add variable to store current Result and add Method to recalculate 2025-06-02 13:28:46 +02:00
Ruben
637478b1c3 feat: activate recompilation 2025-06-02 13:07:57 +02:00
Ruben
24c5cd823f feat: remove Diagnostic if it has been selected 2025-05-14 15:28:39 +02:00
Ruben
26eedc5b32 feat: remove Typehint if it has been selected 2025-05-14 15:18:19 +02:00
Ruben
c21f09496e feat: fix position of Hints when new Text is added to the same line 2025-05-14 14:27:49 +02:00
Ruben
39ae1d66bc feat: add compiler jar to LSP in libs Folder 2025-05-13 19:15:41 +02:00
Ruben
6ee0a74b22 feat: change Name and update jar 2025-05-12 19:51:15 +02:00
Ruben
ca6fa89e3f Merge remote-tracking branch 'origin/main' 2025-05-12 19:46:28 +02:00
Ruben
8cde997c15 feat: deactivate display if one Variable is beeing inserted 2025-05-12 19:46:17 +02:00
47 changed files with 1666 additions and 630 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@@ -1,28 +0,0 @@
plugins {
id 'java'
id 'org.jetbrains.intellij.platform' version '2.2.1'
}
group = 'org.example'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven { url "https://jitpack.io" }
intellijPlatform {
defaultRepositories()
}
}
dependencies {
testImplementation platform('org.junit:junit-bom:5.10.0')
testImplementation 'org.junit.jupiter:junit-jupiter'
implementation "com.github.Ballerina-Platform.lsp4intellij:lsp4intellij:master-SNAPSHOT"
}
test {
useJUnitPlatform()
}

View File

@@ -0,0 +1,41 @@
plugins {
id("org.jetbrains.intellij") version "1.17.3"
kotlin("jvm") version "1.9.0"
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
dependencies {
implementation(kotlin("stdlib"))
implementation("com.github.ballerina-platform:lsp4intellij:0.9.0")
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "17"
}
}
intellij {
version.set("2023.3")
}
tasks {
patchPluginXml {
sinceBuild.set("233")
untilBuild.set("233.*")
}
}

View File

@@ -0,0 +1,13 @@
# Installation des Intellij Language Clients
Um den Language Client für Intellij installieren zu können, kann die Erweiterung
[LSP4IJ](https://plugins.jetbrains.com/plugin/23257-lsp4ij) installiert werden.
## Installation
1. Installiere [LSP4IJ](https://plugins.jetbrains.com/plugin/23257-lsp4ij)
2. Öffne den Language Server Tab
3. Füge einen neuen Language-Server hinzu
4. Vergebe einen Namen und füge folgenden Command hinzu: `java -jar "<path/to/LanguageServer.jar>`
5. Füge unter Mappings -> File name patterns *.jav und Language ID java_tx hinzu
6. öffne eine Datei mit Dateiendung .jav
7. Fertig

View File

@@ -0,0 +1,14 @@
package kotlin.com.example.lsp;
import com.intellij.openapi.application.PreloadingActivity;
import com.intellij.openapi.progress.ProgressIndicator;
import org.wso2.lsp4intellij.IntellijLanguageClient;
import org.wso2.lsp4intellij.client.languageserver.serverdefinition.RawCommandServerDefinition;
public class PreloadActivityTX extends PreloadingActivity {
@Override
public void preload(ProgressIndicator indicator) {
String[] command = new String[]{"java", "-jar", "/JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar"};
IntellijLanguageClient.addServerDefinition(new RawCommandServerDefinition("jav", command));
}
}

View File

@@ -13,7 +13,7 @@ see also jetbrains documentation: https://plugins.jetbrains.com/docs/intellij/pl
<extensions defaultExtensionNs="com.intellij">
<!-- register a preloading activity. You need to init IntellijLanguageClient with your config, see readme -->
<preloadingActivity implementation="your.plugin.MyPreloadingActivity" id="your.plugin.MyPreloadingActivity"/>
<preloadingActivity implementation="kotlin.com.example.lsp.PreloadActivityTX" id="kotlin.com.example.lsp.PreloadActivityTX"/>
<!-- register intellijLanguageClient as a Service OR as a plugin component (see readme)... -->
<applicationService serviceImplementation="org.wso2.lsp4intellij.IntellijLanguageClient"/>

View File

@@ -9,3 +9,7 @@ vsc-extension-quickstart.md
**/*.map
**/*.ts
**/.vscode-test.*
!JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar
!JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar

View File

@@ -1,71 +1,3 @@
# lspclient README
This is the README for your extension "lspclient". After writing up a brief description, we recommend including the following sections.
## Features
Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
For example if there is an image subfolder under your extension project workspace:
\!\[feature X\]\(images/feature-x.png\)
> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
## Requirements
If you have any requirements or dependencies, add a section describing those and how to install and configure them.
## Extension Settings
Include if your extension adds any VS Code settings through the `contributes.configuration` extension point.
For example:
This extension contributes the following settings:
* `myExtension.enable`: Enable/disable this extension.
* `myExtension.thing`: Set to `blah` to do something.
## Known Issues
Calling out known issues can help limit users opening duplicate issues against your extension.
## Release Notes
Users appreciate release notes as you update your extension.
### 1.0.0
Initial release of ...
### 1.0.1
Fixed issue #.
### 1.1.0
Added features X, Y, and Z.
---
## Following extension guidelines
Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension.
* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines)
## Working with Markdown
You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts:
* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux).
* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux).
* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets.
## For more information
* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown)
* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
**Enjoy!**
This is the README for the Java-TX LSP Client.

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 KiB

View File

@@ -1,12 +1,12 @@
{
"name": "lspclient",
"version": "0.0.1",
"version": "0.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lspclient",
"version": "0.0.1",
"version": "0.0.2",
"dependencies": {
"vscode-languageclient": "^9.0.1"
},

View File

@@ -1,8 +1,9 @@
{
"name": "lspclient",
"displayName": "LSPClient",
"description": "",
"version": "0.0.1",
"icon": "TX.png",
"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.2",
"engines": {
"vscode": "^1.94.0"
},

View File

@@ -42,10 +42,11 @@ export function activate(context: vscode.ExtensionContext) {
revealOutputChannelOn: 4
};
// Language Client erstellen und starten
const client = new LanguageClient(
'javaLanguageServer', // ID des Clients
'Java Language Server', // Name des Clients
'javaTxLanguageServer', // ID des Clients
'Java-TX Language Server', // Name des Clients
serverOptions,
clientOptions
);

View File

@@ -20,6 +20,11 @@
<artifactId>antlr4</artifactId>
<version>4.11.1</version>
</dependency>
<dependency>
<groupId>io.github.java-diff-utils</groupId>
<artifactId>java-diff-utils</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
@@ -75,6 +80,12 @@
<version>0.1</version>
</dependency>
</dependencies>
<properties>
<!-- Setzt Java 21 als globale Version -->
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.release>21</maven.compiler.release>
</properties>
<build>
<plugins>
@@ -96,6 +107,7 @@
<configuration>
<source>21</source>
<target>21</target>
<release>21</release>
</configuration>
</plugin>

View File

@@ -8,7 +8,6 @@ import org.eclipse.lsp4j.services.TextDocumentService;
import org.eclipse.lsp4j.services.WorkspaceService;
import org.eclipse.lsp4j.services.LanguageServer;
import java.net.URI;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**

View File

@@ -1,56 +1,77 @@
package de.dhbw;
import com.google.common.base.Stopwatch;
import de.dhbw.handler.*;
import de.dhbw.service.CacheService;
import de.dhbw.service.ClientService;
import de.dhbw.service.LogService;
import de.dhbw.helper.CodeSnippetOptions;
import de.dhbw.helper.ConversionHelper;
import de.dhbw.helper.TextHelper;
import de.dhbw.helper.TypeResolver;
import de.dhbw.model.LSPVariable;
import de.dhbw.model.SnippetWithName;
import de.dhbw.model.Type;
import de.dhbwstuttgart.languageServerInterface.LanguageServerInterface;
import de.dhbwstuttgart.languageServerInterface.ParserInterface;
import de.dhbwstuttgart.languageServerInterface.model.ParserError;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import de.dhbw.service.ParserService;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
/**
* Handles Actions in Documents, such as Autocompletion, Change-Events and Syntax-Checks
*/
public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.TextDocumentService {
private final FormattingHandler formattingHandler;
private final SaveHandler saveHandler;
private final ParserService parserService;
private final TypeResolver typeResolver;
private final de.dhbw.service.TextDocumentService textDocumentService;
private final LogService logService;
private final ClientService clientService;
private final CacheService cacheService;
private final ConversionHelper conversionHelper;
private final ChangeHandler changeHandler;
private final TextHelper textHelper;
private final CodeActionHandler codeActionHandler;
private final InlayHintAdjusterDiffUtils inlayHintAdjusterDiffUtils;
private static final Logger logger = LogManager.getLogger(JavaTXTextDocumentService.class);
LanguageClient client;
HashMap<String, List<InlayHint>> globalInlayHintMap = new HashMap<>();
Boolean currentlyCalculating = false;
HashMap<String, List<Diagnostic>> globalDiagnosticsMap = new HashMap<>();
HashMap<String, String> textDocuments = new HashMap<>();
CodeSnippetOptions codeSnippetOptions = new CodeSnippetOptions();
TextHelper textHelper = new TextHelper();
TypeResolver typeResolver = new TypeResolver();
Boolean dontShowHints = false;
Path fileRoot = null;
Boolean singleFileOpened = false;
public JavaTXTextDocumentService() {
this.textHelper = new TextHelper();
this.inlayHintAdjusterDiffUtils = new InlayHintAdjusterDiffUtils();
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);
this.saveHandler = new SaveHandler(typeResolver, textDocumentService, logService, cacheService, conversionHelper, clientService, parserService);
this.changeHandler = new ChangeHandler(textDocumentService, parserService, conversionHelper, clientService, typeResolver, cacheService, logService, inlayHintAdjusterDiffUtils);
}
public void setClient(LanguageClient client) {
this.client = client;
clientService.setClient(client);
}
public void setFileRoot(List<WorkspaceFolder> root) {
if (root == null) {
singleFileOpened = true;
}
//TODO: Nicht nur das erste Element nehmen sondern alle beachten
fileRoot = Path.of(URI.create(root.get(0).getUri()));
}
@@ -89,8 +110,10 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
@Override
public void didOpen(DidOpenTextDocumentParams params) {
textDocuments.put(params.getTextDocument().getUri(), params.getTextDocument().getText());
textDocumentService.saveFileWithUri(params.getTextDocument().getUri(), params.getTextDocument().getText());
}
/**
* Handles didChange-Event.
* updates textDocument-State on Server and run Syntax-Check. If an Error is found it will get displayed as a Diagnostic.
@@ -99,35 +122,8 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
*/
@Override
public void didChange(DidChangeTextDocumentParams params) {
log("[didChange] Client triggered didChange Event.", MessageType.Info);
AtomicReference<String> summedUp = new AtomicReference<>("");
params.getContentChanges().forEach(el -> summedUp.set(summedUp.get() + el.getText()));
textDocuments.put(params.getTextDocument().getUri(), summedUp.get());
String input = summedUp.get();
ParserInterface parserInterface = new ParserInterface();
List<ParserError> parserErrors = parserInterface.getParseErrors(input);
List<Diagnostic> diagnostics = parserErrors.stream().map(el -> {
Range errorRange = new Range(
new Position(el.getLine() - 1, el.getCharPositionInLine()), // Startposition
new Position(el.getLine() - 1, el.getEndCharPosition()) // Endposition
);
return new Diagnostic(
errorRange,
el.getMsg(),
DiagnosticSeverity.Error,
"JavaTX Language Server"
);
}).toList();
PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(params.getTextDocument().getUri(), diagnostics);
client.publishDiagnostics(diagnosticsParams);
logService.log("[didChange] Client triggered didChange Event.", MessageType.Info);
changeHandler.didChange(params);
}
/**
@@ -137,179 +133,27 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
*/
@Override
public CompletableFuture<List<? extends TextEdit>> formatting(DocumentFormattingParams params) {
log("[formatting] Client requested formatting.", MessageType.Info);
List<TextEdit> edits = new ArrayList<>();
String[] lines = textDocuments.get(params.getTextDocument().getUri()).split("\n");
StringBuilder formattedText = new StringBuilder();
for (String line : lines) {
formattedText.append(line.stripTrailing()).append("\n");
}
TextEdit edit = new TextEdit();
edit.setRange(new Range(new Position(0, 0), new Position(lines.length, 0)));
edit.setNewText(formattedText.toString().trim());
edits.add(edit);
return CompletableFuture.completedFuture(edits);
logService.log("[formatting] Client requested formatting.", MessageType.Info);
return CompletableFuture.completedFuture(formattingHandler.handleFormat(params));
}
@Override
public void didClose(DidCloseTextDocumentParams params) {
}
private void log(String message, MessageType type) {
client.logMessage(new MessageParams(type, message));
switch (type) {
case Error -> logger.error(message);
case Warning -> logger.warn(message);
case Info -> logger.info(message);
default -> logger.debug(message);
}
}
private InlayHint getInlayHint(LSPVariable variable) {
InlayHint inlayHint = new InlayHint();
String typeDisplay = "";
for (Type type : variable.getPossibleTypes()) {
typeDisplay += " | " + type.getType().replaceAll("GTV ", "");
}
inlayHint.setLabel(typeDisplay.length() > 2 ? typeDisplay.substring(2) : typeDisplay);
inlayHint.setPosition(new Position(variable.getLine() - 1, variable.getCharPosition()));
inlayHint.setKind(InlayHintKind.Parameter);
inlayHint.setPaddingRight(true);
inlayHint.setPaddingRight(true);
return inlayHint;
}
private Diagnostic getDiagnostic(LSPVariable variable, String fileUri, Type type) {
Range errorRange = new Range(
new Position(variable.getLine() - 1, variable.getCharPosition()), // Startposition
new Position(variable.getLine() - 1, textHelper.getEndingCharOfStartingChar(variable.getLine() - 1, variable.getCharPosition(), textDocuments.get(fileUri))) // Endposition
);
Diagnostic diagnostic = new Diagnostic(
errorRange,
//TODO: REMOVE! Temporary Fix because GTV, like TPH can be thrown away in the TypeResolver
type.getType().replaceAll("GTV ", ""),
DiagnosticSeverity.Hint,
"JavaTX Language Server"
);
diagnostic.setCode(type.isGeneric() ? "GENERIC" : "TYPE");
return diagnostic;
}
private void updateGlobalMaps(List<Diagnostic> diagnostics, List<InlayHint> typeHint, String uri) {
globalDiagnosticsMap.put(uri, diagnostics);
globalInlayHintMap.put(uri, typeHint);
}
private void updateClient(LanguageClient client) {
client.refreshInlayHints();
client.refreshDiagnostics();
}
private void startLoading(String taskName, String title, LanguageClient client) {
Either<String, Integer> token = Either.forLeft(taskName);
client.createProgress(new WorkDoneProgressCreateParams(token));
WorkDoneProgressBegin begin = new WorkDoneProgressBegin();
begin.setTitle(title);
begin.setCancellable(false);
begin.setPercentage(0);
ProgressParams beginParams = new ProgressParams(token, Either.forLeft(begin));
client.notifyProgress(beginParams);
}
private void stopLoading(String taskName, String title, LanguageClient client) {
Either<String, Integer> token = Either.forLeft(taskName);
WorkDoneProgressEnd end = new WorkDoneProgressEnd();
end.setMessage(title);
ProgressParams endParams = new ProgressParams(token, Either.forLeft(end));
client.notifyProgress(endParams);
}
@Override
public void didSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {
log("[didSave] Client triggered didSave-Event.", MessageType.Info);
startLoading("compile-task", "Inferring types...", client);
LanguageServerInterface languageServerInterface = new LanguageServerInterface();
if (!currentlyCalculating) {
currentlyCalculating = true;
ArrayList<Diagnostic> diagnostics = new ArrayList<>();
var sWatch = Stopwatch.createUnstarted();
sWatch.start();
try {
if (textDocuments.get(didSaveTextDocumentParams.getTextDocument().getUri()) == null) {
log("[didSave] Input of Text Document is null in TextDocument-Hashmap.", MessageType.Error);
}
ArrayList<LSPVariable> typesOfMethodAndParameters = typeResolver.infereInput(textDocuments.get(didSaveTextDocumentParams.getTextDocument().getUri()), didSaveTextDocumentParams.getTextDocument().getUri());
List<InlayHint> typeHint = new ArrayList<>();
for (var variable : typesOfMethodAndParameters) {
InlayHint inlayHint = getInlayHint(variable);
typeHint.add(inlayHint);
//Diagnostics of Types
for (var type : variable.getPossibleTypes()) {
Diagnostic diagnostic = getDiagnostic(variable, didSaveTextDocumentParams.getTextDocument().getUri(), type);
diagnostics.add(diagnostic);
}
}
updateGlobalMaps(diagnostics, typeHint, didSaveTextDocumentParams.getTextDocument().getUri());
PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(didSaveTextDocumentParams.getTextDocument().getUri(), diagnostics);
client.publishDiagnostics(diagnosticsParams);
} catch (Exception e) {
log("[didSave] Error trying to get Inlay-Hints and Diagnostics for Client: " + e.getMessage(), MessageType.Error);
} finally {
currentlyCalculating = false;
sWatch.stop();
log("[didSave] Finished Calculating in [" + sWatch.elapsed().toSeconds() + "s]", MessageType.Info);
}
}
stopLoading("compile-task", "Types successfully inferred", client);
updateClient(client);
ArrayList<File> files = new ArrayList<>();
try (Stream<Path> stream = Files.walk(Paths.get(fileRoot.toUri()))) {
stream.filter(Files::isRegularFile)
.forEach(el -> files.add(el.toFile()));
} catch (IOException e) {
}
logService.log("[didSave] Client triggered didSave-Event.");
clientService.startLoading("compile-task", "Inferring types...", client);
saveHandler.handleSave(didSaveTextDocumentParams);
clientService.stopLoading("compile-task", "Types successfully inferred", client);
clientService.updateClient(client);
}
@Override
public CompletableFuture<List<InlayHint>> inlayHint(InlayHintParams params) {
log("[inlayHint] The Client requested Inlay-Hints.", MessageType.Info);
return CompletableFuture.supplyAsync(() -> globalInlayHintMap.get(params.getTextDocument().getUri()) == null ? Collections.emptyList() : globalInlayHintMap.get(params.getTextDocument().getUri()));
logService.log("[inlayHint] The Client requested Inlay-Hints.", MessageType.Info);
return CompletableFuture.supplyAsync(() -> dontShowHints ? Collections.emptyList() : cacheService.getGlobalInlayHintMap().get(params.getTextDocument().getUri()) == null ? Collections.emptyList() : cacheService.getGlobalInlayHintMap().get(params.getTextDocument().getUri()));
}
@Override
@@ -441,91 +285,14 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
@Override
public CompletableFuture<List<Either<Command, CodeAction>>> codeAction(CodeActionParams params) {
log("[codeAction] Client requested Insert at Line [" + params.getRange().getStart().getLine() + "] and from Char [" + params.getRange().getStart().getCharacter() + "] to [" + params.getRange().getEnd().getCharacter() + "].", MessageType.Info);
List<Either<Command, CodeAction>> actions = new ArrayList<>();
logService.log("[codeAction] Client requested Insert at Line [" + params.getRange().getStart().getLine() + "] and from Char [" + params.getRange().getStart().getCharacter() + "] to [" + params.getRange().getEnd().getCharacter() + "].", MessageType.Info);
List<Diagnostic> diagnosticInCurrentDocument = params.getContext().getDiagnostics();
Range requestedRange = params.getRange();
logService.log("Code-Action Context was: " + params.getContext().getTriggerKind().name(), MessageType.Info);
//All Diagnostics that are in range of the hover -> All Diagnostics of the selected Variable and thus all Types of the Variable
List<Diagnostic> diagnosticsOverlappingHover = diagnosticInCurrentDocument.stream()
.filter(diagnostic -> rangesOverlap(diagnostic.getRange(), requestedRange)).toList();
Range rangeOfInsert = params.getRange();
String documentUri = params.getTextDocument().getUri();
for (Diagnostic typeDiagnostic : diagnosticsOverlappingHover) {
try {
String typeWithReplacedVariable = typeDiagnostic.getMessage() +
" " +
textHelper.getTextOfChars(
textDocuments.get(params.getTextDocument().getUri()),
rangeOfInsert.getStart().getLine(),
rangeOfInsert.getStart().getCharacter(),
rangeOfInsert.getEnd().getCharacter()
);
ArrayList<TextEdit> listOfChanges = new ArrayList<>();
if (typeDiagnostic.getCode().getLeft().equals("GENERIC")) {
for (var diagnostic : globalDiagnosticsMap.get(params.getTextDocument().getUri())) {
if (diagnostic.getMessage().contains(typeDiagnostic.getMessage()) || typeDiagnostic.getMessage().contains(diagnostic.getMessage())) {
String genericType = diagnostic.getMessage() +
" " +
textHelper.getTextOfChars(
textDocuments.get(params.getTextDocument().getUri()),
diagnostic.getRange().getStart().getLine(),
diagnostic.getRange().getStart().getCharacter(),
diagnostic.getRange().getEnd().getCharacter()
);
listOfChanges.add(new TextEdit(diagnostic.getRange(), genericType));
}
}
} else {
listOfChanges.add(new TextEdit(rangeOfInsert, typeWithReplacedVariable));
}
var isTypeImported = false;
if (!typeDiagnostic.getCode().getLeft().equalsIgnoreCase("generic")) {
isTypeImported = typeResolver.isTypeImported(textDocuments.get(params.getTextDocument().getUri()), typeDiagnostic.getMessage());
}
if (!isTypeImported && !typeDiagnostic.getMessage().equals("void") && !typeDiagnostic.getCode().getLeft().equals("GENERIC")) {
Range importRange = new Range(new Position(0, 0), new Position(0, 0));
var typeWithoutGenerics = typeDiagnostic.getMessage().contains("<") ? typeDiagnostic.getMessage().substring(0, typeDiagnostic.getMessage().indexOf('<')) : typeDiagnostic.getMessage();
listOfChanges.add(new TextEdit(importRange, "import " + typeWithoutGenerics + ";\n"));
}
Map<String, List<TextEdit>> changes = new HashMap<>();
changes.put(documentUri, listOfChanges);
WorkspaceEdit edit = new WorkspaceEdit();
edit.setChanges(changes);
CodeAction action = new CodeAction("Insert " + typeDiagnostic.getMessage());
action.setKind(CodeActionKind.QuickFix);
action.setEdit(edit);
actions.add(Either.forRight(action));
} catch (Exception e) {
log("Error creating Actions, returning empty List. The Error was: " + e.getMessage(), MessageType.Error);
}
}
return CompletableFuture.completedFuture(actions);
}
private boolean rangesOverlap(Range range1, Range range2) {
int start1 = range1.getStart().getLine() * 1000 + range1.getStart().getCharacter();
int end1 = range1.getEnd().getLine() * 1000 + range1.getEnd().getCharacter();
int start2 = range2.getStart().getLine() * 1000 + range2.getStart().getCharacter();
int end2 = range2.getEnd().getLine() * 1000 + range2.getEnd().getCharacter();
return start1 <= end2 && start2 <= end1;
return CompletableFuture.supplyAsync(() -> {
return codeActionHandler.handleCodeAction(params);
});
}
@Override

View File

@@ -3,13 +3,8 @@ package de.dhbw;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.WorkspaceService;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
* Handles Actions in Workspace

View File

@@ -0,0 +1,177 @@
package de.dhbw.handler;
import com.google.common.base.Stopwatch;
import de.dhbw.helper.ConversionHelper;
import de.dhbw.helper.TypeResolver;
import de.dhbw.model.DiagnosticsAndTypehints;
import de.dhbw.model.DocumentChanges;
import de.dhbw.model.LSPVariable;
import de.dhbw.model.LineCharPosition;
import de.dhbw.service.*;
import org.eclipse.lsp4j.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
public class ChangeHandler {
private final TextDocumentService textDocumentService;
private final ParserService parserService;
private final ConversionHelper conversionHelper;
private final ClientService clientService;
private final TypeResolver typeResolver;
private final CacheService cacheService;
private final LogService logService;
private final InlayHintAdjusterDiffUtils inlayHintAdjusterDiffUtils;
public ChangeHandler(TextDocumentService textDocumentService, ParserService parserService, ConversionHelper conversionHelper, ClientService clientService, TypeResolver typeResolver, CacheService cacheService, LogService logService, InlayHintAdjusterDiffUtils inlayHintAdjusterDiffUtils) {
this.textDocumentService = textDocumentService;
this.parserService = parserService;
this.conversionHelper = conversionHelper;
this.clientService = clientService;
this.typeResolver = typeResolver;
this.cacheService = cacheService;
this.logService = logService;
this.inlayHintAdjusterDiffUtils = inlayHintAdjusterDiffUtils;
}
public void didChange(DidChangeTextDocumentParams params) {
String currentText = textDocumentService.getFileOfUri(params.getTextDocument().getUri());
AtomicReference<String> summedUp = new AtomicReference<>("");
params.getContentChanges().forEach(el -> summedUp.set(summedUp.get() + el.getText()));
textDocumentService.saveFileWithUri(params.getTextDocument().getUri(), summedUp.get());
DocumentChanges documentChanges = textDocumentService.calculateDifference(currentText, summedUp.get());
HashMap<LineCharPosition, String> preciseChanges = documentChanges.getPreciseChanges();
HashMap<Integer, List<String>> textChanges;
ArrayList<Integer> offsetPerLine = documentChanges.getOffsetPerLine();
//Have to check of old saved Input because the result set and Inlay Hints will be updated according to the old AST which contains the old Positions
if(cacheService.getLastSavedFiles().containsKey(params.getTextDocument().getUri())){
DocumentChanges changesFromOldSave = textDocumentService.calculateDifference(cacheService.getLastSavedFiles().get(params.getTextDocument().getUri()), summedUp.get());
offsetPerLine = changesFromOldSave.getOffsetPerLine();
textChanges = changesFromOldSave.getTextChanges();
preciseChanges = changesFromOldSave.getPreciseChanges();
logService.log(textChanges.values().stream().map(el -> String.join(", ", el)).collect(Collectors.joining("\n")));
} else {
textChanges = documentChanges.getTextChanges();
}
String input = summedUp.get();
typeResolver.reduceCurrent(preciseChanges, cacheService.getVariables());
try{
File tempDir = new File(System.getProperty("java.io.tmpdir"));
File tempFile = File.createTempFile("newText", ".tmp", tempDir);
FileWriter fileWriter = new FileWriter(tempFile, true);
System.out.println(tempFile.getAbsolutePath());
BufferedWriter bw = new BufferedWriter(fileWriter);
bw.write(summedUp.get());
bw.close();
typeResolver.updateAst(tempFile.toURI().getPath());
}catch (Exception e){
logService.log(e.getMessage());
}
var sWatch = Stopwatch.createUnstarted();
sWatch.start();
try {
String currentInput = textDocumentService.getFileOfUri(params.getTextDocument().getUri());
if (currentInput == null) {
logService.log("[didChange] Input of Text Document is null in TextDocument-Hashmap.", MessageType.Error);
}
ArrayList<LSPVariable> typesOfMethodAndParameters = typeResolver.infereInput(currentInput, params.getTextDocument().getUri());
DiagnosticsAndTypehints diagnosticsAndTypehints = conversionHelper.variablesToDiagnosticsAndTypehints(typesOfMethodAndParameters, params.getTextDocument().getUri());
List<InlayHint> typeHint = diagnosticsAndTypehints.getInlayHints();
List<Diagnostic> diagnostics = diagnosticsAndTypehints.getDiagnostics();
cacheService.updateGlobalMaps(diagnostics, typeHint, params.getTextDocument().getUri());
} catch (Exception e) {
logService.log("[didChange] Error trying to get Inlay-Hints and Diagnostics for Client: " + e.getMessage(), MessageType.Error);
for(var stackTrace : e.getStackTrace()){
logService.log(stackTrace.toString());
}
clientService.showMessage(MessageType.Error, e.getMessage());
cacheService.updateGlobalMaps(new ArrayList<>(), new ArrayList<>(), params.getTextDocument().getUri());
} finally {
sWatch.stop();
logService.log("[didChange] Finished Calculating in [" + sWatch.elapsed().toSeconds() + "s]", MessageType.Info);
}
//updatePositions(params, offsetPerLine);
cacheService.getGlobalInlayHintMap().put(params.getTextDocument().getUri(), cacheService.getGlobalInlayHintMap().get(params.getTextDocument().getUri()).stream().filter(el -> {
//TODO: Hier das Label aufspalten an | weil die Typehints immer mit und getrennt sind und so jeder Typhint für sich durchlaufen werden kann.
logService.log(el.getLabel().getLeft().replaceAll(" ", "") + "<>" + String.join(",", textChanges.get(el.getPosition().getLine())) + ": " + (!textChanges.get(el.getPosition().getLine()).contains(el.getLabel().getLeft().replaceAll(" ", "")) ? "true" : "false"), MessageType.Info);
return !textChanges.get(el.getPosition().getLine()).contains(el.getLabel().getLeft().replaceAll(" ", ""));
}).toList());
cacheService.getGlobalDiagnosticsMap().put(params.getTextDocument().getUri(), cacheService.getGlobalDiagnosticsMap().get(params.getTextDocument().getUri()).stream().filter(el -> {
logService.log(el.getMessage().replaceAll(" ", "") + "<>" + String.join(",", textChanges.get(el.getRange().getStart().getLine())) + ": " + (!textChanges.get(el.getRange().getStart().getLine()).contains(el.getMessage().replaceAll(" ", "")) ? "true" : "false"), MessageType.Info);
return !textChanges.get(el.getRange().getStart().getLine()).contains(el.getMessage().replaceAll(" ", ""));
}).toList());
List<Diagnostic> typeDiagnostics = cacheService.getGlobalDiagnosticsMap().get(params.getTextDocument().getUri());
List<Diagnostic> parserErrors = parserService.getDiagnosticsOfErrors(input, params.getTextDocument().getUri());
ArrayList<Diagnostic> allDiagnostics = new ArrayList<>(typeDiagnostics);
allDiagnostics.addAll(parserErrors);
clientService.publishDiagnostics(params.getTextDocument().getUri(), allDiagnostics);
}
private void updatePositions(DidChangeTextDocumentParams params, ArrayList<Integer> offsetPerLine, String old, String newText){
cacheService.getGlobalInlayHintMap().put(params.getTextDocument().getUri(), inlayHintAdjusterDiffUtils.adjustInlayHintsByLineDiff(old, newText, cacheService.getGlobalInlayHintMap().get(params.getTextDocument().getUri())));
for (var diagnostic : cacheService.getGlobalDiagnosticsMap().get(params.getTextDocument().getUri())) {
diagnostic.getRange().getStart().setCharacter(diagnostic.getRange().getStart().getCharacter() + offsetPerLine.get(diagnostic.getRange().getStart().getLine()));
diagnostic.getRange().getEnd().setCharacter(diagnostic.getRange().getEnd().getCharacter() + offsetPerLine.get(diagnostic.getRange().getEnd().getLine()));
}
clientService.updateClient();
}
private void updatePositions(DidChangeTextDocumentParams params, ArrayList<Integer> offsetPerLine){
for (var inlayHint : cacheService.getGlobalInlayHintMap().get(params.getTextDocument().getUri())) {
inlayHint.getPosition().setCharacter(inlayHint.getPosition().getCharacter() + offsetPerLine.get(inlayHint.getPosition().getLine()));
}
for (var diagnostic : cacheService.getGlobalDiagnosticsMap().get(params.getTextDocument().getUri())) {
diagnostic.getRange().getStart().setCharacter(diagnostic.getRange().getStart().getCharacter() + offsetPerLine.get(diagnostic.getRange().getStart().getLine()));
diagnostic.getRange().getEnd().setCharacter(diagnostic.getRange().getEnd().getCharacter() + offsetPerLine.get(diagnostic.getRange().getEnd().getLine()));
}
clientService.updateClient();
}
}

View File

@@ -0,0 +1,107 @@
package de.dhbw.handler;
import de.dhbw.helper.TextHelper;
import de.dhbw.helper.TypeResolver;
import de.dhbw.service.CacheService;
import de.dhbw.service.LogService;
import de.dhbw.service.TextDocumentService;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CodeActionHandler {
private final TextHelper textHelper;
private final TextDocumentService textDocumentService;
private final CacheService cacheService;
private final TypeResolver typeResolver;
private final LogService logService;
public CodeActionHandler(TextHelper textHelper, TextDocumentService textDocumentService, CacheService cacheService, TypeResolver typeResolver, LogService logService) {
this.textHelper = textHelper;
this.textDocumentService = textDocumentService;
this.cacheService = cacheService;
this.typeResolver = typeResolver;
this.logService = logService;
}
public List<Either<Command, CodeAction>> handleCodeAction(CodeActionParams params) {
String documentUri = params.getTextDocument().getUri();
List<Diagnostic> diagnosticInCurrentDocument = params.getContext().getDiagnostics();
Range rangeOfInsert = params.getRange();
//All Diagnostics that are in range of the hover -> All Diagnostics of the selected Variable and thus all Types of the Variable
List<Diagnostic> diagnosticsOverlappingHover = diagnosticInCurrentDocument.stream()
.filter(diagnostic -> textDocumentService.rangesOverlap(diagnostic.getRange(), rangeOfInsert)).toList();
List<Either<Command, CodeAction>> actions = new ArrayList<>();
for (Diagnostic typeDiagnostic : diagnosticsOverlappingHover) {
try {
String typeWithReplacedVariable = typeDiagnostic.getMessage() +
" " +
textHelper.getTextOfChars(
textDocumentService.getFileOfUri(documentUri),
rangeOfInsert.getStart().getLine(),
rangeOfInsert.getStart().getCharacter(),
rangeOfInsert.getEnd().getCharacter()
);
ArrayList<TextEdit> listOfChanges = new ArrayList<>();
if (typeDiagnostic.getCode().getLeft().equals("GENERIC")) {
for (var diagnostic : cacheService.getGlobalDiagnosticsMap().get(documentUri)) {
if (diagnostic.getCode().getLeft().equals("GENERIC")) {
String genericType = diagnostic.getMessage() +
" " +
textHelper.getTextOfChars(
textDocumentService.getFileOfUri(params.getTextDocument().getUri()),
diagnostic.getRange().getStart().getLine(),
diagnostic.getRange().getStart().getCharacter(),
diagnostic.getRange().getEnd().getCharacter()
);
listOfChanges.add(new TextEdit(diagnostic.getRange(), genericType));
}
}
} else {
listOfChanges.add(new TextEdit(rangeOfInsert, typeWithReplacedVariable));
}
var isTypeImported = false;
if (!typeDiagnostic.getCode().getLeft().equalsIgnoreCase("generic")) {
isTypeImported = typeResolver.isTypeImported(textDocumentService.getFileOfUri(params.getTextDocument().getUri()), typeDiagnostic.getMessage());
}
if (!isTypeImported && !typeDiagnostic.getMessage().equals("void") && !typeDiagnostic.getCode().getLeft().equals("GENERIC")) {
Range importRange = new Range(new Position(0, 0), new Position(0, 0));
var typeWithoutGenerics = typeDiagnostic.getMessage().contains("<") ? typeDiagnostic.getMessage().substring(0, typeDiagnostic.getMessage().indexOf('<')) : typeDiagnostic.getMessage();
listOfChanges.add(new TextEdit(importRange, "import " + typeWithoutGenerics + ";\n"));
}
Map<String, List<TextEdit>> changes = new HashMap<>();
changes.put(documentUri, listOfChanges);
WorkspaceEdit edit = new WorkspaceEdit();
edit.setChanges(changes);
CodeAction action = new CodeAction("Insert " + typeDiagnostic.getMessage());
action.setKind(CodeActionKind.QuickFix);
action.setEdit(edit);
actions.add(Either.forRight(action));
} catch (Exception e) {
logService.log("Error creating Actions, returning empty List. The Error was: " + e.getMessage(), MessageType.Error);
}
}
return actions;
}
}

View File

@@ -0,0 +1,38 @@
package de.dhbw.handler;
import de.dhbw.service.TextDocumentService;
import org.eclipse.lsp4j.DocumentFormattingParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import java.util.ArrayList;
import java.util.List;
public class FormattingHandler {
private final TextDocumentService textDocumentService;
public FormattingHandler(TextDocumentService textDocumentService) {
this.textDocumentService = textDocumentService;
}
public List<TextEdit> handleFormat(DocumentFormattingParams params){
List<TextEdit> edits = new ArrayList<>();
String[] lines = textDocumentService.getFileOfUri(params.getTextDocument().getUri()).split("\n");
StringBuilder formattedText = new StringBuilder();
for (String line : lines) {
formattedText.append(line.stripTrailing()).append("\n");
}
TextEdit edit = new TextEdit();
edit.setRange(new Range(new Position(0, 0), new Position(lines.length, 0)));
edit.setNewText(formattedText.toString().trim());
edits.add(edit);
return edits;
}
}

View File

@@ -0,0 +1,55 @@
package de.dhbw.handler;
import com.github.difflib.DiffUtils;
import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.DeltaType;
import com.github.difflib.patch.Patch;
import org.eclipse.lsp4j.InlayHint;
import org.eclipse.lsp4j.Position;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class InlayHintAdjusterDiffUtils {
public List<InlayHint> adjustInlayHintsByLineDiff(String oldText, String newText, List<InlayHint> oldHints) {
List<String> oldLines = Arrays.asList(oldText.split("\n", -1));
List<String> newLines = Arrays.asList(newText.split("\n", -1));
Patch<String> patch = DiffUtils.diff(oldLines, newLines);
List<AbstractDelta<String>> deltas = patch.getDeltas();
List<InlayHint> adjusted = new ArrayList<>();
for (InlayHint hint : oldHints) {
int oldLine = hint.getPosition().getLine();
int lineShift = calculateLineShift(deltas, oldLine);
int newLine = Math.max(0, oldLine + lineShift);
adjusted.add(new InlayHint(new Position(newLine, hint.getPosition().getCharacter()), hint.getLabel()));
}
return adjusted;
}
private static int calculateLineShift(List<AbstractDelta<String>> deltas, int oldLine) {
int shift = 0;
for (AbstractDelta<String> delta : deltas) {
int deltaLine = delta.getSource().getPosition();
int linesRemoved = delta.getSource().size();
int linesAdded = delta.getTarget().size();
if (oldLine > deltaLine) {
if (delta.getType() == DeltaType.INSERT) {
shift += linesAdded;
} else if (delta.getType() == DeltaType.DELETE) {
shift -= linesRemoved;
} else if (delta.getType() == DeltaType.CHANGE) {
shift += linesAdded - linesRemoved;
}
}
}
return shift;
}
}

View File

@@ -0,0 +1,75 @@
package de.dhbw.handler;
import com.google.common.base.Stopwatch;
import de.dhbw.model.DiagnosticsAndTypehints;
import de.dhbw.service.*;
import de.dhbw.helper.ConversionHelper;
import de.dhbw.helper.TypeResolver;
import de.dhbw.model.LSPVariable;
import org.eclipse.lsp4j.*;
import java.util.ArrayList;
import java.util.List;
public class SaveHandler {
private final TypeResolver typeResolver;
private final TextDocumentService textDocumentService;
private final LogService logService;
private final CacheService cacheService;
private final ConversionHelper conversionHelper;
private final ClientService clientService;
private final ParserService parserService;
public SaveHandler(TypeResolver typeResolver, TextDocumentService textDocumentService, LogService logService, CacheService cacheService, ConversionHelper conversionHelper, ClientService clientService, ParserService parserService) {
this.typeResolver = typeResolver;
this.textDocumentService = textDocumentService;
this.logService = logService;
this.cacheService = cacheService;
this.conversionHelper = conversionHelper;
this.clientService = clientService;
this.parserService = parserService;
}
public void handleSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {
var sWatch = Stopwatch.createUnstarted();
sWatch.start();
try {
String fileInput = textDocumentService.getFileOfUri(didSaveTextDocumentParams.getTextDocument().getUri());
cacheService.getLastSavedFiles().put(didSaveTextDocumentParams.getTextDocument().getUri(), fileInput);
typeResolver.getCompilerInput(didSaveTextDocumentParams.getTextDocument().getUri(), fileInput);
if (fileInput == null) {
logService.log("[didSave] Input of Text Document is null in TextDocument-Hashmap.", MessageType.Error);
}
ArrayList<LSPVariable> variables = typeResolver.infereInput(fileInput, didSaveTextDocumentParams.getTextDocument().getUri());
cacheService.setVariables(variables);
DiagnosticsAndTypehints diagnosticsAndTypehints = conversionHelper.variablesToDiagnosticsAndTypehints(variables, didSaveTextDocumentParams.getTextDocument().getUri());
List<InlayHint> typeHint = diagnosticsAndTypehints.getInlayHints();
List<Diagnostic> diagnostics = diagnosticsAndTypehints.getDiagnostics();
cacheService.updateGlobalMaps(diagnostics, typeHint, didSaveTextDocumentParams.getTextDocument().getUri());
List<Diagnostic> allDiagnostics = new ArrayList<>(diagnostics);
allDiagnostics.addAll(parserService.getDiagnosticsOfErrors(fileInput, didSaveTextDocumentParams.getTextDocument().getUri()));
clientService.publishDiagnostics(didSaveTextDocumentParams.getTextDocument().getUri(), allDiagnostics);
} 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());
cacheService.updateGlobalMaps(new ArrayList<>(), new ArrayList<>(), didSaveTextDocumentParams.getTextDocument().getUri());
} finally {
sWatch.stop();
logService.log("[didSave] Finished Calculating in [" + sWatch.elapsed().toSeconds() + "s]", MessageType.Info);
}
}
}

View File

@@ -0,0 +1,162 @@
package de.dhbw.helper;
import de.dhbw.model.*;
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.Pattern;
import de.dhbwstuttgart.syntaxtree.statement.Assign;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ASTTransformationHelper {
private static final Logger log = Logger.getLogger(ASTTransformationHelper.class);
private final DuplicationUtils duplicationUtils;
private final TypeUtils typeUtils;
private final GenericUtils genericUtils;
public ASTTransformationHelper(DuplicationUtils duplicationUtils, TypeUtils typeUtils, GenericUtils genericUtils) {
this.duplicationUtils = duplicationUtils;
this.typeUtils = typeUtils;
this.genericUtils = genericUtils;
}
public List<LSPParameter> constructorToVariable(LanguageServerTransferObject transferObject) {
List<LSPParameter> methodsWithParametersLSPVariableList = new ArrayList<>();
for (var constructor : transferObject.getAst().KlassenVektor.getFirst().getConstructors()) {
for (var constructorParam : constructor.getParameterList().getFormalparalist()) {
var types = typeUtils.getAvailableTypes(transferObject.getResultSets(), constructorParam.getType());
methodsWithParametersLSPVariableList.add(new LSPParameter("", types, constructorParam.getOffset().getLine(), constructorParam.getOffset().getCharPositionInLine(), constructorParam.getOffset().getStopIndex(), constructorParam.getType()));
}
}
return methodsWithParametersLSPVariableList;
}
public List<LSPParameter> fieldDeclToVariable(LanguageServerTransferObject transferObject) {
List<LSPParameter> methodsWithParametersLSPVariableList = new ArrayList<>();
for (var fieldDecl : transferObject.getAst().KlassenVektor.getFirst().getFieldDecl()) {
var types = typeUtils.getAvailableTypes(transferObject.getResultSets(), fieldDecl.getReturnType());
methodsWithParametersLSPVariableList.add(new LSPParameter("", types, fieldDecl.getOffset().getLine(), fieldDecl.getOffset().getCharPositionInLine(), fieldDecl.getOffset().getStopIndex(), fieldDecl.getReturnType()));
}
if (transferObject.getAst().KlassenVektor.getFirst().getfieldInitializations().isPresent()) {
methodsWithParametersLSPVariableList.addAll(lambdaExpressionToVariable(transferObject.getAst().KlassenVektor.getFirst().getfieldInitializations().get().block.statements, transferObject));
}
return methodsWithParametersLSPVariableList;
}
public List<LSPClass> addGenericClassPosition(LanguageServerTransferObject transferObject, String input) {
List<LSPClass> methodsWithParametersLSPVariableList = new ArrayList<>();
// for (var method : transferObject.getAst().getAllMethods()) {
// for (var clazz : transferObject.getAst().getClasses()) {
// ArrayList<Type> genericTypes = genericUtils.getClassGenerics(transferObject.getGeneratedGenerics(), method, clazz);
// TextHelper helper = new TextHelper();
// if (!genericTypes.isEmpty()) {
// methodsWithParametersLSPVariableList.add(new LSPClass("test", genericTypes, clazz.getOffset().getLine(), helper.getClassPositionForGeneric(clazz.getOffset().getLine() - 1, input, clazz.getOffset().getStopIndex()), clazz.getOffset().getStopIndex(), clazz.getReturnType()));
// }
// }
//
// }
return methodsWithParametersLSPVariableList;
}
public List<LSPVariable> methodsWithParameterToVariable(LanguageServerTransferObject transferObj, boolean ENABLE_GENERICS) {
List<LSPVariable> methodsWithParametersLSPVariableList = new ArrayList<>();
for (var method : transferObj.getAst().getAllMethods()) {
methodsWithParametersLSPVariableList.addAll(methodToVariable(transferObj, method, ENABLE_GENERICS));
for (var param : method.getParameterList()) {
methodsWithParametersLSPVariableList.addAll(parameterToVariable(transferObj, param, method, ENABLE_GENERICS));
}
methodsWithParametersLSPVariableList.addAll(lambdaExpressionToVariable(method.block.statements, transferObj));
}
return methodsWithParametersLSPVariableList;
}
private List<LSPParameter> lambdaExpressionToVariable(List<Statement> statements, LanguageServerTransferObject transferObj) {
List<LSPParameter> methodsWithParametersLSPVariableList = new ArrayList<>();
for (var statement : statements) {
if (statement instanceof Assign assign) {
if (assign.rightSide instanceof LambdaExpression lambdaExpression)
for (var param : lambdaExpression.params.getFormalparalist()) {
var types = typeUtils.getAvailableTypes(transferObj.getResultSets(), param.getType());
methodsWithParametersLSPVariableList.add(new LSPParameter("", types, param.getOffset().getLine(), param.getOffset().getCharPositionInLine(), param.getOffset().getStopIndex(), param.getType()));
}
}
}
return methodsWithParametersLSPVariableList;
}
private List<LSPMethod> methodToVariable(LanguageServerTransferObject transferObj, Method method, boolean ENABLE_GENERICS) {
List<LSPMethod> methodsWithParametersLSPVariableList = new ArrayList<>();
var types = typeUtils.getAvailableTypes(transferObj.getResultSets(), method);
if (!duplicationUtils.filterOutDuplicates(types).isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPMethod(method.name, duplicationUtils.filterOutDuplicates(types), method.getOffset().getLine(), method.getOffset().getCharPositionInLine(), method.getOffset().getStopIndex(), method.getReturnType()));
}
if (ENABLE_GENERICS) {
var generics = genericUtils.getAvailableGenericTypes(transferObj.getGeneratedGenerics().values().stream().flatMap(List::stream).collect(Collectors.toList()), method);
if (!generics.isEmpty()) {
ArrayList<Type> typesThatAreGeneric = duplicationUtils.filterOutDuplicates(generics, types);
typesThatAreGeneric.forEach(el -> el.setType("<" + el.getType() + "> " + el.getType()));
//TODO: Muss Global und wird mehrmals so gemacht. Das if hier ist eigentlich falsch wegen unnötiger Berechnungszeit
if (!duplicationUtils.filterOutDuplicates(typesThatAreGeneric).isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPMethod(method.name, duplicationUtils.filterOutDuplicates(typesThatAreGeneric), method.getOffset().getLine(), method.getOffset().getCharPositionInLine(), method.getOffset().getStopIndex(), method.getReturnType()));
}
}
}
return methodsWithParametersLSPVariableList;
}
private List<LSPParameter> parameterToVariable(LanguageServerTransferObject transferObj, Pattern param, Method method, boolean ENABLE_GENERICS) {
List<LSPParameter> parameters = new ArrayList<>();
ArrayList<Type> typeParam = typeUtils.getAvailableTypes(transferObj.getResultSets(), param.getType());
if (!typeParam.isEmpty()) {
parameters.add(new LSPParameter(method.name, duplicationUtils.filterOutDuplicates(typeParam), param.getOffset().getLine(), param.getOffset().getCharPositionInLine(), param.getOffset().getStopIndex(), param.getType()));
}
if (ENABLE_GENERICS) {
ArrayList<Type> genericParam = genericUtils.getAvailableGenericTypes(transferObj.getGeneratedGenerics().values().stream().flatMap(List::stream).collect(Collectors.toList()), param.getType());
if (!genericParam.isEmpty()) {
ArrayList<Type> typesThatAreGeneric = duplicationUtils.filterOutDuplicates(genericParam, typeParam);
if (!duplicationUtils.filterOutDuplicates(typesThatAreGeneric).isEmpty()) {
parameters.add(new LSPParameter(method.name, duplicationUtils.filterOutDuplicates(typesThatAreGeneric), method.getOffset().getLine(), param.getOffset().getCharPositionInLine(), param.getOffset().getStopIndex(), param.getType()));
parameters.add(new LSPParameter(method.name, new ArrayList<>(duplicationUtils.filterOutDuplicates(typesThatAreGeneric).stream().map(el -> new Type("<" + el.getType() + ">", true)).toList()), method.getOffset().getLine(), method.getOffset().getCharPositionInLine(), method.getOffset().getStopIndex(), method.getReturnType()));
}
}
}
return parameters;
}
}

View File

@@ -0,0 +1,89 @@
package de.dhbw.helper;
import de.dhbw.model.DiagnosticsAndTypehints;
import de.dhbw.service.TextDocumentService;
import de.dhbw.model.LSPVariable;
import de.dhbw.model.Type;
import de.dhbwstuttgart.languageServerInterface.model.ParserError;
import org.eclipse.lsp4j.*;
import java.util.ArrayList;
import java.util.List;
public class ConversionHelper {
private final TextHelper textHelper;
private final TextDocumentService textDocumentService;
public ConversionHelper(TextHelper textHelper, TextDocumentService textDocumentService) {
this.textHelper = textHelper;
this.textDocumentService = textDocumentService;
}
public InlayHint getInlayHint(LSPVariable variable) {
InlayHint inlayHint = new InlayHint();
String typeDisplay = "";
for (Type type : variable.getPossibleTypes()) {
typeDisplay += " | " + type.getType().replaceAll("GTV ", "");
}
inlayHint.setLabel(typeDisplay.length() > 2 ? typeDisplay.substring(2) : typeDisplay);
inlayHint.setPosition(new Position(variable.getLine() - 1, variable.getCharPosition()));
inlayHint.setKind(InlayHintKind.Parameter);
inlayHint.setPaddingRight(true);
inlayHint.setPaddingRight(true);
return inlayHint;
}
public Diagnostic getDiagnostic(LSPVariable variable, String fileUri, Type type) {
Range errorRange = new Range(
new Position(variable.getLine() - 1, variable.getCharPosition()), // Startposition
new Position(variable.getLine() - 1, textHelper.getEndingCharOfStartingChar(variable.getLine() - 1, variable.getCharPosition(), textDocumentService.getFileOfUri(fileUri))) // Endposition
);
Diagnostic diagnostic = new Diagnostic(
errorRange,
//TODO: REMOVE! Temporary Fix because GTV, like TPH can be thrown away in the TypeResolver
type.getType().replaceAll("GTV ", ""),
DiagnosticSeverity.Hint,
"JavaTX Language Server"
);
diagnostic.setCode(type.isGeneric() ? "GENERIC" : "TYPE");
return diagnostic;
}
public List<Diagnostic> parseErrorToDiagnostic(List<ParserError> parserErrors){
return parserErrors.stream().map(el -> {
Range errorRange = new Range(
new Position(el.getLine() - 1, el.getCharPositionInLine()), // Startposition
new Position(el.getLine() - 1, el.getEndCharPosition()) // Endposition
);
return new Diagnostic(
errorRange,
el.getMsg(),
DiagnosticSeverity.Error,
"JavaTX Language Server"
);
}).toList();
}
public DiagnosticsAndTypehints variablesToDiagnosticsAndTypehints(ArrayList<LSPVariable> typesOfMethodAndParameters, String uri){
List<InlayHint> typeHint = new ArrayList<>();
ArrayList<Diagnostic> diagnostics = new ArrayList<>();
for (var variable : typesOfMethodAndParameters) {
InlayHint inlayHint = getInlayHint(variable);
typeHint.add(inlayHint);
for (var type : variable.getPossibleTypes()) {
Diagnostic diagnostic = getDiagnostic(variable, uri, type);
diagnostics.add(diagnostic);
}
}
return new DiagnosticsAndTypehints(diagnostics, typeHint);
}
}

View File

@@ -0,0 +1,34 @@
package de.dhbw.helper;
import de.dhbw.model.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DuplicationUtils {
public ArrayList<Type> filterOutDuplicates(List<Type> typeListOne, List<Type> typeListTwo) {
ArrayList<Type> filteredArrayList = new ArrayList<>();
typeListOne.forEach(el -> {
boolean found = false;
for (Type typeInListTwo : typeListTwo) {
found = found || typeInListTwo.getType().equals(el.getType());
}
if (!found) {
filteredArrayList.add(el);
}
});
return filteredArrayList;
}
public ArrayList<Type> filterOutDuplicates(List<Type> typeListOne) {
HashMap<String, Type> hashMap = new HashMap<>();
typeListOne.forEach(el -> {
hashMap.put(el.getType(), el);
});
return new ArrayList<>(hashMap.values());
}
}

View File

@@ -0,0 +1,69 @@
package de.dhbw.helper;
import de.dhbw.model.Type;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.generate.GenericsResult;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GenericUtils {
public ArrayList<Type> getClassGenerics(Map<SourceFile, List<GenericsResult>> genericsResult, Method method, ClassOrInterface clazz) {
ArrayList<Type> genericTypes = new ArrayList<>();
genericsResult.forEach(((key, value) -> value.forEach(genericResultSet -> {
var result = genericResultSet.resolveTarget(method.getReturnType());
var genericResult = genericResultSet.getBounds(method.getReturnType(), clazz, method);
if (result != null && genericResult != null) {
genericResult.forEach(res -> {
if (res != null && !res.isOnMethod()) {
genericTypes.add(new Type("<" + result.name() + (res.bound().toString().equals("java.lang.Object") ? ">" : " extends " + res.bound().toString() + ">"), true));
}
}
);
}
})));
return genericTypes;
}
public ArrayList<Type> getAvailableGenericTypes(List<GenericsResult> genericsResult, RefTypeOrTPHOrWildcardOrGeneric parameter) {
ArrayList<String> paramTypes = new ArrayList<>();
genericsResult.forEach(conSet -> {
if (parameter.toString().toLowerCase().contains("tph ")) {
paramTypes.add(conSet.resolveTarget(parameter).name());
}
});
return new ArrayList<>(paramTypes.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, true)).toList());
}
public ArrayList<Type> getAvailableGenericTypes(List<GenericsResult> genericsResult, Method method) {
ArrayList<String> genericTypes = new ArrayList<>();
genericsResult.forEach(conSet -> {
if (method.getReturnType().toString().toLowerCase().contains("tph ")) {
if (conSet.resolveTarget(method.getReturnType()) != null && conSet.resolveTarget(method.getReturnType()).name() != null && conSet.resolveTarget(method.getReturnType()).name().contains("GTV")) {
genericTypes.add(conSet.resolveTarget(method.getReturnType()).name().replaceAll("GTV ", ""));
}
}
});
return new ArrayList<>(genericTypes.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, true)).toList());
}
}

View File

@@ -0,0 +1,18 @@
package de.dhbw.helper;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import org.eclipse.lsp4j.InlayHint;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
public class PositionAdjustmentHelper {
private final TypeResolver typeResolver;
public PositionAdjustmentHelper(TypeResolver typeResolver) {
this.typeResolver = typeResolver;
}
}

View File

@@ -2,8 +2,6 @@ package de.dhbw.helper;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TextHelper {

View File

@@ -4,64 +4,40 @@ package de.dhbw.helper;
import de.dhbw.model.*;
import de.dhbwstuttgart.languageServerInterface.LanguageServerInterface;
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
* Helper-Class for finding the Type of a selected Word
*/
public class TypeResolver {
HashMap<Integer, LanguageServerTransferObject> dataCache = new HashMap<>();
private static final Logger logger = LogManager.getLogger(TypeResolver.class);
private final ASTTransformationHelper astTransformationHelper;
private final TypeUtils typeUtils;
private final GenericUtils genericUtils;
private final DuplicationUtils duplicationUtils;
private final boolean ENABLE_GENERICS = true;
private List<ResultSet> currentResults = new ArrayList<>();
//Somehow you have to reset to the Letter N to keep the naming of the TPHs consistent
private final String RESET_TO_LETTER = "N";
public List<ResultSet> getCurrentResults() {
return currentResults;
}
public void setCurrentResults(List<ResultSet> currentResults) {
this.currentResults = currentResults;
}
public void addToCurrentResults(List<ResultSet> additionalResults) {
this.currentResults.addAll(additionalResults);
}
private LanguageServerTransferObject current;
public TypeResolver() {
this.typeUtils = new TypeUtils();
this.genericUtils = new GenericUtils();
this.duplicationUtils = new DuplicationUtils();
this.astTransformationHelper = new ASTTransformationHelper(duplicationUtils, typeUtils, genericUtils);
}
private LanguageServerTransferObject getCacheOrCalculate(String input, String path) throws IOException, ClassNotFoundException, URISyntaxException {
logger.info("Trying to find cached Compiler-Answer for input with key [" + input.hashCode() + "].");
LanguageServerInterface languageServer = new LanguageServerInterface();
if (dataCache.containsKey(input.hashCode())) {
logger.info("Found Cache for the Input with key [" + input.hashCode() + "].");
return dataCache.get(input.hashCode());
} else {
logger.info("Could not find Cache for Input with key [" + input.hashCode() + "]. Using Compiler Interface and Saving the Answer in Cache.");
var transferObject = languageServer.getResultSetAndAbstractSyntax(path, input);
dataCache.put(input.hashCode(), transferObject);
return transferObject;
}
}
public boolean isTypeImported(String input, String type) {
// try {
// var transferObject = getCacheOrCalculate(input);
@@ -80,110 +56,19 @@ public class TypeResolver {
return true;
}
public ArrayList<Type> getAvailableTypes(List<ResultSet> resultSets, Method method) {
logger.info("Searching for resulting Types of Placeholder [" + method.getReturnType().toString() + "].");
ArrayList<String> normalType = new ArrayList<>();
resultSets.forEach(conSet -> {
if (method.getReturnType().toString().toLowerCase().contains("tph ")) {
normalType.add(conSet.resolveType(method.getReturnType()).resolvedType.toString());
}
});
return new ArrayList<>(normalType.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, false)).toList());
public void getCompilerInput(String path, String input) throws IOException, URISyntaxException, ClassNotFoundException {
LanguageServerInterface languageServer = new LanguageServerInterface();
var transferObj = languageServer.getResultSetAndAbstractSyntax(path);
current = transferObj;
}
public ArrayList<Type> getAvailableGenericTypes(List<GenericsResult> genericsResult, Method method) {
logger.info("Searching for resulting Types of Placeholder [" + method.getReturnType().toString() + "].");
ArrayList<String> genericTypes = new ArrayList<>();
genericsResult.forEach(conSet -> {
if (method.getReturnType().toString().toLowerCase().contains("tph ")) {
genericTypes.add(conSet.resolveTarget(method.getReturnType()).name().replaceAll("GTV ", ""));
}
});
return new ArrayList<>(genericTypes.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, true)).toList());
}
public ArrayList<Type> getAvailableGenericTypes(List<GenericsResult> genericsResult, RefTypeOrTPHOrWildcardOrGeneric parameter) {
logger.info("Searching for resulting Types of Placeholder [" + parameter.toString() + "].");
ArrayList<String> paramTypes = new ArrayList<>();
genericsResult.forEach(conSet -> {
if (parameter.toString().toLowerCase().contains("tph ")) {
paramTypes.add(conSet.resolveTarget(parameter).name());
}
});
return new ArrayList<>(paramTypes.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, true)).toList());
}
public ArrayList<Type> getAvailableTypes(List<ResultSet> resultSets, RefTypeOrTPHOrWildcardOrGeneric parameter) {
logger.info("Searching for resulting Types of Placeholder [" + parameter.toString() + "].");
ArrayList<String> paramTypes = new ArrayList<>();
resultSets.forEach(conSet -> {
if (parameter.toString().toLowerCase().contains("tph ")) {
paramTypes.add(conSet.resolveType(parameter).resolvedType.toString());
}
});
return new ArrayList<>(paramTypes.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, false)).toList());
}
public ArrayList<Type> filterOutDuplicates(List<Type> typeListOne, List<Type> typeListTwo) {
ArrayList<Type> filteredArrayList = new ArrayList<>();
typeListOne.forEach(el -> {
boolean found = false;
for (Type typeInListTwo : typeListTwo) {
found = found || typeInListTwo.getType().equals(el.getType());
}
if (!found) {
filteredArrayList.add(el);
}
});
return filteredArrayList;
}
public ArrayList<Type> filterOutDuplicates(List<Type> typeListOne) {
HashMap<String, Type> hashMap = new HashMap<>();
typeListOne.forEach(el -> {
hashMap.put(el.getType(), el);
});
return new ArrayList<>(hashMap.values());
}
public ArrayList<Type> getClassGenerics(Map<SourceFile, List<GenericsResult>> genericsResult, Method method, ClassOrInterface clazz) {
ArrayList<Type> genericTypes = new ArrayList<>();
genericsResult.forEach(((key, value) -> value.forEach(genericResultSet -> {
var result = genericResultSet.resolveTarget(method.getReturnType());
var genericResult = genericResultSet.getBounds(method.getReturnType(), clazz, method);
if (result != null && genericResult != null) {
genericResult.forEach(res -> {
if (res != null && !res.isOnMethod()) {
genericTypes.add(new Type("<" + result.name() + (res.bound().toString().equals("java.lang.Object") ? ">" : " extends " + res.bound().toString() + ">"), true));
}
}
);
}
})));
return genericTypes;
public LanguageServerTransferObject updateIfNotPresent(String path, String input) throws IOException, URISyntaxException, ClassNotFoundException {
if (current == null) {
LanguageServerInterface languageServer = new LanguageServerInterface();
LanguageServerTransferObject transferObj = languageServer.getResultSetAndAbstractSyntax(path);
return transferObj;
}
return current;
}
/**
@@ -192,64 +77,86 @@ public class TypeResolver {
public ArrayList<LSPVariable> infereInput(String input, String path) throws IOException, ClassNotFoundException, URISyntaxException {
logger.info("Infering Types for Input.");
LanguageServerInterface languageServer = new LanguageServerInterface();
var transferObj = languageServer.getResultSetAndAbstractSyntax(path, input);
current = updateIfNotPresent(path, input);
LanguageServerTransferObject transferObj = current;
ArrayList<LSPVariable> methodsWithParametersLSPVariableList = new ArrayList<>();
//TODO: Hier noch irgendwie die Klasse rausfinden oder durchgehen.
//GENERICS OF CLASS
for (var method : transferObj.getAst().getAllMethods()) {
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.constructorToVariable(transferObj));
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.fieldDeclToVariable(transferObj));
for (var clazz : transferObj.getAst().getClasses()) {
ArrayList<Type> genericTypes = getClassGenerics(transferObj.getGeneratedGenerics(), method, clazz);
TextHelper helper = new TextHelper();
if (!genericTypes.isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPClass("test", genericTypes, clazz.getOffset().getLine(), helper.getClassPositionForGeneric(clazz.getOffset().getLine() - 1, input, clazz.getOffset().getStopIndex()), clazz.getOffset().getStopIndex()));
}
if (!transferObj.getResultSets().isEmpty()) {
//TODO: Hier noch irgendwie die Klasse rausfinden oder durchgehen.
if (ENABLE_GENERICS) {
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.addGenericClassPosition(transferObj, input));
}
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.methodsWithParameterToVariable(transferObj, ENABLE_GENERICS));
}
for (var method : transferObj.getAst().getAllMethods()) {
var types = getAvailableTypes(transferObj.getResultSets(), method);
var generics = getAvailableGenericTypes(transferObj.getGeneratedGenerics().values().stream().flatMap(List::stream).collect(Collectors.toList()), method);
return methodsWithParametersLSPVariableList;
}
if (!filterOutDuplicates(types).isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPMethod(method.name, filterOutDuplicates(types), method.getOffset().getLine(), method.getOffset().getCharPositionInLine(), method.getOffset().getStopIndex()));
}
if (!generics.isEmpty()) {
ArrayList<Type> typesThatAreGeneric = filterOutDuplicates(generics, types);
typesThatAreGeneric.forEach(el -> el.setType("<" + el.getType() + "> " + el.getType()));
//TODO: Muss Global und wird mehrmals so gemacht. Das if hier ist eigentlich falsch wegen unnötiger Berechnungszeit
if (!filterOutDuplicates(typesThatAreGeneric).isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPMethod(method.name, filterOutDuplicates(typesThatAreGeneric), method.getOffset().getLine(), method.getOffset().getCharPositionInLine(), method.getOffset().getStopIndex()));
}
public ArrayList<LSPVariable> infereInput(String input, String path, SourceFile sourceFile) throws IOException, ClassNotFoundException, URISyntaxException {
logger.info("Infering Types for Input.");
current = updateIfNotPresent(path, input);
LanguageServerTransferObject transferObj = current;
transferObj = new LanguageServerTransferObject(transferObj.getResultSets(), sourceFile, "", transferObj.getGeneratedGenerics());
ArrayList<LSPVariable> methodsWithParametersLSPVariableList = new ArrayList<>();
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.constructorToVariable(transferObj));
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.fieldDeclToVariable(transferObj));
if (!transferObj.getResultSets().isEmpty()) {
//TODO: Hier noch irgendwie die Klasse rausfinden oder durchgehen.
if (ENABLE_GENERICS) {
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.addGenericClassPosition(transferObj, input));
}
for (var param : method.getParameterList()) {
ArrayList<Type> typeParam = getAvailableTypes(transferObj.getResultSets(), param.getType());
ArrayList<Type> genericParam = getAvailableGenericTypes(transferObj.getGeneratedGenerics().values().stream().flatMap(List::stream).collect(Collectors.toList()), param.getType());
if (!typeParam.isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPParameter(method.name, filterOutDuplicates(typeParam), param.getOffset().getLine(), param.getOffset().getCharPositionInLine(), param.getOffset().getStopIndex()));
}
if (!genericParam.isEmpty()) {
ArrayList<Type> typesThatAreGeneric = filterOutDuplicates(genericParam, typeParam);
if (!filterOutDuplicates(typesThatAreGeneric).isEmpty()) {
methodsWithParametersLSPVariableList.add(new LSPParameter(method.name, filterOutDuplicates(typesThatAreGeneric), method.getOffset().getLine(), param.getOffset().getCharPositionInLine(), param.getOffset().getStopIndex()));
methodsWithParametersLSPVariableList.add(new LSPParameter(method.name, new ArrayList<>(filterOutDuplicates(typesThatAreGeneric).stream().map(el -> new Type("<" + el.getType() + ">", true)).toList()), method.getOffset().getLine(), method.getOffset().getCharPositionInLine(), method.getOffset().getStopIndex()));
}
}
}
methodsWithParametersLSPVariableList.addAll(astTransformationHelper.methodsWithParameterToVariable(transferObj, ENABLE_GENERICS));
}
return methodsWithParametersLSPVariableList;
}
public void reduceCurrent(HashMap<LineCharPosition, String> combinedList, List<LSPVariable> variables) {
for (var lines : combinedList.entrySet()) {
var contentChange = lines.getValue();
for (LSPVariable variable : variables) {
for (Type typeOfVariable : variable.getPossibleTypes()) {
if (typeOfVariable.getType().equalsIgnoreCase(contentChange.replaceAll(" ", ""))) {
if (variable.getLine() - 1 == lines.getKey().line && variable.getCharPosition() == lines.getKey().charPosition) {
current.getResultSets().removeIf(el -> !el.resolveType(variable.getOriginalTphName()).resolvedType.toString().equalsIgnoreCase(contentChange.replaceAll(" ", "")));
return;
}
}
}
}
}
}
public SourceFile getNewAst(String uri) throws IOException, URISyntaxException, ClassNotFoundException {
LanguageServerInterface languageServerInterface = new LanguageServerInterface();
return languageServerInterface.getAst(uri, RESET_TO_LETTER);
}
public void updateAst(String uri) throws IOException, URISyntaxException, ClassNotFoundException {
current = new LanguageServerTransferObject(current.getResultSets(), getNewAst(uri), "", current.getGeneratedGenerics());
}
}

View File

@@ -0,0 +1,39 @@
package de.dhbw.helper;
import de.dhbw.model.Type;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class TypeUtils {
public ArrayList<Type> getAvailableTypes(List<ResultSet> resultSets, RefTypeOrTPHOrWildcardOrGeneric parameter) {
ArrayList<String> paramTypes = new ArrayList<>();
resultSets.forEach(conSet -> {
if (parameter.toString().toLowerCase().contains("tph ")) {
paramTypes.add(conSet.resolveType(parameter).resolvedType.toString());
}
});
return new ArrayList<>(paramTypes.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, false)).toList());
}
public ArrayList<Type> getAvailableTypes(List<ResultSet> resultSets, Method method) {
ArrayList<String> normalType = new ArrayList<>();
resultSets.forEach(conSet -> {
if (method.getReturnType().toString().toLowerCase().contains("tph ")) {
normalType.add(conSet.resolveType(method.getReturnType()).resolvedType.toString());
}
});
return new ArrayList<>(normalType.stream().filter(el -> !el.contains("TPH ")).map(el -> new Type(el, false)).toList());
}
}

View File

@@ -0,0 +1,33 @@
package de.dhbw.model;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.InlayHint;
import java.util.List;
public class DiagnosticsAndTypehints {
private List<Diagnostic> diagnostics;
private List<InlayHint> inlayHints;
public List<Diagnostic> getDiagnostics() {
return diagnostics;
}
public List<InlayHint> getInlayHints() {
return inlayHints;
}
public void setDiagnostics(List<Diagnostic> diagnostics) {
this.diagnostics = diagnostics;
}
public void setInlayHints(List<InlayHint> inlayHints) {
this.inlayHints = inlayHints;
}
public DiagnosticsAndTypehints(List<Diagnostic> diagnostics, List<InlayHint> inlayHints){
this.diagnostics = diagnostics;
this.inlayHints = inlayHints;
}
}

View File

@@ -0,0 +1,41 @@
package de.dhbw.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DocumentChanges {
HashMap<LineCharPosition, String> preciseChanges = new HashMap<>();
ArrayList<Integer> offsetPerLine = new ArrayList<>();
HashMap<Integer, List<String>> textChanges = new HashMap<>();
public ArrayList<Integer> getOffsetPerLine() {
return offsetPerLine;
}
public HashMap<Integer, List<String>> getTextChanges() {
return textChanges;
}
public HashMap<LineCharPosition, String> getPreciseChanges() {
return preciseChanges;
}
public void setOffsetPerLine(ArrayList<Integer> offsetPerLine) {
this.offsetPerLine = offsetPerLine;
}
public void setPreciseChanges(HashMap<LineCharPosition, String> preciseChanges) {
this.preciseChanges = preciseChanges;
}
public void setTextChanges(HashMap<Integer, List<String>> textChanges) {
this.textChanges = textChanges;
}
public DocumentChanges(HashMap<LineCharPosition, String> preciseChanges, ArrayList<Integer> offsetPerLine, HashMap<Integer, List<String>> textChanges){
this.preciseChanges = preciseChanges;
this.offsetPerLine = offsetPerLine;
this.textChanges = textChanges;
}
}

View File

@@ -1,9 +1,11 @@
package de.dhbw.model;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.ArrayList;
public class LSPClass extends LSPVariable{
public LSPClass(String name, ArrayList<Type> possibleTypes, int line, int charPosition, int endPosition) {
super(name, possibleTypes, line, charPosition, endPosition);
public LSPClass(String name, ArrayList<Type> possibleTypes, int line, int charPosition, int endPosition, RefTypeOrTPHOrWildcardOrGeneric originalTphName) {
super(name, possibleTypes, line, charPosition, endPosition, originalTphName);
}
}

View File

@@ -1,9 +1,11 @@
package de.dhbw.model;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.ArrayList;
public class LSPMethod extends LSPVariable {
public LSPMethod(String name, ArrayList<Type> type, int line, int charPosition, int endPosition) {
super(name, type, line, charPosition, endPosition);
public LSPMethod(String name, ArrayList<Type> type, int line, int charPosition, int endPosition, RefTypeOrTPHOrWildcardOrGeneric originalTphName) {
super(name, type, line, charPosition, endPosition, originalTphName);
}
}

View File

@@ -1,10 +1,12 @@
package de.dhbw.model;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.ArrayList;
public class LSPParameter extends LSPMethod {
public class LSPParameter extends LSPVariable {
public LSPParameter(String name, ArrayList<Type> type, int line, int charPosition, int endPosition) {
super(name, type, line, charPosition, endPosition);
public LSPParameter(String name, ArrayList<Type> type, int line, int charPosition, int endPosition, RefTypeOrTPHOrWildcardOrGeneric originalTphName) {
super(name, type, line, charPosition, endPosition, originalTphName);
}
}

View File

@@ -1,20 +1,33 @@
package de.dhbw.model;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.ArrayList;
public class LSPVariable { String name;
public class LSPVariable {
String name;
ArrayList<Type> possibleTypes;
int line;
int charPosition;
int endPosition;
boolean needsInference;
RefTypeOrTPHOrWildcardOrGeneric originalTphName;
public LSPVariable(String name, ArrayList<Type> possibleTypes, int line, int charPosition, int endPosition) {
public LSPVariable(String name, ArrayList<Type> possibleTypes, int line, int charPosition, int endPosition, RefTypeOrTPHOrWildcardOrGeneric originalTphName) {
this.name = name;
this.possibleTypes = possibleTypes;
this.line = line;
this.charPosition = charPosition;
this.endPosition = endPosition;
this.originalTphName = originalTphName;
}
public RefTypeOrTPHOrWildcardOrGeneric getOriginalTphName() {
return originalTphName;
}
public void setOriginalTphName(RefTypeOrTPHOrWildcardOrGeneric originalTphName) {
this.originalTphName = originalTphName;
}
public int getEndPosition() {

View File

@@ -0,0 +1,25 @@
package de.dhbw.model;
public class LineCharPosition {
public final int line;
public final int charPosition;
public LineCharPosition(int line, int charPosition) {
this.line = line;
this.charPosition = charPosition;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof LineCharPosition)) return false;
LineCharPosition that = (LineCharPosition) o;
return line == that.line && charPosition == that.charPosition;
}
@Override
public String toString() {
return "Line " + line + ", Char " + charPosition;
}
}

View File

@@ -0,0 +1,129 @@
package de.dhbw.service;
import de.dhbw.helper.CodeSnippetOptions;
import de.dhbw.helper.TextHelper;
import de.dhbw.helper.TypeResolver;
import de.dhbw.model.LSPVariable;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.InlayHint;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class CacheService {
private HashMap<String, List<InlayHint>> globalInlayHintMap = new HashMap<>();
private HashMap<String, String> lastSavedFiles = new HashMap<>();
private Boolean currentlyCalculating = false;
private HashMap<String, List<Diagnostic>> globalDiagnosticsMap = new HashMap<>();
private HashMap<String, String> textDocuments = new HashMap<>();
private CodeSnippetOptions codeSnippetOptions = new CodeSnippetOptions();
private TextHelper textHelper = new TextHelper();
private Boolean dontShowHints = false;
private TypeResolver typeResolver = new TypeResolver();
private Path fileRoot = null;
private Boolean singleFileOpened = false;
private List<LSPVariable> variables = new ArrayList<>();
public void updateGlobalMaps(List<Diagnostic> diagnostics, List<InlayHint> typeHint, String uri) {
globalDiagnosticsMap.put(uri, diagnostics);
globalInlayHintMap.put(uri, typeHint);
}
public Boolean getCurrentlyCalculating() {
return currentlyCalculating;
}
public Boolean getDontShowHints() {
return dontShowHints;
}
public Boolean getSingleFileOpened() {
return singleFileOpened;
}
public HashMap<String, String> getLastSavedFiles() {
return lastSavedFiles;
}
public void setLastSavedFiles(HashMap<String, String> lastSavedFiles) {
this.lastSavedFiles = lastSavedFiles;
}
public CodeSnippetOptions getCodeSnippetOptions() {
return codeSnippetOptions;
}
public HashMap<String, List<Diagnostic>> getGlobalDiagnosticsMap() {
return globalDiagnosticsMap;
}
public HashMap<String, List<InlayHint>> getGlobalInlayHintMap() {
return globalInlayHintMap;
}
public HashMap<String, String> getTextDocuments() {
return textDocuments;
}
public List<LSPVariable> getVariables() {
return variables;
}
public Path getFileRoot() {
return fileRoot;
}
public TextHelper getTextHelper() {
return textHelper;
}
public TypeResolver getTypeResolver() {
return typeResolver;
}
public void setCodeSnippetOptions(CodeSnippetOptions codeSnippetOptions) {
this.codeSnippetOptions = codeSnippetOptions;
}
public void setCurrentlyCalculating(Boolean currentlyCalculating) {
this.currentlyCalculating = currentlyCalculating;
}
public void setDontShowHints(Boolean dontShowHints) {
this.dontShowHints = dontShowHints;
}
public void setFileRoot(Path fileRoot) {
this.fileRoot = fileRoot;
}
public void setGlobalDiagnosticsMap(HashMap<String, List<Diagnostic>> globalDiagnosticsMap) {
this.globalDiagnosticsMap = globalDiagnosticsMap;
}
public void setGlobalInlayHintMap(HashMap<String, List<InlayHint>> globalInlayHintMap) {
this.globalInlayHintMap = globalInlayHintMap;
}
public void setSingleFileOpened(Boolean singleFileOpened) {
this.singleFileOpened = singleFileOpened;
}
public void setTextDocuments(HashMap<String, String> textDocuments) {
this.textDocuments = textDocuments;
}
public void setTextHelper(TextHelper textHelper) {
this.textHelper = textHelper;
}
public void setTypeResolver(TypeResolver typeResolver) {
this.typeResolver = typeResolver;
}
public void setVariables(List<LSPVariable> variables) {
this.variables = variables;
}
}

View File

@@ -0,0 +1,79 @@
package de.dhbw.service;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClient;
import java.util.List;
public class ClientService {
private LanguageClient client;
public ClientService(LanguageClient client) {
this.client = client;
}
public void publishDiagnostics(String uri, List<Diagnostic> diagnostics){
PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(uri, diagnostics);
client.publishDiagnostics(diagnosticsParams);
}
public void sendClientLog(MessageType type, String message){
client.logMessage(new MessageParams(type, message));
}
public void sendClientLog(String message){
client.logMessage(new MessageParams(MessageType.Info, message));
}
public void showMessage(MessageType type, String message) {
client.showMessage(new MessageParams(type, message));
}
public void showMessage(String message) {
client.showMessage(new MessageParams(MessageType.Info, message));
}
public void setClient(LanguageClient client) {
this.client = client;
}
public void updateClient(LanguageClient client) {
client.refreshInlayHints();
client.refreshDiagnostics();
}
public void updateClient() {
client.refreshInlayHints();
client.refreshDiagnostics();
}
public LanguageClient getClient() {
return client;
}
public void startLoading(String taskName, String title, LanguageClient client) {
Either<String, Integer> token = Either.forLeft(taskName);
client.createProgress(new WorkDoneProgressCreateParams(token));
WorkDoneProgressBegin begin = new WorkDoneProgressBegin();
begin.setTitle(title);
begin.setCancellable(false);
begin.setPercentage(0);
ProgressParams beginParams = new ProgressParams(token, Either.forLeft(begin));
client.notifyProgress(beginParams);
}
public void stopLoading(String taskName, String title, LanguageClient client) {
Either<String, Integer> token = Either.forLeft(taskName);
WorkDoneProgressEnd end = new WorkDoneProgressEnd();
end.setMessage(title);
ProgressParams endParams = new ProgressParams(token, Either.forLeft(end));
client.notifyProgress(endParams);
}
}

View File

@@ -0,0 +1,31 @@
package de.dhbw.service;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.eclipse.lsp4j.MessageType;
public class LogService {
private final Logger logger = LogManager.getLogger(LogService.class);
private final ClientService clientService;
public LogService(ClientService clientService) {
this.clientService = clientService;
}
public void log(String message, MessageType type) {
clientService.sendClientLog(type, message);
switch (type) {
case Error -> logger.error(message);
case Warning -> logger.warn(message);
case Info -> logger.info(message);
default -> logger.debug(message);
}
}
public void log(String message) {
clientService.sendClientLog(MessageType.Info, message);
logger.info(message);
}
}

View File

@@ -0,0 +1,35 @@
package de.dhbw.service;
import de.dhbw.helper.ConversionHelper;
import de.dhbwstuttgart.languageServerInterface.ParserInterface;
import de.dhbwstuttgart.languageServerInterface.model.ParserError;
import org.eclipse.lsp4j.Diagnostic;
import java.util.List;
public class ParserService {
private final ConversionHelper conversionHelper;
private final ClientService clientService;
public ParserService(ConversionHelper conversionHelper, ClientService clientService, CacheService cacheService) {
this.conversionHelper = conversionHelper;
this.clientService = clientService;
}
public List<ParserError> getParserErrors(String input){
ParserInterface parserInterface = new ParserInterface();
return parserInterface.getParseErrors(input);
}
public void checkParser(String input, String uri) {
List<Diagnostic> diagnosticsList = conversionHelper.parseErrorToDiagnostic(getParserErrors(input));
clientService.publishDiagnostics(uri, diagnosticsList);
}
public List<Diagnostic> getDiagnosticsOfErrors(String input, String uri) {
return conversionHelper.parseErrorToDiagnostic(getParserErrors(input));
}
}

View File

@@ -0,0 +1,116 @@
package de.dhbw.service;
import de.dhbw.model.DocumentChanges;
import de.dhbw.model.LineCharPosition;
import org.eclipse.lsp4j.Range;
import java.util.*;
public class TextDocumentService {
private final HashMap<String, String> files = new HashMap<>();
public TextDocumentService(){
}
public String getFileOfUri(String uri) {
return files.get(uri);
}
public void saveFileWithUri(String uri, String input) {
files.put(uri, input);
}
public DocumentChanges calculateDifference(String currentText, String newText){
ArrayList<String> currentTextLines = new ArrayList<>(Arrays.stream(currentText.split("\n")).toList());
ArrayList<String> newTextLines = new ArrayList<>(Arrays.stream(newText.split("\n")).toList());
HashMap<LineCharPosition, String> preciseChanges = new HashMap<>();
ArrayList<Integer> offsetPerLine = new ArrayList<>();
HashMap<Integer, List<String>> textChanges = new HashMap<>();
int index = 0;
for (String newTextLine : newTextLines) {
if (!(currentTextLines.size() > index)) {
offsetPerLine.add(0);
} else {
Map<LineCharPosition, String> lineDiffs = differenceLinePos(currentTextLines.get(index), newTextLine, index);
preciseChanges.putAll(lineDiffs);
textChanges.put(index, difference(currentTextLines.get(index), newTextLine).stream().map(el -> el.replaceAll(" ", "")).toList());
offsetPerLine.add(newTextLine.length() - currentTextLines.get(index).length());
}
index++;
}
return new DocumentChanges(preciseChanges, offsetPerLine, textChanges);
}
public Map<LineCharPosition, String> differenceLinePos(String first, String second, int line) {
Map<LineCharPosition, String> result = new HashMap<>();
int i = 0, j = 0;
int startDiff = -1;
while (j < second.length()) {
if (i < first.length() && first.charAt(i) == second.charAt(j)) {
if (startDiff != -1) {
String diff = second.substring(startDiff, j);
result.put(new LineCharPosition(line, startDiff), diff);
startDiff = -1;
}
i++;
j++;
} else {
if (startDiff == -1) {
startDiff = j;
}
j++;
}
}
if (startDiff != -1) {
String diff = second.substring(startDiff);
result.put(new LineCharPosition(line, startDiff), diff);
}
return result;
}
public ArrayList<String> difference(String first, String second) {
ArrayList<String> result = new ArrayList<>();
int i = 0, j = 0;
int startDiff = -1;
while (j < second.length()) {
if (i < first.length() && first.charAt(i) == second.charAt(j)) {
if (startDiff != -1) {
result.add(second.substring(startDiff, j));
startDiff = -1;
}
i++;
j++;
} else {
if (startDiff == -1) {
startDiff = j;
}
j++;
}
}
if (startDiff != -1) {
result.add(second.substring(startDiff));
}
return result;
}
public boolean rangesOverlap(Range range1, Range range2) {
int start1 = range1.getStart().getLine() * 1000 + range1.getStart().getCharacter();
int end1 = range1.getEnd().getLine() * 1000 + range1.getEnd().getCharacter();
int start2 = range2.getStart().getLine() * 1000 + range2.getStart().getCharacter();
int end2 = range2.getEnd().getLine() * 1000 + range2.getEnd().getCharacter();
return start1 <= end2 && start2 <= end1;
}
}

View File

@@ -1,6 +1,5 @@
import de.dhbw.helper.CodeSnippetOptions;
import de.dhbw.model.SnippetWithName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

View File

@@ -6,25 +6,35 @@ import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.net.URISyntaxException;
public class CompilerInterfaceTest {
@Test
public void testAbstractSyntaxAsString() throws IOException, ClassNotFoundException {
// LanguageServerInterface languageServer = new LanguageServerInterface();
// var res = languageServer.getResultSetAndAbstractSyntax("import java.lang.Integer;\n import java.lang.String;\n" +
// "public class test{\n" +
// "public main(test){" +
// "if(0>1){" +
// "return \"w\";" +
// "}" +
// "Integer i = 0;" +
// "return i;" +
// "}" +
// "}", "TEST");
//
// System.out.println("TEST OUTPUT:");
public void testAbstractSyntaxAsString() throws IOException, ClassNotFoundException, URISyntaxException {
TypeResolver typeResolver = new TypeResolver();
var res = typeResolver.infereInput("import java.lang.Integer;\n import java.lang.String;\n" +
"public class test{\n" +
"public main(test){" +
"if(0>1){" +
"return \"w\";" +
"}" +
"Integer i = 0;" +
"return i;" +
"}" +
"}", "c%3A/Users/ruben/Neuer%20Ordner%20%282%29/LSP-Vortrag/images/test.jav");
var res2 = typeResolver.infereInput("import java.lang.Integer;\n import java.lang.String;\n" +
"public class test{\n" +
"public main(test){" +
"if(0>1){" +
"return \"w\";" +
"}" +
"Integer i = 0;" +
"return i;" +
"}" +
"}", "c%3A/Users/ruben/Neuer%20Ordner%20%282%29/LSP-Vortrag/images/test.jav");
System.out.println("TEST OUTPUT:");
//
// ArrayList<String> allTypes = new ArrayList<>();
//
@@ -40,18 +50,16 @@ public class CompilerInterfaceTest {
}
@Test
public void testConstraintTypes() throws IOException, ClassNotFoundException {
// LanguageServerInterface languageServer = new LanguageServerInterface();
// TypeResolver typeResolver = new TypeResolver();
//
//
// var res = typeResolver.infereInput("import java.lang.Integer; public class test{\n" +
// " \n" +
// " public main(testa){\n" +
// " return testa;\n" +
// " }\n" +
// "}");
// res.forEach(el -> el.getPossibleTypes().forEach(el2 -> System.out.println(el2.getType() + " " + (el2.isGeneric() ? "GENERIC" : "NO GENERIC"))));
public void testConstraintTypes() throws IOException, ClassNotFoundException, URISyntaxException {
LanguageServerInterface languageServer = new LanguageServerInterface();
TypeResolver typeResolver = new TypeResolver();
var res = languageServer.getResultSetAndAbstractSyntax("/home/ruben/Documents/JavaTXLanguageServer/test/test.jav");
var res2 = languageServer.getResultSetAndAbstractSyntax("/home/ruben/Documents/JavaTXLanguageServer/test/test.jav");
System.out.println("");
}
@Test
@@ -114,7 +122,7 @@ public class CompilerInterfaceTest {
@Test
public void testCharEnding() throws IOException, ClassNotFoundException {
TextHelper textHelper = new TextHelper();
var endingChar = textHelper.getEndingCharOfStartingChar(3,13,"import java.lang.Integer;\n" +
var endingChar = textHelper.getEndingCharOfStartingChar(3, 13, "import java.lang.Integer;\n" +
"import java.lang.String; \n" +
"public class test{\n" +
" public main(test, test2){\n" +

View File

@@ -1,7 +1,3 @@
import de.dhbw.JavaTXTextDocumentService;
import de.dhbw.helper.CodeSnippetOptions;
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.junit.Ignore;
import org.junit.jupiter.api.Test;
@@ -11,6 +7,7 @@ public class JavaTXLanguageDocumentServiceTest {
@Test
@Ignore
public void testWordExtraction() {
JavaTXTextDocumentService service = new JavaTXTextDocumentService();
// JavaTXTextDocumentService service = new JavaTXTextDocumentService();
// service.didSave(new DidSaveTextDocumentParams(new TextDocumentIdentifier("file:///c%3A/Users/ruben/Neuer%20Ordner%20%282%29/LSP-Vortrag/images/test.jav")));
}
}

5
test/test.jav Normal file
View File

@@ -0,0 +1,5 @@
public class t{
public test(){
return 1;
}
}