2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.jetbrains
.idea
.maven
.dom
;
18 import com
.intellij
.codeInsight
.CodeInsightSettings
;
19 import com
.intellij
.codeInsight
.TargetElementUtil
;
20 import com
.intellij
.codeInsight
.TargetElementUtilBase
;
21 import com
.intellij
.codeInsight
.documentation
.DocumentationManager
;
22 import com
.intellij
.codeInsight
.highlighting
.HighlightUsagesHandler
;
23 import com
.intellij
.codeInsight
.intention
.IntentionAction
;
24 import com
.intellij
.codeInsight
.lookup
.LookupElement
;
25 import com
.intellij
.find
.findUsages
.PsiElement2UsageTargetAdapter
;
26 import com
.intellij
.lang
.documentation
.DocumentationProvider
;
27 import com
.intellij
.openapi
.actionSystem
.DataProvider
;
28 import com
.intellij
.openapi
.actionSystem
.LangDataKeys
;
29 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
30 import com
.intellij
.openapi
.command
.WriteCommandAction
;
31 import com
.intellij
.openapi
.editor
.Editor
;
32 import com
.intellij
.openapi
.editor
.markup
.RangeHighlighter
;
33 import com
.intellij
.openapi
.util
.Comparing
;
34 import com
.intellij
.openapi
.vfs
.VirtualFile
;
35 import com
.intellij
.psi
.PsiElement
;
36 import com
.intellij
.psi
.PsiFile
;
37 import com
.intellij
.psi
.PsiManager
;
38 import com
.intellij
.psi
.PsiReference
;
39 import com
.intellij
.psi
.impl
.source
.resolve
.reference
.impl
.PsiMultiReference
;
40 import com
.intellij
.psi
.search
.searches
.ReferencesSearch
;
41 import com
.intellij
.psi
.util
.PsiTreeUtil
;
42 import com
.intellij
.psi
.xml
.XmlTag
;
43 import com
.intellij
.refactoring
.rename
.PsiElementRenameHandler
;
44 import com
.intellij
.refactoring
.rename
.RenameHandler
;
45 import com
.intellij
.refactoring
.rename
.RenameHandlerRegistry
;
46 import com
.intellij
.testFramework
.MapDataContext
;
47 import com
.intellij
.testFramework
.fixtures
.CodeInsightTestFixture
;
48 import com
.intellij
.testFramework
.fixtures
.CodeInsightTestUtil
;
49 import com
.intellij
.testFramework
.fixtures
.IdeaTestFixtureFactory
;
50 import com
.intellij
.usages
.UsageTarget
;
51 import com
.intellij
.usages
.UsageTargetUtil
;
52 import com
.intellij
.util
.Function
;
53 import com
.intellij
.util
.containers
.ContainerUtil
;
54 import gnu
.trove
.THashMap
;
55 import org
.jetbrains
.annotations
.NonNls
;
56 import org
.jetbrains
.idea
.maven
.MavenImportingTestCase
;
57 import org
.jetbrains
.idea
.maven
.dom
.model
.MavenDomProjectModel
;
58 import org
.jetbrains
.idea
.maven
.dom
.references
.MavenPsiElementWrapper
;
60 import java
.io
.IOException
;
61 import java
.util
.ArrayList
;
62 import java
.util
.Arrays
;
63 import java
.util
.List
;
66 public abstract class MavenDomTestCase
extends MavenImportingTestCase
{
67 protected CodeInsightTestFixture myCodeInsightFixture
;
68 private final Map
<VirtualFile
, Long
> myConfigTimestamps
= new THashMap
<VirtualFile
, Long
>();
69 private boolean myOriginalAutoCompletion
;
72 protected void setUpFixtures() throws Exception
{
73 myTestFixture
= IdeaTestFixtureFactory
.getFixtureFactory().createFixtureBuilder().getFixture();
75 myCodeInsightFixture
= IdeaTestFixtureFactory
.getFixtureFactory().createCodeInsightFixture(myTestFixture
);
76 myCodeInsightFixture
.setUp();
78 myCodeInsightFixture
.enableInspections(MavenModelInspection
.class);
80 myOriginalAutoCompletion
= CodeInsightSettings
.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION
;
81 CodeInsightSettings
.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION
= false;
85 protected void tearDownFixtures() throws Exception
{
86 CodeInsightSettings
.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION
= myOriginalAutoCompletion
;
87 myCodeInsightFixture
.tearDown();
88 myConfigTimestamps
.clear();
91 protected PsiFile
findPsiFile(VirtualFile f
) {
92 return PsiManager
.getInstance(myProject
).findFile(f
);
95 private void configTest(VirtualFile f
) throws IOException
{
96 if (Comparing
.equal(myConfigTimestamps
.get(f
), f
.getModificationStamp())) return;
97 myCodeInsightFixture
.configureFromExistingVirtualFile(f
);
98 myConfigTimestamps
.put(f
, f
.getModificationStamp());
101 protected PsiReference
getReferenceAtCaret(VirtualFile f
) throws IOException
{
103 return findPsiFile(f
).findReferenceAt(getEditorOffset(f
));
106 protected PsiElement
getElementAtCaret(VirtualFile f
) throws IOException
{
108 return findPsiFile(f
).findElementAt(getEditorOffset(f
));
111 protected Editor
getEditor() throws IOException
{
112 return getEditor(myProjectPom
);
115 protected Editor
getEditor(VirtualFile f
) throws IOException
{
117 return myCodeInsightFixture
.getEditor();
120 protected int getEditorOffset() throws IOException
{
121 return getEditorOffset(myProjectPom
);
124 protected int getEditorOffset(VirtualFile f
) throws IOException
{
125 return getEditor(f
).getCaretModel().getOffset();
128 protected PsiFile
getTestPsiFile() throws IOException
{
129 return getTestPsiFile(myProjectPom
);
132 private PsiFile
getTestPsiFile(VirtualFile f
) throws IOException
{
134 return myCodeInsightFixture
.getFile();
137 protected XmlTag
findTag(String path
) {
138 return findTag(myProjectPom
, path
);
141 protected XmlTag
findTag(VirtualFile file
, String path
) {
142 return findTag(file
, path
, MavenDomProjectModel
.class);
145 protected XmlTag
findTag(VirtualFile file
, String path
, Class
<?
extends MavenDomElement
> clazz
) {
146 MavenDomElement model
= MavenDomUtil
.getMavenDomModel(myProject
, file
, clazz
);
147 assertNotNull("Model is not of " + clazz
, model
);
148 return MavenDomUtil
.findTag(model
, path
);
151 protected void assertNoReferences(VirtualFile file
, Class refClass
) throws IOException
{
152 PsiReference ref
= getReferenceAtCaret(file
);
153 if (ref
== null) return;
154 PsiReference
[] refs
= ref
instanceof PsiMultiReference ?
((PsiMultiReference
)ref
).getReferences() : new PsiReference
[]{ref
};
155 for (PsiReference each
: refs
) {
156 assertFalse(each
.toString(), refClass
.isInstance(each
));
160 protected void assertUnresolved(VirtualFile file
) throws IOException
{
161 PsiReference ref
= getReferenceAtCaret(file
);
163 assertNull(ref
.resolve());
166 protected void assertUnresolved(VirtualFile file
, String expectedText
) throws IOException
{
167 PsiReference ref
= getReferenceAtCaret(file
);
169 assertNull(ref
.resolve());
170 assertEquals(expectedText
, ref
.getCanonicalText());
173 protected void assertResolved(VirtualFile file
, PsiElement expected
) throws IOException
{
174 doAssertResolved(file
, expected
);
177 protected void assertResolved(VirtualFile file
, PsiElement expected
, String expectedText
) throws IOException
{
178 PsiReference ref
= doAssertResolved(file
, expected
);
179 assertEquals(expectedText
, ref
.getCanonicalText());
182 private PsiReference
doAssertResolved(VirtualFile file
, PsiElement expected
) throws IOException
{
183 assertNotNull("expected reference is null", expected
);
185 PsiReference ref
= getReferenceAtCaret(file
);
187 PsiElement resolved
= ref
.resolve();
188 if (resolved
instanceof MavenPsiElementWrapper
) {
189 resolved
= ((MavenPsiElementWrapper
)resolved
).getWrappee();
191 assertEquals(expected
, resolved
);
195 protected void assertCompletionVariants(VirtualFile f
, String
... expected
) throws IOException
{
196 List
<String
> actual
= getCompletionVariants(f
);
197 assertUnorderedElementsAreEqual(actual
, expected
);
200 protected void assertCompletionVariantsInclude(VirtualFile f
, String
... expected
) throws IOException
{
201 assertInclude(getCompletionVariants(f
), expected
);
204 protected <T
> void assertInclude(List
<?
extends T
> actual
, T
... expected
) throws IOException
{
205 List
<T
> expectedList
= Arrays
.asList(expected
);
206 assertTrue("expected: " + expectedList
+ "\n" + "actual: " + actual
.toString(), actual
.containsAll(expectedList
));
209 protected void assertDoNotInclude(List
<String
> actual
, String
... expected
) throws IOException
{
210 List
<String
> actualCopy
= new ArrayList
<String
>(actual
);
211 actualCopy
.removeAll(Arrays
.asList(expected
));
212 assertTrue(actual
.toString(), actualCopy
.size() == actual
.size());
215 protected void assertCompletionVariantsDoNotInclude(VirtualFile f
, String
... expected
) throws IOException
{
216 assertDoNotInclude(getCompletionVariants(f
), expected
);
219 protected List
<String
> getCompletionVariants(VirtualFile f
) throws IOException
{
221 LookupElement
[] variants
= myCodeInsightFixture
.completeBasic();
223 List
<String
> result
= new ArrayList
<String
>();
224 for (LookupElement each
: variants
) {
225 result
.add(each
.getLookupString());
230 protected void assertDocumentation(String expectedText
) throws IOException
{
231 PsiElement originalElement
= getElementAtCaret(myProjectPom
);
232 PsiElement targetElement
= DocumentationManager
.getInstance(myProject
)
233 .findTargetElement(getEditor(), getTestPsiFile(), originalElement
);
235 DocumentationProvider provider
= DocumentationManager
.getProviderFromElement(targetElement
);
236 assertEquals(expectedText
, provider
.generateDoc(targetElement
, originalElement
));
238 // should work for lookup as well as for tags
239 PsiElement lookupElement
= provider
.getDocumentationElementForLookupItem(PsiManager
.getInstance(myProject
),
240 originalElement
.getText(),
242 assertSame(targetElement
, lookupElement
);
245 protected void checkHighlighting() throws IOException
{
246 checkHighlighting(myProjectPom
);
249 protected void checkHighlighting(VirtualFile f
) throws IOException
{
250 configTest(myProjectPom
);
252 myCodeInsightFixture
.testHighlighting(true, true, true, f
);
254 catch (Throwable throwable
) {
255 throw new RuntimeException(throwable
);
259 protected IntentionAction
getIntentionAtCaret(String intentionName
) throws IOException
{
260 configTest(myProjectPom
);
262 List
<IntentionAction
> intentions
= myCodeInsightFixture
.getAvailableIntentions();
264 return CodeInsightTestUtil
.findIntentionByText(intentions
, intentionName
);
266 catch (Throwable throwable
) {
267 throw new RuntimeException(throwable
);
271 protected void assertRenameResult(String value
, String expectedXml
) throws Exception
{
272 doRename(myProjectPom
, value
);
273 assertEquals(createPomXml(expectedXml
), getTestPsiFile(myProjectPom
).getText());
276 protected void doRename(final VirtualFile f
, String value
) throws IOException
{
277 final MapDataContext context
= createRenameDataContext(f
, value
);
278 final RenameHandler renameHandler
= RenameHandlerRegistry
.getInstance().getRenameHandler(context
);
279 assertNotNull(renameHandler
);
281 invokeRename(context
, renameHandler
);
284 protected void assertCannotRename() throws IOException
{
285 MapDataContext context
= createRenameDataContext(myProjectPom
, "new name");
286 RenameHandler handler
= RenameHandlerRegistry
.getInstance().getRenameHandler(context
);
287 if (handler
== null) return;
289 invokeRename(context
, handler
);
291 catch (Exception e
) {
292 assertTrue(e
.getMessage(), e
.getMessage().startsWith("Cannot perform refactoring."));
296 private void invokeRename(final MapDataContext context
, final RenameHandler renameHandler
) {
297 new WriteCommandAction
.Simple(myProject
) {
299 protected void run() throws Throwable
{
300 renameHandler
.invoke(myProject
, PsiElement
.EMPTY_ARRAY
, context
);
305 private MapDataContext
createDataContext(VirtualFile f
) throws IOException
{
306 MapDataContext context
= new MapDataContext();
307 context
.put(PlatformDataKeys
.EDITOR
, getEditor(f
));
308 context
.put(LangDataKeys
.PSI_FILE
, getTestPsiFile(f
));
309 context
.put(LangDataKeys
.PSI_ELEMENT
, TargetElementUtil
.findTargetElement(getEditor(f
),
310 TargetElementUtilBase
.REFERENCED_ELEMENT_ACCEPTED
311 | TargetElementUtilBase
.ELEMENT_NAME_ACCEPTED
));
315 private MapDataContext
createRenameDataContext(VirtualFile f
, String value
) throws IOException
{
316 MapDataContext context
= createDataContext(f
);
317 context
.put(PsiElementRenameHandler
.DEFAULT_NAME
, value
);
321 protected void assertSearchResults(VirtualFile file
, PsiElement
... expected
) throws IOException
{
322 assertUnorderedElementsAreEqual(search(file
), expected
);
325 protected void assertSearchResultsContain(VirtualFile file
, PsiElement
... expected
) throws IOException
{
326 assertInclude(search(file
), expected
);
329 protected List
<PsiElement
> search(VirtualFile file
) throws IOException
{
330 final MapDataContext context
= createDataContext(file
);
331 UsageTarget
[] targets
= UsageTargetUtil
.findUsageTargets(new DataProvider() {
332 public Object
getData(@NonNls String dataId
) {
333 return context
.getData(dataId
);
336 PsiElement target
= ((PsiElement2UsageTargetAdapter
)targets
[0]).getElement();
337 List
<PsiReference
> result
= new ArrayList
<PsiReference
>(ReferencesSearch
.search(target
).findAll());
338 return ContainerUtil
.map(result
, new Function
<PsiReference
, PsiElement
>() {
339 public PsiElement
fun(PsiReference psiReference
) {
340 return psiReference
.getElement();
345 protected void assertHighlighted(VirtualFile file
, HighlightInfo
... expected
) throws IOException
{
346 Editor editor
= getEditor(file
);
347 HighlightUsagesHandler
.invoke(myProject
, editor
, getTestPsiFile(file
));
349 RangeHighlighter
[] highlighters
= editor
.getMarkupModel().getAllHighlighters();
350 List
<HighlightInfo
> actual
= new ArrayList
<HighlightInfo
>();
351 for (RangeHighlighter each
: highlighters
) {
352 int offset
= each
.getStartOffset();
353 PsiElement element
= getTestPsiFile(file
).findElementAt(offset
);
354 element
= PsiTreeUtil
.getParentOfType(element
, XmlTag
.class);
355 String text
= editor
.getDocument().getText().substring(offset
, each
.getEndOffset());
356 actual
.add(new HighlightInfo(element
, text
));
359 assertUnorderedElementsAreEqual(actual
, expected
);
362 protected static class HighlightInfo
{
363 public PsiElement element
;
366 public HighlightInfo(PsiElement element
, String text
) {
367 this.element
= element
;
372 public boolean equals(Object o
) {
373 if (this == o
) return true;
374 if (o
== null || getClass() != o
.getClass()) return false;
376 HighlightInfo that
= (HighlightInfo
)o
;
378 if (element
!= null ?
!element
.equals(that
.element
) : that
.element
!= null) return false;
379 if (text
!= null ?
!text
.equals(that
.text
) : that
.text
!= null) return false;
385 public int hashCode() {
386 int result
= element
!= null ? element
.hashCode() : 0;
387 result
= 31 * result
+ (text
!= null ? text
.hashCode() : 0);