use of com.intellij.psi.xml.XmlFile in project intellij-community by JetBrains.
the class SmartPsiElementPointersTest method testManyPsiChangesWithManySmartPointersPerformance.
public void testManyPsiChangesWithManySmartPointersPerformance() throws Exception {
String eachTag = "<a>\n" + StringUtil.repeat(" <a> </a>\n", 9) + "</a>\n";
XmlFile file = (XmlFile) createFile("a.xml", "<root>\n" + StringUtil.repeat(eachTag, 500) + "</root>");
List<XmlTag> tags = ContainerUtil.newArrayList(PsiTreeUtil.findChildrenOfType(file.getDocument(), XmlTag.class));
List<SmartPsiElementPointer> pointers = tags.stream().map(this::createPointer).collect(Collectors.toList());
ApplicationManager.getApplication().runWriteAction(() -> PlatformTestUtil.startPerformanceTest("smart pointer range update after PSI change", 21000, () -> {
for (int i = 0; i < tags.size(); i++) {
XmlTag tag = tags.get(i);
SmartPsiElementPointer pointer = pointers.get(i);
assertEquals(tag.getName().length(), TextRange.create(pointer.getRange()).getLength());
assertEquals(tag.getName().length(), TextRange.create(pointer.getPsiRange()).getLength());
tag.setName("bar1" + (i % 10));
assertEquals(tag.getName().length(), TextRange.create(pointer.getRange()).getLength());
assertEquals(tag.getName().length(), TextRange.create(pointer.getPsiRange()).getLength());
}
PostprocessReformattingAspect.getInstance(myProject).doPostponedFormatting();
}).cpuBound().useLegacyScaling().assertTiming());
}
use of com.intellij.psi.xml.XmlFile in project intellij-plugins by JetBrains.
the class FlexResolveHelper method importClass.
public boolean importClass(final PsiScopeProcessor processor, final PsiNamedElement file) {
// there is no need to process package stuff at function level
if (file instanceof JSFunction)
return true;
if (file instanceof XmlBackedJSClassImpl) {
if (!processInlineComponentsInScope((XmlBackedJSClassImpl) file, inlineComponent -> processor.execute(inlineComponent, ResolveState.initial()))) {
return false;
}
}
final String packageQualifierText = JSResolveUtil.findPackageStatementQualifier(file);
final Project project = file.getProject();
GlobalSearchScope scope = JSResolveUtil.getResolveScope(file);
final MxmlAndFxgFilesProcessor filesProcessor = new MxmlAndFxgFilesProcessor() {
final PsiManager manager = PsiManager.getInstance(project);
public void addDependency(final PsiDirectory directory) {
}
public boolean processFile(final VirtualFile file, final VirtualFile root) {
final PsiFile xmlFile = manager.findFile(file);
if (!(xmlFile instanceof XmlFile))
return true;
return processor.execute(XmlBackedJSClassFactory.getXmlBackedClass((XmlFile) xmlFile), ResolveState.initial());
}
};
PsiFile containingFile = file.getContainingFile();
boolean completion = containingFile.getOriginalFile() != containingFile;
if (completion) {
return processAllMxmlAndFxgFiles(scope, project, filesProcessor, null);
} else {
if (packageQualifierText != null && packageQualifierText.length() > 0) {
if (!processMxmlAndFxgFilesInPackage(scope, project, packageQualifierText, filesProcessor))
return false;
}
return processMxmlAndFxgFilesInPackage(scope, project, "", filesProcessor);
}
}
use of com.intellij.psi.xml.XmlFile in project android by JetBrains.
the class LayoutPsiPullParserTest method testEmptyLayout.
public void testEmptyLayout() throws XmlPullParserException {
XmlFile emptyFile = mock(XmlFile.class);
when(emptyFile.getRootTag()).thenReturn(null);
RenderLogger logger = new RenderLogger("test", myModule);
assertEmptyParser(LayoutPsiPullParser.create(emptyFile, logger));
XmlTag emptyTag = mock(XmlTag.class);
assertEmptyParser(new LayoutPsiPullParser(mock(XmlTag.class), logger));
when(emptyTag.isValid()).thenReturn(true);
assertEmptyParser(new LayoutPsiPullParser(mock(XmlTag.class), logger));
}
use of com.intellij.psi.xml.XmlFile in project android by JetBrains.
the class LayoutPsiPullParserTest method testDesignAttributes.
public void testDesignAttributes() throws Exception {
@SuppressWarnings("SpellCheckingInspection") VirtualFile virtualFile = myFixture.copyFileToProject("xmlpull/designtime.xml", "res/layout/designtime.xml");
assertNotNull(virtualFile);
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(virtualFile);
assertTrue(psiFile instanceof XmlFile);
XmlFile xmlFile = (XmlFile) psiFile;
LayoutPsiPullParser parser = LayoutPsiPullParser.create(xmlFile, new RenderLogger("test", myModule));
assertEquals(START_TAG, parser.nextTag());
assertEquals("LinearLayout", parser.getName());
assertEquals(START_TAG, parser.nextTag());
assertEquals("TextView", parser.getName());
assertEquals("@+id/first", parser.getAttributeValue(ANDROID_URI, ATTR_ID));
assertEquals(END_TAG, parser.nextTag());
assertEquals(START_TAG, parser.nextTag());
assertEquals("TextView", parser.getName());
// auto converted from match_parent
assertEquals("fill_parent", parser.getAttributeValue(ANDROID_URI, ATTR_LAYOUT_WIDTH));
assertEquals("wrap_content", parser.getAttributeValue(ANDROID_URI, ATTR_LAYOUT_HEIGHT));
// overriding runtime text attribute
assertEquals("Designtime Text", parser.getAttributeValue(ANDROID_URI, ATTR_TEXT));
assertEquals("@android:color/darker_gray", parser.getAttributeValue(ANDROID_URI, "textColor"));
assertEquals(END_TAG, parser.nextTag());
assertEquals(START_TAG, parser.nextTag());
assertEquals("TextView", parser.getName());
assertEquals("@+id/blank", parser.getAttributeValue(ANDROID_URI, ATTR_ID));
// Don't unset when no framework attribute is defined
assertEquals("", parser.getAttributeValue(ANDROID_URI, ATTR_TEXT));
assertEquals(END_TAG, parser.nextTag());
assertEquals(START_TAG, parser.nextTag());
assertEquals("ListView", parser.getName());
assertEquals("@+id/listView", parser.getAttributeValue(ANDROID_URI, ATTR_ID));
// Cleared by overriding defined framework attribute
assertNull(parser.getAttributeValue(ANDROID_URI, "fastScrollAlwaysVisible"));
}
use of com.intellij.psi.xml.XmlFile in project android by JetBrains.
the class ResourceNotificationManagerTest method test.
public void test() {
@Language("XML") String xml;
// Setup sample project: a strings file, and a couple of layout file
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + " android:layout_width=\"match_parent\"\n" + " android:layout_height=\"match_parent\">\n" + " <!-- My comment -->\n" + " <TextView " + " android:layout_width=\"match_parent\"\n" + " android:layout_height=\"match_parent\"\n" + " android:text=\"@string/hello\" />\n" + "</FrameLayout>";
final XmlFile layout1 = (XmlFile) myFixture.addFileToProject("res/layout/my_layout1.xml", xml);
@SuppressWarnings("ConstantConditions") VirtualFile resourceDir = layout1.getParent().getParent().getVirtualFile();
assertNotNull(resourceDir);
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + " android:layout_width=\"match_parent\"\n" + " android:layout_height=\"match_parent\" />\n";
final XmlFile layout2 = (XmlFile) myFixture.addFileToProject("res/layout/my_layout2.xml", xml);
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<resources>\n" + " <string name=\"hello\">Hello</string>\n" + "\n" + " <!-- Base application theme. -->\n" + " <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n" + " <!-- Customize your theme here. -->\n" + " <item name=\"android:colorBackground\">#ff0000</item>\n" + " </style>" + "</resources>";
final XmlFile values1 = (XmlFile) myFixture.addFileToProject("res/values/my_values1.xml", xml);
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<resources>\n" + " \n" + "</resources>";
myFixture.addFileToProject("res/values/colors.xml", xml);
final Configuration configuration1 = myFacet.getConfigurationManager().getConfiguration(layout1.getVirtualFile());
final ResourceNotificationManager manager = ResourceNotificationManager.getInstance(getProject());
// Listener 1: Listens for changes in layout 1
final Ref<Boolean> called1 = new Ref<>(false);
final Ref<Set<Reason>> calledValue1 = new Ref<>();
ResourceChangeListener listener1 = new ResourceChangeListener() {
@Override
public void resourcesChanged(@NotNull Set<Reason> reason) {
called1.set(true);
calledValue1.set(reason);
}
};
// Listener 2: Only listens for general changes in the module
final Ref<Boolean> called2 = new Ref<>(false);
final Ref<Set<Reason>> calledValue2 = new Ref<>();
ResourceChangeListener listener2 = new ResourceChangeListener() {
@Override
public void resourcesChanged(@NotNull Set<Reason> reason) {
called2.set(true);
calledValue2.set(reason);
}
};
manager.addListener(listener1, myFacet, layout1, configuration1);
manager.addListener(listener2, myFacet, null, null);
// Make sure that when we're modifying multiple files, with complicated
// edits (that trigger full file rescans), we handle that scenario correctly.
clear(called1, calledValue1, called2, calledValue2);
// There's actually some special optimizations done via PsiResourceItem#recomputeValue
// to only mark the resource repository changed if the value has actually been looked
// up. This allows us to not recompute layout if you're editing some string that
// hasn't actually been looked up and rendered in a layout. In order to make sure
// that that optimization doesn't kick in here, we need to look up the value of
// the resource item first:
//noinspection ConstantConditions
assertEquals("#ff0000", configuration1.getResourceResolver().getStyle("AppTheme", false).getItem("colorBackground", true).getValue());
AndroidResourceUtil.createValueResource(getProject(), resourceDir, "color2", ResourceType.COLOR, "colors.xml", Collections.singletonList("values"), "#fa2395");
ensureCalled(called1, calledValue1, called2, calledValue2, Reason.RESOURCE_EDIT);
clear(called1, calledValue1, called2, calledValue2);
@SuppressWarnings("ConstantConditions") final XmlTag tag = values1.getDocument().getRootTag().getSubTags()[1].getSubTags()[0];
assertEquals("item", tag.getName());
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
@Override
public void run() {
tag.getValue().setEscapedText("@color/color2");
}
});
ensureCalled(called1, calledValue1, called2, calledValue2, Reason.RESOURCE_EDIT);
// First check: Modify the layout by changing @string/hello to @string/hello_world
// and verify that our listeners are called.
ResourceVersion version1 = manager.getCurrentVersion(myFacet, layout1, configuration1);
addText(layout1, "@string/hello^", "_world");
ensureCalled(called1, calledValue1, called2, calledValue2, Reason.EDIT);
ResourceVersion version2 = manager.getCurrentVersion(myFacet, layout1, configuration1);
assertFalse(version1.toString(), version1.equals(version2));
// Next check: Modify a <string> value definition in a values file
// and check that those changes are flagged too
clear(called1, calledValue1, called2, calledValue2);
ResourceVersion version3 = manager.getCurrentVersion(myFacet, layout1, configuration1);
addText(values1, "name=\"hello^\"", "_world");
ensureCalled(called1, calledValue1, called2, calledValue2, Reason.RESOURCE_EDIT);
ResourceVersion version4 = manager.getCurrentVersion(myFacet, layout1, configuration1);
assertFalse(version4.toString(), version3.equals(version4));
// Next check: Modify content in a comment and verify that no changes are fired
clear(called1, calledValue1, called2, calledValue2);
addText(layout1, "My ^comment", "new ");
ensureNotCalled(called1, called2);
// Check that editing text in a layout file has no effect
clear(called1, calledValue1, called2, calledValue2);
addText(layout1, " ^ <TextView", "abc");
ensureNotCalled(called1, called2);
// Make sure that's true for replacements too
replaceText(layout1, "^abc", "abc".length(), "def");
ensureNotCalled(called1, called2);
// ...and for deletions
removeText(layout1, "^def", "def".length());
ensureNotCalled(called1, called2);
// Check that editing text in a *values file* -does- have an effect
// Read the value first to ensure that we trigger it as a read (see comment above for previous
// resource resolver lookup)
//noinspection ConstantConditions
assertEquals("Hello", configuration1.getResourceResolver().findResValue("@string/hello_world", false).getValue());
addText(values1, "Hello^</string>", " World");
ensureCalled(called1, calledValue1, called2, calledValue2, Reason.RESOURCE_EDIT);
// Check that recreating AppResourceRepository object doesn't affect the ResourceNotificationManager
clear(called1, calledValue1, called2, calledValue2);
myFacet.refreshResources();
AndroidResourceUtil.createValueResource(getProject(), resourceDir, "color4", ResourceType.COLOR, "colors.xml", Collections.singletonList("values"), "#ff2300");
ensureCalled(called1, calledValue1, called2, calledValue2, Reason.RESOURCE_EDIT);
// Finally check that once we remove the listeners there are no more notifications
manager.removeListener(listener1, myFacet, layout1, configuration1);
manager.removeListener(listener2, myFacet, layout2, configuration1);
clear(called1, calledValue1, called2, calledValue2);
addText(layout1, "@string/hello_world^", "2");
ensureNotCalled(called1, called2);
// TODO: Check that editing a partial URL doesn't re-render
// Check module dependency triggers!
// TODO: Test that remove and replace editing also works as expected
}
Aggregations