Skip to content

Commit

Permalink
Merge branch 'FeKozma:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Livila authored Mar 6, 2024
2 parents ae6740a + 840b77d commit f4fe586
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 152 deletions.
42 changes: 16 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Code Check #

Do you have a problem with duplicated functions in your java project? Here is the solution on how to find all the duplicate functions, specify the location of your repository in the local-config.properties file (just make a copy of config.properties) and run the code! Then you will get a file in "results" with all the places where functions match.
Expand Down Expand Up @@ -66,32 +67,21 @@ The results will be shown in the `/results/` folder. By default, the result nami
## Configuration file ##
You can edit some configuration in `config.properties`.

<details>
<summary>
Default configuration (click to expand)
</summary>

###### *config.properties*
```shell
LOGGING_LEVEL=INFO
# This is related to TEMP_FILE below.
TEMP_FILE_ENABLED=false
# If enabled, this file will be deleted and replaced every run instead of using the results files.
TEMP_FILE=debugFile.txt
# Directory of where the result files are saved. They range from 0 to 99.
PATH_TO_RESULTS=results
# Set this property to a path that should be excluded. It's regex based, so writing [file1, file2] would exclude any file containing file1 and file2.
EXCLUDED_PATHS=[]
# Prefix for the result files.
RESULT_NAME_PREFIX=result_{nr}
# The LLM located in project root.
LLM_FILE=models/ggml-model-gpt4all-falcon-q4_0.bin
# Run with LLM - needs a model defined and will take more computing power and time to run.
RUN_WITH_LLM=false
# Directory path to where the code is to be scanned.
PATH_TO_CODE=src/test/resources/
```
</details>
### Properties

| Property | Default values if not set (if not required) | Type | Description |
|----------------------|---------------------------------------------|--------------|--------------------------------------------------------------|
| LOGGING_LEVEL | INFO | String | Which level to show the logging in. |
| PATH_TO_CODE | src/test/resources/ | String | Required attribute. Where the code is located. |
| PATH_TO_RESULTS | results | String | Results directory. |
| RESULT_NAME_PREFIX | result_{nr} | String | Result name. {nr} will be replaced by an incremental number. |
| RESULTS_FILE_LIMIT | 100 | Integer | Since it's creating a new file each run, there is a limit. |
| EXCLUDED_PATHS | [] | List<String> | Separated by commas. Files/Paths to exclude during a run. |
| RUN_WITH_LLM | false | String | Whether to use LLM during the run or not. |
| LLM_FILE | models/ggml-model-gpt4all-falcon-q4_0.bin | String | If running with LLM, this has to be set linking to a model. |
| LLM_THREADS | 4 | Integer | How many threads the LLM will be using. |
| TEMP_FILE_ENABLED | false | Boolean | Whether to use a temporary file. |
| TEMP_FILE | debugFile.txt | String | Where the temporary file is located. |

