// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.facet; import com.intellij.facet.mock.MockFacet; import com.intellij.facet.mock.MockFacetConfiguration; import com.intellij.facet.mock.MockFacetType; import com.intellij.facet.mock.MockSubFacetType; import com.intellij.idea.TestFor; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.module.EmptyModuleType; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.roots.ModuleRootEvent; import com.intellij.openapi.roots.ModuleRootListener; import org.jetbrains.annotations.NotNull; import java.io.File; public class FacetManagerTest extends FacetTestCase { public void testAddDeleteFacet() { myProject.getMessageBus().connect(getTestRootDisposable()).subscribe(ModuleRootListener.TOPIC, new ModuleRootListener() { @Override public void rootsChanged(@NotNull ModuleRootEvent event) { fail("rootsChanged must not be called on change of facets"); } }); final FacetManager manager = getFacetManager(); assertEquals(0, manager.getAllFacets().length); assertEquals(0, manager.getFacetsByType(MockFacetType.ID).size()); assertNull(manager.getFacetByType(MockFacetType.ID)); ModifiableFacetModel model = manager.createModifiableModel(); final MockFacet facet = createFacet(); model.addFacet(facet); assertTrue(model.isNewFacet(facet)); assertEquals(0, manager.getAllFacets().length); assertSame(facet, assertOneElement(model.getAllFacets())); assertSame(facet, assertOneElement(model.getFacetsByType(MockFacetType.ID))); assertFalse(facet.isInitialized()); commit(model); assertTrue(facet.isInitialized()); assertSame(facet, assertOneElement(manager.getAllFacets())); assertSame(facet, assertOneElement(manager.getFacetsByType(MockFacetType.ID))); model = manager.createModifiableModel(); assertFalse(model.isNewFacet(facet)); model.removeFacet(facet); assertFalse(facet.isDisposed()); assertFalse(model.isNewFacet(facet)); commit(model); assertEquals(0, manager.getAllFacets().length); assertEquals(0, manager.getFacetsByType(MockFacetType.ID).size()); assertTrue(facet.isDisposed()); } public void testAddFacetToNotYetCommittedModule() { ModifiableModuleModel moduleModel = ModuleManager.getInstance(myProject).getModifiableModel(); Module newModule = moduleModel.newModule(new File(myProject.getBasePath(), "new.iml").toPath(), EmptyModuleType.EMPTY_MODULE); FacetManager manager = FacetManager.getInstance(newModule); assertNull(manager.getFacetByType(MockFacetType.ID)); ModifiableFacetModel model = manager.createModifiableModel(); final MockFacet facet = new MockFacet(newModule, "mock"); model.addFacet(facet); assertSame(facet, assertOneElement(model.getAllFacets())); assertSame(facet, assertOneElement(model.getFacetsByType(MockFacetType.ID))); commit(model); assertSame(facet, assertOneElement(manager.getAllFacets())); assertSame(facet, assertOneElement(manager.getFacetsByType(MockFacetType.ID))); WriteAction.runAndWait(() -> moduleModel.commit()); assertSame(facet, assertOneElement(manager.getAllFacets())); assertSame(facet, assertOneElement(manager.getFacetsByType(MockFacetType.ID))); } public void testAddRemoveSubFacet() { final MockFacet mockFacet = addFacet(); assertNull(getFacetManager().getFacetByType(mockFacet, MockSubFacetType.ID)); assertNull(getFacetManager().getFacetByType(mockFacet, MockFacetType.ID)); final Facet subFacet = addSubFacet(mockFacet, "sub"); assertSame(subFacet, getFacetManager().getFacetByType(mockFacet, MockSubFacetType.ID)); assertNull(getFacetManager().getFacetByType(mockFacet, MockFacetType.ID)); ModifiableFacetModel model = getFacetManager().createModifiableModel(); model.removeFacet(subFacet); commit(model); assertNull(getFacetManager().getFacetByType(MockSubFacetType.ID)); assertSame(mockFacet, getFacetManager().getFacetByType(MockFacetType.ID)); model = getFacetManager().createModifiableModel(); model.removeFacet(mockFacet); commit(model); assertNull(getFacetManager().getFacetByType(MockFacetType.ID)); } public void testTwoSubFacets() { MockFacet mockFacet = addFacet(); Facet subFacet1 = addSubFacet(mockFacet, "sub1"); Facet subFacet2 = addSubFacet(mockFacet, "sub2"); assertSameElements(getFacetManager().getFacetsByType(mockFacet, MockSubFacetType.ID), subFacet1, subFacet2); ModifiableFacetModel model = getFacetManager().createModifiableModel(); model.removeFacet(subFacet1); commit(model); assertSameElements(getFacetManager().getFacetsByType(mockFacet, MockSubFacetType.ID), subFacet2); assertSameElements(getFacetManager().getFacetsByType(MockSubFacetType.ID), subFacet2); model = getFacetManager().createModifiableModel(); model.removeFacet(mockFacet); commit(model); assertNull(getFacetManager().getFacetByType(MockFacetType.ID)); assertNull(getFacetManager().getFacetByType(MockSubFacetType.ID)); } public void testChangeFacetConfiguration() { String configData = "data"; ModifiableFacetModel model = getFacetManager().createModifiableModel(); MockFacet mockFacet = new MockFacet(myModule, "mock"); model.addFacet(mockFacet); mockFacet.getConfiguration().setData(configData); commit(model); MockFacet facetByType = getFacetManager().getFacetByType(MockFacetType.ID); assertEquals(configData, facetByType.getConfiguration().getData()); assertSame(mockFacet, facetByType); } public void testAddRemoveFacetWithSubFacet() { assertNull(getFacetManager().getFacetByType(MockSubFacetType.ID)); assertNull(getFacetManager().getFacetByType(MockFacetType.ID)); ModifiableFacetModel model = getFacetManager().createModifiableModel(); MockFacet mockFacet = new MockFacet(myModule, "mock"); model.addFacet(mockFacet); Facet subFacet = MockSubFacetType.getInstance().createFacet(myModule, "mock", new MockFacetConfiguration(), mockFacet); model.addFacet(subFacet); commit(model); assertSame(subFacet, getFacetManager().getFacetByType(mockFacet, MockSubFacetType.ID)); assertSame(mockFacet, getFacetManager().getFacetByType(MockFacetType.ID)); assertNull(getFacetManager().getFacetByType(mockFacet, MockFacetType.ID)); model = getFacetManager().createModifiableModel(); model.removeFacet(subFacet); model.removeFacet(mockFacet); commit(model); assertNull(getFacetManager().getFacetByType(MockSubFacetType.ID)); assertNull(getFacetManager().getFacetByType(MockFacetType.ID)); } public void testRenameNewFacet() { final FacetManager manager = getFacetManager(); final ModifiableFacetModel model = manager.createModifiableModel(); final MockFacet facet = createFacet(); model.addFacet(facet); model.rename(facet, "newName"); commit(model); assertEquals("newName", assertOneElement(manager.getAllFacets()).getName()); } public void testRenameExistingFacet() { final MockFacet mockFacet = addFacet("facet"); assertEquals("facet", mockFacet.getName()); renameFacet(mockFacet, "newName"); assertEquals("newName", mockFacet.getName()); } @TestFor(issues = "IDEA-296991") public void testFacetIsCreatedOnlyOnce() { MockFacet.setConstructorCounter(0); addFacet("facet"); assertEquals(1, MockFacet.getConstructorCounter()); } public void testListeners() { final FacetManager manager = getFacetManager(); final MyFacetManagerListener listener = new MyFacetManagerListener(); myModule.getProject().getMessageBus().connect(/*getTestRootDisposable()*/).subscribe(FacetManager.FACETS_TOPIC, listener); ModifiableFacetModel model = manager.createModifiableModel(); final MockFacet facet = new MockFacet(myModule, "1"); model.addFacet(facet); assertEquals("", listener.getEvents()); commit(model); assertEquals("before added[1]\nadded[1]\n", listener.getEvents()); FacetManager.getInstance(myModule).facetConfigurationChanged(facet); assertEquals("changed[1]\n", listener.getEvents()); facet.getConfiguration().setData("updated"); FacetManager.getInstance(myModule).facetConfigurationChanged(facet); assertEquals("changed[1]\n", listener.getEvents()); model = manager.createModifiableModel(); model.rename(facet, "3"); assertEquals("", listener.getEvents()); commit(model); assertEquals("before renamed[1]\nrenamed[3]\n", listener.getEvents()); model = manager.createModifiableModel(); model.removeFacet(facet); commit(model); assertEquals("before removed[3]\nremoved[3]\n", listener.getEvents()); model = manager.createModifiableModel(); final MockFacet facet2 = new MockFacet(myModule, "2"); model.addFacet(facet2); model.removeFacet(facet2); commit(model); assertTrue(listener.getEvents().isEmpty()); } public void testGetSortedFacets() { final MockFacet facet = addFacet(); assertOrderedEquals(getFacetManager().getSortedFacets(), facet); final Facet subFacet = addSubFacet(facet, "subfacet"); assertOrderedEquals(getFacetManager().getSortedFacets(), facet, subFacet); } private static class MyFacetManagerListener implements FacetManagerListener { private final StringBuilder myEvents = new StringBuilder(); @Override public void beforeFacetAdded(@NotNull Facet facet) { myEvents.append("before added[").append(facet.getName()).append("]\n"); } @Override public void beforeFacetRemoved(@NotNull Facet facet) { myEvents.append("before removed[").append(facet.getName()).append("]\n"); } @Override public void beforeFacetRenamed(@NotNull final Facet facet) { myEvents.append("before renamed[").append(facet.getName()).append("]\n"); } @Override public void facetRenamed(@NotNull final Facet facet, @NotNull final String oldName) { myEvents.append("renamed[").append(facet.getName()).append("]\n"); } @Override public void facetConfigurationChanged(@NotNull final Facet facet) { myEvents.append("changed[").append(facet.getName()).append("]\n"); } @Override public void facetAdded(@NotNull Facet facet) { myEvents.append("added[").append(facet.getName()).append("]\n"); } @Override public void facetRemoved(@NotNull Facet facet) { myEvents.append("removed[").append(facet.getName()).append("]\n"); } public String getEvents() { final String s = myEvents.toString(); myEvents.setLength(0); return s; } } }