Skip to content

Commit

Permalink
Force document save before Pants compile action (#338)
Browse files Browse the repository at this point in the history
### Problem and Solution

Sometimes when running a test configuration, the plugin misses the change in the project and reuses last compile outputs. Therefore this change forces a save before Pants compile so file tracker will pick up the change before compile action.
  • Loading branch information
wisechengyi authored Mar 29, 2018
1 parent 5624a8b commit 67c6d81
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 88 deletions.
15 changes: 11 additions & 4 deletions src/com/twitter/intellij/pants/execution/PantsMakeBeforeRun.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,16 @@ public void onTextAvailable(ProcessEvent event, Key outputType) {
public PantsExecuteTaskResult executeCompileTask(@NotNull Project currentProject,
@NotNull Set<String> targetAddressesToCompile,
boolean useCleanAll) {

ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
/* Force cached changes to disk so {@link com.twitter.intellij.pants.file.FileChangeTracker} can mark the project dirty. */
FileDocumentManager.getInstance().saveAllDocuments();
currentProject.save();
}
}, ModalityState.NON_MODAL);

// If project has not changed since last Compile, return immediately.
if (!FileChangeTracker.shouldRecompileThenReset(currentProject, targetAddressesToCompile)) {
PantsExternalMetricsListenerManager.getInstance().logIsPantsNoopCompile(true);
Expand All @@ -339,17 +349,14 @@ public void run() {
}

private void prepareIDE(Project project) {
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
/* Clear message window. */
ConsoleView executionConsole = PantsConsoleManager.getOrMakeNewConsole(project);
executionConsole.getComponent().setVisible(true);
executionConsole.clear();
ToolWindowManagerEx.getInstance(project).getToolWindow(PantsConstants.PANTS_CONSOLE_NAME).activate(null);
/* Force cached changes to disk. */
FileDocumentManager.getInstance().saveAllDocuments();
project.save();
}
}, ModalityState.NON_MODAL);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.twitter.intellij.pants.util.PantsUtil;
import org.jetbrains.annotations.NotNull;

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

Expand Down Expand Up @@ -91,4 +98,45 @@ protected void assertProjectJdkAndLanguageLevel() {
projectLanguageLevel.equals(LanguageLevel.JDK_1_8)
);
}

@NotNull
protected Document getTestData(String testDataPath) {
File dataFile = PantsTestUtils.findTestPath(testDataPath);
VirtualFile dataVirtualFile = LocalFileSystem.getInstance().findFileByPath(dataFile.getPath());
assertNotNull(dataVirtualFile);
Document dataDocument = FileDocumentManager.getInstance().getDocument(dataVirtualFile);
assertNotNull(dataDocument);
return dataDocument;
}

/**
* Find document in project by filename.
*/
@NotNull
protected Document getDocumentFileInProject(String filename) {
VirtualFile sourceFile = searchForVirtualFileInProject(filename);
Document doc = FileDocumentManager.getInstance().getDocument(sourceFile);
assertNotNull(String.format("%s not found.", filename), doc);
return doc;
}

/**
* Find VirtualFile in project by filename.
*/
@NotNull
protected VirtualFile searchForVirtualFileInProject(String filename) {
Collection<VirtualFile> files = FilenameIndex.getVirtualFilesByName(myProject, filename, GlobalSearchScope.allScope(myProject));
assertEquals(String.format("%s not found.", filename), 1, files.size());
return files.iterator().next();
}

/**
* Find VirtualFile in project by filename.
*/
@NotNull
protected VirtualFile firstMatchingVirtualFileInProject(String filename) {
Collection<VirtualFile> files = FilenameIndex.getVirtualFilesByName(myProject, filename, GlobalSearchScope.allScope(myProject));
assertTrue(String.format("Filename %s not found in project", filename), files.size() > 0);
return files.iterator().next();
}
}
95 changes: 70 additions & 25 deletions tests/com/twitter/intellij/pants/integration/NoopCompileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package com.twitter.intellij.pants.integration;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.twitter.intellij.pants.settings.PantsSettings;
import com.twitter.intellij.pants.testFramework.OSSPantsIntegrationTest;
Expand All @@ -15,20 +17,26 @@

