Skip to content

Commit

Permalink
Merge pull request #66 from zbynek/optimize-ast-lookup
Browse files Browse the repository at this point in the history
Optimize tree lookup for custom AST files
  • Loading branch information
zbynek authored Jul 18, 2023
2 parents 1a121ef + 76842c7 commit 7a39972
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,34 @@
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.gradle.api.file.FileTree;
import org.gradle.api.logging.Logger;

public class CompiledJavaccFile {
private static final Pattern PACKAGE_DECLARATION_PATTERN = Pattern.compile("package\\s+([^\\s.;]+(\\.[^\\s.;]+)*)\\s*;");

private File compiledJavaccFile;
private File outputDirectory;
private FileTree customAstClassesDirectory;
private File targetDirectory;
private Logger logger;

CompiledJavaccFile(File file, File outputDirectory, FileTree customAstClassesDirectory, File targetDirectory, Logger logger) {
public CompiledJavaccFile(File file, File outputDirectory, File targetDirectory, Logger logger) {
this.compiledJavaccFile = file;
this.outputDirectory = outputDirectory;
this.customAstClassesDirectory = customAstClassesDirectory;
this.targetDirectory = targetDirectory;
this.logger = logger;
}

public boolean customAstClassExists() {
return customAstClassExists(customAstClassesDirectory);
}

public boolean customAstClassExists(FileTree fileTree) {
File customAstClassInputFile = getCustomAstClassInputFile(fileTree);

return (customAstClassInputFile != null) && customAstClassInputFile.exists();
}

private File getCustomAstClassInputFile(FileTree fileTree) {
public File getCustomAstClassInputFile(Collection<File> sourceFiles) {
File customAstClassInputFile;
String compiledJavaccFilePackage = getPackageName(compiledJavaccFile);

if (fileTree != null) {
Collection<File> sourceFiles = fileTree.getFiles();
return scanSourceFiles(compiledJavaccFilePackage, sourceFiles);
if (sourceFiles != null) {
customAstClassInputFile = scanSourceFiles(compiledJavaccFilePackage, sourceFiles);
} else {
return null;
customAstClassInputFile = null;
}

return customAstClassInputFile != null && customAstClassInputFile.exists() ? customAstClassInputFile : null;
}

private File scanSourceFiles(String compiledJavaccFilePackage, Collection<File> sourceFiles) {
Expand Down Expand Up @@ -105,29 +94,47 @@ public void copyCompiledFileToTargetDirectory() {
}
}

public void copyCustomAstClassToTargetDirectory(FileTree sourceTree) {
public void copyCustomAstClassToTargetDirectory(File customAstClassInputFile) {
logger.info("Not copying compiled file {} from {} to {} because it is overridden by the custom AST class {}", compiledJavaccFile, outputDirectory, targetDirectory,
getCustomAstClassInputFile(sourceTree));
customAstClassInputFile);

String packagePath = getPackageName(compiledJavaccFile).replaceAll("\\.", Matcher.quoteReplacement(File.separator));
File destination = new File(targetDirectory.getAbsolutePath() + File.separator + packagePath, compiledJavaccFile.getName());
logger.info("Copying custom AST class [{}] to [{}]", getCustomAstClassInputFile(sourceTree), destination);
logger.info("Copying custom AST class [{}] to [{}]", customAstClassInputFile, destination);

try {
FileUtils.copyFile(getCustomAstClassInputFile(sourceTree), destination);
FileUtils.copyFile(customAstClassInputFile, destination);
} catch (IOException e) {
String errorMessage = String.format("Could not copy %s to %s", getCustomAstClassInputFile(sourceTree), targetDirectory);
String errorMessage = String.format("Could not copy %s to %s", customAstClassInputFile, targetDirectory);
throw new CompiledJavaccFileOperationException(errorMessage, e);
}
}

public void ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTree(FileTree javaSourceTree) {
public void ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTree(File customAst) {
logger.info("Ignoring compiled file {} because it is overridden by the custom AST class in Java source tree {}", compiledJavaccFile,
getCustomAstClassInputFile(javaSourceTree));
customAst);
}

@Override
public String toString() {
return compiledJavaccFile.getAbsolutePath();
}

public boolean handleCustomAstInJavacc(Collection<File> javaSourceFiles) {
File customAst = getCustomAstClassInputFile(javaSourceFiles);
if (customAst != null) {
copyCustomAstClassToTargetDirectory(customAst);
return true;
}
return false;
}

public boolean handleCustomAstInJava(Collection<File> javaSourceFiles) {
File customAst = getCustomAstClassInputFile(javaSourceFiles);
if (customAst != null) {
ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTree(customAst);
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.gradle.api.file.FileTree;
import org.gradle.api.logging.Logger;

public class CompiledJavaccFilesDirectory {
private File outputDirectory;
private FileTree customAstClassesDirectory;
private File targetDirectory;
private Logger logger;

CompiledJavaccFilesDirectory(File outputDirectory, FileTree customAstClassesDirectory, File targetDirectory, Logger logger) {
CompiledJavaccFilesDirectory(File outputDirectory, File targetDirectory, Logger logger) {
this.outputDirectory = outputDirectory;
this.customAstClassesDirectory = customAstClassesDirectory;
this.targetDirectory = targetDirectory;
this.logger = logger;
}
Expand All @@ -27,7 +24,7 @@ public Collection<CompiledJavaccFile> listFiles() {
Collection<CompiledJavaccFile> compiledJavaccFiles = new ArrayList<>();

for (File file : files) {
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);
compiledJavaccFiles.add(compiledJavaccFile);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,19 @@

import java.io.File;

import org.gradle.api.file.FileTree;
import org.gradle.api.logging.Logger;

public class CompiledJavaccFilesDirectoryFactory {

public CompiledJavaccFilesDirectory getCompiledJavaccFilesDirectory(File outputDirectory, FileTree customAstClassesDirectory, File targetDirectory, Logger logger) {
public CompiledJavaccFilesDirectory getCompiledJavaccFilesDirectory(File outputDirectory, File targetDirectory, Logger logger) {
if ((outputDirectory == null) || !outputDirectory.exists() || !outputDirectory.isDirectory()) {
throw new IllegalArgumentException("outputDirectory [" + outputDirectory + "] must be an existing directory");
}

if (customAstClassesDirectory == null) {
throw new IllegalArgumentException("customAstClassesDirectory [" + outputDirectory + "] must not be null");
}


if ((targetDirectory == null) || !targetDirectory.exists() || !targetDirectory.isDirectory()) {
throw new IllegalArgumentException("targetDirectory [" + targetDirectory + "] must be an existing directory");
}
return new CompiledJavaccFilesDirectory(outputDirectory, customAstClassesDirectory, targetDirectory, logger);

return new CompiledJavaccFilesDirectory(outputDirectory, targetDirectory, logger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,9 @@ private FileTree excludeOutputDirectory(FileTree sourceTree) {
return null;
}

Spec<File> outputDirectoryFilter = file -> file.getAbsolutePath()
Spec<File> notInOutputDirectory = file -> !file.getAbsolutePath()
.contains(getOutputDirectory().getAbsolutePath());

FileTree fileTree = sourceTree.minus(sourceTree.filter(outputDirectoryFilter)).getAsFileTree();
return fileTree;
return sourceTree.filter(notInOutputDirectory).getAsFileTree();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.javacc.plugin.gradle.javacc.compiler;

import java.io.File;
import java.util.Collection;
import java.util.Collections;

import org.apache.commons.io.FileUtils;
import org.gradle.api.file.FileTree;
Expand Down Expand Up @@ -81,20 +83,25 @@ private ProgramArguments buildProgramArguments(File inputDirectory, RelativePath
@Override
public void copyCompiledFilesFromTempOutputDirectoryToOutputDirectory() {
CompiledJavaccFilesDirectory compiledJavaccFilesDirectory = compiledJavaccFilesDirectoryFactory.getCompiledJavaccFilesDirectory(
configuration.getTempOutputDirectory(), configuration.getCompleteSourceTree(), getOutputDirectory(), getLogger());

configuration.getTempOutputDirectory(), getOutputDirectory(), getLogger());
Collection<File> javaSourceFiles = getFiles(configuration.getJavaSourceTree());
Collection<File> javaccSourceFiles = getFiles(configuration.getSource());
for (CompiledJavaccFile compiledJavaccFile : compiledJavaccFilesDirectory.listFiles()) {
FileTree javaSourceTree = configuration.getJavaSourceTree();
if (compiledJavaccFile.customAstClassExists(javaSourceTree)) {
compiledJavaccFile.ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTree(javaSourceTree);
} else if (compiledJavaccFile.customAstClassExists()) {
compiledJavaccFile.copyCustomAstClassToTargetDirectory(configuration.getCompleteSourceTree());
} else {

if (!compiledJavaccFile.handleCustomAstInJava(javaSourceFiles)
&& !compiledJavaccFile.handleCustomAstInJavacc(javaccSourceFiles)) {
compiledJavaccFile.copyCompiledFileToTargetDirectory();
}
}
}

private Collection<File> getFiles(FileTree javaSourceTree) {
if (javaSourceTree == null) {
return Collections.emptySet();
}
return javaSourceTree.getFiles();
}

@Override
public String supportedSuffix() {
return programInvoker.supportedSuffix();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.doThrow;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.gradle.api.file.FileTree;
import org.gradle.api.logging.Logger;
import org.junit.After;
import org.junit.Before;
Expand All @@ -32,7 +33,7 @@
@PrepareForTest(FileUtils.class)
public class CompiledJavaccFileTest {
private File outputDirectory;
private FileTree customAstClassesDirectory;
private Collection<File> customAstClassesDirectory;
private File targetDirectory;
private Logger logger;

Expand All @@ -44,8 +45,7 @@ public void createCompiledJavaccFile() {

Set<File> sourceTree = new HashSet<>();
sourceTree.add(new File(getClass().getResource("/compiledJavaccFile/customAstClasses").getFile()));
customAstClassesDirectory = mock(FileTree.class);
when(customAstClassesDirectory.getFiles()).thenReturn(sourceTree);
customAstClassesDirectory = sourceTree;
}

@After
Expand All @@ -57,51 +57,51 @@ public void deleteFiles() throws IOException {
@Test
public void customAstClassDoesNotExist() {
File file = new File(outputDirectory, "FileWithNoCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

boolean customAstClassExists = compiledJavaccFile.customAstClassExists();
File customAstFile = compiledJavaccFile.getCustomAstClassInputFile(customAstClassesDirectory);

assertFalse(customAstClassExists);
assertNull(customAstFile);
}

@Test
public void customAstClassExists() {
File file = new File(outputDirectory, "FileWithCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

boolean customAstClassExists = compiledJavaccFile.customAstClassExists();
File customAstFile = compiledJavaccFile.getCustomAstClassInputFile(customAstClassesDirectory);

assertTrue(customAstClassExists);
assertNotNull(customAstFile);
}

@Test
public void customAstClassDoesNotExistInSpecificDirectory() {
File file = new File(outputDirectory, "FileWithNoCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

boolean customAstClassExists = compiledJavaccFile.customAstClassExists(customAstClassesDirectory);
File customAstClassExists = compiledJavaccFile.getCustomAstClassInputFile(customAstClassesDirectory);

assertFalse(customAstClassExists);
assertNull(customAstClassExists);
}

@Test
public void customAstClassExistsInSpecificDirectory() {
File file = new File(outputDirectory, "FileWithCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

boolean customAstClassExists = compiledJavaccFile.customAstClassExists(customAstClassesDirectory);
File customAstClassExists = compiledJavaccFile.getCustomAstClassInputFile(customAstClassesDirectory);

assertTrue(customAstClassExists);
assertNotNull(customAstClassExists);
}

@Test
public void customAstClassCantExistInNullDirectory() {
File file = new File(outputDirectory, "FileWithCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

boolean customAstClassExists = compiledJavaccFile.customAstClassExists(null);
File customAstClassExists = compiledJavaccFile.getCustomAstClassInputFile(null);

assertFalse(customAstClassExists);
assertNull(customAstClassExists);
}

@Test
Expand All @@ -110,7 +110,7 @@ public void copyCompiledFileToTargetDirectory() {
assertFalse(expectedFile.exists());

File file = new File(outputDirectory, "FileWithNoCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

compiledJavaccFile.copyCompiledFileToTargetDirectory();

Expand All @@ -120,7 +120,7 @@ public void copyCompiledFileToTargetDirectory() {
@Test(expected = CompiledJavaccFileOperationException.class)
public void copyCompiledFileToTargetDirectoryFails() {
File file = new File(outputDirectory, "DoesNotExist.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

compiledJavaccFile.copyCompiledFileToTargetDirectory();
}
Expand All @@ -131,9 +131,9 @@ public void copyCustomAstClassToTargetDirectory() {
assertFalse(expectedFile.exists());

File file = new File(outputDirectory, "FileWithCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

compiledJavaccFile.copyCustomAstClassToTargetDirectory(customAstClassesDirectory);
compiledJavaccFile.handleCustomAstInJavacc(customAstClassesDirectory);

assertTrue(expectedFile.exists());
}
Expand All @@ -145,15 +145,15 @@ public void copyCustomAstClassToTargetDirectoryFails() throws Exception {
FileUtils.copyFile(any(File.class), any(File.class));

File file = new File(outputDirectory, "FileWithCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

compiledJavaccFile.copyCustomAstClassToTargetDirectory(customAstClassesDirectory);
compiledJavaccFile.handleCustomAstInJavacc(customAstClassesDirectory);
}

@Test
public void toStringReturnsAbsoluteFileName() {
File file = new File(outputDirectory, "FileWithCorrespondingCustomAstClass.java");
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

String stringValue = compiledJavaccFile.toString();

Expand All @@ -163,10 +163,9 @@ public void toStringReturnsAbsoluteFileName() {
@Test
public void ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTreeOnlyLogsThatCompiledFileIsNotActedUpon() {
File file = mock(File.class);
FileTree javaSourceTree = mock(FileTree.class);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, customAstClassesDirectory, targetDirectory, logger);
CompiledJavaccFile compiledJavaccFile = new CompiledJavaccFile(file, outputDirectory, targetDirectory, logger);

compiledJavaccFile.ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTree(javaSourceTree);
compiledJavaccFile.ignoreCompiledFileAndUseCustomAstClassFromJavaSourceTree(file);

verify(logger).info(anyString(), eq(file), anyString());
}
Expand Down
Loading

0 comments on commit 7a39972

Please sign in to comment.