95 Commits

Author SHA1 Message Date
RubenKraft
72ef89baa9 Update README.md 2025-05-12 17:06:28 +00:00
Ruben
51edd4193f fix: disable Compiling of whole Workspace 2025-05-12 18:57:24 +02:00
Ruben
ade00dff4f fix: add Generic Type back in 2025-05-12 16:04:58 +02:00
Ruben
a17a7a6c83 fix: relative log File and add Logging in Client 2025-05-12 14:50:29 +02:00
Ruben
680e8b17b1 refactor: refactoring and adding Methods instead of calculating everything in one method 2025-05-09 14:47:36 +02:00
Ruben
4958fd8b44 feat: compile whole project if more then two Files exist 2025-05-08 19:26:56 +02:00
Ruben
c85f2f3c13 feat: refresh typehints and diagnostics after compiling 2025-05-08 17:58:20 +02:00
Ruben
669dc9b535 feat: add loading symbol when compiling 2025-05-08 17:51:00 +02:00
Ruben
6b3ede2deb fix: remove empty labels that are beeing displayed 2025-05-08 17:09:19 +02:00
Ruben
d5ee17b3d3 feat: add calculating Variable to not Compute every Time 2025-05-07 14:13:52 +02:00
Ruben
bb79020028 feat: generate Bytecode when Saving File 2025-05-06 15:46:52 +02:00
Ruben
3b0c261ebe feat: add Jar as Maven Library 2025-05-05 16:01:08 +02:00
Ruben
1eb136be73 feat: add Jar instead of Files of Compiler 2025-05-05 15:15:54 +02:00
Ruben
a63af12365 feat: make retry higher and change adding of Generics to filter out duplicates 2025-04-01 18:45:43 +02:00
Ruben
4971e0762c feat: add retries for higher Chance to get a Result from the Compiler 2025-04-01 18:06:26 +02:00
Ruben
f072e26e1d feat: make every Generic to Method Generic Temporarly and do not Import Generics 2025-04-01 17:40:57 +02:00
Ruben
1e3fa2d315 refactor: fix naming of Methods 2025-03-31 17:00:00 +02:00
Ruben
119ced125d refactor: Major refactoring of Typefinding Algorithm 2025-03-31 16:52:28 +02:00
Ruben
306204d436 refactor: enhance Logging 2025-03-05 17:27:40 +01:00
Ruben
bdc0b8a2b6 feat: cleanup, added padding for Typehints, fixed Variable Namings, deleted extends Object, ... 2025-02-26 16:07:23 +01:00
Ruben
ecd57ceec7 fix: remove display of "extends java.lang.Object" on Generics when Generic extends from Object 2025-02-26 12:49:05 +01:00
Ruben
1803fec36a fix: remove display of GTV in Typehints and Diagnostics. This Fix is temporary and should be fixed by adding GTV to the remove-Logic 2025-02-26 12:09:08 +01:00
RubenKraft
c3d2252476 Update README.md 2025-02-26 10:55:32 +00:00
RubenKraft
1dfa30e05e docs: update readme 2025-02-26 10:19:56 +00:00
Ruben
b08c921933 fix: fix position of Diagnostics 2025-02-24 15:56:44 +01:00
Ruben
252f64a2bb Merge remote-tracking branch 'origin/main' 2025-02-20 15:52:28 +01:00
Ruben
7143126741 feat: add First Version of Intellij-Client not working yet 2025-02-20 15:52:18 +01:00
Ruben
de2595cf62 feat: add First Version of Intellij-Client (not working yet) 2025-02-20 15:51:18 +01:00
RubenKraft
58a895b581 Update README.md 2025-02-20 13:16:49 +00:00
Ruben
0740f95c26 feat: add selection of Generics 2025-02-20 14:13:56 +01:00
Ruben
b192e33615 fix: disable unnecessary display of TPHs as Typehints 2025-02-19 18:11:24 +01:00
Ruben
4219678db6 feat: add Bounds and Parameter-Generics 2025-02-19 16:45:02 +01:00
Ruben
12781de581 feat: add Bounds and Parameter-Generics 2025-02-19 15:23:41 +01:00
Ruben
89af1759ff feat: add first Version of Generics 2025-02-19 14:29:06 +01:00
RubenKraft
1e117600f9 docs: update Readme 2025-02-14 12:56:52 +00:00
Ruben
6f457479aa test: add Tests for Generics 2025-02-13 17:33:21 +01:00
Ruben
3b0b97841e feat: add Parser Interface to get Parse Errors on API instead of doing it without it 2025-02-13 16:34:34 +01:00
Ruben
fbf8704af6 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	Clients/VisualStudioCode/JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar
2025-02-12 17:03:05 +01:00
Ruben
dc896a453d feat: add Generic ResultSet in DTO 2025-02-12 17:02:52 +01:00
Ruben
5d41a19705 feat: add Generic ResultSet in DTO 2025-02-12 17:00:52 +01:00
Ruben
ae2461b99d fix: fix Algorithm of getting all Types of Result-Set 2025-01-30 17:54:04 +01:00
RubenKraft
234e6eed1a Update README.md 2025-01-30 12:11:05 +00:00
RubenKraft
9ea1bff5f4 docs: update Readme 2025-01-29 17:40:55 +00:00
Ruben
a4060225e1 fix: use Hashmap instead of Input String as Key in Cache again. 2025-01-29 18:35:39 +01:00
Ruben
2a72aa3a57 fix: remove unneccesary newLine 2025-01-29 18:29:25 +01:00
Ruben
cabb7258aa Merge remote-tracking branch 'origin/main' 2025-01-29 18:22:48 +01:00
Ruben
25a1876b8f refactor #23: refactoring and cleanup 2025-01-29 18:22:39 +01:00
RubenKraft
d9177cbdf2 docs: update Readme 2025-01-29 17:05:49 +00:00
Ruben
c0b7f55491 fix: Fix import of only Main-Type when Type that is selected has Generic Type. 2025-01-29 17:55:03 +01:00
Ruben
6d0f243c80 feat #3: using Hashcode instead of complete String for Memory-Efficiency 2025-01-28 19:21:29 +01:00
Ruben
bc09039e73 feat #3: implement Cache one Layer Deeper 2025-01-28 19:15:54 +01:00
Ruben
6d6786d3b7 feat #3: implement Cache one Layer Deeper 2025-01-28 19:15:46 +01:00
Ruben
d470a93645 feat: add Log-Message for how many Typehints are beeing returned. 2025-01-28 18:58:33 +01:00
Ruben
535e121c0f feat: add simple Cache for Types 2025-01-28 18:53:11 +01:00
Ruben
077abb2c09 refactor: renaming TypeFinder to TypeResolver 2025-01-28 17:32:33 +01:00
Ruben
2b62965c44 feat #16: add import Statement if Type is not imported. 2025-01-28 17:02:40 +01:00
Ruben
a9eee2e4cf feat #16: add import Statement for all Types. CAREFUL - EXPERIMENTAL 2025-01-28 16:26:47 +01:00
Ruben
c47e8f4a9d feat: add Logger in every Class 2025-01-27 17:50:18 +01:00
Ruben
ac99140020 fix: add Log4J as Logging Framework and Configuring it 2025-01-27 17:38:41 +01:00
Ruben
3ee03cc788 fix: fix trimming one char too much 2025-01-27 17:36:12 +01:00
Ruben
80f533913c refactoring: minor refactoring 2025-01-27 16:52:02 +01:00
Ruben
05ef4123f0 refactoring: minor refactoring and renaming 2025-01-27 16:32:45 +01:00
Ruben
57f41cf534 feat: update jar for Client 2025-01-26 11:08:56 +01:00
Ruben
04894b3667 test: add Test for End-Of-Word Algorithm 2025-01-26 11:08:32 +01:00
Ruben
63a2876959 feat #9 #2: add Algorithm for finding Ending of Word and fix Positioning of Hints 2025-01-26 11:05:12 +01:00
Ruben
24d01f756b feat: add setTrace Method so Client does not throw Error when sending setTrace Message 2025-01-26 11:02:09 +01:00
Ruben
cda180fbb8 fix: add jar in Client so Client is actually usable. 2025-01-25 22:29:54 +01:00
Ruben
ca020b2929 refactor: minor cleanup 2025-01-25 22:27:50 +01:00
Ruben
463fdc97a3 feat: replace Information-Text from "replace" to "insert" 2025-01-25 22:21:58 +01:00
Ruben
dd91476f04 feat #17: add Hashmap for Documents in Server 2025-01-25 22:09:08 +01:00
Ruben
e3a4a981ba feat: load Textdocument on Document Open 2025-01-25 21:54:04 +01:00
Ruben
acd5d5f09c feat: changed direct activation instead of activating extension with command 2025-01-25 21:48:04 +01:00
Ruben
b6bf0d8b17 feat: remove null and add save returns for all Methods 2025-01-25 21:40:03 +01:00
Ruben
2de2617a8d feat: fix position of Method-Names 2025-01-25 21:11:51 +01:00
Ruben
1cc5f8a4fd docs: update drawio to English 2025-01-24 15:17:39 +01:00
Ruben
58e31a8bea docs: moved to separate Folder 2025-01-23 12:03:35 +01:00
RubenKraft
cbeaa12d9c docs: add drawio-File 2025-01-23 10:59:17 +00:00
RubenKraft
2f08a2acb6 docs: update Readme 2025-01-23 10:55:36 +00:00
RubenKraft
856f7f4bd0 docs: upload simple Logic Diagram 2025-01-23 10:52:20 +00:00
RubenKraft
5bc8683665 docs: update Readme 2025-01-23 10:31:22 +00:00
Ruben
2056e5504c feat: change from Error to Hint Diagnostic 2025-01-22 18:47:38 +01:00
Ruben
a540a3f54a fix #12: deactivate Workspace Feature that leads to crashes of the Language Server 2025-01-22 18:09:05 +01:00
Ruben
bdf3e890a5 fix #1: Path is now dynamic. 2025-01-22 17:55:02 +01:00
Ruben
46e4be9ff5 feat: add Type replacement of typless Varibales in Parameters with Quick Fix 2025-01-22 17:35:36 +01:00
RubenKraft
64124daa61 Update README.md 2025-01-16 14:43:27 +00:00
Ruben
5da122db9c feat: add Diagnostic for every Type of infered Types to select from. 2025-01-15 15:57:10 +01:00
Ruben
236be16fda refactor: refactoring of Code to optimize the runtime 2025-01-15 15:47:06 +01:00
Ruben
2c6ccf0c48 fix: changed Types of Messages 2025-01-15 15:00:14 +01:00
Ruben
3038cd7e68 fix: temporarly fix position of placed Typeplaceholders but need to implement correct Algorithmn for that 2025-01-15 14:52:22 +01:00
Ruben
d56d06f752 feat: deactivate Hover effect and add Selection of Type. 2025-01-10 12:32:00 +01:00
Ruben
a447cd3f39 Merge remote-tracking branch 'origin/main' 2025-01-08 17:01:51 +01:00
Ruben
0173dd86da fix & feat: implement Display of Parameter in Code and Fix System.out 2025-01-08 17:01:35 +01:00
RubenKraft
214e80cfa2 Update README.md 2025-01-08 15:39:10 +00:00
Ruben
d5d562cee1 Merge remote-tracking branch 'origin/main' 2025-01-08 16:37:05 +01:00
Ruben
a236add9f6 feat: add TypeHints for Parameters 2025-01-08 16:36:54 +01:00
305 changed files with 1698 additions and 51753 deletions

6
.idea/JavaTXLanguageServer.iml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" />
</component>
</module>

42
Clients/Intellij/.gitignore vendored Normal file
View File

@@ -0,0 +1,42 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

3
Clients/Intellij/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

17
Clients/Intellij/.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

7
Clients/Intellij/.idea/misc.xml generated Normal file
View File

@@ -0,0 +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">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
Clients/Intellij/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,28 @@
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()
}

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Thu Feb 20 15:20:24 CET 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
Clients/Intellij/gradlew vendored Executable file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
Clients/Intellij/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,2 @@
rootProject.name = 'Intellij'

View File

@@ -0,0 +1,17 @@
package org.example;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void main(String[] args) {
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
// to see how IntelliJ IDEA suggests fixing it.
System.out.printf("Hello and welcome!");
for (int i = 1; i <= 5; i++) {
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
System.out.println("i = " + i);
}
}
}

View File

@@ -0,0 +1,76 @@
<!--
an example how you can configure an plugin xml with you plugin
see also jetbrains documentation: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
<idea-plugin>
<id>your.plugin.namespace</id>
<name>Your Plugin Name</name>
<vendor>your company/org</vendor>
<description>a description of your plugin</description>
<!-- Product and plugin compatibility requirements -->
<!-- https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html -->
<depends>com.intellij.modules.platform</depends>
<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"/>
<!-- register intellijLanguageClient as a Service OR as a plugin component (see readme)... -->
<applicationService serviceImplementation="org.wso2.lsp4intellij.IntellijLanguageClient"/>
<!-- register a listener on editor events, required for lsp file sync -->
<editorFactoryListener implementation="org.wso2.lsp4intellij.listeners.LSPEditorListener"/>
<fileDocumentManagerListener implementation="org.wso2.lsp4intellij.listeners.LSPFileDocumentManagerListener"/>
<!-- for displaying notifications by lsp -->
<notificationGroup id="lsp" displayType="STICKY_BALLOON"/>
<!-- for displaying progress notifications by lsp in the Event Log -->
<notificationGroup id="LSPProgressNotification" displayType="NONE" />
<!-- for displaying the statusbar icon -->
<statusBarWidgetFactory implementation="org.wso2.lsp4intellij.statusbar.LSPServerStatusWidgetFactory"
id="org.wso2.lsp4intellij.statusbar.LSPServerStatusWidgetFactory"
order="first" />
<!-- needed for completion -->
<completion.contributor implementationClass="org.wso2.lsp4intellij.contributors.LSPCompletionContributor"
id="org.wso2.lsp4intellij.contributors.LSPCompletionContributor" language="YOUR_LANGUAGE_ID"/>
<!-- needed for completion as well as signature help -->
<typedHandler implementation="org.wso2.lsp4intellij.listeners.LSPTypedHandler"
id="LSPTypedHandler"/>
<!-- needed for code diagnostics -->
<externalAnnotator id="LSPAnnotator" language="YOUR_LANGUAGE_ID"
implementationClass="org.wso2.lsp4intellij.contributors.annotator.LSPAnnotator"/>
<!-- needed for Workspace Symbols -->
<gotoSymbolContributor implementation="org.wso2.lsp4intellij.contributors.symbol.LSPSymbolContributor"
id="LSPSymbolContributor"/>
<!-- needed for renaming -->
<renameHandler implementation="org.wso2.lsp4intellij.contributors.rename.LSPRenameHandler" id="LSPRenameHandler" order="first"/>
<renamePsiElementProcessor implementation="org.wso2.lsp4intellij.contributors.rename.LSPRenameProcessor" id="LSPRenameProcessor" order="first"/>
<!-- needed for folding support -->
<lang.foldingBuilder language="YOUR_LANGUAGE_ID" implementationClass="org.wso2.lsp4intellij.contributors.LSPFoldingRangeProvider" id="LSPFoldingRangeProvider" order="first" />
</extensions>
<actions>
<!-- needed for hover -->
<action id="org.intellij.sdk.action.QuickDocAction" class="org.wso2.lsp4intellij.actions.LSPQuickDocAction">
</action>
<!-- needed for find references -->
<action class="org.wso2.lsp4intellij.actions.LSPReferencesAction" id="LSPFindUsages">
<keyboard-shortcut first-keystroke="shift alt F7" keymap="$default"/>
</action>
</actions>
<applicationListeners>
<!-- required for lsp file sync -->
<listener class="org.wso2.lsp4intellij.listeners.VFSListener"
topic="com.intellij.openapi.vfs.VirtualFileListener"/>
<listener class="org.wso2.lsp4intellij.listeners.LSPProjectManagerListener"
topic="com.intellij.openapi.project.ProjectManagerListener"/>
</applicationListeners>
</idea-plugin>

View File

@@ -9,7 +9,9 @@
"categories": [
"Other"
],
"activationEvents": [],
"activationEvents": [
"onLanguage:java"
],
"main": "./out/extension.js",
"contributes": {
"commands": [

View File

@@ -10,28 +10,34 @@ import {
TransportKind
} from 'vscode-languageclient/node';
// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
const workspaceFolder = context.extensionPath;
const serverOptions: ServerOptions = {
run: {
command: 'java',
args: ['-jar', "C:\\Users\\ruben\\JavaTXLanguageServer\\JavaTXLanguageServer\\LanguageServer\\target\\JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar"], // Absolute Pfadangabe
args: ['-jar', workspaceFolder + "/JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar"], // Absolute Pfadangabe
},
debug: {
command: 'java',
args: ['-jar', "C:\\Users\\ruben\\JavaTXLanguageServer\\JavaTXLanguageServer\\LanguageServer\\target\\JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar"], // Absolute Pfadangabe für Debug
args: ['-jar', workspaceFolder + "/JavaTXLanguageServer-1.0-SNAPSHOT-jar-with-dependencies.jar"], // Absolute Pfadangabe für Debug
}
};
console.log("SERVER CREATED.")
console.log(workspaceFolder)
// Clientoptionen: definiere, welche Dateitypen der Client unterstützt
const clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'java' }],
synchronize: {
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.java')
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.jav')
},
revealOutputChannelOn: 4
};

View File

@@ -20,6 +20,22 @@
<artifactId>antlr4</artifactId>
<version>4.11.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
@@ -36,6 +52,7 @@
<artifactId>classgraph</artifactId>
<version>4.8.172</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@@ -52,6 +69,11 @@
<artifactId>org.eclipse.lsp4j</artifactId>
<version>0.23.1</version>
</dependency>
<dependency>
<groupId>de.dhbwstuttgart</groupId>
<artifactId>JavaTXcompiler</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
@@ -72,8 +94,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>23</source>
<target>23</target>
<source>21</source>
<target>21</target>
</configuration>
</plugin>

View File

