mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-67650 support for fragments in layout xml files
This commit is contained in:
@@ -38,6 +38,7 @@ import org.jetbrains.android.dom.attrs.AttributeFormat;
|
||||
import org.jetbrains.android.dom.attrs.StyleableDefinition;
|
||||
import org.jetbrains.android.dom.converters.CompositeConverter;
|
||||
import org.jetbrains.android.dom.converters.ResourceReferenceConverter;
|
||||
import org.jetbrains.android.dom.layout.Fragment;
|
||||
import org.jetbrains.android.dom.layout.Include;
|
||||
import org.jetbrains.android.dom.layout.LayoutElement;
|
||||
import org.jetbrains.android.dom.layout.LayoutViewElement;
|
||||
@@ -375,7 +376,8 @@ public class AndroidDomExtender extends DomExtender<AndroidDomElement> {
|
||||
private static final MyAttributeProcessor ourLayoutAttrsProcessor = new MyAttributeProcessor() {
|
||||
@Override
|
||||
public void process(@NotNull XmlName attrName, @NotNull DomExtension extension, @NotNull DomElement element) {
|
||||
if (element instanceof LayoutViewElement && SdkConstants.NS_RESOURCES.equals(attrName.getNamespaceKey())) {
|
||||
if ((element instanceof LayoutViewElement || element instanceof Fragment) &&
|
||||
SdkConstants.NS_RESOURCES.equals(attrName.getNamespaceKey())) {
|
||||
XmlElement xmlElement = element.getXmlElement();
|
||||
XmlTag tag = xmlElement instanceof XmlTag ? (XmlTag)xmlElement : null;
|
||||
String tagName = tag != null ? tag.getName() : null;
|
||||
@@ -422,15 +424,21 @@ public class AndroidDomExtender extends DomExtender<AndroidDomElement> {
|
||||
}
|
||||
return;
|
||||
}
|
||||
String tagName = tag.getName();
|
||||
if (!tagName.equals("view")) {
|
||||
PsiClass c = map.get(tagName);
|
||||
registerAttributesForClassAndSuperclasses(facet, element, c, registrar, ourLayoutAttrsProcessor);
|
||||
else if (element instanceof Fragment) {
|
||||
registerAttributes(facet, element, new String[]{"Fragment"}, registrar, ourLayoutAttrsProcessor);
|
||||
}
|
||||
else {
|
||||
String[] styleableNames = getClassNames(map.values());
|
||||
registerAttributes(facet, element, styleableNames, registrar, ourLayoutAttrsProcessor);
|
||||
String tagName = tag.getName();
|
||||
if (!tagName.equals("view")) {
|
||||
PsiClass c = map.get(tagName);
|
||||
registerAttributesForClassAndSuperclasses(facet, element, c, registrar, ourLayoutAttrsProcessor);
|
||||
}
|
||||
else {
|
||||
String[] styleableNames = getClassNames(map.values());
|
||||
registerAttributes(facet, element, styleableNames, registrar, ourLayoutAttrsProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
registerLayoutAttributes(facet, element, tag, registrar, ourLayoutAttrsProcessor);
|
||||
|
||||
for (String viewClassName : map.keySet()) {
|
||||
|
||||
+15
-15
@@ -66,28 +66,28 @@ public class PackageClassConverter extends ResolvingConverter<PsiClass> implemen
|
||||
if (s == null) return null;
|
||||
DomElement domElement = context.getInvocationElement();
|
||||
Manifest manifest = domElement.getParentOfType(Manifest.class, true);
|
||||
if (manifest != null) {
|
||||
s = s.replace('$', '.');
|
||||
String packageName = manifest.getPackage().getValue();
|
||||
String className;
|
||||
s = s.replace('$', '.');
|
||||
String packageName = manifest != null ? manifest.getPackage().getValue() : null;
|
||||
String className = null;
|
||||
|
||||
if (packageName != null) {
|
||||
if (s.startsWith(".")) {
|
||||
className = packageName + s;
|
||||
}
|
||||
else {
|
||||
className = packageName + "." + s;
|
||||
}
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getPsiManager().getProject());
|
||||
final Module module = context.getModule();
|
||||
GlobalSearchScope scope = module != null
|
||||
? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)
|
||||
: context.getInvocationElement().getResolveScope();
|
||||
PsiClass psiClass = facade.findClass(className, scope);
|
||||
if (psiClass == null) {
|
||||
psiClass = facade.findClass(s, scope);
|
||||
}
|
||||
return psiClass;
|
||||
}
|
||||
return null;
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getPsiManager().getProject());
|
||||
final Module module = context.getModule();
|
||||
GlobalSearchScope scope = module != null
|
||||
? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)
|
||||
: context.getInvocationElement().getResolveScope();
|
||||
PsiClass psiClass = className != null ? facade.findClass(className, scope) : null;
|
||||
if (psiClass == null) {
|
||||
psiClass = facade.findClass(s, scope);
|
||||
}
|
||||
return psiClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.android.dom.layout;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.util.xml.Attribute;
|
||||
import com.intellij.util.xml.Convert;
|
||||
import com.intellij.util.xml.ExtendClass;
|
||||
import com.intellij.util.xml.GenericAttributeValue;
|
||||
import org.jetbrains.android.dom.AndroidAttributeValue;
|
||||
import org.jetbrains.android.dom.converters.PackageClassConverter;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public interface Fragment extends LayoutElement {
|
||||
@Attribute("name")
|
||||
@Convert(PackageClassConverter.class)
|
||||
@ExtendClass("android.app.Fragment")
|
||||
AndroidAttributeValue<PsiClass> getFragmentName();
|
||||
|
||||
@Attribute("class")
|
||||
@Convert(PackageClassConverter.class)
|
||||
@ExtendClass("android.app.Fragment")
|
||||
GenericAttributeValue<PsiClass> getFragmentClass();
|
||||
}
|
||||
@@ -46,4 +46,6 @@ public interface LayoutViewElement extends LayoutElement {
|
||||
GenericAttributeValue<PsiClass> getViewClass();
|
||||
|
||||
List<Include> getIncludes();
|
||||
|
||||
List<Fragment> getFragments();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
package android.app;
|
||||
|
||||
public class Fragment {}
|
||||
@@ -0,0 +1,6 @@
|
||||
package p1.p2;
|
||||
|
||||
public class MyFragmentActivity extends android.app.Activity {
|
||||
public static class MyFragment extends android.app.Fragment {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<fragment class="p<caret>"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<fragment class="p1.p2.MyFragmentActivity$MyFragment"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<frag<caret>/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<fragment/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<fragment android:ta<caret>/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<fragment android:tag=""/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,19 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<fragment class="p1.p2.MyFragmentActivity$MyFragment" android:layout_weight="1"
|
||||
android:layout_width="0px" android:layout_height="match_parent" />
|
||||
|
||||
<fragment class="<error>aba</error>" android:layout_weight="1"
|
||||
android:layout_width="0px" android:layout_height="match_parent" />
|
||||
|
||||
<fragment android:name="p1.p2.MyFragmentActivity$MyFragment" android:layout_weight="1"
|
||||
android:layout_width="0px" android:layout_height="match_parent" />
|
||||
|
||||
<fragment android:name="<error>aba</error>" android:layout_weight="1"
|
||||
android:layout_width="0px" android:layout_height="match_parent" />
|
||||
|
||||
<<error>fragment</error> class="p1.p2.MyFragmentActivity$MyFragment"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -22,6 +22,10 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, SdkConstants.FN_ANDROID_MANIFEST_XML);
|
||||
|
||||
// copy mock fragment, because it is not included to old android.jar
|
||||
// todo: create normal mock Android sdk
|
||||
copyFileToProject("Fragment.java", "src/android/app/Fragment.java");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -206,6 +210,24 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
|
||||
doTestHighlighting("merge.xml");
|
||||
}
|
||||
|
||||
public void testFragmentHighlighting() throws Throwable {
|
||||
copyFileToProject("MyFragmentActivity.java", "src/p1/p2/MyFragmentActivity.java");
|
||||
doTestHighlighting(getTestName(true) + ".xml");
|
||||
}
|
||||
|
||||
public void testFragmentCompletion1() throws Throwable {
|
||||
copyFileToProject("MyFragmentActivity.java", "src/p1/p2/MyFragmentActivity.java");
|
||||
toTestCompletion(getTestName(true) + ".xml", getTestName(true) + "_after.xml");
|
||||
}
|
||||
|
||||
public void testFragmentCompletion2() throws Throwable {
|
||||
toTestCompletion(getTestName(true) + ".xml", getTestName(true) + "_after.xml");
|
||||
}
|
||||
|
||||
public void testFragmentCompletion3() throws Throwable {
|
||||
toTestCompletion(getTestName(true) + ".xml", getTestName(true) + "_after.xml");
|
||||
}
|
||||
|
||||
/*public void testCustomAttrsPerformance() throws Throwable {
|
||||
myFixture.copyFileToProject("dom/resources/bigfile.xml", "res/values/bigfile.xml");
|
||||
myFixture.copyFileToProject("dom/resources/bigattrs.xml", "res/values/bigattrs.xml");
|
||||
|
||||
Reference in New Issue
Block a user