#### LOGGING_LEVEL
The different options are the following:
Expand Down
29 changes: 17 additions & 12 deletions config.properties
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
LOGGING_LEVEL=DEBUG
# This is related to TEMP_FILE below.
TEMP_FILE_ENABLED=false
# If enabled, this file will be deleted and replaced every run instead of using the results files.
TEMP_FILE=debugFile.txt
# Directory of where the result files are saved. They range from 0 to 99.
# Valid values in order: OFF, ERROR, WARNING, INFO, DEBUG, TRACE.
LOGGING_LEVEL=INFO
# Directory path to where the code will be scanned.
PATH_TO_CODE=src/test/resources/
# Directory of where the result files are saved. By default, it ranges from 0 to 99, and can be changed in `RESULTS_FILE_LIMIT`.
PATH_TO_RESULTS=results
# Set this property to a path that should be excluded. It's regex based, so writing [file1, file2] would exclude any file containing file1 and file2.
EXCLUDED_PATHS=[]
# Prefix for the result files.
RESULT_NAME_PREFIX=result_{nr}
# The LLM located in project root.
LLM_FILE=models/ggml-model-gpt4all-falcon-q4_0.bin
# Max amount of results files to create before the limit is reached. Starting from 0. The default value is 100.
RESULTS_FILE_LIMIT=100
# Set this property to a path that should be excluded. It's regex based, so writing [file1, file2] would exclude any file containing file1 and file2.
EXCLUDED_PATHS=[]
# Run with LLM - needs a model defined and will take more computing power and time to run.
RUN_WITH_LLM=false
# Directory path to where the code is to be scanned.
PATH_TO_CODE=src/test/resources/
# The LLM located in project root.
LLM_FILE=models/ggml-model-gpt4all-falcon-q4_0.bin
# How many threads the LLM will be using when it's running.
LLM_THREADS=4
# This is related to the `TEMP_FILE` option. If the temp file option should be enabled or not.
TEMP_FILE_ENABLED=false
# If enabled, this file will be deleted and replaced every run instead of using the result files option.
TEMP_FILE=debugFile.txt
8 changes: 5 additions & 3 deletions src/main/java/CodeCheck/CheckDirectory.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.function.Predicate;
Expand All @@ -16,6 +17,7 @@ public class CheckDirectory {
private final List<Pattern> EXCLUDED_PATHS = ConfigInterface
.conf
.getList("EXCLUDED_PATHS")
.orElse(Collections.emptyList())
.stream()
.filter(Predicate.not(String::isEmpty))
.map(path -> "((?i)" + path.trim() + "(?-i))")
Expand All @@ -26,7 +28,7 @@ public void startModel() {
llm.initModel();
}

public void stopModel() throws Exception {
public void stopModel() {
llm.cleanModel();
}

Expand Down Expand Up @@ -81,8 +83,8 @@ public ManyFunctions checkFile(File file) {
manyFunctions.commitFile(file.getName());
manyFunctions.commitLine(lineNumber);

Log.trace("Full path: " + file.getAbsolutePath());
Log.debug("Function: " +
Log.debug("Accessing file at the path: " + file.getAbsolutePath());
Log.trace("Function: " +
manyFunctions.commit.name + " in " +
manyFunctions.commit.file + ":" +
manyFunctions.commit.line + " with " +
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/CodeCheck/CodeCheck.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import java.util.List;

public interface CodeCheck {

static void execute() throws Exception {
ConfigInterface.conf.loadConfig();
String PATH_TO_CODE = Util.checkIfHomePath(ConfigInterface.conf.getString("PATH_TO_CODE"));

String PATH_TO_CODE = Util.checkIfHomePath(ConfigInterface.conf.getProperty("PATH_TO_CODE"));
File baseCodeDir = new File(PATH_TO_CODE);

CheckDirectory checkDirectory = new CheckDirectory();
Expand Down
78 changes: 57 additions & 21 deletions src/main/java/CodeCheck/ConfigInterface.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package CodeCheck;

import java.io.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.*;

public interface ConfigInterface {
Config conf = new Config();
Expand Down Expand Up @@ -54,36 +51,75 @@ public void loadConfig() throws IOException {
}
}

public String getString(String key) {
if (appProps == null) return null;
return appProps.get(key).toString();
public String getProperty(String key) {
if (appProps == null) {
Log.warning("'%s' not initialized. The key '%s' was not loaded".formatted(appProps.getClass().getSimpleName(), key));
throw new RuntimeException("'appProps' is null - cannot continue. Configuration not initialized.");
}

try {
return appProps.get(key).toString().strip();
} catch (NullPointerException e) {
throw new NullPointerException(e.getMessage());
}
}

public Boolean getBoolean(String key) {
return appProps.get(key).toString().equalsIgnoreCase("true");
public Optional<String> getString(String key) {
try {
return Optional.of(getProperty(key));
} catch (NullPointerException e) {
return Optional.empty();
}
}

public List<String> getList(String key) {
String value = getString(key);
public Optional<Boolean> getBoolean(String key) {
try {
return Optional.of(getProperty(key).equalsIgnoreCase("true"));
} catch (NullPointerException e) {
return Optional.empty();
}
}

if (value == null)
return Collections.emptyList();
public Optional<Integer> getInteger(String key) {
try {
return Optional.of(Integer.parseInt(getProperty(key)));
} catch (NumberFormatException | NullPointerException e) {
return Optional.empty();
}
}

return Arrays
.stream(value.substring(1, value.length() - 1).split(","))
.map(String::strip)
.toList();
public Optional<List<String>> getList(String key) {
try {
String value = getProperty(key);

if (value == null)
return Optional.of(Collections.emptyList());

return Optional.of(
Arrays
.stream(value.substring(1, value.length() - 1).split(","))
.map(String::strip)
.toList());
} catch (NullPointerException e) {
return Optional.empty();
}
}

public LoggingLevel getLogLvl() {
String loggingLevel = getString("LOGGING_LEVEL");
if (loggingLevel == null) loggingLevel = "DEBUG";
return LoggingLevel.valueOf(loggingLevel);
String loggingLevel = getString("LOGGING_LEVEL")
.orElse("INFO");

try {
return LoggingLevel.valueOf(loggingLevel.toUpperCase());
} catch (IllegalArgumentException e) {
Log.error(getLogLvl().name() + "::LoggingLevel got an error. %s.".formatted(e.getMessage()));
return LoggingLevel.INFO;
}
}

private int countLines(File file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
int lines = 0;
BufferedReader reader = new BufferedReader(new FileReader(file));
while (reader.readLine() != null) lines++;
reader.close();
return lines;
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/CodeCheck/LLM.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public void initModel() {
startTime = System.currentTimeMillis();

runIfConfig(() -> {
Path modelPath = Path.of(Util.checkIfHomePath(
ConfigInterface.conf.getString("LLM_FILE")));
Path modelPath = ConfigInterface.conf.getBoolean("RUN_WITH_LLM")
.orElse(false) ? Path.of(Util.checkIfHomePath(ConfigInterface.conf.getProperty("LLM_FILE"))) : null;

if (Files.isDirectory(modelPath)) {
Log.error("LLM_FILE not configured correctly - it is a directory, but was expecting a model file. Please change it into a correct model filepath.");
Expand All @@ -33,7 +33,8 @@ public void initModel() {
}

model = new LLModel(modelPath);
model.setThreadCount(6);
model.setThreadCount(ConfigInterface.conf.getInteger("LLM_THREADS")
.orElse(4));

Log.debug("Thread Count: " + model.threadCount());

Expand All @@ -51,26 +52,24 @@ public void cleanModel() {
try {
model.close();
} catch (Exception e) {
String errorMessage = "LLM is not closing...";
Log.error(errorMessage);
throw new RuntimeException(errorMessage, e);
throw new RuntimeException("LLM is not closing...", e);
}
return true;
});

int[] formattedTime = Util.getFormattedDurationTime(startTime);
Log.log(String.format("LLM run completed in %02d hours, %02d minutes, %02d seconds and %02d milliseconds.",
int[] formattedTime = Util.getPreparedDurationTime(startTime);
Log.log(String.format("Run completed in %02d hours, %02d minutes, %02d seconds and %02d milliseconds.",
formattedTime[0], formattedTime[1], formattedTime[2], formattedTime[3]));
}

public String getAnswer(String question) {

Log.debug("Question: " + question);
Log.trace("Question: " + question);

return runIfConfig(() -> {
String answer = model.chatCompletion(createMessage(question), config).choices.toString();

Log.debug("Answer: " + answer);
Log.trace("Answer: " + answer);

return answer;
}).orElse("LLM has not been configured.");
Expand All @@ -81,7 +80,8 @@ private List<Map<String, String>> createMessage(String content) {
}

private <T> Optional<T> runIfConfig(Supplier<T> supplier) {
if (ConfigInterface.conf.getBoolean("RUN_WITH_LLM")) {
if (ConfigInterface.conf.getBoolean("RUN_WITH_LLM")
.orElse(false)) {
return Optional.of(supplier.get());
}
return Optional.empty();
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/CodeCheck/Main.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package CodeCheck;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Main {

public static void main(String[] args) throws Exception {
Log.log("Starting up...");
long startTime = System.currentTimeMillis();
Log.log("Starting up at: %s.".formatted(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))));
Log.log("Running on %s.".formatted(System.getProperty("os.name")));

CodeCheck.execute();

Log.log("Shutting down...");
Log.log("Shutting down at: %s.".formatted(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))));
Log.log("Total duration: %s".formatted(Util.getFormattedDurationTime(startTime)));
}
}
Loading

0 comments on commit f4fe586

Please sign in to comment.