@@ -1,11 +1,14 @@
package de.dhbw;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
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;
/**
@@ -14,17 +17,20 @@ import java.util.concurrent.CompletableFuture;
*
* */
public class JavaTXLanguageServer implements LanguageServer {
private static final Logger logger = LogManager.getLogger(JavaTXLanguageServer.class);
private LanguageClient client;
public void connect(LanguageClient client) {
this.client = client;
textDocumentService.setClient(client);
}
private final JavaTXTextDocumentService textDocumentService = new JavaTXTextDocumentService();
private final JavaTXWorkspaceService workspaceService = new JavaTXWorkspaceService();
@Override
public void setTrace(SetTraceParams params) {
}
/**
* Configure the Features of the LanguageServer
* */
@@ -33,12 +39,16 @@ public class JavaTXLanguageServer implements LanguageServer {
ServerCapabilities capabilities = new ServerCapabilities();
capabilities.setDocumentFormattingProvider(true);
capabilities.setTextDocumentSync(TextDocumentSyncKind.Full);
capabilities.setHoverProvider(true);
capabilities.setHoverProvider(false);
capabilities.setInlayHintProvider(true);
capabilities.setCodeActionProvider(true);
capabilities.setTextDocumentSync(TextDocumentSyncKind.Full);
capabilities.setCompletionProvider(new CompletionOptions(true, List.of()));
capabilities.setWorkspaceSymbolProvider(false);
capabilities.setWorkspaceSymbolProvider(true);
if(params.getWorkspaceFolders() != null && !params.getWorkspaceFolders().isEmpty()) {
textDocumentService.setFileRoot(params.getWorkspaceFolders());
}
return CompletableFuture.supplyAsync(() -> new InitializeResult(capabilities));
}

View File

@@ -1,13 +1,10 @@
package de.dhbw;
import org.antlr.v4.runtime.Token;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.eclipse.lsp4j.launch.LSPLauncher;
import org.eclipse.lsp4j.services.LanguageClient;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.HashSet;
/**
*
@@ -16,10 +13,11 @@ import java.util.HashSet;
* */
public class JavaTXLanguageServerLauncher {
private static final Logger logger = LogManager.getLogger(JavaTXLanguageServerLauncher.class);
public static void main(String[] args) {
try {
JavaTXLanguageServer server = new JavaTXLanguageServer();
var launcher = LSPLauncher.createServerLauncher(server, System.in, System.out);
LanguageClient client = launcher.getRemoteProxy();

View File

@@ -1,52 +1,67 @@
package de.dhbw;
import de.dhbw.compiler.languageServerInterface.LanguageServerInterface;
import com.google.common.base.Stopwatch;
import de.dhbw.helper.CodeSnippetOptions;
import de.dhbw.helper.TypeFinder;
import de.dhbw.model.ParseError.DiagnoseErrorListener;
import de.dhbw.helper.TextHelper;
import de.dhbw.helper.TypeResolver;
import de.dhbw.model.LSPVariable;
import de.dhbw.model.SnippetWithName;
import de.dhbw.parser.Java17Lexer;
import de.dhbw.parser.Java17Parser;
import de.dhbw.parser.Java17ParserBaseListener;
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 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 org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import java.util.stream.Stream;
/**
*
* Handles Actions in Documents, such as Autocompletion, Change-Events and Syntax-Checks
*
* */
* Handles Actions in Documents, such as Autocompletion, Change-Events and Syntax-Checks
*/
public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.TextDocumentService {
private static final Logger logger = LogManager.getLogger(JavaTXTextDocumentService.class);
LanguageClient client;
String currentTextDocument;
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();
Path fileRoot = null;
public void setClient(LanguageClient client) {
this.client = client;
}
public void setFileRoot(List<WorkspaceFolder> root) {
//TODO: Nicht nur das erste Element nehmen sondern alle beachten
fileRoot = Path.of(URI.create(root.get(0).getUri()));
}
/**
*
* Handles Completion Events
* Handles Completion Events.
* In this case you can select codeSnippets.
*
* @param params the completion Context
* @return the Auto-Completion Items that will be displayed
* */
*/
@Override
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams params) {
List<CompletionItem> completions = new ArrayList<>();
@@ -66,62 +81,68 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
/**
*
* Handles didOpen Events
* Handles didOpen-Event.
* Puts the Text-Document in the text-Document Hashmap
*
* @param params the Context of the newly opened Document
* */
*/
@Override
public void didOpen(DidOpenTextDocumentParams params) {
textDocuments.put(params.getTextDocument().getUri(), params.getTextDocument().getText());
}
/**
*
* Handles didChange
* Handles didChange-Event.
* updates textDocument-State on Server and run Syntax-Check. If an Error is found it will get displayed as a Diagnostic.
*
* @param params the Context of the Changed Document, including the incremental change as well as the whole Document
* */
*/
@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()));
currentTextDocument = summedUp.get();
DiagnoseErrorListener errorListener = new DiagnoseErrorListener();
textDocuments.put(params.getTextDocument().getUri(), summedUp.get());
String input = summedUp.get();
CharStream charStream = CharStreams.fromString(input);
Java17Lexer lexer = new Java17Lexer(charStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ParserInterface parserInterface = new ParserInterface();
Java17Parser parser = new Java17Parser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(errorListener);
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();
ParseTree tree = parser.sourceFile();
ParseTreeWalker walker = new ParseTreeWalker();
Java17ParserBaseListener listener = new Java17ParserBaseListener();
walker.walk(listener, tree);
PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(params.getTextDocument().getUri(), errorListener.getErrorMessages());
PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(params.getTextDocument().getUri(), diagnostics);
client.publishDiagnostics(diagnosticsParams);
}
/**
*
* Handles a Formatting-Event
*
* @param params the Context of the Formatting
* */
*/
@Override
public CompletableFuture<List<? extends TextEdit>> formatting(DocumentFormattingParams params) {
log("[formatting] Client requested formatting.", MessageType.Info);
List<TextEdit> edits = new ArrayList<>();
String[] lines = currentTextDocument.split("\n");
String[] lines = textDocuments.get(params.getTextDocument().getUri()).split("\n");
StringBuilder formattedText = new StringBuilder();
for (String line : lines) {
@@ -138,40 +159,159 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
@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) {
//Irgendwie so machen das man nur dan inlayHints bekommt wenn man das DOkument speichert.
}
@Override
public CompletableFuture<List<InlayHint>> inlayHint(InlayHintParams params) {
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();
TypeFinder typeFinder = new TypeFinder();
try {
//TODO: change to get current Textdocument String
var languageServer = new LanguageServerInterface();
var typesOfMethods = typeFinder.infereMethodType(currentTextDocument);
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 typeOfMethod : typesOfMethods) {
InlayHint inlayHint = new InlayHint();
inlayHint.setLabel(":" + typeOfMethod.getType());
inlayHint.setPosition(new Position(typeOfMethod.getLine()-1, typeOfMethod.getCharPosition()+1));
inlayHint.setKind(InlayHintKind.Type);
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);
return CompletableFuture.completedFuture(typeHint);
} catch (Exception e) {
return CompletableFuture.completedFuture(Collections.emptyList());
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) {
}
}
@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()));
}
@Override
public void willSave(WillSaveTextDocumentParams params) {
TextDocumentService.super.willSave(params);
@@ -179,53 +319,53 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
@Override
public CompletableFuture<List<TextEdit>> willSaveWaitUntil(WillSaveTextDocumentParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<DocumentLink>> documentLink(DocumentLinkParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<DocumentLink> documentLinkResolve(DocumentLink params) {
return null;
return CompletableFuture.completedFuture(new DocumentLink());
}
@Override
public CompletableFuture<List<ColorInformation>> documentColor(DocumentColorParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<ColorPresentation>> colorPresentation(ColorPresentationParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<FoldingRange>> foldingRange(FoldingRangeRequestParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<CallHierarchyItem>> prepareCallHierarchy(CallHierarchyPrepareParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<CallHierarchyIncomingCall>> callHierarchyIncomingCalls(CallHierarchyIncomingCallsParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<CallHierarchyOutgoingCall>> callHierarchyOutgoingCalls(CallHierarchyOutgoingCallsParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<SelectionRange>> selectionRange(SelectionRangeParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
@@ -235,153 +375,191 @@ public class JavaTXTextDocumentService implements org.eclipse.lsp4j.services.Tex
@Override
public CompletableFuture<Either<SemanticTokens, SemanticTokensDelta>> semanticTokensFullDelta(SemanticTokensDeltaParams params) {
return null;
return CompletableFuture.completedFuture(Either.forLeft(new SemanticTokens()));
}
@Override
public CompletableFuture<SemanticTokens> semanticTokensRange(SemanticTokensRangeParams params) {
return null;
return CompletableFuture.completedFuture(new SemanticTokens());
}
@Override
public CompletableFuture<List<Moniker>> moniker(MonikerParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<CompletionItem> resolveCompletionItem(CompletionItem unresolved) {
return null;
return CompletableFuture.completedFuture(new CompletionItem());
}
/**
*
* returns the whole Word of the selected Character - Currently not correctly working
*
* @param line the line of the Character
* @param character the character in the line
* @param document the Document-Content as String
*
* @return the String containing the Word
* */
public String getWordOfLineAndCharacter(int line, int character, String document) {
var textArr = document.replace(";", " ; ").replace("{", " { ").replace("}", " } ").split("\n");
var selectedLine = textArr[line];
var hoverWord = "";
var index = 0;
for (String word : selectedLine.split(" ")) {
index += word.length();
if (index - word.length() <= character && index >= character) {
hoverWord = word.replace(" ", "");
}
}
return hoverWord;
}
/**
*
* Handles a Hover-Event
*
* @param params the Context of the Hovering
* */
@Override
public CompletableFuture<Hover> hover(HoverParams params) {
String hoverText = getWordOfLineAndCharacter(params.getPosition().getLine(), params.getPosition().getCharacter(), currentTextDocument);
MarkupContent markupContent = new MarkupContent();
markupContent.setKind("markdown");
markupContent.setValue(hoverText);
return CompletableFuture.completedFuture(new Hover(markupContent));
return CompletableFuture.completedFuture(new Hover());
}
@Override
public CompletableFuture<SignatureHelp> signatureHelp(SignatureHelpParams params) {
return null;
return CompletableFuture.completedFuture(new SignatureHelp());
}
@Override
public CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>> declaration(DeclarationParams params) {
return null;
return CompletableFuture.completedFuture(Either.forLeft(Collections.emptyList()));
}
@Override
public CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>> definition(DefinitionParams params) {
return null;
return CompletableFuture.completedFuture(Either.forLeft(Collections.emptyList()));
}
@Override
public CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>> typeDefinition(TypeDefinitionParams params) {
return null;
return CompletableFuture.completedFuture(Either.forLeft(Collections.emptyList()));
}
@Override
public CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>> implementation(ImplementationParams params) {
return null;
return CompletableFuture.completedFuture(Either.forLeft(Collections.emptyList()));
}
@Override
public CompletableFuture<List<? extends Location>> references(ReferenceParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<? extends DocumentHighlight>> documentHighlight(DocumentHighlightParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> documentSymbol(DocumentSymbolParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<Either<Command, CodeAction>>> codeAction(CodeActionParams params) {
return null;
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<>();
List<Diagnostic> diagnosticInCurrentDocument = params.getContext().getDiagnostics();
Range requestedRange = 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 -> 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;
}
@Override
public CompletableFuture<CodeAction> resolveCodeAction(CodeAction unresolved) {
return null;
return CompletableFuture.completedFuture(new CodeAction());
}
@Override
public CompletableFuture<List<? extends CodeLens>> codeLens(CodeLensParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<CodeLens> resolveCodeLens(CodeLens unresolved) {
return null;
return CompletableFuture.completedFuture(new CodeLens());
}
@Override
public CompletableFuture<List<? extends TextEdit>> rangeFormatting(DocumentRangeFormattingParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<List<? extends TextEdit>> onTypeFormatting(DocumentOnTypeFormattingParams params) {
return null;
return CompletableFuture.completedFuture(Collections.emptyList());
}
@Override
public CompletableFuture<WorkspaceEdit> rename(RenameParams params) {
return null;
return CompletableFuture.completedFuture(new WorkspaceEdit());
}
@Override
public CompletableFuture<LinkedEditingRanges> linkedEditingRange(LinkedEditingRangeParams params) {
return null;
return CompletableFuture.completedFuture(new LinkedEditingRanges());
}
}

View File

@@ -1,8 +1,14 @@
package de.dhbw;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
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 org.eclipse.lsp4j.DidChangeWatchedFilesParams;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@@ -11,7 +17,7 @@ import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
* */
public class JavaTXWorkspaceService implements WorkspaceService {
private static final Logger logger = LogManager.getLogger(JavaTXWorkspaceService.class);
@Override
public void didChangeConfiguration(DidChangeConfigurationParams didChangeConfigurationParams) {
@@ -19,7 +25,6 @@ public class JavaTXWorkspaceService implements WorkspaceService {
@Override
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
// Reagiere auf Änderungen im Dateisystem
System.out.println("Dateiänderungen im Arbeitsbereich: " + params.getChanges());
}
}

View File

@@ -1,7 +0,0 @@
package de.dhbw.compiler.bytecode;
public class CodeGenException extends RuntimeException {
public CodeGenException(String cause) {
super(cause);
}
}

View File

@@ -1,212 +0,0 @@
package de.dhbw.compiler.bytecode;
import de.dhbw.compiler.syntaxtree.statement.Break;
import de.dhbw.compiler.target.tree.TargetGeneric;
import de.dhbw.compiler.target.tree.type.*;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import java.sql.Array;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.objectweb.asm.Opcodes.*;
/**
* //ToDo beschreiben
*
* @since Studienarbeit Type Erasure
* @author etiennezink
*/
public class FunNGenerator {
private static final String argumentGenericBase = "T";
private static final String returnGeneric = "R";
private static final String methodName = "apply";
private static final int bytecodeVersion = V1_8;
private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
private static final String objectSignature = applySignature(TargetType.Object);
private static final String VOID = "Ljava/lang/Void;";
public static class GenericParameters {
int start;
public List<TargetType> parameters = new ArrayList<>();
final String descriptor;
public final List<TargetType> inParams;
public final List<TargetType> realParams;
public GenericParameters(List<TargetType> params, int numReturns) {
this.realParams = params;
this.inParams = flattenTypeParams(params);
var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1, numReturns), params);
descriptor = applyDescriptor(type, this);
}
private static List<TargetType> flattenTypeParams(List<TargetType> params) {
var res = new ArrayList<TargetType>();
for (var param : params) {
if (param instanceof TargetSpecializedType tspec) {
res.addAll(flattenTypeParams(tspec.params()));
} else {
res.add(param);
}
}
return res;
}
public TargetType getReturnType() {
return FunNGenerator.getReturnType(realParams);
}
public List<TargetType> getArguments() {
return FunNGenerator.getArguments(realParams);
}
}
private static String applyDescriptor(TargetType type, GenericParameters gep) {
if (type == null) return VOID;
var res = "L" + type.getInternalName();
if (type instanceof TargetSpecializedType a) {
if (a.params().size() > 0) {
res += "<";
for (var param : a.params()) {
if (param instanceof TargetGenericType gp) {
gep.parameters.add(param);
res += "TT" + gep.start + ";";
gep.start += 1;
} else {
res += applyDescriptor(param, gep);
}
}
res += ">";
}
} else {
gep.parameters.add(null);
return type.toDescriptor();
}
res += ";";
return res;
}
private static String applySignature(TargetType a) { return a.toSignature(); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
public static String encodeType(TargetType type) {
if (type == null) return VOID;
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
}
public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) {
StringBuilder superFunNClassSignature = new StringBuilder("<");
StringBuilder superFunNMethodSignature = new StringBuilder("(");
StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){
superFunNClassSignature.append(String.format("%s%d:%s", argumentGenericBase, currentParameter, objectSignature));
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
superFunNMethodDescriptor.append(objectSignature);
}
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
if (numReturnTypes > 0) {
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
} else {
superFunNMethodSignature.append(")V");
superFunNMethodDescriptor.append(")V");
}
System.out.println(superFunNMethodSignature);
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments, numReturnTypes), superFunNClassSignature.toString(), objectSuperType, null);
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
methodVisitor.visitEnd();
classWriter.visitEnd();
return classWriter.toByteArray();
}
public static String getSuperClassName(int numberArguments, int returnArguments) {
return returnArguments > 0 ? String.format("Fun%d$$", numberArguments) : String.format("FunVoid%d$$", numberArguments);
}
public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) {
var argumentTypes = gep.getArguments();
var returnType = gep.getReturnType();
StringBuilder funNClassSignature = new StringBuilder(objectSignature + gep.descriptor);
boolean containsGeneric = false;
String genericSignature = "<";
for (var i = 0; i < gep.start; i++) {
genericSignature += String.format("T%d:%s", i, objectSignature);
containsGeneric = true;
}
genericSignature += ">";
if (containsGeneric) funNClassSignature.insert(0, genericSignature);
for (var superInterface : superInterfaces) {
funNClassSignature.append('L');
funNClassSignature.append(superInterface);
funNClassSignature.append(';');
}
var interfaces = new ArrayList<>(superInterfaces);
interfaces.add(getSuperClassName(argumentTypes.size(), returnType != null ? 1 : 0));
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, interfaces.toArray(String[]::new));
classWriter.visitEnd();
return classWriter.toByteArray();
}
private static void collectGenericTypeArguments(Map<TargetGenericType, Integer> generics, TargetType typeArgument) {
if (typeArgument instanceof TargetSpecializedType specializedType) {
for (var arg : specializedType.params())
collectGenericTypeArguments(generics, arg);
} else if (typeArgument instanceof TargetGenericType genericType) {
if (generics.containsKey(genericType))
generics.put(genericType, generics.get(genericType) + 1);
else generics.put(genericType, 0);
}
}
public static String getSpecializedClassName(GenericParameters gep) {
return getSpecializedClassName(gep.getArguments(), gep.getReturnType());
}
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
var arguments = argumentTypes
.stream()
.map(FunNGenerator::encodeType)
.collect(Collectors.joining());
if (returnType != null)
return String.format("Fun%d$$%s%s",
argumentTypes.size(),
arguments,
encodeType(returnType));
else return String.format("FunVoidImpl%d$$%s",
argumentTypes.size(),
arguments);
}
public static List<TargetType> getArguments(List<TargetType> list) {
return list
.stream()
.limit(Math.max(0, list.size() - 1))
.collect(Collectors.toList());
}
public static TargetType getReturnType(List<TargetType> list) {
if(list.isEmpty())
throw new IndexOutOfBoundsException();
return list.getLast();
}
}

View File

@@ -1,30 +0,0 @@
package de.dhbw.compiler.bytecode;
import org.objectweb.asm.*;
public class JavaTXSignatureAttribute extends Attribute {
public String signature;
public JavaTXSignatureAttribute() {
super("JavaTXSignature");
}
protected JavaTXSignatureAttribute(String signature) {
this();
this.signature = signature;
}
@Override
protected Attribute read(ClassReader classReader, int offset, int length, char[] charBuffer, int codeAttributeOffset, Label[] labels) {
var data = new byte[length];
System.arraycopy(classReader.b, offset, data, 0, length);
var constantPoolOffset = data[0] << 8 | data[1];
return new JavaTXSignatureAttribute((String) classReader.readConst(constantPoolOffset, charBuffer));
}
@Override
protected ByteVector write(ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
var data = new ByteVector();
data.putShort(classWriter.newConst(this.signature));
return data;
}
}

View File

@@ -1,46 +0,0 @@
package de.dhbw.compiler.core;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.*;
public class ConsoleInterface {
private static final String directory = System.getProperty("user.dir");
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<File> input = new ArrayList<>();
List<File> classpath = new ArrayList<>();
String outputPath = null;
Iterator<String> it = Arrays.asList(args).iterator();
if(args.length == 0){
System.out.println("No input files given. Get help with --help");
System.exit(1);
}else if(args.length == 1 && args[0].equals("--help")){
System.out.println("Usage: javatx [OPTION]... [FILE]...\n" +
"\t-cp\tSet Classpath\n" +
"\t-d\tSet destination directory");
System.exit(1);
}
while(it.hasNext()){
String arg = it.next();
if(arg.equals("-d")){
outputPath = it.next();
}else if(arg.startsWith("-d")) {
outputPath = arg.substring(2);
}else if(arg.equals("-cp") || arg.equals("-classpath")){
String[] cps = it.next().split(":");
for(String cp : cps){
classpath.add(new File(cp));
}
}else{
input.add(new File(arg));
}
}
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
//compiler.typeInference();
compiler.generateBytecode();
}
}

View File

@@ -1,9 +0,0 @@
package de.dhbw.compiler.core;
import org.antlr.v4.runtime.Token;
public interface IItemWithOffset
{
Token getOffset();
}

View File

@@ -1,795 +0,0 @@
//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen
package de.dhbw.compiler.core;
import de.dhbw.compiler.bytecode.Codegen;
import de.dhbw.compiler.environment.CompilationEnvironment;
import de.dhbw.compiler.environment.DirectoryClassLoader;
import de.dhbw.compiler.exceptions.DebugException;
import de.dhbw.compiler.languageServerInterface.LanguageServerTransferObject;
import de.dhbw.compiler.parser.JavaTXParser;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.scope.GenericsRegistry;
import de.dhbw.compiler.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.parser.scope.JavaClassRegistry;
import de.dhbw.compiler.syntaxtree.ClassOrInterface;
import de.dhbw.compiler.syntaxtree.GenericTypeVar;
import de.dhbw.compiler.syntaxtree.Method;
import de.dhbw.compiler.syntaxtree.ParameterList;
import de.dhbw.compiler.syntaxtree.SourceFile;
import de.dhbw.compiler.syntaxtree.GenericDeclarationList;
import de.dhbw.compiler.syntaxtree.factory.ASTFactory;
import de.dhbw.compiler.syntaxtree.factory.UnifyTypeFactory;
import de.dhbw.compiler.syntaxtree.type.ExtendsWildcardType;
import de.dhbw.compiler.syntaxtree.type.GenericRefType;
import de.dhbw.compiler.syntaxtree.type.RefType;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.syntaxtree.type.SuperWildcardType;
import de.dhbw.compiler.syntaxtree.type.TypePlaceholder;
import de.dhbw.compiler.syntaxtree.type.TypeVisitor;
import de.dhbw.compiler.syntaxtree.visual.ASTTypePrinter;
import de.dhbw.compiler.target.generate.ASTToTargetAST;
import de.dhbw.compiler.target.generate.GenericsResult;
import de.dhbw.compiler.typeinference.constraints.Constraint;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import de.dhbw.compiler.typeinference.constraints.Pair;
import de.dhbw.compiler.typeinference.result.ResultSet;
import de.dhbw.compiler.typeinference.typeAlgo.TYPE;
import de.dhbw.compiler.typeinference.unify.RuleSet;
import de.dhbw.compiler.typeinference.unify.TypeUnify;
import de.dhbw.compiler.typeinference.unify.distributeVariance;
import de.dhbw.compiler.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbw.compiler.typeinference.unify.model.PairOperator;
import de.dhbw.compiler.typeinference.unify.model.PlaceholderType;
import de.dhbw.compiler.typeinference.unify.model.UnifyPair;
import de.dhbw.compiler.typeinference.unify.model.UnifyType;
import de.dhbw.compiler.typeinference.unify.TypeUnifyTask;
import de.dhbw.compiler.typeinference.unify.UnifyResultListener;
import de.dhbw.compiler.typeinference.unify.UnifyResultListenerImpl;
import de.dhbw.compiler.typeinference.unify.UnifyResultModel;
import de.dhbw.compiler.typeinference.unify.UnifyTaskModel;
import java.io.*;
import java.lang.reflect.Modifier;
import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
import de.dhbw.parser.Java17Parser;
import org.apache.commons.io.output.NullOutputStream;
public class JavaTXCompiler {
// public static JavaTXCompiler INSTANCE;
final CompilationEnvironment environment;
Boolean resultmodel = true;
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
public final DirectoryClassLoader classLoader;
public final List<File> classPath;
private final File outputPath;
public DirectoryClassLoader getClassLoader() {
return classLoader;
}
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Arrays.asList(sourceFile), List.of(), new File("."));
}
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
this(sourceFile);
this.log = log;
}
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
this(sourceFiles, List.of(), new File("."));
}
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
var path = new ArrayList<>(contextPath);
if (contextPath.isEmpty()) {
// When no contextPaths are given, the working directory is the sources root
path.add(new File(System.getProperty("user.dir")));
}
if (outputPath != null) path.add(outputPath);
classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader());
environment = new CompilationEnvironment(sources, classLoader);
classPath = path;
this.outputPath = outputPath;
for (File s : sources) {
parse(s);
}
// INSTANCE = this;
}
private void addSourceFile(File file, SourceFile sf) {
sourceFiles.put(file, sf);
}
public ClassOrInterface getClass(JavaClassName name) {
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
for (var sf : sourceFiles.values()) {
for (var clazz : sf.KlassenVektor) {
if (clazz.getClassName().equals(name)) return clazz;
}
}
try {
var clazz = classLoader.loadClass(name.toString());
if (clazz != null)
return ASTFactory.createClass(clazz);
} catch (ClassNotFoundException ignored) {}
return null;
}
public ConstraintSet<Pair> getConstraints(File sourceFile) throws ClassNotFoundException, IOException {
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
ClassOrInterface objectClass = ASTFactory.createClass(Object.class);
var recordClass = ASTFactory.createClass(Record.class);
allClasses.add(objectClass);
allClasses.add(recordClass);
var sf = sourceFiles.get(sourceFile);
var importedClasses = new ArrayList<ClassOrInterface>();
for (JavaClassName name : sf.getImports()) {
importedClasses.addAll(getAvailableClasses(name));
}
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), sourceFile, this)) {
ClassOrInterface importedClass = ASTFactory.createClass(c);
importedClasses.add(importedClass);
}
sf.availableClasses.addAll(importedClasses);
SourceFile sf_new = new SourceFile(sf.getPkgName(), sf.KlassenVektor.stream().map(cl -> new ClassOrInterface(cl)).collect(Collectors.toCollection(ArrayList::new)), sf.imports);
// sf enthaelt neues Source-File, neue Klassen-Objekte und neue
// ArrayListen-Objekte fuer Fields, Construktoren und Methoden
// Alle anderen Objekte werden nur kopiert.
var isCached = false;
for (var clazz : sf.availableClasses) {
if (loadedClasses.containsKey(clazz.getClassName())) {
allClasses.removeIf(cl -> cl.getClassName().equals(clazz.getClassName()));
var cif = loadedClasses.get(clazz.getClassName()).cif();
allClasses.add(cif);
isCached = true;
}
}
if (!isCached) {
sf_new.KlassenVektor.forEach(cl -> addMethods(sf_new, cl, sf.availableClasses, objectClass));
allClasses.addAll(sf_new.getClasses());
}
allClasses.addAll(sf.KlassenVektor);
TYPE ty = new TYPE(sf, allClasses);
var constraints = ty.getConstraints();
return constraints;
}
void addMethods(SourceFile sf, ClassOrInterface cl, List<ClassOrInterface> importedClasses, ClassOrInterface objectClass) {
if (!cl.areMethodsAdded()) {
ClassOrInterface superclass = null;
Optional<ClassOrInterface> optSuperclass = importedClasses.stream().filter(x -> x.getClassName().equals(cl.getSuperClass().getName())).findFirst();
if (optSuperclass.isPresent()) {
superclass = optSuperclass.get();
} else {
optSuperclass = sf.KlassenVektor.stream().filter(x -> x.getClassName().equals(cl.getSuperClass().getName())).findFirst();
if (optSuperclass.isPresent()) {
superclass = optSuperclass.get();
addMethods(sf, superclass, importedClasses, objectClass);
} else {
try {
var className = cl.getSuperClass().getName().toString();
superclass = ASTFactory.createClass(classLoader.loadClass(className));
} catch (ClassNotFoundException ignored) {}
// throw new ClassNotFoundException("");
}
}
Iterator<RefTypeOrTPHOrWildcardOrGeneric> paraIt = cl.getSuperClass().getParaList().iterator();
Iterator<GenericTypeVar> tvarVarIt = superclass.getGenerics().iterator();
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
while (paraIt.hasNext()) {
gtvs.put(tvarVarIt.next().getName(), paraIt.next());
}
for (Method m : superclass.getMethods()) {
if (m.isInherited || Modifier.isStatic(m.modifier)) continue;
// TODO: Add gtvs from method itself
ParameterList newParaList = new ParameterList(m.getParameterList().getFormalparalist().stream().map(fp -> fp.withType(fp.getType().acceptTV(new TypeExchanger(gtvs)))).collect(Collectors.toCollection(ArrayList::new)), m.getParameterList().getOffset());
cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block,
// new GenericDeclarationList(newGenericsList,
// ((GenericDeclarationList)m.getGenerics()).getOffset()),
(GenericDeclarationList) m.getGenerics(), m.getOffset(), true, false));
}
}
cl.setMethodsAdded();
}
private Set<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
Set<ClassOrInterface> allClasses = new HashSet<>();
var clazz = loadJavaTXClass(name);
if (clazz == null) {
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
allClasses.add(importedClass);
} else {
allClasses.add(clazz);
}
return allClasses;
}
public Set<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException {
// PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal
// hinzugefuegt werden
// List<ClassOrInterface> allClasses = new
// ArrayList<>();//environment.getAllAvailableClasses();
Set<ClassOrInterface> allClasses = new HashSet<>();
for (JavaClassName name : forSourceFile.getImports()) {
allClasses.addAll(getAvailableClasses(name));
}
return allClasses;
}
/*
* public List<ResultSet> typeInferenceOld() throws ClassNotFoundException { List<ClassOrInterface> allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC for(SourceFile sf : this.sourceFiles.values()) { allClasses.addAll(getAvailableClasses(sf)); allClasses.addAll(sf.getClasses()); }
*
* final ConstraintSet<Pair> cons = getConstraints();
*
* FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses); System.out.println(finiteClosure); ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
*
* TypeUnify unify = new TypeUnify(); Set<Set<UnifyPair>> results = new HashSet<>(); try { File logPath = new File(System.getProperty("user.dir")+"/target/logFiles/"); logPath.mkdirs(); FileWriter logFile = new FileWriter(new File(logPath, "log")); logFile.write("FC:\\" + finiteClosure.toString()+"\n"); for(SourceFile sf : this.sourceFiles.values()) { logFile.write(ASTTypePrinter.print(sf)); } logFile.flush(); Set<List<Constraint<UnifyPair>>> cardProd = unifyCons.cartesianProduct(); for
* (List<Constraint<UnifyPair>> xCons : cardProd ){ Set<UnifyPair> xConsSet = new HashSet<>(); for (Constraint<UnifyPair> constraint : xCons) { xConsSet.addAll(constraint); } //.collect(Collectors.toCollection(ArrayList::new)))) System.out.println(xConsSet); Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() .stream().filter(z -> z.getType() instanceof TypePlaceholder) .map(z ->
* ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection( HashSet::new))) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
*
* Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist() .stream().filter(z -> z.getType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection( HashSet::new))) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
*
* Set<String> paraTypeVarNames = methodParaTypeVarNames; paraTypeVarNames.addAll(constructorParaTypeVarNames);
*
* Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
*
* Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
*
* returnTypeVarNames.addAll(fieldTypeVarNames);
*
* xConsSet = xConsSet.stream().map(x -> { //Hier muss ueberlegt werden, ob //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs // mit disableWildcardtable() werden. //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen //PL 2018-04-23 if ((x.getLhsType() instanceof PlaceholderType)) { if (paraTypeVarNames.contains(x.getLhsType().getName())) { ((PlaceholderType)x.getLhsType()).setVariance((byte)1);
* ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } if (returnTypeVarNames.contains(x.getLhsType().getName())) { ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } } if ((x.getRhsType() instanceof PlaceholderType)) { if (paraTypeVarNames.contains(x.getRhsType().getName())) { ((PlaceholderType)x.getRhsType()).setVariance((byte)1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } if
* (returnTypeVarNames.contains(x.getRhsType().getName())) { ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } } return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE }).map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ) .collect(Collectors.toCollection(HashSet::new)); varianceInheritance(xConsSet); Set<Set<UnifyPair>> result =
* unify.unifySequential(xConsSet, finiteClosure, logFile, log); //Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure); System.out.println("RESULT: " + result); logFile.write("RES: " + result.toString()+"\n"); logFile.flush(); results.addAll(result); }
*
* results = results.stream().map(x -> { Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> { if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); return y; //alle Paare a <.? b erden durch a =. b ersetzt }).collect(Collectors.toCollection(HashSet::new))); if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); } else return x; //wenn nichts
* veraendert wurde wird x zurueckgegeben }).collect(Collectors.toCollection(HashSet::new)); System.out.println("RESULT Final: " + results); logFile.write("RES_FINAL: " + results.toString()+"\n"); logFile.flush(); logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); logFile.flush(); } catch (IOException e) { e.printStackTrace(); } return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs,
* generateTPHMap(cons))))).collect(Collectors.toList()); }
*/
/**
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
*
*
*/
/*
* private void varianceInheritance(Set<UnifyPair> eq) { Set<PlaceholderType> usedTPH = new HashSet<>(); Set<PlaceholderType> phSet = eq.stream().map(x -> { Set<PlaceholderType> pair = new HashSet<>(); if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); return pair; }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;});
*
* ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet); phSetVariance.removeIf(x -> (x.getVariance() == 0)); while(!phSetVariance.isEmpty()) { PlaceholderType a = phSetVariance.remove(0); usedTPH.add(a); //HashMap<PlaceholderType,Integer> ht = new HashMap<>(); //ht.put(a, a.getVariance()); Set<UnifyPair> eq1 = new HashSet<>(eq); eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); eq1.stream().forEach(x -> {
* x.getRhsType().accept(new distributeVariance(), a.getVariance());}); eq1 = new HashSet<>(eq); eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); phSetVariance = new ArrayList<>(phSet); phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); } }
*/
public UnifyResultModel typeInferenceAsync(UnifyResultListener resultListener, Writer logFile) throws ClassNotFoundException, IOException {
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
for (Entry<File, SourceFile> source : this.sourceFiles.entrySet()) {
SourceFile sf = source.getValue();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
}
final ConstraintSet<Pair> cons = new ConstraintSet<>();
for (var f : this.sourceFiles.keySet()) {
cons.addAll(getConstraints(f));
}
Set<Set<UnifyPair>> results = new HashSet<>();
UnifyResultModel urm = null;
// urm.addUnifyResultListener(resultListener);
try {
logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile;
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader(), this);
System.out.println(finiteClosure);
urm = new UnifyResultModel(cons, finiteClosure);
urm.addUnifyResultListener(resultListener);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
((PlaceholderType) lhs).setInnerType(true);
((PlaceholderType) rhs).setInnerType(true);
}
return x;
};
logFile.write(unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars);
logFile.write(unifyCons.toString());
TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
for (SourceFile f : this.sourceFiles.values()) {
logFile.write(ASTTypePrinter.print(f));
}
logFile.flush();
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
/*
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
*/
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
// logFile, log);
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()/*
* .stream().map(x -> { Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors. toCollection(ArrayList::new))
*/;
unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
} catch (IOException e) {
System.err.println("kein LogFile");
}
return urm;
}
/**
* TEMPORARY - Only for Language Server Usage
*/
public LanguageServerTransferObject getResultSetAndAbstractSyntax(File file) throws IOException, ClassNotFoundException {
var sf = sourceFiles.get(file);
Set<ClassOrInterface> allClasses = new HashSet<>();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
final ConstraintSet<Pair> cons = getConstraints(file);
Set<Set<UnifyPair>> results = new HashSet<>();
try {
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
if (log) logFolder.mkdirs();
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
((PlaceholderType) lhs).setInnerType(true);
((PlaceholderType) rhs).setInnerType(true);
}
return x;
};
logFile.write("Unify:" + unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars);
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString());
TypeUnify unify = new TypeUnify();
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
logFile.write(ASTTypePrinter.print(sf));
logFile.flush();
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints();
if (resultmodel) {
/* UnifyResultModel Anfang */
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li);
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush();
return new LanguageServerTransferObject(li.getResults(), sf, ASTTypePrinter.print(sf));
}
/* UnifyResultModel End */
else {
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
logFile.write("RES: " + result.toString() + "\n");
logFile.flush();
results.addAll(result);
results = results.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
y.setPairOp(PairOperator.EQUALSDOT);
return y; // alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure);
} else
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new));
logFile.write("RES_FINAL: " + results.toString() + "\n");
logFile.flush();
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS);
logFile.flush();
}
} catch (IOException | ClassNotFoundException e) {
}
return new LanguageServerTransferObject(results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList()), sf, ASTTypePrinter.print(sf));
}
public List<ResultSet> typeInference(File file) throws ClassNotFoundException, IOException {
var sf = sourceFiles.get(file);
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
final ConstraintSet<Pair> cons = getConstraints(file);
Set<Set<UnifyPair>> results = new HashSet<>();
try {
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
if (log) logFolder.mkdirs();
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this);
System.out.println(finiteClosure);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
System.out.println("xxx1");
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
((PlaceholderType) lhs).setInnerType(true);
((PlaceholderType) rhs).setInnerType(true);
}
return x;
};
logFile.write("Unify:" + unifyCons.toString());
System.out.println("Unify:" + unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars);
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString());
TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
logFile.write(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf));
logFile.flush();
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
/*
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
*/
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
// logFile, log);
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()// .stream().map(x -> {
/*
* Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors.toCollection(ArrayList::new))
*/;
if (resultmodel) {
/* UnifyResultModel Anfang */
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li);
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
System.out.println("RESULT Final: " + li.getResults());
System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush();
return li.getResults();
}
/* UnifyResultModel End */
else {
// Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(),
// oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons,
// finiteClosure));
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
System.out.println("RESULT: " + result);
logFile.write("RES: " + result.toString() + "\n");
logFile.flush();
results.addAll(result);
results = results.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
y.setPairOp(PairOperator.EQUALSDOT);
return y; // alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure);
} else
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new));
System.out.println("RESULT Final: " + results);
System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + results.toString() + "\n");
logFile.flush();
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS);
logFile.flush();
}
} catch (IOException e) {
System.err.println("kein LogFile");
}
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList());
}
/**
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
*
*
*/
private Set<PlaceholderType> varianceInheritanceConstraintSet(ConstraintSet<UnifyPair> cons) {
Set<UnifyPair> eq = cons.getAll();
Set<PlaceholderType> usedTPH = new HashSet<>();
Set<PlaceholderType> phSet = eq.stream().map(x -> {
Set<PlaceholderType> pair = new HashSet<>();
if (x.getLhsType() instanceof PlaceholderType)
pair.add((PlaceholderType) x.getLhsType());
if (x.getRhsType() instanceof PlaceholderType)
pair.add((PlaceholderType) x.getRhsType());
return pair;
}).reduce(new HashSet<>(), (a, b) -> {
a.addAll(b);
return a;
}, (c, d) -> {
c.addAll(d);
return c;
});
ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet);
phSetVariance.removeIf(x -> (x.getVariance() == 0));
while (!phSetVariance.isEmpty()) {
PlaceholderType a = phSetVariance.remove(0);
usedTPH.add(a);
// HashMap<PlaceholderType,Integer> ht = new HashMap<>();
// ht.put(a, a.getVariance());
// ConstraintSet<UnifyPair> eq1 = cons;
// eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType &&
// ((PlaceholderType)x.getLhsType()).equals(a)));
// durch if-Abfrage im foreach geloest
cons.forEach(x -> {
if (x.getLhsType() instanceof PlaceholderType && ((PlaceholderType) x.getLhsType()).equals(a)) {
x.getRhsType().accept(new distributeVariance(), a.getVariance());
}
});
// ` eq1 = new HashSet<>(eq);
// eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType &&
// ((PlaceholderType)x.getRhsType()).equals(a)));
// durch if-Abfrage im foreach geloest
cons.forEach(x -> {
if (x.getRhsType() instanceof PlaceholderType && ((PlaceholderType) x.getRhsType()).equals(a)) {
x.getLhsType().accept(new distributeVariance(), a.getVariance());
}
});
phSetVariance = new ArrayList<>(phSet); // macht vermutlich keinen Sinn PL 2018-10-18, doch, es koennen neue
// TPHs mit Variancen dazugekommen sein PL 2018-11-07
phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x)));
}
return usedTPH;
}
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
public record ClassEntry(File classFile, ClassOrInterface cif) {}
public final Map<JavaClassName, ClassEntry> loadedClasses = new HashMap<>();
private SourceFile parse(File sourceFile) throws IOException, ClassNotFoundException {
if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile);
Java17Parser.SourceFileContext tree = JavaTXParser.parse(sourceFile);
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile("", classes, generator.imports);
addSourceFile(sourceFile, sf);
generator.convert(classes, tree, environment.packageCrawler);
sf.setPackageName(generator.pkgName);
sf.imports.addAll(generator.imports);
return sf;
}
/**
* When an import tries to import a JavaTX class it first looks it up in the cache and
* if it doesn't exist it's going to compile it and add it to the source files list
* @param name
*/
public ClassOrInterface loadJavaTXClass(JavaClassName name) {
var file = findFileForClass(name);
if (file != null) {
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
try {
var tree = JavaTXParser.parse(file);
classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away?
environment.addClassesToRegistry(classRegistry, tree, file, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), file.getName());
var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile("", classes, generator.imports);
addSourceFile(file, sf);
generator.convert(classes, tree, environment.packageCrawler);
sf.setPackageName(generator.pkgName);
var classFiles = generateBytecode(file);
sf.setGenerated();
writeClassFile(classFiles, outputPath != null ? outputPath : new File("."), false);
var clazz = classLoader.loadClass(name.toString());
var classOrInterface = ASTFactory.createClass(clazz);
loadedClasses.put(name, new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface));
return classOrInterface;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return null;
}
public File findFileForClass(JavaClassName name) {
var packageName = name.getPackageName();
var className = name.getClassName().split("\\.")[0];
for (var cp : classPath) {
var file = new File(cp, packageName.replaceAll("\\.", "/") + "/" + className + ".jav");
if (file.exists()) return file;
}
return null;
}
public void generateBytecode() throws ClassNotFoundException, IOException {
for (var file : sourceFiles.keySet()) {
var sf = sourceFiles.get(file);
if (sf.isGenerated()) continue;
var classes = generateBytecode(file);
sf.setGenerated();
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
}
}
/**
* @param path - output-Directory can be null, then class file output is in the same directory as the parsed source files
* @return
*/
public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
var sf = sourceFiles.get(sourceFile);
if (sf.isGenerated()) return null;
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
var classes = generateBytecode(sf, typeinferenceResult);
sf.setGenerated();
return classes;
}
private Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {
return generatedGenerics;
}
/**
* @param outputPath - can be null, then class file output is in the same directory as the parsed source files
* @param typeinferenceResult
* @throws IOException
*/
public void generateBytecode(File outputPath, List<ResultSet> typeinferenceResult) throws IOException {
for (File f : sourceFiles.keySet()) {
HashMap<JavaClassName, byte[]> classFiles = new HashMap<>();
SourceFile sf = sourceFiles.get(f);
File path = outputPath;
if (outputPath == null) {
path = f.getParentFile(); // Set path to path of the parsed .jav file
}
var generatedClasses = generateBytecode(sf, typeinferenceResult);
writeClassFile(generatedClasses, path, outputPath == null);
}
}
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
var generatedClasses = new HashMap<JavaClassName, byte[]>();
for (var clazz : sf.getClasses()) {
var codegen = new Codegen(converter.convert(clazz), this, converter);
var code = codegen.generate();
generatedClasses.put(clazz.getClassName(), code);
converter.auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
return generatedClasses;
}
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path, boolean preserveHierarchy) throws IOException {
FileOutputStream output;
for (JavaClassName name : classFiles.keySet()) {
byte[] bytecode = classFiles.get(name);
System.out.println("generating " + name + ".class file ...");
var subPath = preserveHierarchy ? path : Path.of(path.toString(), name.getPackageName().split("\\.")).toFile();
File outputFile = new File(subPath, name.getClassName() + ".class");
outputFile.getAbsoluteFile().getParentFile().mkdirs();
System.out.println(outputFile);
output = new FileOutputStream(outputFile);
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
}
}
/* PL 2020-03-17 mit TypeExchanger in FCGenerator.java zusammenfuehren */
/**
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus.
*/
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric> {
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
TypeExchanger(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
this.gtvs = gtvs;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for (RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()) {
params.add(param.acceptTV(this));
}
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
SuperWildcardType ret = new SuperWildcardType(superWildcardType.getInnerType().acceptTV(this), superWildcardType.getOffset());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
return typePlaceholder; // TypePlaceholder der vererbert wird kann bei der Vererbung nicht instanziert
// werden.
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
ExtendsWildcardType ret = new ExtendsWildcardType(extendsWildcardType.getInnerType().acceptTV(this), extendsWildcardType.getOffset());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
if (!gtvs.containsKey(genericRefType.getParsedName()))
throw new DebugException("Dieser Fall darf nicht auftreten");
return gtvs.get(genericRefType.getParsedName());
}
}
}

