| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * 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 |
| * |
| * http://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. |
| */ |
| package com.android.tools.idea.gradle.parser; |
| |
| import com.android.SdkConstants; |
| import com.android.tools.idea.gradle.util.GradleUtil; |
| import com.google.common.base.Joiner; |
| import com.google.common.base.Predicate; |
| import com.google.common.base.Predicates; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Iterables; |
| import com.intellij.openapi.application.Result; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.openapi.editor.Document; |
| import com.intellij.openapi.fileEditor.FileDocumentManager; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VfsUtilCore; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.PsiDocumentManager; |
| import com.intellij.testFramework.IdeaTestCase; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Map; |
| import java.util.Set; |
| |
| public class GradleSettingsFileTest extends IdeaTestCase { |
| private Document myDocument; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| myDocument = null; |
| } |
| |
| public void testGetModules() throws Exception { |
| GradleSettingsFile file = getSimpleTestFile(); |
| String[] expected = new String[] { |
| ":one", ":two", ":three" |
| }; |
| assert Arrays.equals(expected, Iterables.toArray(file.getModules(), String.class)); |
| } |
| |
| public void testAddModuleToEmptyFile() throws Exception { |
| final GradleSettingsFile file = getEmptyTestFile(); |
| addModule(file, ":one"); |
| String expected = "include ':one'"; |
| assertContents(file, expected); |
| } |
| |
| public void testAddModuleToExistingFile() throws Exception { |
| final GradleSettingsFile file = getSimpleTestFile(); |
| addModule(file, ":four"); |
| String expected = |
| "include ':one', ':two', ':four'\n" + |
| "include ':three'\n" + |
| "include callSomeMethod()"; |
| |
| assertContents(file, expected); |
| } |
| |
| /** |
| * Module should be imported and its locations should be set to path relative to parent project root. |
| */ |
| public void testAddModuleWithNondefaultLocationWithinProject() throws IOException { |
| final String modulePath = "directory/module"; |
| final GradleSettingsFile file = getSimpleTestFile(); |
| File moduleLocation = new File(VfsUtilCore.virtualToIoFile(file.getFile().getParent()), modulePath); |
| assertModuleWithNonDefaultLocation(file, ":mymodule", modulePath, moduleLocation); |
| } |
| |
| /** |
| * Module should be imported and its locations should be set to absolute path. |
| */ |
| public void testAddModuleWithNondefaultLocationOutsideProject() throws IOException { |
| final String modulePath = FileUtil.toSystemIndependentName(FileUtil.getTempDirectory()) + "/directory/module"; |
| File moduleLocation = new File(modulePath); |
| final GradleSettingsFile file = getSimpleTestFile(); |
| assertModuleWithNonDefaultLocation(file, ":mymodule", modulePath, moduleLocation); |
| } |
| |
| private void assertModuleWithNonDefaultLocation(final GradleSettingsFile file, |
| final String moduleName, |
| String expectedPath, |
| final File moduleLocation) throws IOException { |
| WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() { |
| @Override |
| public void run() { |
| file.addModule(moduleName, moduleLocation); |
| } |
| }); |
| String expected = |
| "include ':one', ':two', '%1$s'\n" + |
| "include ':three'\n" + |
| "include callSomeMethod()\n" + |
| "project('%1$s').projectDir = new File('%2$s')"; |
| assertContents(file, String.format(expected, moduleName, expectedPath)); |
| } |
| |
| public void testAddModuleToLineContainingMethodCall() throws Exception { |
| final GradleSettingsFile file = getMethodCallTestFile(); |
| addModule(file, ":one"); |
| String expected = |
| "include callSomeMethod(), ':one'"; |
| |
| assertContents(file, expected); |
| } |
| |
| public void testRemovesFromLineWithMultipleModules() throws Exception { |
| final GradleSettingsFile file = getSimpleTestFile(); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable() { |
| @Override |
| public void run() { |
| file.removeModule(":two"); |
| } |
| }); |
| String expected = |
| "include ':one'\n" + |
| "include ':three'\n" + |
| "include callSomeMethod()"; |
| |
| assertContents(file, expected); |
| } |
| |
| public void testRemovesEntireLine() throws Exception { |
| final GradleSettingsFile file = getSimpleTestFile(); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable() { |
| @Override |
| public void run() { |
| file.removeModule(":three"); |
| } |
| }); |
| String expected = |
| "include ':one', ':two'\n" + |
| "include callSomeMethod()"; |
| |
| assertContents(file, expected); |
| } |
| |
| public void testRemovesMultipleEntries() throws Exception { |
| final GradleSettingsFile file = getTestFile( |
| "include ':one'\n" + |
| "include ':one', ':two'" |
| ); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable() { |
| @Override |
| public void run() { |
| file.removeModule(":one"); |
| } |
| }); |
| assertContents(file, "include ':two'"); |
| } |
| |
| public void testRemoveModuleAndLocation() throws IOException { |
| final GradleSettingsFile file = getTestFile("include ':one', 'two'\n" + |
| "project('two').projectDir = new File('modules/three')\n" + |
| "project(':one').projectDir = new File('modules/four')"); |
| WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() { |
| @Override |
| public void run() { |
| file.removeModule("two"); |
| } |
| }); |
| assertContents(file, "include ':one'\n" + |
| "project(':one').projectDir = new File('modules/four')"); |
| } |
| |
| public void testAddModuleStringChecksInitialization() { |
| GradleSettingsFile file = getBadGradleSettingsFile(); |
| try { |
| file.addModule("asdf", GradleUtil.getModuleDefaultPath(file.getFile(), ":asdf")); |
| } catch (IllegalStateException e) { |
| // expected |
| return; |
| } |
| fail("Failed to get expected IllegalStateException"); |
| } |
| |
| public void testAddModuleChecksInitialization() { |
| GradleSettingsFile file = getBadGradleSettingsFile(); |
| try { |
| file.addModule(myModule); |
| } catch (IllegalStateException e) { |
| // expected |
| return; |
| } |
| fail("Failed to get expected IllegalStateException"); |
| } |
| |
| public void testGetModulesChecksInitialization() { |
| GradleSettingsFile file = getBadGradleSettingsFile(); |
| try { |
| file.getModules(); |
| } catch (IllegalStateException e) { |
| // expected |
| return; |
| } |
| fail("Failed to get expected IllegalStateException"); |
| } |
| |
| public void testRemoveModuleStringChecksInitialization() { |
| GradleSettingsFile file = getBadGradleSettingsFile(); |
| try { |
| file.removeModule("asdf"); |
| } catch (IllegalStateException e) { |
| // expected |
| return; |
| } |
| fail("Failed to get expected IllegalStateException"); |
| } |
| |
| public void testRemoveModuleChecksInitialization() { |
| GradleSettingsFile file = getBadGradleSettingsFile(); |
| try { |
| file.removeModule(myModule); |
| } catch (IllegalStateException e) { |
| // expected |
| return; |
| } |
| fail("Failed to get expected IllegalStateException"); |
| } |
| |
| public void testGetModulePath() throws IOException { |
| GradleSettingsFile file = getTestFile("include ':one', 'two\n" + |
| "project(':two').projectDir = new File('modules/three')\n" |
| ); |
| Map<String, File> map = file.getModulesWithLocation(); |
| assertEquals(map.toString(), 2, map.size()); |
| assertEquals(new File("one"), map.get(":one")); |
| assertEquals(new File("modules", "three"), map.get(":two")); |
| } |
| |
| public void testRemoveModuleSpecifiedWithInclude() throws IOException { |
| Collection<String> modules = Arrays.asList("one", "two", "three", "four", "five"); |
| final String body = getSettingsFileWithModules(modules); |
| for (final String module : modules) { |
| final GradleSettingsFile file = getTestFile(body); |
| new WriteCommandAction<Object>(getProject(), file.getPsiFile()) { |
| @Override |
| protected void run(@NotNull Result<Object> result) throws Throwable { |
| file.removeModule(module); |
| } |
| }.execute(); |
| Set<String> postDelete = ImmutableSet.copyOf(file.getModules()); |
| assertEquals(module + " was not deleted", modules.size() - 1, postDelete.size()); |
| assertFalse(module + " was not deleted", postDelete.contains(module)); |
| Predicate<String> notCurrentModule = Predicates.not(Predicates.equalTo(module)); |
| String expectedFileContents = getSettingsFileWithModules(Iterables.filter(modules, notCurrentModule)); |
| assertEquals(expectedFileContents, file.getPsiFile().getText()); |
| } |
| } |
| |
| private static String getSettingsFileWithModules(Iterable<String> modules) { |
| return "include \'" + Joiner.on("\'\ninclude \'").join(modules) + "\'\n"; |
| } |
| |
| private static void addModule(final GradleSettingsFile file, final String name) { |
| WriteCommandAction.runWriteCommandAction(null, new Runnable() { |
| @Override |
| public void run() { |
| file.addModule(name, GradleUtil.getModuleDefaultPath(file.getFile().getParent(), name)); |
| } |
| }); |
| } |
| |
| private GradleSettingsFile getSimpleTestFile() throws IOException { |
| String contents = |
| "include ':one', ':two'\n" + |
| "include ':three'\n" + |
| "include callSomeMethod()"; |
| return getTestFile(contents); |
| } |
| |
| private GradleSettingsFile getMethodCallTestFile() throws IOException { |
| String contents = |
| "include callSomeMethod()"; |
| return getTestFile(contents); |
| } |
| |
| private GradleSettingsFile getEmptyTestFile() throws IOException { |
| return getTestFile(""); |
| } |
| |
| private GradleSettingsFile getTestFile(String... contents) throws IOException { |
| String fileContents = Joiner.on("\n").join(contents); |
| VirtualFile vf = getVirtualFile(createTempFile(SdkConstants.FN_SETTINGS_GRADLE, fileContents)); |
| myDocument = FileDocumentManager.getInstance().getDocument(vf); |
| return new GradleSettingsFile(vf, getProject()); |
| } |
| |
| private GradleSettingsFile getBadGradleSettingsFile() { |
| // Use an intentionally invalid file path so that GradleSettingsFile will remain uninitialized. This simulates the condition of |
| // the PSI file not being parsed yet. GradleSettingsFile will warn about the PSI file; this is expected. |
| VirtualFile vf = LocalFileSystem.getInstance().findFileByPath(FileUtil.getTempDirectory()); |
| assertNotNull(vf); |
| return new GradleSettingsFile(vf, getProject()); |
| } |
| |
| private void assertContents(GradleSettingsFile file, String expected) throws IOException { |
| PsiDocumentManager.getInstance(getProject()).commitDocument(myDocument); |
| String actual = myDocument.getText(); |
| assertEquals(expected, actual); |
| } |
| } |