Duplicates Finder (Java)
The Duplicates Finder (Java) Build Runner is intended for catching similar code fragments and providing a report on discovered repetitive blocks of Java code. This runner is based on IntelliJ IDEA capabilities, so an IntelliJ IDEA project file (.ipr) or directory (.idea) is required to configure the runner. Since TeamCity 2017.1, in addition to the bundled version, it is possible to install another version of JetBrains IntelliJ Inspections and Duplicates Engine and/or change the defaults using the Administration | Tools page.
The Duplicates Finder (Java) can also find Java duplicates in projects built by Maven2 or above.
This page contains reference information about the following Duplicates Finder (Java) Build Runner fields:
IntelliJ IDEA Project Settings
Option | Description |
---|---|
Project file type | To be able to run IntelliJ IDEA inspections on your code, TeamCity requires either an IntelliJ IDEA project file\directory, Maven pom.xml or Gradle build.gradle to be specified here. |
Path to the project | Depending on the type of project selected in the Project file type, specify here:
|
Detect global libraries and module-based JDK in the *.iml files | This option is available if you use an IntelliJ IDEA project. In IntelliJ IDEA, the module settings are stored in *.iml files, thus, if this option is checked, all the module files will be automatically scanned for references to the global libraries and module JDKs when saved. This helps ensure that all references will be properly resolved. |
Check/Reparse Project | This option is available if you use an IntelliJ IDEA project. Click this button to reparse your IntelliJ IDEA project and import the build settings right from the project, for example the list of JDKs. |
Working directory | Enter a path to a Build Working Directory if it differs from the Build Checkout Directory. Optional, specify if differs from the checkout directory. |
Unresolved Project Modules and Path Variables
This section is displayed, when an IntelliJ IDEA module file (.iml) referenced from an IPR-file:
cannot be found
allows you to enter the values of path variables used in the IPR-file.
To refresh values in this section click Check/Reparse Project.
Option | Description |
---|---|
<path_variable_name> | This field appears if the project file contains path macros, defined in the Path Variables dialog of IntelliJ IDEA's Settings dialog. In Set value to field, specify a path to the project resources to be used on different build agents. |
Project JDKs
This section provides the list of JDKs detected in the project.
Option | Description |
---|---|
JDK Home | Use this field to specify the JDK home for the project. |
JDK Jar File Patterns | Click this link to open a text area where you can define templates for the jar files of the project JDK. Use Ant rules to define the jar file patterns. The default value is used for Linux and Windows operating systems: jre/lib/*.jar
For Mac OS X, use the following lines: lib/*.jar
../Classes/*.jar
|
IDEA Home | If your project uses the IDEA JDK, specify the location of the IDEA home directory |
IDEA Jar Files Patterns | Click this link to open a text area, where you can define templates for the jar files of the IDEA JDK. |
Duplicate Finder Settings
Option | Description |
---|---|
If this option is checked, the test sources will be included in the duplicates analysis. |
Include / exclude patterns| Optional, specify to restrict the sources scope to run duplicates analysis on. For details, refer to the section below| #IdeaPatterns]|
Option | Description |
---|---|
Use these options to define which elements of the source code should be distinguished when searching for repetitive code fragments. Code fragments can be considered duplicated if they are structurally similar, but contain different variables, fields, methods, types or literals. Refer to the samples below: | |
If this option is checked, the similar contents with different variable names will be recognized as different. If this option is not checked, such contents will be recognized as duplicated: public static void main(String[] args) {
int i = 0;
int j = 0;
if (i == j) {
System.out.println("sum of " + i + " and " + j + " = " + i + j);
}
long k = 0;
long n = 0;
if (k == n) {
System.out.println("sum of " + k + " and " + n + " = " + k + n);
}
}
| |
If this option is checked, the similar contents with different field names will be recognized as different. If this option is not checked, such contents will be recognized as duplicated: myTable.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
/*.....**/
});
myTree.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
/*.....**/
});
| |
If this option is checked, the methods of similar structure will be recognized as different. If this option is not checked, such methods will be recognized as duplicated. In this case, they can be extracted and reused. Initial version: public void buildCanceled(Build build, SessionData data) {
/* ... **/
for (IListener listener : getListeners()) {
listener.buildCanceled(build, data);
}
}
public void buildFinished(Build build, SessionData data) {
/* ... **/
for (IListener listener : getListeners()) {
listener.buildFinished(build, data);
}
}
After analysiing code for duplicates without distinguishing methods, the duplicated fragments can be extracted: public void buildCanceled(final Build build, final SessionData data) {
enumerateListeners(new Processor() {
public void process(final IListener listener) {
listener.buildCanceled(build, data);
}
});
}
public void buildFinished(final Build build, final SessionData data) {
enumerateListeners(new Processor() {
public void process(final IListener listener) {
listener.buildFinished(build, data);
}
});
}
private void enumerateListeners(Processor processor) {/* ... **/
for (IListener listener : getListeners()) {
processor.process(listener);
}
}
private interface Processor {
void process(IListener listener);
}
| |
If this option is checked, the similar code fragments with different type names will be recognized as different. If this option is not checked, such code fragments will be recognized as duplicates. new MyIDE().updateStatus()
new TheirIDE().updateStatus()
| |
If this option is checked, similar line of code with different litarels will be considered different If this option is not checked, such lines will be recognized as duplicates. myWatchedLabel.setToolTipText("Not Logged In");
myWatchedLabel.setToolTipText("Logging In...");
| |
Complexity of the source code is defined by the amount of statements, expressions, declarations and method calls. Complexity of each of them is defined by its cost. Summarized costs of all these elements of the source code fragment yields the total complexity. Use this field to specify the lowest level of complexity of the source code to be taken into consideration when detecting duplicates. For meaningful results start with value 10. | |
Use this field to specify the lowest level of complexity of subexpressions to be taken into consideration when detecting duplicates. | |
If this option is checked, the duplicated subexpressions can be extracted. |