View File

@@ -1,13 +0,0 @@
package de.dhbw.compiler.environment;
public class ByteArrayClassLoader extends ClassLoader implements IByteArrayClassLoader {
@Override
public Class _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError {
return defineClass(name, code, i, length);
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name);
}
}

View File

@@ -1,107 +0,0 @@
package de.dhbw.compiler.environment;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import com.google.common.collect.Lists;
import de.dhbw.compiler.core.JavaTXCompiler;
import de.dhbw.compiler.syntaxtree.ClassOrInterface;
import de.dhbw.compiler.syntaxtree.factory.ASTFactory;
import de.dhbw.compiler.exceptions.DebugException;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.compiler.parser.JavaTXParser;
import de.dhbw.compiler.parser.scope.GatherNames;
import de.dhbw.compiler.parser.scope.JavaClassRegistry;
import de.dhbw.parser.Java17Parser;
/**
* Stellt die Java-Environment dar und speichert alle Binarys, Librarys und Sourcefiles im zu kompilierenden Projekt Sie erstellt anhand dieser Informationen die JavaClassNameRegistry
*
* TODO: Zur Initialisierung der CompilationEnvironment sollten alle SourceFiles mit ANTLR geparst werden und alle Klassen Generics und Typen herausgefunden werden
*/
public class CompilationEnvironment {
private final List<URL> librarys;
private final List<File> sourceFiles;
public final PackageCrawler packageCrawler;
/**
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<74>lt automatisch die Java Standard Library
*
* @param sourceFiles die zu kompilierenden Dateien
*/
public CompilationEnvironment(List<File> sourceFiles, DirectoryClassLoader classLoader) {
/**
* Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9
*
*/
// String bootClassPath = System.getProperty("sun.boot.class.path");
// DirectoryClassLoader cl = DirectoryClassLoader.getPlatformClassLoader();
String bootClassPath = System.getProperty("java.class.path");
librarys = new ArrayList<>();
for (String path : bootClassPath.split(File.pathSeparator)) {
try {
librarys.add(new URL("file:" + path));
} catch (MalformedURLException e) {
new DebugException("Fehler im Classpath auf diesem System");
}
}
// URLClassLoader loader = new URLClassLoader(new URL[0], cl);
// librarys = Arrays.asList(loader.getURLs());
this.sourceFiles = sourceFiles;
this.packageCrawler = new PackageCrawler(classLoader);
}
public void addClassesToRegistry(JavaClassRegistry registry, Java17Parser.SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException {
Map<String, Integer> allNames;
if (tree instanceof Java17Parser.SrcfileContext srcfile) {
allNames = GatherNames.getNames((Java17Parser.SrcfileContext) tree, packageCrawler, compiler);
for (Class c : loadDefaultPackageClasses(getPackageName(srcfile), sourceFile, compiler)) {
allNames.put(c.getName(), c.getTypeParameters().length);
}
registry.addNames(allNames);
} else {
throw new NotImplementedException();
}
}
public static List<Class> loadDefaultPackageClasses(String packageName, File sourceFile, JavaTXCompiler compiler) throws IOException, ClassNotFoundException {
ClassLoader classLoader = compiler.getClassLoader();
List<Class> ret = new ArrayList<>();
// Set classLoader to include default package for this specific source file
File dir = sourceFile.getAbsoluteFile().getParentFile();
String dirPath = dir.toString() + "/";
if (!packageName.isEmpty())
dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1);
String path = dirPath;
ArrayList<File> defaultPath = Lists.newArrayList(new File(path));
classLoader = new DirectoryClassLoader(defaultPath, classLoader);
// Gather all names in the default package for this source file (classes that are imported by default)
File[] files = dir.listFiles((dir1, name) -> name.endsWith(".class"));
if (files != null)
for (File classFile : files) {
String className = classFile.getName().substring(0, classFile.getName().length() - 6);
if (className.matches("Fun\\d+\\$\\$.*"))
continue;
var name = packageName;
if (!packageName.isEmpty()) name += ".";
name += className;
ret.add(classLoader.loadClass(name));
}
return ret;
}
private static String getPackageName(Java17Parser.SrcfileContext forTree) {
String packageName = "";
if (forTree.packageDeclaration() != null && !forTree.packageDeclaration().qualifiedName().identifier().isEmpty())
packageName = forTree.packageDeclaration().qualifiedName().getText();
return packageName;
}
}

View File

@@ -1,78 +0,0 @@
package de.dhbw.compiler.environment;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader {
// public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
// super(generateURLArray(dirToURL(directory)), parent);
// }
public DirectoryClassLoader(List<File> directory, ClassLoader parent) {
super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent.getParent());
}
private static URL[] generateURLArray(URL url) {
return new URL[]{url};
}
private static List<URL> dirToURL(File file) {
//if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory");
Path dir;
if (file.isDirectory()) {
try {
return List.of(file.toURI().toURL()); // if file is a directory, use it as is
} catch (MalformedURLException e) {
e.printStackTrace();
return List.of();
}
}
dir = file.toPath().getParent(); // if file is not a directory, get its parent directory
String pattern = file.toPath().getFileName().toString(); // use the file name as a glob pattern
List<URL> urls = new ArrayList<>();
try {
urls = Files.walk(dir)
.filter(Files::isRegularFile) // only consider files (not directories)
.filter(path -> {
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
return matcher.matches(path.getFileName()); // match the file name against the pattern
})
.map(path -> {
try {
return path.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}) // convert the path to a URL
.toList(); // print the path of each matching file
} catch (IOException | RuntimeException e) {
e.printStackTrace();
}
return urls;
}
@Override
public Class<?> _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError {
return defineClass(name, code, i, length);
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name);
}
public Class<?> _findLoadedClass(String name) throws ClassNotFoundException {
return super.findLoadedClass(name);
}
}

View File

@@ -1,23 +0,0 @@
package de.dhbw.compiler.environment;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public interface IByteArrayClassLoader {
Class loadClass(String path) throws ClassNotFoundException;
default Class loadClass(byte[] code) {
return this._defineClass(null, code, 0, code.length);
}
default Class loadClass(Path path) throws IOException {
var code = Files.readAllBytes(path);
return this._defineClass(null, code, 0, code.length);
}
public Class<?> findClass(String name) throws ClassNotFoundException;
Class _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError;
}

View File

@@ -1,52 +0,0 @@
package de.dhbw.compiler.environment;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
import java.util.*;
/**
* Hilft beim Durchsuchen von Packages
* Benutzt die Reflections-Library (https://github.com/ronmamo/reflections)
* Hilfe dazu: http://stackoverflow.com/a/9571146
*/
public class PackageCrawler {
final DirectoryClassLoader classLoader;
public PackageCrawler(DirectoryClassLoader classLoader) {
this.classLoader = classLoader;
}
public Set<Class<?>> getClassesInPackage(String packageName) {
var res = new HashSet<Class<?>>();
try (ScanResult result = new ClassGraph()
.enableClassInfo()
.enableSystemJarsAndModules()
.addClassLoader(classLoader)
.acceptPackages(packageName)
.scan()) {
for (var info : result.getAllClasses()) {
try {
var clazz = Class.forName(info.getName());
res.add(clazz);
} catch (ClassNotFoundException ignored) {}
}
};
return res;
}
public Map<String, Integer> getClassNames(String packageName){
Map<String, Integer> nameList = new HashMap<>();
Set<Class<?>> classes = getClassesInPackage(packageName);
if(packageName.equals("java.lang") && ! classes.contains(Object.class)) {
classes.add(Object.class);
}
for(Class c : classes){
nameList.put(c.getName(), c.getTypeParameters().length);
}
return nameList;
}
}