public class NoopCompileTest extends OSSPantsIntegrationTest {

private static final String HELLO_SRC_JAVA_MODULE = "examples_src_java_org_pantsbuild_example_hello_greet_greet";
private static final String HELLO_SRC_SCALA_MODULE = "examples_src_scala_org_pantsbuild_example_hello_welcome_welcome";
private static final String HELLO_TEST_MODULE = "examples_tests_scala_org_pantsbuild_example_hello_welcome_welcome";
private static final String HELLO_RESOURCES_MODULE = "examples_src_resources_org_pantsbuild_example_hello_hello";
private static class ScalaProjectData {
static final String path = "examples/tests/scala/org/pantsbuild/example/hello/welcome";
static final String HELLO_SRC_JAVA_MODULE = "examples_src_java_org_pantsbuild_example_hello_greet_greet";
static final String HELLO_SRC_SCALA_MODULE = "examples_src_scala_org_pantsbuild_example_hello_welcome_welcome";
static final String HELLO_TEST_MODULE = "examples_tests_scala_org_pantsbuild_example_hello_welcome_welcome";
static final String HELLO_RESOURCES_MODULE = "examples_src_resources_org_pantsbuild_example_hello_hello";
}

@Override
public void setUp() throws Exception {
super.setUp();
doImport("examples/tests/scala/org/pantsbuild/example/hello/welcome");
}

private void importScalaHello() {
doImport(ScalaProjectData.path);
assertFirstSourcePartyModules(
HELLO_RESOURCES_MODULE,
HELLO_SRC_JAVA_MODULE,
HELLO_SRC_SCALA_MODULE,
HELLO_TEST_MODULE
ScalaProjectData.HELLO_RESOURCES_MODULE,
ScalaProjectData.HELLO_SRC_JAVA_MODULE,
ScalaProjectData.HELLO_SRC_SCALA_MODULE,
ScalaProjectData.HELLO_TEST_MODULE
);
}

Expand All @@ -39,19 +47,42 @@ public void tearDown() throws Exception {
}

public void testNoop() throws Throwable {
importScalaHello();

// The first compile has to execute.
assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
// Second compile without any change should be noop.
assertPantsCompileNoop(pantsCompileProject());
}

public void testEditFileInProjectShouldOp() throws Throwable {
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
modify("org.pantsbuild.example.hello.welcome.WelSpec");
assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
}

public void testEditDocInProjectShouldOp() throws Throwable {
// Using a Java target because it is consistent throughout Pants versions.
doImport("examples/tests/java/org/pantsbuild/example/hello/greet");

assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
assertPantsCompileNoop(pantsCompileProject());
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Document doc = getDocumentFileInProject("GreetingTest.java");
doc.setText(doc.getText() + " ");
}
});
assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
assertPantsCompileNoop(pantsCompileProject());
}

public void testAddFileInsideProjectShouldOp() throws Throwable {
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
// Simulate out of band adding a file outside of IDE
Path newFilePath = Paths.get(getProjectFolder().getPath(), "examples/tests/scala/org/pantsbuild/example/hello/welcome/a.txt");
Expand All @@ -62,6 +93,8 @@ public void testAddFileInsideProjectShouldOp() throws Throwable {
}

public void testAddThenDeleteSameFileInsideProjectShouldNoop() throws Throwable {
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
// Simulate out of band adding a file outside of IDE
Path newFilePath = Paths.get(getProjectFolder().getPath(), "examples/tests/scala/org/pantsbuild/example/hello/welcome/a.txt");
Expand Down Expand Up @@ -91,6 +124,8 @@ public void testAddThenDeleteSameFileInsideProjectShouldNoop() throws Throwable
//}

public void testAddThenDeleteFileInProjectShouldOp() throws Throwable {
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileProject());
// Simulate out of band adding a file outside of IDE
Path newFilePath = Paths.get(getProjectFolder().getPath(), "examples/tests/scala/org/pantsbuild/example/hello/welcome/a.txt");
Expand All @@ -103,45 +138,55 @@ public void testAddThenDeleteFileInProjectShouldOp() throws Throwable {
}

public void testCompileDifferentModule() throws Throwable {
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
// Compile a different module, should not noop.
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_SCALA_MODULE));
assertPantsCompileNoop(pantsCompileModule(HELLO_SRC_SCALA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_SCALA_MODULE));
assertPantsCompileNoop(pantsCompileModule(ScalaProjectData.HELLO_SRC_SCALA_MODULE));
// Switch back should compile again.
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
}