View File

@@ -1,8 +0,0 @@
package de.dhbw.compiler.exceptions;
public class DebugException extends RuntimeException {
public DebugException(String message) {
System.err.print(message);
}
}

View File

@@ -1,11 +0,0 @@
package de.dhbw.compiler.exceptions;
public class NotImplementedException extends RuntimeException {
public NotImplementedException() {
}
public NotImplementedException(String string) {
super(string);
}
}

View File

@@ -1,10 +0,0 @@
package de.dhbw.compiler.exceptions;
import org.antlr.v4.runtime.Token;
public class ParserError extends TypeinferenceException{
public ParserError(Token offset){
super("Fehler beim Parsen", offset);
}
}

View File

@@ -1,46 +0,0 @@
package de.dhbw.compiler.exceptions;
import de.dhbw.compiler.syntaxtree.SyntaxTreeNode;
import org.antlr.v4.runtime.Token;
/**
* Eine RuntimeException, welche bei einem Fehler während des Typinferenzalgorithmus ausgelöst wird.
* Dies wird zum Beispiel durch Programmierfehler in der Java-Eingabedatei ausgelöst.
* @author Andreas Stadelmeier, a10023
*
*/
//TODO: Diese Klasse muss von Exception erben
public class TypeinferenceException extends RuntimeException {
/**
* Das Offset im Quelltext bei dem das Problem aufgetaucht ist
*/
private Token offset;
private String message;
public TypeinferenceException(String message, SyntaxTreeNode problemSource)
{
super(message);
this.message=message;
if(problemSource == null)throw new DebugException("TypinferenzException ohne Offset: "+this.message);
this.offset=problemSource.getOffset();
}
public TypeinferenceException(String message, Token offset){
this.message=message;
this.offset = offset;
}
/**
*
* @return Der Offset an dem im Quellcode der Fehler aufgetreten ist.
*/
public Token getOffset(){
return offset;
}
public String getMessage(){
return this.message;
}
}

View File

@@ -1,34 +0,0 @@
package de.dhbw.compiler.languageServerInterface;
import de.dhbw.compiler.syntaxtree.SourceFile;
import de.dhbw.compiler.syntaxtree.visual.ASTTypePrinter;
import de.dhbw.compiler.typeinference.result.ResultSet;
import de.dhbw.compiler.core.JavaTXCompiler;
import java.io.*;
import java.util.List;
/**
* Implementation of an Interface for the Language-Server to get the Resultset and abstract Syntax.
* */
public class LanguageServerInterface {
/**
* get final Result Set
* */
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String input) throws IOException, ClassNotFoundException {
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
File tempSourcefile = File.createTempFile("temp", ".java");
tempSourcefile.deleteOnExit();
BufferedWriter out = new BufferedWriter(new FileWriter(tempSourcefile));
out.write(input);
out.close();
JavaTXCompiler tx = new JavaTXCompiler(tempSourcefile);
var test = tx.getResultSetAndAbstractSyntax(tempSourcefile);
System.setOut(System.out);
return test;
}
}

View File

@@ -1,21 +0,0 @@
package de.dhbw.compiler.languageServerInterface;
import de.dhbw.compiler.syntaxtree.SourceFile;
import de.dhbw.compiler.typeinference.result.ResultSet;
import java.util.List;
public class LanguageServerTransferObject {
List<ResultSet> resultSets;
SourceFile Ast;
String printedAst;
public LanguageServerTransferObject(List<ResultSet> resultSets, SourceFile Ast, String printedAst) {
this.resultSets = resultSets;
this.Ast = Ast;
this.printedAst = printedAst;
}
public List<ResultSet> getResultSets() {return resultSets;}
public SourceFile getAst() {return Ast;}
public String getPrintedAst() {return printedAst;}
}

View File

@@ -1,37 +0,0 @@
package de.dhbw.compiler.parser;
import de.dhbw.compiler.environment.CompilationEnvironment;
import de.dhbw.compiler.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
import de.dhbw.compiler.parser.scope.JavaClassRegistry;
import de.dhbw.compiler.syntaxtree.SourceFile;
import de.dhbw.parser.Java17Lexer;
import de.dhbw.parser.Java17Parser;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class JavaTXParser {
public static Java17Parser.SourceFileContext parse(File source) throws IOException, ClassNotFoundException {
InputStream stream = new FileInputStream(source);
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);
CharStream input = CharStreams.fromStream(stream);
Java17Lexer lexer = new Java17Lexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
Java17Parser parser = new Java17Parser(tokens);
return parser.sourceFile();
/*
* SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(source)); return generator.convert(tree);
*/
}
/*
* Für das Typsystem ist es notwendig, dass sich der Source in einer Datei befindet: public SourceFile parse(String fileContent) throws IOException, java.lang.ClassNotFoundException { return this.parse(new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8))); }
*/
}

View File

@@ -1,57 +0,0 @@
package de.dhbw.compiler.parser;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenSource;
public class NullToken implements Token {
@Override
public String getText() {
return "";
}
@Override
public int getType() {
return 0;
}
@Override
public int getLine() {
return 0;
}
@Override
public int getCharPositionInLine() {
return 0;
}
@Override
public int getChannel() {
return 0;
}
@Override
public int getTokenIndex() {
return 0;
}
@Override
public int getStartIndex() {
return 0;
}
@Override
public int getStopIndex() {
return 0;
}
@Override
public TokenSource getTokenSource() {
return null;
}
@Override
public CharStream getInputStream() {
return null;
}
}

View File

@@ -1,4 +0,0 @@
package de.dhbw.compiler.parser;
public record SourceLoc(String file, int line) {
}

View File

@@ -1,20 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.statement.AssignLeftSide;
import de.dhbw.compiler.syntaxtree.statement.Expression;
import de.dhbw.compiler.syntaxtree.statement.LocalVar;
public class AssignToLocal extends AssignLeftSide {
public final LocalVar localVar;
public AssignToLocal(LocalVar leftSide) {
super(leftSide.getType(), leftSide.getOffset());
localVar = leftSide;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,252 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import de.dhbw.compiler.core.JavaTXCompiler;
import de.dhbw.compiler.exceptions.DebugException;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.syntaxtree.ClassOrInterface;
import de.dhbw.compiler.syntaxtree.GenericTypeVar;
import de.dhbw.compiler.syntaxtree.Method;
import de.dhbw.compiler.syntaxtree.Pattern;
import de.dhbw.compiler.syntaxtree.factory.ASTFactory;
import de.dhbw.compiler.syntaxtree.factory.UnifyTypeFactory;
import de.dhbw.compiler.syntaxtree.type.*;
import de.dhbw.compiler.typeinference.constraints.Pair;
import de.dhbw.compiler.typeinference.unify.model.*;
import java.util.*;
import java.util.stream.Collectors;
import org.antlr.v4.runtime.Token;
public class FCGenerator {
/**
* Baut die FiniteClosure aus availableClasses.
* Klassen welche nicht in availableClasses vorkommen werden im Java Classpath nachgeschlagen.
*
* @param availableClasses - Alle geparsten Klassen
*/
public static Set<UnifyPair> toUnifyFC(JavaTXCompiler compiler, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(compiler, t)).collect(Collectors.toSet());
}
public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
HashSet<Pair> pairs = new HashSet<>();
//PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden.
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
for(ClassOrInterface cly : availableClasses){
List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader);
pairs.addAll(newPairs);
//For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC
if (isFunctionalInterface(cly)) {
pairs.add(genImplFunType(cly, newPairs.get(0).TA1, gtvs));
}
}
return pairs;
}
private static Boolean isFunctionalInterface(ClassOrInterface cly) {
return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1));
}
private static Pair genImplFunType(ClassOrInterface cly, RefTypeOrTPHOrWildcardOrGeneric fIType, HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
for(Method m : cly.getMethods()) {
if (!java.lang.reflect.Modifier.isAbstract(m.modifier))
continue;
List<RefTypeOrTPHOrWildcardOrGeneric> tl =
(m.getParameterList().getFormalparalist()
.stream().map(p -> p.getType().acceptTV(new TypeExchanger(gtvs)))
.collect(Collectors.toList()));
tl.add(m.getReturnType().acceptTV(new TypeExchanger(gtvs)));
return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()),
fIType, PairOperator.SMALLER);
}
return null; //kann nicht passieren, da die Methode nur aufgerufen wird wenn cl Functional Interface ist
}
/**
* Bildet eine Kette vom übergebenen Typ bis hin zum höchsten bekannten Typ
* Als Generics werden TPHs benutzt, welche der Unifikationsalgorithmus korrekt interpretieren muss.
* Die verwendeten TPHs werden in der Kette nach oben gereicht, so erhält der selbe GTV immer den selben TPH
* @param forType
* @return
*/
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
return getSuperTypes(forType, availableClasses, new HashMap<>(), classLoader);
}
/**
*
* @param forType
* @param availableClasses
* @param gtvs
* @return
* @throws ClassNotFoundException
*/
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs, ClassLoader classLoader) throws ClassNotFoundException {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
//Die GTVs, die in forType hinzukommen:
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> newGTVs = new HashMap<>();
//Generics mit gleichem Namen müssen den selben TPH bekommen
for(GenericTypeVar gtv : forType.getGenerics()){
if(!gtvs.containsKey(gtv.getName())){
TypePlaceholder replacePlaceholder = TypePlaceholder.fresh(new NullToken());
gtvs.put(gtv.getName(), replacePlaceholder);
newGTVs.put(gtv.getName(), replacePlaceholder);
}
params.add(gtvs.get(gtv.getName()));
}
List<RefType> superClasses = new ArrayList<>();
superClasses.add(forType.getSuperClass());
superClasses.addAll(forType.getSuperInterfaces());
List<Pair> retList = new ArrayList<>();
for(RefType superType : superClasses){
Optional<ClassOrInterface> hasSuperclass = availableClasses.stream().filter(cl -> superType.getName().equals(cl.getClassName())).findAny();
ClassOrInterface superClass;
if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception
{
superClass = ASTFactory.createClass(classLoader.loadClass(superType.getName().toString()));
}else{
superClass = hasSuperclass.get();
}
/*
Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse
modifiziert werden
Beispie: Matrix<A> extends Vector<Vector<A>>
Den ersten Parameter mit Vector<A> austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen
*/
//Hier vermerken, welche Typen in der Superklasse ausgetauscht werden müssen
Iterator<GenericTypeVar> itGenParams = superClass.getGenerics().iterator();
Iterator<RefTypeOrTPHOrWildcardOrGeneric> itSetParams = superType.getParaList().iterator();
while(itSetParams.hasNext()){
RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next();
//In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen:
RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs));
newGTVs.put(itGenParams.next().getName(), setSetType);
}
//Für den superType kann man nun zum Austauschen der Generics wieder die gtvs nehmen:
//Die newGTVs sind nur für den superClass ClassOrInterface welches möglicherweise per reflection geladen wurde abgestimmt
RefTypeOrTPHOrWildcardOrGeneric superRefType = superType.acceptTV(new TypeExchanger(gtvs));
RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken());
RefTypeOrTPHOrWildcardOrGeneric t2 = superRefType;
Pair ret = new Pair(t1, t2, PairOperator.SMALLER);
List<Pair> superTypes;
//Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse:
if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){
superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER));
}else{
superTypes = getSuperTypes(superClass, availableClasses, newGTVs, classLoader);
}
retList.add(ret);
retList.addAll(superTypes);
}
return retList;
}
/**
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf der direkten Argumentebene.
* Hier sind keine Wildcards zulässig
*/
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
TypeExchanger(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs){
this.gtvs = gtvs;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
params.add(param.acceptTV(new TypeExchangerInner(gtvs)));
}
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
if(! gtvs.containsKey(genericRefType.getParsedName()))
throw new DebugException("Dieser Fall darf nicht auftreten");
return gtvs.get(genericRefType.getParsedName());
}
}
/**
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf den Argumenten der Argumente.
* Hier sind Wildcards zulässig
*/
private static class TypeExchangerInner implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
TypeExchangerInner(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs){
this.gtvs = gtvs;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
params.add(param.acceptTV(this));
}
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
return superWildcardType;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
return extendsWildcardType;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
if(! gtvs.containsKey(genericRefType.getParsedName()))
throw new DebugException("Dieser Fall darf nicht auftreten");
return gtvs.get(genericRefType.getParsedName());
}
}
}

View File

@@ -1,6 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public record FieldEntry(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifiers) {
}

View File

@@ -1,14 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import de.dhbw.compiler.parser.scope.JavaClassName;
public class GenericContext {
private final String parentMethod;
private final JavaClassName parentClass;
public GenericContext(JavaClassName parentClass, String parentMethod) {
if(parentMethod == null)parentMethod = "";
this.parentClass = parentClass;
this.parentMethod = parentMethod;
}
}

View File

@@ -1,51 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.syntaxtree.AbstractASTWalker;
import de.dhbw.compiler.syntaxtree.Constructor;
import de.dhbw.compiler.syntaxtree.statement.*;
import java.util.List;
public class SyntacticSugar {
public static List<Statement> addTrailingReturn(List<Statement> statements) {
if (statements.size() != 0) {
Statement lastStmt = statements.get(statements.size() - 1);
ReturnFinder hasReturn = new ReturnFinder();
lastStmt.accept(hasReturn);
if (hasReturn.hasReturn)
return statements;
}
statements.add(new ReturnVoid(new NullToken()));
return statements;
}
private static class ReturnFinder extends AbstractASTWalker {
public boolean hasReturn = false;
@Override
public void visit(Return aReturn) {
hasReturn = true;
}
@Override
public void visit(ReturnVoid aReturn) {
hasReturn = true;
}
@Override
public void visit(LambdaExpression le) {
//PL 2024-04-09 Do nothing, as in a LambdaExpression a return could be
}
}
private static boolean hasReturn(Block block) {
for (Statement s : block.getStatements())
if (s instanceof Return)
return true;
return false;
}
}

View File

@@ -1,604 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import de.dhbw.compiler.core.JavaTXCompiler;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.syntaxtree.*;
import de.dhbw.compiler.syntaxtree.Record;
import de.dhbw.compiler.syntaxtree.statement.*;
import de.dhbw.parser.Java17Parser;
import de.dhbw.parser.Java17Parser.*;
import org.antlr.v4.runtime.CommonToken;
import org.antlr.v4.runtime.Token;
import com.google.common.graph.ElementOrder.Type;
import de.dhbw.compiler.environment.PackageCrawler;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.compiler.exceptions.TypeinferenceException;
import de.dhbw.compiler.parser.scope.GatherNames;
import de.dhbw.compiler.parser.scope.GenericsRegistry;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.parser.scope.JavaClassRegistry;
import de.dhbw.compiler.syntaxtree.factory.ASTFactory;
import de.dhbw.compiler.syntaxtree.type.RefType;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.syntaxtree.type.TypePlaceholder;
import de.dhbw.compiler.syntaxtree.type.Void;
public class SyntaxTreeGenerator {
private JavaClassRegistry reg;
private final GenericsRegistry globalGenerics;
public String pkgName = "";
public Set<JavaClassName> imports = new HashSet<>();
HashMap<String, Integer> allmodifiers = new HashMap<>();
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
// bekommen
private final Map<String, FieldEntry> fields = new HashMap<>();
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
List<Statement> fieldInitializations = new ArrayList<>();
List<Statement> staticFieldInitializations = new ArrayList<>();
private final JavaTXCompiler compiler;
private RefType superClass;
public final String fileName;
public SyntaxTreeGenerator(JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry globalGenerics, String fileName) {
// Die Generics müssen während des Bauens des AST erstellt werden,
// da diese mit der Methode oder Klasse, in welcher sie deklariert werden
// verknüpft sein müssen. Dennoch werden die Namen aller Generics in einer
// globalen Datenbank benötigt.
this.globalGenerics = globalGenerics;
this.reg = reg;
this.allmodifiers.put(Modifier.toString(Modifier.PUBLIC), Modifier.PUBLIC);
this.allmodifiers.put(Modifier.toString(Modifier.PRIVATE), Modifier.PRIVATE);
this.allmodifiers.put(Modifier.toString(Modifier.PROTECTED), Modifier.PROTECTED);
this.allmodifiers.put(Modifier.toString(Modifier.ABSTRACT), Modifier.ABSTRACT);
this.allmodifiers.put(Modifier.toString(Modifier.STATIC), Modifier.STATIC);
this.allmodifiers.put(Modifier.toString(Modifier.STRICT), Modifier.STRICT);
this.allmodifiers.put(Modifier.toString(Modifier.FINAL), Modifier.FINAL);
this.allmodifiers.put(Modifier.toString(Modifier.TRANSIENT), Modifier.TRANSIENT);
this.allmodifiers.put(Modifier.toString(Modifier.VOLATILE), Modifier.VOLATILE);
this.allmodifiers.put(Modifier.toString(Modifier.SYNCHRONIZED), Modifier.SYNCHRONIZED);
this.allmodifiers.put(Modifier.toString(Modifier.NATIVE), Modifier.NATIVE);
this.allmodifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
this.allmodifiers.put("sealed", 4096);
this.allmodifiers.put("non-sealed", 8192);
this.allmodifiers.put("default", 16384);
this.allmodifiers.put("strictfp", 32768);
this.compiler = compiler;
this.fileName = fileName;
}
public JavaClassRegistry getReg() {
return this.reg;
}
public String convertQualifiedName(Java17Parser.QualifiedNameContext ctx) {
/*
* String ret = ""; for (Java17Parser.IdentifierContext ident : ctx.identifier()) { ret += ident.getText(); if (ctx.identifier().iterator().hasNext()) { ret += '.'; } }
*/
return ctx.getText();
}
public void convert(List<ClassOrInterface> classes, Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException, NotImplementedException {
SrcfileContext srcfile;
if (ctx instanceof Java17Parser.SrcfileContext) {
srcfile = (SrcfileContext) ctx;
} else {
return;
}
if (srcfile.packageDeclaration() != null)
this.pkgName = convert(srcfile.packageDeclaration());
Map<String, Integer> imports = GatherNames.getImports(srcfile, packageCrawler, compiler);
this.imports.addAll(imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet()));
for (Java17Parser.ClassOrInterfaceContext type : srcfile.classOrInterface()) {
ClassorinterfacedeclContext clsoif;
if (type instanceof NoclassorinterfaceContext) {
continue;
} else {
clsoif = (ClassorinterfacedeclContext) type;
}
ClassOrInterface newClass;
int modifiers = 0;
if (!clsoif.classOrInterfaceModifier().isEmpty()) {
for (Java17Parser.ClassOrInterfaceModifierContext mod : clsoif.classOrInterfaceModifier()) {
modifiers += allmodifiers.get(mod.getText());
}
}
fieldInitializations = new ArrayList<>(); // PL 2019-10-22: muss für jede Klasse neu initilisiert werden
staticFieldInitializations = new ArrayList<>();
if (!Objects.isNull(clsoif.classDeclaration())) {
newClass = convertClass(clsoif.classDeclaration(), modifiers);
} else if (!Objects.isNull(clsoif.interfaceDeclaration())) {
newClass = convertInterface(clsoif.interfaceDeclaration(), modifiers);
} else if (!Objects.isNull(clsoif.recordDeclaration())) {
newClass = convertRecord(clsoif.recordDeclaration(), modifiers);
} else {
throw new NotImplementedException();
}
classes.add(newClass);
}
if (classes.isEmpty()) {
throw new NotImplementedException("SourceFile enthält keine Klassen");
}
}
private String convert(Java17Parser.PackageDeclarationContext ctx) {
return convertQualifiedName(ctx.qualifiedName());
}
private ClassOrInterface convertClass(Java17Parser.ClassDeclarationContext ctx, int modifiers) {
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + ctx.identifier().getText();
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart());
}
GenericsRegistry generics = createGenerics(ctx.genericDeclarationList(), name, "", reg, new GenericsRegistry(globalGenerics));
Token offset = ctx.getStart();
GenericDeclarationList genericClassParameters;
if (ctx.genericDeclarationList() == null) {
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), ctx.classBody().getStart());
} else {
genericClassParameters = TypeGenerator.convert(ctx.genericDeclarationList(), name, "", reg, generics);
}
RefType superClass;
if (ctx.EXTENDS() != null) {
superClass = convertSuperType(ctx.typeType());
} else {
superClass = new RefType(ASTFactory.createObjectClass().getClassName(), ctx.getStart());
}
this.superClass = superClass;
List<Field> fielddecl = new ArrayList<>();
List<Method> methods = new ArrayList<>();
List<Constructor> constructors = new ArrayList<>();
Boolean isInterface = false;
Boolean isFunctionalInterface = false;
List<RefType> implementedInterfaces = new ArrayList<>();
List<RefType> permittedSubtypes = new ArrayList<>();
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
convert(clsbodydecl, fielddecl, constructors, methods, name, superClass, generics);
}
if (constructors.isEmpty()) {
constructors.add(generateStandardConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset));
}
if (ctx.IMPLEMENTS() != null) {
implementedInterfaces.addAll(convert(ctx.typeList(0), generics));
}
// Ist Bit für 'sealed'-Modifier gesetzt
if ((modifiers & 4096) != 0) {
if (!Objects.isNull(ctx.PERMITS())) {
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
} else {
// falls sealed modifier ohne 'permits'-List oder umgekehrt
throw new NotImplementedException("Invalid sealed class declaration");
}
}
var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset));
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset, fileName);
}
private Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
this.superClass = new RefType(new JavaClassName("java.lang.Record"), new NullToken());
String identifier = recordDeclaration.identifier().getText();
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + identifier;
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
Token offset = recordDeclaration.getStart();
GenericsRegistry generics = createGenerics(recordDeclaration.genericDeclarationList(), name, "", reg, new GenericsRegistry(globalGenerics));
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), recordDeclaration.getStart());
}
GenericDeclarationList genericClassParameters;
if (recordDeclaration.genericDeclarationList() == null) {
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), recordDeclaration.recordBody().getStart());
} else {
genericClassParameters = TypeGenerator.convert(recordDeclaration.genericDeclarationList(), name, "", reg, generics);
}
RefType superClass = new RefType(ASTFactory.createClass(java.lang.Record.class).getClassName(), offset);
List<Field> fielddecl = new ArrayList<>();
List<Method> methods = new ArrayList<>();
List<Constructor> constructors = new ArrayList<>();
Boolean isInterface = false;
List<RefType> implementedInterfaces = new ArrayList<>();
List<Pattern> constructorParameters = new ArrayList<>();
List<Statement> constructorStatements = new ArrayList<>();
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
for (RecordComponentContext component : components) {
int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final");
String fieldname = component.identifier().getText();
Token fieldoffset = component.getStart();
RefTypeOrTPHOrWildcardOrGeneric fieldtype = null;
if (Objects.isNull(component.typeType())) {
fieldtype = TypePlaceholder.fresh(offset);
} else {
fieldtype = TypeGenerator.convert(component.typeType(), reg, generics);
}
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset);
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
Statement returnStatement = new Return(fieldvar, offset);
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
}
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), genericClassParameters, offset);
Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), prepareBlock(new Block(constructorStatements, offset), superClass), genericClassParameters, offset);
//Optional<Constructor> initializations = Optional.of(implicitConstructor);
constructors.add(implicitConstructor);
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics);
}
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
}
var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset, fileName);
}
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
MemberdeclContext member;
if (classBody instanceof MemberdeclContext) {
member = (MemberdeclContext) classBody;
Integer membermodifiers = 0;
for (ModifierContext mod : member.modifier()) {
if (mod.classOrInterfaceModifier() != null && mod.classOrInterfaceModifier().annotation() != null)
continue; // TODO don't eat annotations
membermodifiers += allmodifiers.get(mod.getText());
}
switch (member.memberDeclaration()) {
case MemberclassorinterfaceContext memberclsoif: {
break;
}
case MemberfieldContext memberfield: {
fields.addAll(convert(memberfield.fieldDeclaration(), membermodifiers, generics));
break;
}
case MembermethodContext membermethod: {
Method convertedMethod = convert(membermodifiers, membermethod.method(), name, superClass, generics);
if (convertedMethod instanceof Constructor constructor) {
constructors.add(constructor);
} else {
methods.add(convertedMethod);
}
break;
}
case MemberconstructorContext memberconstructor: {
constructors.add(convert(membermodifiers, memberconstructor.constructor(), name, superClass, generics));
break;
}
default:
break;
}
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
// Static blocks
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, this.fields, new HashMap<>());
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
staticFieldInitializations.addAll(block.statements);
}
}
private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) {
this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken());
String className = (this.pkgName.length() > 0 ? this.pkgName + "." : "") + ctx.identifier().getText();
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart());
}
if (!Modifier.isInterface(modifiers))
modifiers += Modifier.INTERFACE;
GenericsRegistry generics = createGenerics(ctx.genericDeclarationList(), name, "", reg, new GenericsRegistry(globalGenerics));
GenericDeclarationList genericParams;
if (!Objects.isNull(ctx.genericDeclarationList())) {
genericParams = TypeGenerator.convert(ctx.genericDeclarationList(), name, "", reg, generics);
} else {
genericParams = createEmptyGenericDeclarationList(ctx.identifier().getStart());
}
RefType superClass = ASTFactory.createObjectType();
List<Field> fields = new ArrayList<>();
List<Method> methods = new ArrayList<>();
for (InterfaceBodyDeclarationContext interfacebody : ctx.interfaceBody().interfaceBodyDeclaration()) {
if (interfacebody instanceof Java17Parser.EmptyinterfaceContext) {
continue;
} else {
InterfacememberContext interfacemember = (InterfacememberContext) interfacebody;
int membermodifiers = 0;
for (ModifierContext mod : interfacemember.modifier()) {
membermodifiers += allmodifiers.get(mod.getText());
}
int methodmodifiers = membermodifiers;
switch (interfacemember.interfaceMemberDeclaration()) {
case InterfaceconstContext constant:
fields.add(convert(constant));
break;
case InterfacemethodContext method:
InterfaceMethodDeclarationContext declaration = method.interfaceMethodDeclaration();
for (InterfaceMethodModifierContext mod : declaration.interfaceMethodModifier()) {
methodmodifiers += allmodifiers.get(mod.getText());
}
InterfaceCommonBodyDeclarationContext commonbody = declaration.interfaceCommonBodyDeclaration();
methods.add(convert(methodmodifiers, commonbody, new GenericDeclarationList(new ArrayList<>(), commonbody.getStart()), generics));
break;
case GenericinterfacemethodContext genericmethod:
GenericInterfaceMethodDeclarationContext genericdeclaration = genericmethod.genericInterfaceMethodDeclaration();
int genericmethodmodifiers = 0;
for (InterfaceMethodModifierContext mod : genericdeclaration.interfaceMethodModifier()) {
genericmethodmodifiers += allmodifiers.get(mod.getText());
}
commonbody = genericdeclaration.interfaceCommonBodyDeclaration();
GenericDeclarationList gtv = TypeGenerator.convert(genericdeclaration.genericDeclarationList(), name, commonbody.identifier().getText(), reg, generics);
methods.add(convert(genericmethodmodifiers, commonbody, gtv, generics));
break;
default:
throw new NotImplementedException();
}
}
}
List<RefType> extendedInterfaces = new ArrayList<>();
if (!Objects.isNull(ctx.EXTENDS())) {
extendedInterfaces.addAll(convert(ctx.typeList(0), generics));
}
List<RefType> permittedSubtypes = null;
// Ist Bit für 'sealed'-Modifier gesetzt
if ((modifiers & 4096) != 0) {
if (!Objects.isNull(ctx.PERMITS())) {
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
permittedSubtypes = new ArrayList<>(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
} else {
// falls sealed modifier ohne 'permits'-List oder umgekehrt
throw new NotImplementedException("Invalid sealed class declaration");
}
}
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart(), fileName);
}
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {
CommonToken gtvOffset = new CommonToken(classNameIdentifier);
gtvOffset.setCharPositionInLine(gtvOffset.getCharPositionInLine() + classNameIdentifier.getText().length());
gtvOffset.setStartIndex(gtvOffset.getStopIndex() + 1);
return new GenericDeclarationList(new ArrayList<>(), gtvOffset);
}
private Field convert(InterfaceconstContext constant) {
// TODO: Erstelle hier ein Feld!
throw new NotImplementedException();
}
private Method convert(int modifiers, InterfaceCommonBodyDeclarationContext bodydeclaration, GenericDeclarationList gtvDeclarations, GenericsRegistry generics) {
String name = bodydeclaration.identifier().getText();
RefTypeOrTPHOrWildcardOrGeneric retType;
if (Objects.isNull(bodydeclaration.refType())) {
retType = TypePlaceholder.fresh(bodydeclaration.getStart());
} else {
if (bodydeclaration.refType() instanceof RefType2Context reftype) {
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
} else {
retType = new Void(bodydeclaration.refType().getStart());
}
}
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList(), true);
MethodBodyContext body = bodydeclaration.methodBody();
Block block = null;
if (!(body instanceof EmptymethodContext)) {
MethodblockContext methodblock = (MethodblockContext) body;
block = stmtgen.convert(methodblock.block(), true);
}
else {
modifiers += Modifier.ABSTRACT;
}
return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, bodydeclaration.getStart());
}
protected static Block prepareBlock(Block constructorBlock, RefType superClass) {
List<Statement> statements = constructorBlock.getStatements();
if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall || statements.get(0) instanceof ThisCall)) {
var signature = new ArrayList<TypePlaceholder>();
signature.add(TypePlaceholder.fresh(new NullToken()));
statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset()));
}
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */
return new Block(statements, constructorBlock.getOffset());
}
/**
* http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9
*/
private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) {
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
ParameterList params = new ParameterList(new ArrayList<>(), offset);
return new Constructor(Modifier.PUBLIC, className, classType, params, prepareBlock(new Block(new ArrayList<>(), offset), superClass), classGenerics, offset); // fieldInitializations // 2018-11-24
}
/*
* fieldInitializations werden in einem Psedokonstruktor in der abstrakten Syntax gespeichert
*/
private Constructor generatePseudoConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
ParameterList params = new ParameterList(new ArrayList<>(), offset);
return new Constructor(Modifier.PUBLIC, className, classType, params, new Block(new ArrayList<>(initializations), offset), classGenerics, offset);
}
private Method generateStaticConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
ParameterList params = new ParameterList(new ArrayList<>(), offset);
Block block = new Block(new ArrayList<>(initializations), offset);
return new Method(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset);
}
private RefType convertSuperType(Java17Parser.TypeTypeContext typeType) {
ClassOrInterfaceTypeContext supertypecontext = typeType.classOrInterfaceType();
if (supertypecontext != null && supertypecontext.DOT().size() > 0) {
throw new NotImplementedException();
} else {
TypeArgumentsContext typeArguments = (typeType.classOrInterfaceType().typeArguments().size() > 0) ? typeType.classOrInterfaceType().typeArguments().get(typeType.classOrInterfaceType().typeArguments().size() - 1) : null;
RefTypeOrTPHOrWildcardOrGeneric ret = TypeGenerator.convertTypeName(typeType.classOrInterfaceType().typeIdentifier().getText(), typeArguments, typeType.getStart(), reg, globalGenerics);
if (ret instanceof RefType) {
return (RefType) ret;
} else {
throw new TypeinferenceException(typeType.getText() + " ist kein gültiger Supertyp", typeType.getStart());
}
}
}
private List<RefType> convert(Java17Parser.TypeListContext ctx, GenericsRegistry generics) {
List<RefType> ret = new ArrayList<>();
for (Java17Parser.TypeTypeContext type : ctx.typeType()) {
ret.add((RefType) TypeGenerator.convert(type, reg, generics));
}
return ret;
}
public Method convert(int modifiers, Java17Parser.MethodContext methodContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
GenericsRegistry localgenerics = generics;
MethodDeclarationContext methoddeclaration;
GenericDeclarationListContext genericdeclarations;
GenericDeclarationList gtvDeclarations;
MethodHeaderContext header;
String name;
if (methodContext instanceof GenericmethodContext) {
GenericmethodContext gmc = (GenericmethodContext) methodContext;
genericdeclarations = gmc.genericMethodDeclaration().genericDeclarationList();
methoddeclaration = gmc.genericMethodDeclaration().methodDeclaration();
header = methoddeclaration.methodHeader();
name = header.identifier().getText();
localgenerics.putAll(createGenerics(genericdeclarations, parentClass, name, reg, generics));
gtvDeclarations = TypeGenerator.convert(genericdeclarations, parentClass, name, reg, localgenerics);
} else {
MethoddeclContext mdc = (MethoddeclContext) methodContext;
methoddeclaration = mdc.methodDeclaration();
header = methoddeclaration.methodHeader();
gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart());
name = header.identifier().getText();
}
RefTypeOrTPHOrWildcardOrGeneric retType;
if (Objects.isNull(header.refType())) {
retType = TypePlaceholder.fresh(header.getStart(), -1, false);
} else {
if (header.refType() instanceof RefType2Context reftype) {
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
} else {
retType = new Void(header.refType().getStart());
}
}
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList(), true);
MethodBodyContext body = methoddeclaration.methodBody();
Block block = null;
if (body instanceof EmptymethodContext emptymethod) {
if (!Modifier.isAbstract(modifiers)) {
// TODO: Error! Abstrakte Methode ohne abstrakt Keyword
}
} else {
MethodblockContext methodblock = (MethodblockContext) body;
block = stmtgen.convert(methodblock.block(), true);
}
if (name.equals(parentClass.getClassName())) {
return new Constructor(modifiers, name, retType, paramlist, prepareBlock(block, superClass), gtvDeclarations, methoddeclaration.getStart());
} else {
return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart());
}
}
public Constructor convert(int modifiers, Java17Parser.ConstructorContext constructorContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
GenericsRegistry localgenerics = generics;
GenericDeclarationListContext genericdeclarations;
GenericDeclarationList gtvDeclarations;
ConstructorDeclarationContext constructordeclaration;
String name;
if (constructorContext instanceof GenericconstructorContext) {
GenericconstructorContext genericconstructor = (GenericconstructorContext) constructorContext;
GenericConstructorDeclarationContext gcdeclaration = genericconstructor.genericConstructorDeclaration();
name = gcdeclaration.constructorDeclaration().identifier().getText();
genericdeclarations = gcdeclaration.genericDeclarationList();
constructordeclaration = gcdeclaration.constructorDeclaration();
localgenerics.putAll(createGenerics(genericdeclarations, parentClass, name, reg, generics));
gtvDeclarations = TypeGenerator.convert(genericdeclarations, parentClass, name, reg, localgenerics);
} else {
ConstructordeclContext constructordeclarationcontext = (ConstructordeclContext) constructorContext;
constructordeclaration = constructordeclarationcontext.constructorDeclaration();
name = constructordeclaration.identifier().getText();
gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), constructordeclaration.getStart());
}
RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics);
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList(), true);
Block block = prepareBlock(stmtgen.convert(constructordeclaration.constructorBody, true), superClass);
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
}
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
List<Field> ret = new ArrayList<>();
RefTypeOrTPHOrWildcardOrGeneric fieldType;
if (fieldDeclContext.typeType() != null) {
fieldType = TypeGenerator.convert(fieldDeclContext.typeType(), reg, generics);
} else {
// PL 2019-12-06: variableDeclaratorList() eingefuegt, um als Token nicht die
// Modifier zu bekommen
fieldType = TypePlaceholder.fresh(fieldDeclContext.variableDeclarators().getStart(), -1, false);
}
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
String fieldName = varDecl.variableDeclaratorId().getText();
this.fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
if (varDecl.variableInitializer() != null) {
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics);
}
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
}
return ret;
}
public static String convert(Java17Parser.VariableDeclaratorIdContext variableDeclaratorIdContext) {
return variableDeclaratorIdContext.getText();
}
// Initialize a field by creating implicit constructor.
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
if (isStatic) {
staticFieldInitializations.add(assignment);
}
else fieldInitializations.add(assignment);
}
public int convertModifier(String modifier) {
return allmodifiers.get(modifier);
}
private GenericsRegistry createGenerics(Java17Parser.GenericDeclarationListContext ctx, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
GenericsRegistry ret = new GenericsRegistry(this.globalGenerics);
ret.putAll(generics);
if (ctx == null)
return ret;
for (Java17Parser.GenericTypeVarContext tp : ctx.genericTypeVar()) {
ret.put(tp.identifier().getText(), new GenericContext(parentClass, parentMethod));
TypeGenerator.convert(tp, parentClass, parentMethod, reg, ret);
}
return ret;
}
}

View File

@@ -1,209 +0,0 @@
package de.dhbw.compiler.parser.SyntaxTreeGenerator;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.compiler.exceptions.TypeinferenceException;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.scope.GenericsRegistry;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.parser.scope.JavaClassRegistry;
import de.dhbw.compiler.syntaxtree.GenericDeclarationList;
import de.dhbw.compiler.syntaxtree.GenericTypeVar;
import de.dhbw.compiler.syntaxtree.factory.ASTFactory;
import de.dhbw.compiler.syntaxtree.type.ExtendsWildcardType;
import de.dhbw.compiler.syntaxtree.type.GenericRefType;
import de.dhbw.compiler.syntaxtree.type.RefType;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.syntaxtree.type.SuperWildcardType;
import de.dhbw.compiler.syntaxtree.type.TypePlaceholder;
import de.dhbw.parser.Java17Parser;
import de.dhbw.parser.Java17Parser.*;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TypeGenerator {
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java17Parser.ClassOrInterfaceTypeContext classOrInterfaceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) {
Java17Parser.TypeArgumentsContext arguments = null;
/*
* PL 2019-03-19 auskommentiert ANFANG if(unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType() != null){ arguments = unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); }else{// if(unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType() != null){ arguments = unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType().
* unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); } PL 2019-03-19 auskommentiert ENDE
*/
/**
* Problem sind hier die verschachtelten Typen mit verschachtelten Typargumenten Beispiel: Typ<String>.InnererTyp<Integer>
*/
if (classOrInterfaceTypeContext.typeArguments().size() > 1)
throw new NotImplementedException();
String name = "";
for (IdentifierContext id : classOrInterfaceTypeContext.identifier()) {
name += id.getText() + '.';
}
name += classOrInterfaceTypeContext.typeIdentifier().getText();
if (classOrInterfaceTypeContext.getStop().getText().equals(">")) {
/*
* Fuer Debug-Zwecke unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType(); unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType().getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType(). unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); //UnannClassType_lfno_unannClassOrInterfaceTypeContext unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 0);
* unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 0).getText(); unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 1); unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 1).getText(); unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType().getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lf_unannClassOrInterfaceType(); //unannClassOrInterfaceTypeContext.
* unannInterfaceType_lf_unannClassOrInterfaceType(0).getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lf_unannClassOrInterfaceType(1).getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType().getText();
*/
List<TypeArgumentsContext> typeargs = classOrInterfaceTypeContext.typeArguments();
arguments = typeargs.size() != 0 ? classOrInterfaceTypeContext.typeArguments(0) : null;
}
return convertTypeName(name, arguments, classOrInterfaceTypeContext.getStart(), reg, generics);
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java17Parser.TypeTypeContext typeContext, JavaClassRegistry reg, GenericsRegistry genericsRegistry) {
if (typeContext.primitiveType() != null) {
switch (typeContext.primitiveType().getText()) {
case "boolean":
return new RefType(ASTFactory.createClass(Boolean.class).getClassName(), typeContext.getStart());
case "int":
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
case "double":
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
case "float":
return new RefType(ASTFactory.createClass(Float.class).getClassName(), typeContext.getStart());
default:
throw new NotImplementedException();
}
} else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen
// System.out.println(unannTypeContext.getText());
throw new NotImplementedException();
}
/*
* else if (typeContext.classOrInterfaceType() != null) { JavaClassName name = reg .getName(typeContext.classOrInterfaceType().typeIdentifier().getText()); return new RefType(name, typeContext.getStart()); }
*/
return TypeGenerator.convert(typeContext.classOrInterfaceType(), reg, genericsRegistry);
}
public static GenericDeclarationList convert(Java17Parser.GenericDeclarationListContext typeParametersContext, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
Token endOffset = typeParametersContext.getStop();
List<GenericTypeVar> typeVars = new ArrayList<>();
for (Java17Parser.GenericTypeVarContext typeParameter : typeParametersContext.genericTypeVar()) {
typeVars.add(convert(typeParameter, parentClass, parentMethod, reg, generics));
endOffset = typeParameter.getStop();
}
return new GenericDeclarationList(typeVars, endOffset);
}
public static GenericTypeVar convert(Java17Parser.GenericTypeVarContext typeVar, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
String name = typeVar.identifier().getText();
// TODO: Es müssen erst alle GenericTypeVars generiert werden, dann können die
// bounds dieser Generics ermittelt werden
// Problem <A extends B, B> ist erlaubt, würde aber bei den Bounds von A den
// Generic B nicht als solchen erkennen
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = TypeGenerator.convert(typeVar.typeBound(), reg, generics);
GenericTypeVar ret = new GenericTypeVar(name, bounds, typeVar.getStart(), typeVar.getStop());
return ret;
}
public static List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java17Parser.TypeBoundContext typeBoundContext, JavaClassRegistry reg, GenericsRegistry generics) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
if (Objects.isNull(typeBoundContext)) {
ret.add(ASTFactory.createObjectType());
return ret;
}
if (typeBoundContext.typeType().size() > 0) {
for (TypeTypeContext tt : typeBoundContext.typeType()) {
ret.add(convert(tt, reg, generics));
}
return ret;
}
throw new NotImplementedException();
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java17Parser.WildcardTypeContext wildcardContext, JavaClassRegistry reg, GenericsRegistry generics) {
if (wildcardContext.getChildCount() < 3) {
if (!Objects.isNull(wildcardContext.extendsWildcardType())) {
return new ExtendsWildcardType(convert(wildcardContext.extendsWildcardType().typeType(), reg, generics), wildcardContext.getStart());
} else if (!Objects.isNull(wildcardContext.superWildcardType())) {
return new SuperWildcardType(convert(wildcardContext.superWildcardType().typeType(), reg, generics), wildcardContext.getStart());
} else {
return new ExtendsWildcardType(new RefType(new JavaClassName("java.lang.Object"), new NullToken()), wildcardContext.getStart());
}
} else {
throw new NotImplementedException(); // Wildcard ohne Bound
}
}
public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Token offset, JavaClassRegistry reg, GenericsRegistry generics) {
return convertTypeName(name, (Java17Parser.TypeArgumentsContext) null, offset, reg, generics);
}
public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Java17Parser.TypeArgumentsContext typeArguments, Token offset, JavaClassRegistry reg, GenericsRegistry generics) {
if (!reg.contains(name)) { // Dann könnte es ein generischer Type oder ein FunN$$-Type sein
if (generics.contains(name)) {
return new GenericRefType(name, offset);
} else {
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(name);
if (m.matches()) {// es ist FunN$$-Type
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
} else {
throw new TypeinferenceException("Der Typ " + name + " ist nicht vorhanden", offset);
}
}
}
if (typeArguments == null) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for (int i = 0; i < reg.getNumberOfGenerics(name); i++) {
params.add(TypePlaceholder.fresh(offset));
}
return new RefType(reg.getName(name), params, offset);
} else {
return new RefType(reg.getName(name), convert(typeArguments, reg, generics), offset);
}
}
public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Java17Parser.NonWildcardTypeArgumentsContext typeArguments, Token offset, JavaClassRegistry reg, GenericsRegistry generics) {
if (!reg.contains(name)) { // Dann könnte es ein generischer Type oder ein FunN$$-Type sein
if (generics.contains(name)) {
return new GenericRefType(name, offset);
} else {
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(name);
if (m.matches()) {// es ist FunN$$-Type
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
} else {
throw new TypeinferenceException("Der Typ " + name + " ist nicht vorhanden", offset);
}
}
}
if (typeArguments == null) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for (int i = 0; i < reg.getNumberOfGenerics(name); i++) {
params.add(TypePlaceholder.fresh(offset));
}
return new RefType(reg.getName(name), params, offset);
} else {
return new RefType(reg.getName(name), convert(typeArguments, reg, generics), offset);
}
}
public static List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java17Parser.TypeArgumentsContext typeArguments, JavaClassRegistry reg, GenericsRegistry generics) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
for (Java17Parser.TypeArgumentContext arg : typeArguments.typeArgument()) {
WildcardTypeContext wc = arg.wildcardType();
if (!Objects.isNull(wc)) {
ret.add(convert(wc, reg, generics));
} else {
ret.add(convert(arg.typeType(), reg, generics));
}
}
return ret;
}
public static List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java17Parser.NonWildcardTypeArgumentsContext typeArguments, JavaClassRegistry reg, GenericsRegistry generics) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
for (Java17Parser.TypeTypeContext arg : typeArguments.typeList().typeType()) {
ret.add(convert(arg, reg, generics));
}
return ret;
}
}

View File

@@ -1,5 +0,0 @@
= Grammatik =
* Core-Problem: Typinferenz vs. Konstruktoren
* möglicherweise Problem: falsche Return-Expressions

View File

@@ -1,15 +0,0 @@
* Methode als statische Klasse
* Methode gibt eine JavaClassRegistry zurück (für mehr als 1 S0ourcefile).
* Suchmuster: \n rule
* Generell: lieber leere Listen und wenig null verwenden (Spezialfälle ausgenommen).
== Fehler/Exceptions ==
* Eigene wie z.B. TypeCheckExceptions
* Fehler sollen an Semantikchecker usw. weiter gegeben werden.
== Offset ==
* Evtl. Zeichen im File/in der Klasse durch Antlr ermitteln.
* z.B. ParserRuleContext.getStart()
* Anstatt offset: Instanz des entsprechenden ParserRuleContext (liefert evtl. noch mehr Infos)

View File

@@ -1,3 +0,0 @@
* fieldDeclarations
* Imports
* (Q)Generics

View File

@@ -1,2 +0,0 @@
* Ablegen der Type Parameter: kompletter Name?
* Typen (unannType etc.)

View File