public void testCompileProjectSettings() throws Throwable {
importScalaHello();

PantsSettings settings = PantsSettings.getInstance(myProject);
settings.setUseIdeaProjectJdk(false);
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));

settings.setUseIdeaProjectJdk(true);
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
}

public void testCompileIncrementalImports() throws Throwable {
importScalaHello();

// If a project uses incremental imports, then noop should never happen.
PantsSettings settings = PantsSettings.getInstance(myProject);
settings.setEnableIncrementalImport(true);
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
}

public void testShouldCompileAfterCleanAll() throws Throwable {
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
cmd("./pants", "clean-all");
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
}

public void testShouldCompileAfterOutOfBandPantsCLI() throws Throwable {
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
importScalaHello();

assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
assertPantsCompileNoop(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
cmd("./pants", "export-classpath", "--manifest-jar-only", "examples/tests/java/org/pantsbuild/example/hello/greet");
// Recompile because the sha of manifest.jar will change.
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(HELLO_SRC_JAVA_MODULE));
assertPantsCompileExecutesAndSucceeds(pantsCompileModule(ScalaProjectData.HELLO_SRC_JAVA_MODULE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,35 +59,4 @@ public void tearDown() throws Exception {
gitResetRepoCleanExampleDistDir();
super.tearDown();
}

@NotNull
private Document getTestData(String testDataPath) {
File dataFile = PantsTestUtils.findTestPath(testDataPath);
VirtualFile dataVirtualFile = LocalFileSystem.getInstance().findFileByPath(dataFile.getPath());
assertNotNull(dataVirtualFile);
Document dataDocument = FileDocumentManager.getInstance().getDocument(dataVirtualFile);
assertNotNull(dataDocument);
return dataDocument;
}

/**
* Find document in project by filename.
*/
@NotNull
private Document getDocumentFileInProject(String filename) {
VirtualFile sourceFile = searchForVirtualFileInProject(filename);
Document doc = FileDocumentManager.getInstance().getDocument(sourceFile);
assertNotNull(String.format("%s not found.", filename), doc);
return doc;
}

/**
* Find VirtualFile in project by filename.
*/
@NotNull
private VirtualFile searchForVirtualFileInProject(String filename) {
Collection<VirtualFile> files = FilenameIndex.getVirtualFilesByName(myProject, filename, GlobalSearchScope.allScope(myProject));
assertEquals(1, files.size());
return files.iterator().next();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,13 @@
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.twitter.intellij.pants.PantsBundle;
import com.twitter.intellij.pants.file.FileChangeTracker;
import com.twitter.intellij.pants.testFramework.OSSPantsIntegrationTest;
import com.twitter.intellij.pants.testFramework.PantsTestUtils;
import org.jetbrains.annotations.NotNull;

import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -156,26 +148,6 @@ private void saveFileAndAssertRefreshNotification(Editor editor) {
});
}

/**
* Find VirtualFile in project by filename.
*/
@NotNull
private VirtualFile firstMatchingVirtualFileInProject(String filename) {
Collection<VirtualFile> files = FilenameIndex.getVirtualFilesByName(myProject, filename, GlobalSearchScope.allScope(myProject));
assertTrue(String.format("Filename %s not found in project", filename), files.size() > 0);
return files.iterator().next();
}

@NotNull
private Document getTestData(String testDataPath) {
File dataFile = PantsTestUtils.findTestPath(testDataPath);
VirtualFile dataVirtualFile = LocalFileSystem.getInstance().findFileByPath(dataFile.getPath());
assertNotNull(dataVirtualFile);
Document dataDocument = FileDocumentManager.getInstance().getDocument(dataVirtualFile);
assertNotNull(dataDocument);
return dataDocument;
}

@Override
public void tearDown() throws Exception {
gitResetRepoCleanExampleDistDir();
Expand Down

0 comments on commit 67c6d81

Please sign in to comment.