@@ -1,18 +0,0 @@
* Listener-Pattern für das Projekt eher ungeeignet.
= Herangehensweise/Format =
* CompilatunUnit (Rot) wird zu Source-File (Root)
* Im Paket Syntaxtree finden sich die Klassen, die ich letztendlich erzeugen muss.
* Kann hier auch Veränderungen vornehmen (Pull Request)
* Wichtig! Typnamen müssen aufgelöst werden können (also z.B. java.lang.util.ArrayList (JavaClassRegistry).
= Idee bei mehreren Files =
* Zunächst alle Files anschauen und Pakate/Klassen für die spätere Verwendung "registrieren".
* Danach erst das komplette Package/alle Klassen imselben Verzeichnis parsen.
== Fragen/PProbleme SyntaxTreeGenerator ==
* ClassRegistry: Unklar, woher diese kommen soll.
* Konstruktor für Class fehlt.
* Namenskonflikt Class vs. Class in Java?

View File

@@ -1,154 +0,0 @@
package de.dhbw.compiler.parser.scope;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.google.common.collect.Iterables;
import de.dhbw.compiler.core.JavaTXCompiler;
import de.dhbw.compiler.environment.PackageCrawler;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.parser.Java17Parser;
public class GatherNames {
public static Map<String, Integer> getNames(Java17Parser.SrcfileContext ctx, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
Map<String, Integer> ret = new HashMap<>();
for (Java17Parser.ClassOrInterfaceContext clsoifctx : ctx.classOrInterface()) {
if (clsoifctx instanceof Java17Parser.NoclassorinterfaceContext) {
continue;
}
ret.putAll(getNames(clsoifctx, getPackageName(ctx), packages, compiler));
}
ret.putAll(getImports(ctx, packages, compiler));
return ret;
}
public static Map<String, Integer> getNames(Java17Parser.ClassOrInterfaceContext clsoifctx, String pkgName, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
Map<String, Integer> ret = new HashMap<>();
Java17Parser.ClassorinterfacedeclContext clsoif = (Java17Parser.ClassorinterfacedeclContext) clsoifctx;
String nameString = "";
String fullname = clsoif.getChild(clsoif.getChildCount() - 1).getClass().getName();
String classname = fullname.substring(fullname.indexOf("$") + 1);
int numGenerics = 0;
/*
* Es werden alle Namen gesammelt, die syntaktisch von Java-TX (sprich der Grammatik) erkannt werden. Auch wenn z.B. Annotationen oder Enumerationen noch nicht im Compiler implementiert sind. Die "NotImplementedException" wird dann im "SyntaxTreeGenerator" geworfen. Das Statement soll als Vorbereitung dienen, für den Fall, dass weitere Sprachkonstrukte in den Compiler aufgenommen werden.
*/
switch (classname) {
case "ClassDeclarationContext":
if (!pkgName.isEmpty()) {
nameString = pkgName + "." + clsoif.classDeclaration().identifier().getText();
} else {
nameString = clsoif.classDeclaration().identifier().getText();
}
numGenerics = clsoif.classDeclaration().genericDeclarationList() != null ? clsoif.classDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
ret.put(nameString, numGenerics);
ret.putAll(getNames(clsoif.classDeclaration().classBody().classBodyDeclaration(), pkgName, packages, compiler));
break;
case "EnumDeclarationContext":
if (!pkgName.isEmpty()) {
nameString = pkgName + "." + clsoif.enumDeclaration().identifier().getText();
} else {
nameString = clsoif.enumDeclaration().identifier().getText();
}
numGenerics = 0;
ret.put(nameString, numGenerics);
Java17Parser.EnumConstantsContext enumConstants = clsoif.enumDeclaration().enumConstants();
if (!Objects.isNull(enumConstants)) {
for (Java17Parser.EnumConstantContext enumConstant : enumConstants.enumConstant()) {
Java17Parser.ClassBodyContext enumConstClassBody = enumConstant.classBody();
if (!Objects.isNull(enumConstClassBody)) {
ret.putAll(getNames(enumConstClassBody.classBodyDeclaration(), pkgName, packages, compiler));
}
}
}
break;
case "InterfaceDeclarationContext":
if (pkgName != "") {
nameString = pkgName + "." + clsoif.interfaceDeclaration().identifier().getText();
} else {
nameString = clsoif.interfaceDeclaration().identifier().getText();
}
numGenerics = clsoif.interfaceDeclaration().genericDeclarationList() != null ? clsoif.interfaceDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
ret.put(nameString, numGenerics);
for (Java17Parser.InterfaceBodyDeclarationContext ifbody : clsoif.interfaceDeclaration().interfaceBody().interfaceBodyDeclaration()) {
if (ifbody instanceof Java17Parser.InterfacememberContext member && member.interfaceMemberDeclaration() instanceof Java17Parser.SubclassorinterfaceContext sub) {
ret.putAll(getNames(sub.classOrInterface(), pkgName, packages, compiler));
}
}
break;
case "AnnotationTypeDeclarationContext":
if (pkgName != "") {
nameString = pkgName + "." + clsoif.annotationTypeDeclaration().identifier().getText();
} else {
nameString = clsoif.annotationTypeDeclaration().identifier().getText();
}
numGenerics = 0;
ret.put(nameString, numGenerics);
for (Java17Parser.AnnotationTypeElementDeclarationContext anTypeElem : clsoif.annotationTypeDeclaration().annotationTypeBody().annotationTypeElementDeclaration()) {
Java17Parser.ClassOrInterfaceContext anClsoifctx = anTypeElem.annotationTypeElementRest().classOrInterface();
if (!Objects.isNull(anClsoifctx)) {
ret.putAll(getNames(anClsoifctx, pkgName, packages, compiler));
}
}
break;
case "RecordDeclarationContext":
if (pkgName != "") {
nameString = pkgName + "." + clsoif.recordDeclaration().identifier().getText();
} else {
nameString = clsoif.recordDeclaration().identifier().getText();
}
numGenerics = clsoif.recordDeclaration().genericDeclarationList() != null ? clsoif.recordDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
ret.put(nameString, numGenerics);
ret.putAll(getNames(clsoif.recordDeclaration().recordBody().classBodyDeclaration(), pkgName, packages, compiler));
break;
default:
throw new NotImplementedException();
}
return ret;
}
public static Map<String, Integer> getNames(List<Java17Parser.ClassBodyDeclarationContext> clsBodyDecl, String pkgName, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
Map<String, Integer> ret = new HashMap<>();
for (Java17Parser.ClassBodyDeclarationContext clsbody : clsBodyDecl) {
if (clsbody instanceof Java17Parser.MemberdeclContext member && member.memberDeclaration() instanceof Java17Parser.MemberclassorinterfaceContext memberclsoifctx) {
ret.putAll(getNames(memberclsoifctx.classOrInterface(), pkgName, packages, compiler));
}
}
return ret;
}
public static Map<String, Integer> getImports(Java17Parser.SrcfileContext ctx, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
Map<String, Integer> ret = new HashMap<>();
// ret.putAll(packages.getClassNames("java.lang"));
for (Java17Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()) {
if (importDeclCtx.MUL() == null) {
var name = importDeclCtx.qualifiedName().getText();
var className = new JavaClassName(name);
var clazz = compiler.loadJavaTXClass(className);
if (clazz != null) {
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
} else {
Class<?> cl = compiler.getClassLoader().loadClass(name);
ret.put(cl.getName(), cl.getTypeParameters().length);
}
} else if (importDeclCtx.MUL() != null) {
// TODO Find stuff in user defined packages
ret.putAll(packages.getClassNames(importDeclCtx.qualifiedName().getText()));
}
// Die Unterscheidungen für 'static imports' wurden herausgenommen, da sie den
// auszuführenden Code nicht beeinflussen
}
return ret;
}
private static String getPackageName(Java17Parser.SrcfileContext ctx) {
String pkgName = "";
if (ctx.packageDeclaration() != null) {
pkgName = ctx.packageDeclaration().qualifiedName().getText();
}
return pkgName;
}
}

View File

@@ -1,50 +0,0 @@
package de.dhbw.compiler.parser.scope;
import de.dhbw.compiler.parser.SyntaxTreeGenerator.GenericContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class GenericsRegistry {
private final List<GenericVariable> registry = new ArrayList<>();
public final GenericsRegistry globalRegistry;
public GenericsRegistry(GenericsRegistry globalRegistry){
this.globalRegistry = globalRegistry;
}
public void put(String name, GenericContext genericContext){
registry.add(new GenericVariable(genericContext,name));
if(globalRegistry != null)globalRegistry.put(name, genericContext);
}
public boolean contains(String name) {
Optional<Boolean> ret = registry.stream().<Boolean>map(((GenericVariable genericVariable) -> genericVariable.name.equals(name)))
.reduce(((a, b) -> a || b));
if(ret.isPresent())
return ret.get();
return false;
}
public GenericContext get(String name) {
return registry.stream()
.filter((genericVariable -> genericVariable.name.equals(name))).findAny().get().context;
}
public void putAll(GenericsRegistry generics) {
for(GenericVariable generic : generics.registry){
this.put(generic.name, generic.context);
}
}
}
class GenericVariable{
final GenericContext context;
final String name;
GenericVariable(GenericContext context, String name){
this.context = context;
this.name = name;
}
}

View File

@@ -1,159 +0,0 @@
package de.dhbw.compiler.parser.scope;
import java.util.ArrayList;
import java.util.List;
/**
* Stellt den Namen einer Java Klasse dar.
* Dieser kann auch den Packagenamen mit beinhalten:
* de.dhbwstuttgart.typeinference.Menge
*
* @author Andreas Stadelmeier
*/
public class JavaClassName {
// FIXME It's very much possible to have imports to inner classes
// In that case a.package.Foo.Bar, a.package is the Package and Foo.Bar the class name
// Its impossible to decide what's the package based solely on the name of the class
public static final JavaClassName Void = new JavaClassName("void");
private String name;
private PackageName packageName;
public JavaClassName(String name) {
if (name == null)
throw new NullPointerException();
String[] names = name.split("[.]");
boolean match = true;
if (names.length == 1) {
// packageName = new PackageName();
this.name = name;
} else {
name = names[names.length - 1];
List<String> packageNames = new ArrayList<String>();
for (int i = 0; i < names.length - 1; i++) {
packageNames.add(names[i]);
}
packageName = new PackageName(packageNames);
this.name = names[names.length - 1];
}
}
/**
* Gibt von einem Klassennamen nur den Namen der Klasse zur<75>ck
* Beispiel:
* java.lang.Object wird zu: Object
*/
public static String stripClassName(String className) {
return new JavaClassName(className).name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
/*
* result = prime * result
* + ((packageName == null) ? 0 : packageName.hashCode()); //PackageName does
* not infect hashCode
*/
return result;
}
/**
* Namen sind nur gleich, wenn bei den beiden zu vergleichenden JavaClassNames
* auch das Package angegeben ist
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (obj instanceof String)
return this.toString().equals(obj) || (this.name != null && this.name.equals(obj)); // Auch mit Strings als
// Klassennamen kompatibel
// TODO: sollte bald obsolet
// sein
if (getClass() != obj.getClass())
return false;
JavaClassName other = (JavaClassName) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (packageName != null && other.packageName != null) {
if (!packageName.equals(other.packageName))
return false;// Spezialfall, nicht beide Typen müssen eindeutig mit Packagenamen angegeben
// werden
}
return true;
}
@Override
public String toString() {
return (packageName != null ? packageName.toString() + "." : "") + name;
}
public String getPackageName() {
return (packageName != null ? packageName.toString() : "");
}
public String getClassName() {
return name;
}
}
class PackageName {
List<String> names = new ArrayList<>();
public PackageName(List<String> packageNames) {
names = packageNames;
}
public PackageName() {
// Do nothing
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((names == null) ? 0 : names.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PackageName other = (PackageName) obj;
if (names == null) {
if (other.names != null)
return false;
} else if (!names.equals(other.names))
return false;
return true;
}
@Override
public String toString() {
String ret = "";
if (names == null)
return "";
for (String n : names)
ret += n + ".";
if (ret != null && ret.length() > 0 && ret.charAt(ret.length() - 1) == '.') {
ret = ret.substring(0, ret.length() - 1);
}
return ret;
}
}

View File

@@ -1,65 +0,0 @@
package de.dhbw.compiler.parser.scope;
import de.dhbw.compiler.exceptions.NotImplementedException;
import java.util.*;
/**
* Speichert die Klassen f<>r einen bestimmten Projektscope
*/
public class JavaClassRegistry {
final Map<JavaClassName, Integer> existingClasses = new HashMap<>();
public JavaClassRegistry(Map<String, Integer> initialNames) {
addNames(initialNames);
}
public JavaClassRegistry() {}
public void addNames(Map<String, Integer> names) {
for (String name : names.keySet()) {
existingClasses.put(new JavaClassName(name), names.get(name));
}
}
public void addName(String className, int numberOfGenerics) {
existingClasses.put(new JavaClassName(className), numberOfGenerics);
}
public JavaClassName getName(String className) {
for (JavaClassName name : existingClasses.keySet()) {
if (name.equals(new JavaClassName(className)))
return name;
}
throw new RuntimeException("Class " + className + " not found!");
}
@Override
public String toString() {
return existingClasses.toString();
}
public List<JavaClassName> getAllFromPackage(String packageName) {
List<JavaClassName> ret = new ArrayList<>();
for (JavaClassName className : this.existingClasses.keySet()) {
JavaClassName toCompare = new JavaClassName(
packageName + "." + JavaClassName.stripClassName(className.toString()));
if (toCompare.toString().equals(className.toString())) {
ret.add(className);
}
}
return ret;
}
public boolean contains(String whole) {
return existingClasses.containsKey(new JavaClassName(whole));
}
public boolean contains(JavaClassName name) {
return existingClasses.containsKey(name);
}
public int getNumberOfGenerics(String name) {
return existingClasses.get(new JavaClassName(name));
}
}

View File

@@ -1,43 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.*;
public interface ASTVisitor extends StatementVisitor{
void visit(SourceFile sourceFile);
void visit(GenericTypeVar genericTypeVar);
void visit(FormalParameter formalParameter);
void visit(LiteralPattern literalPattern);
void visit(GenericDeclarationList genericTypeVars);
void visit(Field field);
void visit(Method field);
void visit(Constructor field);
void visit(ParameterList formalParameters);
void visit(ClassOrInterface classOrInterface);
void visit(RefType refType);
void visit(SuperWildcardType superWildcardType);
void visit(TypePlaceholder typePlaceholder);
void visit(ExtendsWildcardType extendsWildcardType);
void visit(GenericRefType genericRefType);
void visit(ExpressionPattern aPattern);
void visit(RecordPattern aRecordPattern);
void visit(GuardedPattern aGuardedPattern);
}

View File

@@ -1,352 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbw.compiler.syntaxtree.statement.*;
import de.dhbw.compiler.syntaxtree.type.*;
import java.util.Iterator;
import java.util.Objects;
public abstract class AbstractASTWalker implements ASTVisitor {
@Override
public void visit(Constructor cons) {
visitMethod(cons);
}
@Override
public void visit(SourceFile sourceFile) {
for (ClassOrInterface cl : sourceFile.getClasses()) {
cl.accept(this);
}
}
@Override
public void visit(ArgumentList argumentList) {
for (Expression expr : argumentList.getArguments()) {
expr.accept(this);
}
}
@Override
public void visit(GenericTypeVar genericTypeVar) {
}
@Override
public void visit(FormalParameter formalParameter) {
formalParameter.getType().accept((ASTVisitor) this);
}
@Override
public void visit(LiteralPattern literalPattern) {
}
@Override
public void visit(GenericDeclarationList genericTypeVars) {
Iterator<GenericTypeVar> genericIterator = genericTypeVars.iterator();
if (genericIterator.hasNext()) {
while (genericIterator.hasNext()) {
genericIterator.next().accept(this);
}
}
}
@Override
public void visit(Field field) {
field.getType().accept(this);
}
@Override
public void visit(Method method) {
visitMethod(method);
}
private void visitMethod(Method method) {
method.getReturnType().accept(this);
method.getParameterList().accept(this);
if (method.block != null)
method.block.accept(this);
}
@Override
public void visit(ParameterList formalParameters) {
Iterator<Pattern> it = formalParameters.getFormalparalist().iterator();
if (it.hasNext()) {
while (it.hasNext()) {
it.next().accept(this);
}
}
}
@Override
public void visit(ClassOrInterface classOrInterface) {
classOrInterface.getGenerics().accept(this);
for (Field f : classOrInterface.getFieldDecl()) {
f.accept(this);
}
for (Constructor c : classOrInterface.getConstructors()) {
c.accept(this);
}
for (Method m : classOrInterface.getMethods()) {
m.accept(this);
}
}
@Override
public void visit(RefType refType) {
Iterator<RefTypeOrTPHOrWildcardOrGeneric> genericIterator = refType.getParaList().iterator();
if (genericIterator.hasNext()) {
while (genericIterator.hasNext()) {
genericIterator.next().accept(this);
}
}
}
@Override
public void visit(SuperWildcardType superWildcardType) {
superWildcardType.getInnerType().accept(this);
}
@Override
public void visit(TypePlaceholder typePlaceholder) {
}
@Override
public void visit(ExtendsWildcardType extendsWildcardType) {
extendsWildcardType.getInnerType().accept(this);
}
@Override
public void visit(GenericRefType genericRefType) {
}
@Override
public void visit(LambdaExpression lambdaExpression) {
lambdaExpression.params.accept(this);
lambdaExpression.methodBody.accept(this);
}
@Override
public void visit(Assign assign) {
assign.lefSide.accept(this);
assign.rightSide.accept(this);
assign.rightSide.getType().accept((ASTVisitor) this);
}
@Override
public void visit(BinaryExpr binary) {
}
@Override
public void visit(BoolExpression logical) {
}
@Override
public void visit(Block block) {
for (Statement stmt : block.getStatements()) {
stmt.accept(this);
}
}
@Override
public void visit(CastExpr castExpr) {
}
@Override
public void visit(EmptyStmt emptyStmt) {
}
@Override
public void visit(FieldVar fieldVar) {
fieldVar.receiver.accept(this);
}
@Override
public void visit(ForStmt forStmt) {
forStmt.block.accept(this);
}
@Override
public void visit(ForEachStmt forEachStmt) {
forEachStmt.block.accept(this);
}
@Override
public void visit(IfStmt ifStmt) {
ifStmt.then_block.accept(this);
if (!Objects.isNull(ifStmt.else_block))
ifStmt.else_block.accept(this);
}
@Override
public void visit(InstanceOf instanceOf) {
}
@Override
public void visit(LocalVar localVar) {
}
@Override
public void visit(LocalVarDecl localVarDecl) {
localVarDecl.getType().accept(this);
}
@Override
public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this);
methodCall.getArgumentList().accept(this);
methodCall.getArgumentList().getArguments().forEach(a -> a.getType().accept((ASTVisitor) this));
}
@Override
public void visit(NewClass methodCall) {
visit((MethodCall) methodCall);
}
@Override
public void visit(NewArray newArray) {
}
@Override
public void visit(ExpressionReceiver receiver) {
receiver.expr.accept(this);
}
@Override
public void visit(UnaryExpr unaryExpr) {
unaryExpr.expr.accept(this);
}
@Override
public void visit(Return aReturn) {
aReturn.retexpr.accept(this);
aReturn.getType().accept((ASTVisitor) this);
}
@Override
public void visit(ReturnVoid aReturn) {
}
@Override
public void visit(Break aBreak) {
aBreak.accept(this);
}
@Override
public void visit(Continue aContinue) {
aContinue.accept(this);
}
@Override
public void visit(StaticClassName staticClassName) {
}
@Override
public void visit(Super aSuper) {
}
@Override
public void visit(This aThis) {
}
@Override
public void visit(WhileStmt whileStmt) {
whileStmt.loopBlock.accept(this);
}
@Override
public void visit(DoStmt whileStmt) {
whileStmt.loopBlock.accept(this);
}
@Override
public void visit(Literal literal) {
}
@Override
public void visit(Throw aThrow) {
}
@Override
public void visit(AssignToField assignLeftSide) {
assignLeftSide.field.accept(this);
}
@Override
public void visit(AssignToLocal assignLeftSide) {
assignLeftSide.localVar.accept(this);
}
@Override
public void visit(SuperCall superCall) {
this.visit((MethodCall) superCall);
}
@Override
public void visit(ThisCall thisCall) {
}
@Override
public void visit(Switch switchStmt) {
switchStmt.getSwitch().accept(this);
switchStmt.getBlocks().stream().forEach((switchBlock) -> {
switchBlock.accept(this);
});
}
@Override
public void visit(SwitchBlock switchBlock) {
switchBlock.getLabels().stream().forEach((label) -> {
label.accept(this);
});
switchBlock.getStatements().stream().forEach((stmt) -> {
stmt.accept(this);
});
}
@Override
public void visit(SwitchLabel switchLabel) {
}
@Override
public void visit(Yield aYield) {
}
@Override
public void visit(ExpressionPattern aPattern) {
}
@Override
public void visit(RecordPattern aRecordPattern) {
}
@Override
public void visit(GuardedPattern aGuardedPattern) {
}
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
}
}

View File

@@ -1,202 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.syntaxtree.type.GenericRefType;
import de.dhbw.compiler.syntaxtree.type.RefType;
import de.dhbw.compiler.syntaxtree.type.TypePlaceholder;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
*/
public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private Boolean methodAdded = false; // wird benoetigt bei in JavaTXCompiler.getConstraints()
protected int modifiers;
protected JavaClassName name;
private final String fileName;
private List<Field> fields = new ArrayList<>();
private Optional<Constructor> fieldInitializations; // PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen
private Optional<Method> staticInitializer;
private List<Method> methods = new ArrayList<>();
private GenericDeclarationList genericClassParameters;
private RefType superClass;
protected boolean isInterface;
protected boolean isFunctionalInterface;
private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
private List<Constructor> constructors;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset, String fileName) {
super(offset);
if (isInterface) {
modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT;
}
this.modifiers = modifiers;
this.name = name;
this.fields = fielddecl;
this.fieldInitializations = fieldInitializations;
this.staticInitializer = staticInitializer;
this.genericClassParameters = genericClassParameters;
this.superClass = superClass;
this.isInterface = isInterface;
this.isFunctionalInterface= isFunctionalInterface;
this.implementedInterfaces = implementedInterfaces;
this.permittedSubtypes = permittedSubtypes;
this.methods = methods;
this.constructors = constructors;
this.fileName = fileName;
}
/*
* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte alle anderen Datenobjekte werden nur kopiert.
*/
public ClassOrInterface(ClassOrInterface cl) {
super(cl.getOffset());
this.modifiers = cl.modifiers;
this.name = cl.name;
this.fields = new ArrayList<>(cl.fields);
this.fieldInitializations = cl.fieldInitializations;
this.staticInitializer = cl.staticInitializer;
this.genericClassParameters = cl.genericClassParameters;
this.superClass = cl.superClass;
this.isInterface = cl.isInterface;
this.isFunctionalInterface= cl.isFunctionalInterface;
this.implementedInterfaces = cl.implementedInterfaces;
this.methods = new ArrayList<>(cl.methods);
this.constructors = new ArrayList<>(cl.constructors);
this.fileName = cl.fileName;
}
public String getFileName() {
return fileName;
}
public Optional<Field> getField(String name) {
// TODO This should be a map
return fields.stream().filter(field -> field.getName().equals(name)).findFirst();
}
public Optional<Method> getStaticInitializer() {
return staticInitializer;
}
public boolean isSealed() { return permittedSubtypes != null; }
public List<RefType> getPermittedSubtypes() { return permittedSubtypes != null ? permittedSubtypes : List.of(); }
public boolean isInterface() {
return (Modifier.INTERFACE & this.getModifiers()) != 0;
}
public boolean isFunctionalInterface() {
return this.isFunctionalInterface;
}
// Gets if it is added
public Boolean areMethodsAdded() {
return methodAdded;
}
// Sets that it is added
public void setMethodsAdded() {
methodAdded = true;
}
// Gets class name
public JavaClassName getClassName() {
return this.name;
}
// Get modifiers
public int getModifiers() {
return this.modifiers;
}
public List<Field> getFieldDecl() {
return this.fields;
}
public Optional<Constructor> getfieldInitializations() {
return this.fieldInitializations;
}
public List<Method> getMethods() {
return this.methods;
}
/*
* public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); }
*/
// TODO: Das hier ist ein Problem. Je nach Kontext wird hier ein anderer Typ benötigt
public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass, Token offset) {
// Hier wird immer ein generischer Typ generiert, also mit Type placeholdern
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for (GenericTypeVar genericTypeVar : genericsOfClass) {
// params.add(genericTypeVar.getTypePlaceholder());
params.add(TypePlaceholder.fresh(offset));
}
return new RefType(name, params, offset);
}
/**
*
* @return die aktuelle Klasse als RefType
*/
public RefType generateTypeOfThisClass() {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for (GenericTypeVar genericTypeVar : this.getGenerics()) {
// params.add(genericTypeVar.getTypePlaceholder());
params.add(new GenericRefType(genericTypeVar.getName(), new NullToken()));
}
return new RefType(name, params, new NullToken());
}
/**
* Die Superklasse im Kontext dieser ClassOrInterface Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
*/
public RefType getSuperClass() {
return superClass;
}
public GenericDeclarationList getGenerics() {
return this.genericClassParameters;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return null;
}
public List<Constructor> getConstructors() {
return constructors;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public Collection<RefType> getSuperInterfaces() {
return implementedInterfaces;
}
public String toString() {
return this.name.toString() + this.genericClassParameters.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassOrInterface other)) return false;
return Objects.equals(name, other.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}

View File

@@ -1,29 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.syntaxtree.statement.Statement;
import de.dhbw.compiler.syntaxtree.statement.Super;
import de.dhbw.compiler.syntaxtree.statement.SuperCall;
import de.dhbw.compiler.syntaxtree.type.RefType;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.syntaxtree.statement.Block;
import java.sql.Ref;
import java.util.ArrayList;
import java.util.List;
public class Constructor extends Method {
// TODO: Constructor braucht ein super-Statement
public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset) {
super(modifier, name, returnType, parameterList, codeInsideConstructor, gtvDeclarations, offset);
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,14 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.List;
public class ExceptionList
{
private List<RefTypeOrTPHOrWildcardOrGeneric> exceptions;
public ExceptionList(List<RefTypeOrTPHOrWildcardOrGeneric> exceptions){
this.exceptions = exceptions;
}
}

View File

@@ -1,28 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.statement.Expression;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class ExpressionPattern extends Pattern {
private final Expression expression;
public ExpressionPattern(Expression expression, Token offset) {
super(expression.getType(), offset);
this.expression = expression;
}
public Expression getExpression() {
return expression;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public ExpressionPattern withType(RefTypeOrTPHOrWildcardOrGeneric type) {
return new ExpressionPattern(expression, getOffset());
}
}

View File

@@ -1,43 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
public class Field extends SyntaxTreeNode implements TypeScope {
public final int modifier;
private String name;
private RefTypeOrTPHOrWildcardOrGeneric type;
public Field(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifier, Token offset) {
super(offset);
this.name = name;
this.type = type;
this.modifier = modifier;
}
public String getName() {
return this.name;
}
public RefTypeOrTPHOrWildcardOrGeneric getType() {
return type;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
return new ArrayList<>();
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return type;
}
}

View File

@@ -1,28 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.statement.Expression;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
/**
* Eine Feldinitialisation steht für eine Felddeklaration mit gleichzeitiger Wertzuweisung
* Beispiel: 'public Feld FeldVar = FeldWert;'
* @author janulrich
*
*/
public class FieldDeclaration extends Field{
private Expression wert;
/**
* Dieser Konstruktor der FieldDeclaration erstellt den Syntaxknoten vollständig.
* Kein nachträgliches hinzfügen von Informationen oder aufrufen von parserPostProcessing ist notwendig.
*/
public FieldDeclaration(String name, RefTypeOrTPHOrWildcardOrGeneric typ, int modifier, Expression value, Token offset){
super(name, typ, modifier, offset);//Dieser Deklarator wird nicht vom Parser aufgerufen. Dadurch gibt es auch keinen Offset
this.wert = value;
}
}

View File

@@ -1,27 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class FormalParameter extends Pattern {
private String name;
public FormalParameter(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(type, offset);
this.name = name;
}
public String getName() {
return name;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public FormalParameter withType(RefTypeOrTPHOrWildcardOrGeneric type) {
return new FormalParameter(name, type, getOffset());
}
}

View File

@@ -1,65 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import org.antlr.v4.runtime.Token;
import com.google.common.collect.Lists;
import de.dhbw.compiler.parser.NullToken;
import java.util.*;
/**
* Stellt eine Deklarations-Liste von Generischen Variablen dar.
* Kann vor Methoden und Klassen auftauchen. (<....>)
* @author janulrich
*
*/
public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<GenericTypeVar>{
private Token offsetOfLastElement;
private List<GenericTypeVar> gtvs = new ArrayList<>();
@SuppressWarnings("unchecked")
public GenericDeclarationList(Iterable<? extends GenericTypeVar> values, Token endOffset) {
super(endOffset);
gtvs = isListOfGenericTypeVar(values) ? (List<GenericTypeVar>)values : Lists.newArrayList(values);
this.offsetOfLastElement = endOffset;
}
public GenericDeclarationList(ArrayList<GenericTypeVar> values, Token endOffset) {
super(endOffset);
gtvs = values;
this.offsetOfLastElement = endOffset; }
private boolean isListOfGenericTypeVar(Iterable<? extends GenericTypeVar> values) {
return values instanceof List && ((List<?>)values).size() > 0 && ((List<?>)values).get(0) instanceof GenericTypeVar;
}
@Override
public Iterator<GenericTypeVar> iterator() {
return gtvs.iterator();
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public String toString() {
return this.gtvs.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GenericDeclarationList that = (GenericDeclarationList) o;
return gtvs.equals(that.gtvs);
}
@Override
public int hashCode() {
return Objects.hash(gtvs);
}
}

View File

@@ -1,78 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Entspricht einem GenericTypeVar, jedoch mit Bounds
* (d.h. vorgaben, von welchem Typ die Typevar sein darf
* => extends Class x
* => implements Interface y
* ...
* @author hoti 4.5.06
*
*/
public class GenericTypeVar extends SyntaxTreeNode
{
/**
* Hier sind die Bounds in Form von Type-Objekten abgespeichert
*/
List<? extends RefTypeOrTPHOrWildcardOrGeneric> bounds=new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
private Token endOffset;
private String name;
public GenericTypeVar(String s, List<? extends RefTypeOrTPHOrWildcardOrGeneric> bounds, Token offset, Token endOffset)
{
super(offset);
name = s;
if(bounds != null)for(RefTypeOrTPHOrWildcardOrGeneric t : bounds){
//if(t!=null)this.extendVars.add(t);
}
//this.genericTypeVar = new RefType(s,offset);
this.bounds = bounds;
this.endOffset = endOffset;
}
public List<? extends RefTypeOrTPHOrWildcardOrGeneric> getBounds()
{
return bounds;
}
public String toString()
{
return "BoGTV " + this.name + " " + this.bounds;
}
public String getName(){
return name.toString();
}
/*
public JavaClassName definingClass(){
return name.getParentClass();
}
*/
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GenericTypeVar that = (GenericTypeVar) o;
return bounds.equals(that.bounds) && name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(bounds, name);
}
}

View File

@@ -1,35 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.statement.Expression;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class GuardedPattern extends Pattern {
private final Expression condition;
private final Pattern nested;
public GuardedPattern(Expression condition, Pattern nested, Token offset) {
super(nested.getType(), offset);
this.condition = condition;
this.nested = nested;
}
public Expression getCondition() {
return condition;
}
public Pattern getNestedPattern() {
return nested;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public GuardedPattern withType(RefTypeOrTPHOrWildcardOrGeneric type) {
return new GuardedPattern(condition, nested, getOffset());
}
}

View File

@@ -1,29 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.ASTVisitor;
import de.dhbw.compiler.syntaxtree.Pattern;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.statement.Expression;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import org.antlr.v4.runtime.Token;
public class LiteralPattern extends FormalParameter
{
public final Expression value;
public LiteralPattern(RefTypeOrTPHOrWildcardOrGeneric type, Expression value, Token offset) {
super(null, type, offset);
this.value = value;
}
@Override
public FormalParameter withType(RefTypeOrTPHOrWildcardOrGeneric type) {
return new LiteralPattern(type, value, getOffset());
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,119 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import java.util.ArrayList;
import java.util.Objects;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceInformation;
import de.dhbw.compiler.typeinference.typeAlgo.TYPE;
import de.dhbw.compiler.typeinference.typeAlgo.TYPEStmt;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.core.IItemWithOffset;
import de.dhbw.compiler.syntaxtree.statement.Block;
/**
* Stellt eine Methode dar. Problem: Parser kann nicht zwischen Methode und
* Konstruktor unterscheiden. Daher kann diese Klasse beides sein. Dies wird mit
* dem ParserPostProcessing behoben.
*
* @author janulrich
*
*/
public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
{
public final Block block;
public final int modifier;
public final String name;
private ParameterList parameterlist = new ParameterList(new ArrayList<>(), new NullToken());
private ExceptionList exceptionlist;
private GenericDeclarationList generics;
private final RefTypeOrTPHOrWildcardOrGeneric returnType;
public final Boolean isInherited;
public final Boolean isImplemented;
/*
* its Constraints
* eingefuegt PL 2021-02-15
*/
public final ConstraintSet constraints = new ConstraintSet();
public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
GenericDeclarationList gtvDeclarations, Token offset) {
super(offset);
this.name = name;
this.modifier = modifier;
this.returnType = returnType;
this.parameterlist = parameterList;
this.block = block;
this.generics = gtvDeclarations;
this.isInherited = false;
this.isImplemented = false;
}
public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited, Boolean isOverridden) {
super(offset);
this.name = name;
this.modifier = modifier;
this.returnType = returnType;
this.parameterlist = parameterList;
this.block = block;
this.generics = gtvDeclarations;
this.isInherited = isInherited;
this.isImplemented = isOverridden;
}
public ParameterList getParameterList() {
return parameterlist;
}
public GenericDeclarationList getGenerics() {
return generics;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
return this.returnType;
}
public ConstraintSet getConstraints() {
return this.constraints;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public Token getOffset() {
return super.getOffset();
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Method method = (Method) o;
return Objects.equals(name, method.name) && Objects.equals(parameterlist, method.parameterlist) && Objects.equals(returnType, method.returnType);
}
@Override
public int hashCode() {
return Objects.hash(name, parameterlist, returnType);
}
@Override
public String toString() {
return name;
}
}

View File

@@ -1,36 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import org.antlr.v4.runtime.Token;
import java.util.Iterator;
import java.util.List;
public class ParameterList extends SyntaxTreeNode implements Iterable<Pattern> {
private List<Pattern> formalparameter;
public ParameterList(List<Pattern> params, Token offset) {
super(offset);
this.formalparameter = params;
}
public Pattern getParameterAt(int i) {
if (i >= formalparameter.size())
return null;
return formalparameter.get(i);
}
public List<Pattern> getFormalparalist() {
return formalparameter;
}
@Override
public Iterator<Pattern> iterator() {
return formalparameter.iterator();
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,19 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public abstract class Pattern extends SyntaxTreeNode {
private final RefTypeOrTPHOrWildcardOrGeneric type;
public Pattern(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(offset);
this.type = type;
}
public RefTypeOrTPHOrWildcardOrGeneric getType(){
return type;
}
public abstract Pattern withType(RefTypeOrTPHOrWildcardOrGeneric type);
}

View File

@@ -1,19 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.syntaxtree.type.RefType;
import javax.swing.text.html.Option;
public class Record extends ClassOrInterface {
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset, String fileName) {
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset, fileName);
}
}

View File

@@ -1,33 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public class RecordPattern extends FormalParameter {
private final List<Pattern> subPattern;
public RecordPattern(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(name, type, offset);
subPattern = new ArrayList<>();
}
public RecordPattern(List<Pattern> subPattern, String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(name, type, offset);
this.subPattern = subPattern;
}
public List<Pattern> getSubPattern() {
return this.subPattern;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,78 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import java.io.File;
import java.util.*;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceInformation;
//import sun.security.x509.X509CertInfo;
public class SourceFile extends SyntaxTreeNode {
private String pkgName;
public final List<ClassOrInterface> KlassenVektor;
public final Set<JavaClassName> imports;
private boolean isGenerated;
public List<ClassOrInterface> availableClasses = new ArrayList<>();
/**
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
* SourceFile stellt dabei den Wurzelknoten des Syntaxbaumes dar.
*/
public SourceFile(String pkgName, List<ClassOrInterface> classDefinitions, Set<JavaClassName> imports) {
super(new NullToken());
//if (classDefinitions.size() > 0) { // Enthält die Liste Klassen?
this.KlassenVektor = classDefinitions; // Klassen werden übernommen
//} else {
// this.KlassenVektor = null; // es handelt sich um ein "Java Module"
//}
this.pkgName = pkgName;
this.imports = imports;
}
public SourceFile(SourceFile sf) {
super(new NullToken());
this.KlassenVektor = new ArrayList<>(sf.KlassenVektor);
this.imports = new HashSet<>(sf.imports);
}
public void setPackageName(String packageName) {
this.pkgName = packageName;
}
public void setGenerated() {
this.isGenerated = true;
}
public boolean isGenerated() {
return this.isGenerated;
}
public String getPkgName() {
return this.pkgName;
}
// Get imports (to test implementation)
public Set<JavaClassName> getImports() {
return this.imports;
}
public List<ClassOrInterface> getClasses() {
return KlassenVektor;
}
public List<Method> getAllMethods() {
List<Method> ret = new ArrayList<>();
getClasses().forEach(cl -> ret.addAll(cl.getMethods()));
return ret;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,88 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbw.compiler.syntaxtree.statement.*;
public interface StatementVisitor {
void visit(ArgumentList argumentList);
void visit(LambdaExpression lambdaExpression);
void visit(Assign assign);
void visit(BinaryExpr binary);
void visit(BoolExpression logical);
void visit(Block block);
void visit(CastExpr castExpr);
void visit(EmptyStmt emptyStmt);
void visit(FieldVar fieldVar);
void visit(ForStmt forStmt);
void visit(ForEachStmt forEachStmt);
void visit(IfStmt ifStmt);
void visit(InstanceOf instanceOf);
void visit(LocalVar localVar);
void visit(LocalVarDecl localVarDecl);
void visit(MethodCall methodCall);
void visit(NewClass methodCall);
void visit(NewArray newArray);
void visit(Return aReturn);
void visit(ReturnVoid aReturn);
void visit(Switch switchStmt);
void visit(SwitchBlock switchBlock);
void visit(SwitchLabel switchLabel);
void visit(Break aBreak);
void visit(Continue aContinue);
void visit(Yield aYield);
void visit(StaticClassName staticClassName);
void visit(Super aSuper);
void visit(This aThis);
void visit(WhileStmt whileStmt);
void visit(DoStmt whileStmt);
void visit(AssignToField assignLeftSide);
void visit(AssignToLocal assignLeftSide);
void visit(SuperCall superCall);
void visit(ThisCall thisCall);
void visit(ExpressionReceiver expressionReceiver);
void visit(UnaryExpr unaryExpr);
void visit(Literal literal);
void visit(Throw aThrow);
void visit(Ternary ternary);
}

View File

@@ -1,24 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import java.util.ArrayList;
import java.util.List;
import de.dhbw.compiler.core.IItemWithOffset;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceInformation;
import de.dhbw.compiler.core.IItemWithOffset;
import org.antlr.v4.runtime.Token;
//import org.antlr.v4.runtime.misc.Pair;
public abstract class SyntaxTreeNode implements IItemWithOffset {
private final Token offset;
public SyntaxTreeNode(Token offset){
this.offset = offset;
}
public Token getOffset(){
return offset;
}
public abstract void accept(ASTVisitor visitor);
}

View File

@@ -1,12 +0,0 @@
package de.dhbw.compiler.syntaxtree;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.Collection;
public interface TypeScope {
Iterable<? extends GenericTypeVar> getGenerics();
RefTypeOrTPHOrWildcardOrGeneric getReturnType();
}

View File

@@ -1,487 +0,0 @@
package de.dhbw.compiler.syntaxtree.factory;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.*;
import de.dhbw.compiler.bytecode.JavaTXSignatureAttribute;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.syntaxtree.*;
import de.dhbw.compiler.syntaxtree.Field;
import de.dhbw.compiler.syntaxtree.Method;
import de.dhbw.compiler.syntaxtree.type.*;
import de.dhbw.compiler.syntaxtree.type.Void;
import de.dhbw.compiler.syntaxtree.statement.Block;
import de.dhbw.compiler.syntaxtree.statement.Statement;
import de.dhbw.compiler.syntaxtree.type.WildcardType;
import de.dhbw.compiler.util.Pair;
import org.antlr.v4.runtime.Token;
import org.apache.commons.io.IOUtils;
import org.objectweb.asm.*;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
/**
* Anmerkung: Die ASTFactory Methoden, welche ASTBäume aus java.lang.Class Objekten generieren, können davon ausgehen, dass alle Imports und Typnamen korrekt sind und müssen diese nicht überprüfen.
*/
public class ASTFactory {
private static final HashMap<Class, ClassOrInterface> cache = new HashMap<>();
public static ClassOrInterface createClass(Class jreClass) {
if (cache.containsKey(jreClass))
return cache.get(jreClass);
// TODO Inner classes
var methodSignatures = new HashMap<Pair<String, String>, String>();
String classSignature = null;
// Load class with asm to figure out if there's a JavaTX signature
try {
var path = jreClass.getName().replace('.', '/') + ".class";
var classLoader = jreClass.getClassLoader();
if (classLoader != null && new File(path).exists()) {
var bytes = IOUtils.toByteArray(Objects.requireNonNull(classLoader.getResourceAsStream(path)));
var classReader = new ClassReader(bytes);
var classVisitor = new ClassVisitor(Opcodes.ASM7) {
String classSignature;
@Override
public void visitAttribute(Attribute attribute) {
if (attribute.type.equals("JavaTXSignature")) {
classSignature = ((JavaTXSignatureAttribute) attribute).signature;
}
super.visitAttribute(attribute);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
classSignature = signature;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
methodSignatures.put(new Pair<>(name, descriptor), signature);
return new MethodVisitor(Opcodes.ASM7) {
@Override
public void visitAttribute(Attribute attribute) {
if (attribute.type.equals("JavaTXSignature")) {
methodSignatures.put(new Pair<>(name, descriptor), ((JavaTXSignatureAttribute) attribute).signature);
}
super.visitAttribute(attribute);
}
};
}
};
classReader.accept(classVisitor, new Attribute[] { new JavaTXSignatureAttribute() }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
classSignature = classVisitor.classSignature;
}
} catch (IOException e) {
// Skip
}
JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = new ArrayList<>();
List<de.dhbw.compiler.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
for (Constructor constructor : jreClass.getConstructors()) {
var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor)));
createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c));
}
Set<java.lang.reflect.Method> allMethods = new HashSet<>(Arrays.asList(jreClass.getMethods()));
if (jreClass.isInterface())
allMethods.addAll(Arrays.asList(Object.class.getMethods())); // For some reason interfaces don't inherit from Object
Set<java.lang.reflect.Method> allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods()));
Set<java.lang.reflect.Method> allInheritedMethods = new HashSet<>(allMethods);
allInheritedMethods.removeAll(allDeclaredMethods);
for (java.lang.reflect.Method method : allDeclaredMethods) {
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
if (jreClass.getSuperclass()==null) {
methoden.add(createMethod(method, signature, jreClass, false, false));
}
else {
Boolean isImplemented = false;
isImplemented = Arrays.stream(jreClass.getInterfaces()).
reduce(false,
(x,y) -> {
try {
y.getDeclaredMethod(method.getName(), method.getParameterTypes());
return true;
}
catch (NoSuchMethodException e) {
return false;
}},
(x,y) -> (x || y)
);
if (isImplemented) {
methoden.add(createMethod(method, signature, jreClass, false, true));
}
else {
if (Modifier.isAbstract(jreClass.getSuperclass().getModifiers())) {
try {
jreClass.getSuperclass().getDeclaredMethod(method.getName(), method.getParameterTypes());
methoden.add(createMethod(method, signature, jreClass, false, true));
}
catch (NoSuchMethodException e) {
methoden.add(createMethod(method, signature, jreClass, false, false));
}
}
else {
methoden.add(createMethod(method, signature, jreClass, false, false));
}
}
}}
for (java.lang.reflect.Method method : allInheritedMethods) {
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, true, false));
}
List<Field> felder = new ArrayList<>();
for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) {
felder.add(createField(field, name));
}
int modifier = jreClass.getModifiers();
boolean isInterface = jreClass.isInterface();
List<Annotation> aLA;
boolean isFunctionalInterface =
(aLA = Arrays.asList(jreClass.getAnnotations())).size() > 0 &&
aLA.get(0) instanceof FunctionalInterface ?
true :
false;
// see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class
ParameterizedType parameterSuperClass = null;
Type tempSuperClass = jreClass.getGenericSuperclass();
if (tempSuperClass != null && tempSuperClass instanceof ParameterizedType)
parameterSuperClass = (ParameterizedType) tempSuperClass;
Class superjreClass = jreClass.getSuperclass();
RefType superClass;
if (parameterSuperClass != null) {
superClass = (RefType) createType(parameterSuperClass);
} else if (superjreClass != null) {
superClass = (RefType) createType(superjreClass);
} else {// Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!)
superClass = (RefType) createType(Object.class);
}
List<RefType> implementedInterfaces = new ArrayList<>();
for (Type jreInterface : jreClass.getGenericInterfaces()) {
implementedInterfaces.add((RefType) createType(jreInterface));
}
List<RefType> permittedSubtypes = new ArrayList<>();
if (jreClass.isSealed()) {
for (Class subclass : jreClass.getPermittedSubclasses()) {
permittedSubtypes.add((RefType) createType(subclass));
}
}
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null, classSignature);
Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset, null);
cache.put(jreClass, cinf);
return cinf;
}
private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) {
return new Field(field.getName(), createType(field.getGenericType()), field.getModifiers(), new NullToken());
}
// private static RefType createType(Class classType) {
// return createClass(classType).getType();
// }
private static Optional<de.dhbw.compiler.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) {
String name = constructor.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass);
Parameter[] jreParams = constructor.getParameters();
Type[] jreGenericParams = constructor.getGenericParameterTypes();
List<Pattern> params = new ArrayList<>();
int i = 0;
for (Type jreParam : jreGenericParams) {
if (jreParam == null)
continue;
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
i++;
}
ParameterList parameterList = new ParameterList(params, new NullToken());
Block block = new Block(new ArrayList<Statement>(), new NullToken());
GenericDeclarationList gtvDeclarations = createGenerics(constructor.getTypeParameters(), inClass, constructor.getName(), signature);
Token offset = new NullToken();
int modifier = constructor.getModifiers();
if (inClass.equals(Object.class)) {
return Optional.empty();
}
return Optional.of(new de.dhbw.compiler.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */));
}
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, Class inClass, Boolean isInherited, Boolean isImplemented) {
String name = jreMethod.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType;
if (jreMethod.getGenericReturnType() != null) {
jreRetType = jreMethod.getGenericReturnType();
} else {
jreRetType = jreMethod.getReturnType();
}
returnType = createType(jreRetType);
Parameter[] jreParams = jreMethod.getParameters();
Type[] jreGenericParams = jreMethod.getGenericParameterTypes();
List<Pattern> params = new ArrayList<>();
int i = 0;
for (Type jreParam : jreGenericParams) {
if (jreParam == null)
continue;
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
i++;
}
ParameterList parameterList = new ParameterList(params, new NullToken());
Block block = new Block(new ArrayList<Statement>(), new NullToken());
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
Token offset = new NullToken();
return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited, isImplemented);
}
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
if (signature == null) {
List<de.dhbw.compiler.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
for (TypeVariable jreTV : typeParameters) {
de.dhbw.compiler.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
gtvs.add(gtv);
}
return new GenericDeclarationList(gtvs, new NullToken());
} else {
var res = createGenerics(signature);
return res;
}
}
public static GenericDeclarationList createGenerics(String signature) {
if (signature == null)
return new GenericDeclarationList(new ArrayList<>(), new NullToken());
var gtvs = new ArrayList<GenericTypeVar>();
var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = new ArrayList<>();
final Stack<RefTypeOrTPHOrWildcardOrGeneric> bound = new Stack<>();
final Stack<RefType> classTypes = new Stack<>();
// All hail the mighty visitor pattern
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {
};
char wildcard = '=';
@Override
public SignatureVisitor visitSuperclass() {
return doNothing;
}
@Override
public SignatureVisitor visitParameterType() {
return doNothing;
}
@Override
public SignatureVisitor visitReturnType() {
return doNothing;
}
@Override
public SignatureVisitor visitExceptionType() {
return doNothing;
}
@Override
public void visitFormalTypeParameter(String name) {
bounds = new ArrayList<>();
gtvs.add(new GenericTypeVar(name, bounds, new NullToken(), new NullToken()));
}
@Override
public void visitTypeVariable(String name) {
var refType = new GenericRefType(name, new NullToken());
if (classTypes.isEmpty()) {
((List<RefTypeOrTPHOrWildcardOrGeneric>) gtvs.get(gtvs.size() - 1).getBounds()).add(refType);
} else {
pushType(refType);
}
}
@Override
public void visitClassType(String name) {
var refType = new RefType(new JavaClassName(name.replaceAll("/", ".")), new ArrayList<>(), new NullToken());
classTypes.push(refType);
pushType(refType);
}
void pushType(RefTypeOrTPHOrWildcardOrGeneric refType) {
if (wildcard == SignatureVisitor.SUPER) {
bound.push(new SuperWildcardType(refType, new NullToken()));
} else if (wildcard == SignatureVisitor.EXTENDS) {
bound.push(new ExtendsWildcardType(refType, new NullToken()));
} else {
bound.push(refType);
}
}
@Override
public SignatureVisitor visitTypeArgument(char wildcard) {
this.wildcard = wildcard;
return this;
}
boolean equals(RefTypeOrTPHOrWildcardOrGeneric a, RefTypeOrTPHOrWildcardOrGeneric b) {
if (b instanceof SuperWildcardType wc)
return equals(a, wc.getInnerType());
else if (b instanceof ExtendsWildcardType wc)
return equals(a, wc.getInnerType());
return a == b;
}
@Override
public void visitEnd() {
wildcard = '=';
var classType = (RefType) classTypes.pop();
if (!classTypes.isEmpty()) {
var next = classTypes.peek();
var par = bound.pop();
var toAdd = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
while (!equals(next, par)) {
toAdd.add(par);
par = bound.pop();
}
var element = par;
if (par instanceof WildcardType wc) {
element = wc.getInnerType();
}
Collections.reverse(toAdd);
((RefType) element).getParaList().addAll(toAdd);
bound.push(par);
} else {
if (bound.peek() != classType) {
classType.getParaList().add(bound.pop());
bounds.add(classType);
} else {
bounds.add(bound.pop());
}
}
}
};
var sr = new SignatureReader(signature);
sr.accept(signatureVisitor);
return new GenericDeclarationList(gtvs, new NullToken());
}
private static RefTypeOrTPHOrWildcardOrGeneric createType(Type type) {
if (type == null || type.getTypeName().equals("void")) {
return new Void(new NullToken());
} else if (type.getTypeName().equals("int")) {
return new RefType(new JavaClassName("java.lang.Integer"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("byte")) {
return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("boolean")) {
return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("char")) {
return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("short")) {
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("float")) {
return new RefType(new JavaClassName("java.lang.Float"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("double")) {
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("long")) {
return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken(), true);
} else {
if (type instanceof TypeVariable) {
// GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()"
return new GenericRefType(type.getTypeName(), new NullToken());
}
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
if (type instanceof ParameterizedType) {
for (Type t : ((ParameterizedType) type).getActualTypeArguments()) {
params.add(createType(t));
}
}
String name = type.getTypeName();
if (name.contains("<")) { // Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type<A>
// Diese entfernen:
name = name.split("<")[0];
}
if (type instanceof java.lang.reflect.WildcardType) {
java.lang.reflect.WildcardType wildcardType = (java.lang.reflect.WildcardType) type;
if (wildcardType.getLowerBounds().length > 0) {
return new SuperWildcardType(createType(wildcardType.getLowerBounds()[0]), new NullToken());
} else if (wildcardType.getUpperBounds().length > 0) {
return new ExtendsWildcardType(createType(wildcardType.getUpperBounds()[0]), new NullToken());
} else {// Es handelt sich um den '?'-Typ:
return new ExtendsWildcardType(createObjectType(), new NullToken());
}
} else {
RefType ret = new RefType(new JavaClassName(name), params, new NullToken());
return ret;
}
}
}
public static de.dhbw.compiler.syntaxtree.GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod) {
JavaClassName parentClass = new JavaClassName(context.getName());
List<RefTypeOrTPHOrWildcardOrGeneric> genericBounds = new ArrayList<>();
Type[] bounds = jreTypeVar.getBounds();
if (bounds.length > 0) {
for (Type bound : bounds) {
genericBounds.add(createType(bound));
}
}
return new de.dhbw.compiler.syntaxtree.GenericTypeVar(jreTVName, genericBounds, new NullToken(), new NullToken());
}
public static ClassOrInterface createObjectClass() {
return createClass(Object.class);
}
public static RefType createObjectType() {
return new RefType(createClass(Object.class).getClassName(), new NullToken());
}
/*
* public Constructor createEmptyConstructor(Class parent){ Block block = new Block(); block.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); block.statements.add(new SuperCall(block));
*
* return ASTFactory.createConstructor(parent, new ParameterList(), block); }
*
* public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){ block.parserPostProcessing(superClass);
*
* Method method = ASTFactory.createMethod("<init>", paralist, block, superClass); method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
*
* return new Constructor(method, superClass); }
*
* public static Class createClass(String className, RefType type, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent) { // TODO bytecode createClass //String name, RefType superClass, Modifiers modifiers, Menge<String> supertypeGenPara Class generatedClass = new Class(className, type, modifiers, supertypeGenPara); generatedClass.addField(ASTFactory.createEmptyConstructor(generatedClass));
*
* generatedClass.parserPostProcessing(parent);
*
* return generatedClass; }
*
* public static Class createObject(){ return createClass(java.lang.Object.class); }
*
* public static Class createInterface(String className, RefType superClass, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent){ Class generatedClass = new Class(new JavaClassName(className), new ArrayList<Method>(), new ArrayList<Field>(), modifiers, true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1); generatedClass.parserPostProcessing(parent); return generatedClass; }
*
* public static RefType createObjectType(){ return createObjectClass().getType(); }
*/
}

View File

@@ -1,91 +0,0 @@
package de.dhbw.compiler.syntaxtree.factory;
public class NameGenerator {
private static String strNextName = "A";
/**
* Setzt den zu Beginn der Typinferenz auf "A" zurueck.
* Dies ist bei JUnit-Test noetig
* <code>TypePlaceholder</code>. <br>Author: Martin Pluemicke
* @return void
*/
public static void reset() {
strNextName = "A";
}
/**
* Berechnet einen neuen, eindeutigen Namen f�r eine neue
* <code>TypePlaceholder</code>. <br>Author: J�rg B�uerle
* @return Der Name
*/
public static String makeNewName()
{
// otth: Funktion berechnet einen neuen Namen anhand eines alten gespeicherten
String strReturn = strNextName;
// n�chster Name berechnen und in strNextName speichern
inc( strNextName.length() - 1 );
return strReturn;
}
/**
* Hilfsfunktion zur Berechnung eines neuen Namens
* <br>Author: J�rg B�uerle
* @param i
*/
private static void inc(int i)
{
// otth: Hilfsfunktion zur Berechnung eines neuen Namens
// otth: Erh�hung des Buchstabens an der Stelle i im String strNextName
// otth: Nach �berlauf: rekursiver Aufruf
// falls i = -1 --> neuer Buchstabe vorne anf�gen
if ( i == -1 )
{
strNextName = "A" + strNextName;
return;
}
char cBuchstabe = (char)(strNextName.charAt( i ));
cBuchstabe++;
if ( cBuchstabe - 65 > 25 )
{
// aktuelle Stelle: auf A zuruecksetzen
manipulate( i, 'A' );
// vorherige Stelle erh�hen
inc( i - 1 );
}
else
{
// aktueller Buchstabe �ndern
manipulate( i, cBuchstabe );
}
}
/**
* Hilfsfunktion zur Berechnung eines neuen Namens.
* <br>Author: J�rg B�uerle
* @param nStelle
* @param nWert
*/
private static void manipulate( int nStelle, char nWert )
{
// otth: Hilfsfunktion zur Berechnung eines neuen Namens
// otth: Ersetzt im String 'strNextName' an der Position 'nStelle' den Buchstaben durch 'nWert'
String strTemp = "";
for( int i = 0; i < strNextName.length(); i++)
{
if ( i == nStelle )
strTemp = strTemp + nWert;
else
strTemp = strTemp + strNextName.charAt( i );
}
strNextName = strTemp;
}
}

View File

@@ -1,9 +0,0 @@
package de.dhbw.compiler.syntaxtree.factory;
/**
* Generiert Hilfsmethoden für die Unary und Binary Operatoren
* Diese Methoden stellen die möglichen Operationen +,-,++, etc dar
*/
public class PrimitiveMethodsGenerator {
}

View File

@@ -1,297 +0,0 @@
package de.dhbw.compiler.syntaxtree.factory;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import de.dhbw.compiler.core.JavaTXCompiler;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.compiler.parser.NullToken;
import de.dhbw.compiler.parser.SourceLoc;
import de.dhbw.compiler.parser.SyntaxTreeGenerator.FCGenerator;
import de.dhbw.compiler.parser.scope.JavaClassName;
import de.dhbw.compiler.syntaxtree.ClassOrInterface;
import de.dhbw.compiler.syntaxtree.GenericTypeVar;
import de.dhbw.compiler.syntaxtree.type.*;
import de.dhbw.compiler.syntaxtree.type.Void;
import de.dhbw.compiler.syntaxtree.type.WildcardType;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import de.dhbw.compiler.typeinference.constraints.Pair;
import de.dhbw.compiler.typeinference.result.PairNoResult;
import de.dhbw.compiler.typeinference.result.PairTPHEqualTPH;
import de.dhbw.compiler.typeinference.result.PairTPHequalRefTypeOrWildcardType;
import de.dhbw.compiler.typeinference.result.PairTPHsmallerTPH;
import de.dhbw.compiler.typeinference.result.ResultPair;
import de.dhbw.compiler.typeinference.unify.model.*;
import org.antlr.v4.runtime.Token;
public class UnifyTypeFactory {
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>();
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader, JavaTXCompiler compiler) throws ClassNotFoundException {
/*
Die transitive Hülle muss funktionieren.
Man darf schreiben List<A> extends AL<A>
und Vector<B> extends List<B>
hier muss dann aber dennoch die Vererbung V < L < AL
hergestellt werden.
In einem solchen Vererbungsbaum dürfen die TPH auch die gleichen Namen haben.
Generell dürfen sie immer die gleichen Namen haben.
TODO: die transitive Hülle bilden
*/
return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader), logFile, compiler);
}
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.SMALLER, location);
}
public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.SMALLERDOT, location);
}
public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT, location);
}
public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.EQUALSDOT, location);
}
/**
* Convert from
* ASTType -> UnifyType
*/
public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
if (t instanceof GenericRefType){
return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType);
} else if (t instanceof TypePlaceholder){
return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType);
} else if (t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType);
} else if (t instanceof SuperWildcardType) {
return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType);
} else if (t instanceof RefType){
return UnifyTypeFactory.convert(compiler, (RefType)t, innerType);
}
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
}
public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType){
//Check if it is a FunN Type:
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(t.getName().toString());
boolean b = m.matches();
if(b){
Integer N = Integer.valueOf(m.group(1));
if((N + 1) == t.getParaList().size()){
return convertFunN(compiler, t.getParaList(), false);
}
}
UnifyType ret;
List<UnifyType> params = new ArrayList<>();
if (t.getParaList() != null) {
for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) {
params.add(UnifyTypeFactory.convert(compiler, pT, true));
}
}
var clazz = compiler.getClass(t.getName());
if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) {
var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow();
var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true)).toList();
var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList();
return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true), generics);
}
return new ReferenceType(t.getName().toString(),new TypeParams(params));
}
public static UnifyType convertFunN(JavaTXCompiler compiler, List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
UnifyType ret;
List<UnifyType> params = new ArrayList<>();
if(paraList != null && paraList.size() > 0){
for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){
params.add(UnifyTypeFactory.convert(compiler, pT, false));
}
}
ret = FunNType.getFunNType(new TypeParams(params));
return ret;
}
public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType){
if (tph.getName().equals("AFR")) {
System.out.println("XXX"+innerType);
}
PlaceholderType ntph = new PlaceholderType(tph.getName(), tph.getVariance());
ntph.setVariance(tph.getVariance());
ntph.setOrCons(tph.getOrCons());
ntph.setWildcardtable(tph.getWildcardtable());
int in = PLACEHOLDERS.indexOf(ntph);
if (in == -1) {
PLACEHOLDERS.add(ntph);
ntph.setInnerType(innerType);
return ntph;
}
else {
PlaceholderType oldpht = PLACEHOLDERS.get(in);
oldpht.setInnerType(oldpht.isInnerType() || innerType);
return oldpht;
}
}
public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType){
return new ReferenceType(t.getParsedName(), true);
}
public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType){
if(t.isExtends())
return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
else if(t.isSuper())
return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
else throw new NotImplementedException();
}
public static ConstraintSet<UnifyPair> convert(JavaTXCompiler compiler, ConstraintSet<Pair> constraints) {
return constraints.map(c -> UnifyTypeFactory.convert(compiler, c));
}
//NEVER USED
//public static Constraint<UnifyPair> convert(Constraint<Pair> constraint){
// Constraint<UnifyPair> unifyPairConstraint = constraint.stream()
// .map(UnifyTypeFactory::convert)
// .collect(Collectors.toCollection( () -> new Constraint<UnifyPair> (constraint.isInherited(), convert(constraint.getExtendConstraint()))));
// return unifyPairConstraint;
//}
public static UnifyPair convert(JavaTXCompiler compiler, Pair p) {
UnifyPair ret = null;
if(p.GetOperator().equals(PairOperator.SMALLERDOT)) {
ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret;
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLER)){
ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false),
UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
}else throw new NotImplementedException();
UnifyType lhs, rhs;
if (((lhs = ret.getLhsType()) instanceof PlaceholderType)
&& ((PlaceholderType)lhs).isWildcardable()
&& (rhs = ret.getLhsType()) instanceof PlaceholderType) {
if (lhs.getName().equals("AQ")) {
System.out.println("");
}
((PlaceholderType)rhs).enableWildcardtable();
}
if (((rhs = ret.getLhsType()) instanceof PlaceholderType)
&& ((PlaceholderType)rhs).isWildcardable()
&& (lhs = ret.getLhsType()) instanceof PlaceholderType) {
if (rhs.getName().equals("AQ")) {
System.out.println("");
}
((PlaceholderType)lhs).enableWildcardtable();
}
return ret;
}
/**
* Convert from
* UnifyType -> ASTType
*/
public static Set<ResultPair> convert(Set<UnifyPair> unifyPairSet, Map<String,TypePlaceholder> tphs) {
return unifyPairSet.stream().map(
unifyPair -> convert(unifyPair, tphs))
.collect(Collectors.toSet());
}
public static ResultPair convert(UnifyPair mp, Map<String,TypePlaceholder> tphs) {
if (mp == null) { return null;} //kann bei basePairs passieren
RefTypeOrTPHOrWildcardOrGeneric tl = UnifyTypeFactory.convert(mp.getLhsType(), tphs);
RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs);
if(tl instanceof TypePlaceholder){
if(tr instanceof TypePlaceholder) {
if(mp.getPairOp().equals(PairOperator.EQUALSDOT)) {
return new PairTPHEqualTPH((TypePlaceholder)tl, (TypePlaceholder)tr);
//Einfach ignorieren TODO: Das hier muss ausgebessert werden:
//return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType());
}else{
return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr, convert(mp.getBasePair(), tphs));
}
}else if(tr instanceof RefType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr);
}else if(tr instanceof WildcardType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (WildcardType) tr);
}else if(tr instanceof GenericRefType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (GenericRefType) tr);
}else throw new NotImplementedException();
}else return new PairNoResult(tl, tr);//throw new NotImplementedException();
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) {
if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken());
if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken());
RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken());
return ret;
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map<String,TypePlaceholder> tphs) {
RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs), new NullToken());
return ret;
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(SuperType t, Map<String,TypePlaceholder> tphs) {
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getSuperedType(), tphs);
return new SuperWildcardType(innerType, new NullToken());
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(ExtendsType t, Map<String,TypePlaceholder> tphs) {
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getExtendedType(), tphs);
return new ExtendsWildcardType(innerType, new NullToken());
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(PlaceholderType t, Map<String,TypePlaceholder> tphs) {
TypePlaceholder ret = tphs.get(t.getName());
if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt
ret = TypePlaceholder.fresh(new NullToken());
tphs.put(t.getName(), ret);
}
ret.setVariance(t.getVariance());
return ret;
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(UnifyType t, Map<String,TypePlaceholder> tphs) {
if(t instanceof FunNType)return convert((FunNType) t, tphs);
if(t instanceof ReferenceType)return convert((ReferenceType) t, tphs);
if(t instanceof SuperType)return convert((SuperType) t, tphs);
if(t instanceof ExtendsType)return convert((ExtendsType) t, tphs);
if(t instanceof PlaceholderType)return convert((PlaceholderType) t, tphs);
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
}
private static List<RefTypeOrTPHOrWildcardOrGeneric> convert(TypeParams typeParams, Map<String,TypePlaceholder> tphs) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
for(UnifyType uT : typeParams){
RefTypeOrTPHOrWildcardOrGeneric toAdd = convert(uT, tphs);
ret.add(toAdd);
}
return ret;
}
}

View File

@@ -1,33 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.ASTVisitor;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.SyntaxTreeNode;
import org.antlr.v4.runtime.Token;
import java.util.List;
public class ArgumentList extends SyntaxTreeNode
{
public ArgumentList(List<Expression> expr, Token offset) {
super(offset);
this.expr = expr;
}
private List<Expression> expr;
public List<Expression> getArguments(){
return expr;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,28 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import de.dhbw.compiler.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
/*
Aufbau:
rightSide = leftSide
*/
public class Assign extends Statement {
public final Expression rightSide;
public final AssignLeftSide lefSide;
public Assign(AssignLeftSide leftHandSide, Expression value, Token offset) {
super(leftHandSide.getType(), offset);
this.rightSide = value;
this.lefSide = leftHandSide;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,12 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public abstract class AssignLeftSide extends TypableStatement{
public AssignLeftSide(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(type, offset);
}
}

View File

@@ -1,17 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
public class AssignToField extends AssignLeftSide {
public final FieldVar field;
public AssignToField(FieldVar fieldVar) {
super(fieldVar.getType(), fieldVar.getOffset());
field = fieldVar;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,42 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class BinaryExpr extends Expression {
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
public enum Operator {
ADD, // +
SUB, // -
MUL, // *
MOD, // Modulo Operator %
AND, // &
OR, // |
XOR, // ^
DIV, // /
LESSTHAN, // <
BIGGERTHAN, // >
LESSEQUAL, // <=
BIGGEREQUAL, // >=
EQUAL, // ==
NOTEQUAL // !=
}
public final Operator operation;
public final Expression lexpr;
public final Expression rexpr;
public BinaryExpr(Operator operation, RefTypeOrTPHOrWildcardOrGeneric type, Expression lexpr, Expression rexpr, Token offset) {
super(type, offset);
this.operation = operation;
this.lexpr = lexpr;
this.rexpr = rexpr;
}
}

View File

@@ -1,27 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.TypePlaceholder;
public class Block extends Statement {
public Block(List<Statement> statements, Token offset) {
super(TypePlaceholder.fresh(offset), offset);
this.statements = statements;
}
public List<Statement> statements = new ArrayList<>();
public List<Statement> getStatements() {
return statements;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,31 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public class BoolExpression extends Expression {
public enum Operator {
AND, // &&
OR, // ||
}
public final Operator operation;
public final Expression lexpr;
public final Expression rexpr;
public BoolExpression(Operator operation, RefTypeOrTPHOrWildcardOrGeneric type, Expression lexpr, Expression rexpr, Token offset) {
super(type, offset);
this.operation = operation;
this.lexpr = lexpr;
this.rexpr = rexpr;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,19 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import org.antlr.v4.runtime.Token;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public class Break extends Statement {
public Break(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(type, offset);
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,25 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.exceptions.NotImplementedException;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import org.antlr.v4.runtime.Token;
public class CastExpr extends Expression
{
public CastExpr(RefTypeOrTPHOrWildcardOrGeneric castType, Expression expr, Token offset)
{
super(castType, offset);
this.expr = expr;
}
public Expression expr;
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,18 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class Continue extends Statement {
public Continue(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(type, offset);
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,18 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.TypePlaceholder;
import org.antlr.v4.runtime.Token;
public class DoStmt extends WhileStmt
{
public DoStmt(Expression expr, Statement loopBlock, Token offset)
{
super(expr, loopBlock, offset);
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,22 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.type.Void;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceInformation;
import org.antlr.v4.runtime.Token;
public class EmptyStmt extends Statement
{
public EmptyStmt(Token offset)
{
super(new Void(offset),offset);
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -1,16 +0,0 @@
package de.dhbw.compiler.syntaxtree.statement;
import de.dhbw.compiler.syntaxtree.ASTVisitor;
import de.dhbw.compiler.syntaxtree.StatementVisitor;
import de.dhbw.compiler.syntaxtree.SyntaxTreeNode;
import de.dhbw.compiler.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbw.compiler.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbw.compiler.typeinference.constraints.ConstraintSet;
import org.antlr.v4.runtime.Token;
public abstract class Expression extends TypableStatement {
public Expression(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(type, offset);
}
}

Some files were not shown because too many files have changed in this diff Show More