Search in sources :

Example 11 with XmlName

use of com.intellij.util.xml.XmlName in project android by JetBrains.

the class AttributeProcessingUtil method registerAttribute.

private static void registerAttribute(@NotNull AttributeDefinition attrDef, @Nullable String parentStyleableName, @Nullable String namespaceKey, @NotNull DomElement element, @NotNull AttributeProcessor callback) {
    String name = attrDef.getName();
    if (!NS_RESOURCES.equals(namespaceKey) && name.startsWith(PREFIX_ANDROID)) {
        // A styleable-definition in the app namespace (user specified or from a library) can include
        // a reference to a platform attribute. In such a case, register it under the android namespace
        // as opposed to the app namespace. See https://code.google.com/p/android/issues/detail?id=171162
        name = name.substring(PREFIX_ANDROID.length());
        namespaceKey = NS_RESOURCES;
    }
    XmlName xmlName = new XmlName(name, namespaceKey);
    final DomExtension extension = callback.processAttribute(xmlName, attrDef, parentStyleableName);
    if (extension == null) {
        return;
    }
    Converter converter = AndroidDomUtil.getSpecificConverter(xmlName, element);
    if (converter == null) {
        if (TOOLS_URI.equals(namespaceKey)) {
            converter = ToolsAttributeUtil.getConverter(attrDef);
        } else {
            converter = AndroidDomUtil.getConverter(attrDef);
            if (converter != null && element.getParentOfType(Manifest.class, true) != null) {
                converter = new ManifestPlaceholderConverter(converter);
            }
        }
    }
    if (converter != null) {
        extension.setConverter(converter, mustBeSoft(converter, attrDef.getFormats()));
    }
    // tag completion. If attribute is not required, no additional action is needed.
    if (element instanceof LayoutElement && isLayoutAttributeRequired(xmlName, element) || element instanceof ManifestElement && AndroidManifestUtils.isRequiredAttribute(xmlName, element)) {
        extension.addCustomAnnotation(new RequiredImpl());
    }
}
Also used : DomExtension(com.intellij.util.xml.reflect.DomExtension) ManifestElement(org.jetbrains.android.dom.manifest.ManifestElement) ManifestPlaceholderConverter(org.jetbrains.android.dom.converters.ManifestPlaceholderConverter) XmlName(com.intellij.util.xml.XmlName) CompositeConverter(org.jetbrains.android.dom.converters.CompositeConverter) Converter(com.intellij.util.xml.Converter) ResourceReferenceConverter(org.jetbrains.android.dom.converters.ResourceReferenceConverter) ManifestPlaceholderConverter(org.jetbrains.android.dom.converters.ManifestPlaceholderConverter) ResolvingConverter(com.intellij.util.xml.ResolvingConverter)

Example 12 with XmlName

use of com.intellij.util.xml.XmlName in project android by JetBrains.

the class AttributeProcessingUtil method processXmlAttributes.

/**
   * Yield attributes for resources in xml/ folder
   */
public static void processXmlAttributes(@NotNull AndroidFacet facet, @NotNull XmlTag tag, @NotNull XmlResourceElement element, @NotNull Set<XmlName> skipAttrNames, @NotNull AttributeProcessor callback) {
    final String tagName = tag.getName();
    String styleableName = AndroidXmlResourcesUtil.SPECIAL_STYLEABLE_NAMES.get(tagName);
    if (styleableName != null) {
        final Set<XmlName> newSkipAttrNames = new HashSet<>();
        if (element instanceof Intent) {
            newSkipAttrNames.add(new XmlName("action", NS_RESOURCES));
        }
        registerAttributes(facet, element, styleableName, SYSTEM_RESOURCE_PACKAGE, callback, newSkipAttrNames);
    }
    // for preferences
    Map<String, PsiClass> prefClassMap = getPreferencesClassMap(facet);
    String prefClassName = element.getXmlTag().getName();
    PsiClass c = prefClassMap.get(prefClassName);
    // register attributes by preference class
    registerAttributesForClassAndSuperclasses(facet, element, c, callback, skipAttrNames);
    // register attributes by widget
    String widgetClassName = AndroidTextUtils.trimEndOrNullize(prefClassName, PREFERENCE_TAG_NAME);
    if (widgetClassName != null) {
        PsiClass widgetClass = LayoutViewClassUtils.findClassByTagName(facet, widgetClassName, AndroidUtils.VIEW_CLASS_NAME);
        registerAttributesForClassAndSuperclasses(facet, element, widgetClass, callback, skipAttrNames);
    }
}
Also used : PsiClass(com.intellij.psi.PsiClass) XmlName(com.intellij.util.xml.XmlName) Intent(org.jetbrains.android.dom.xml.Intent)

Example 13 with XmlName

use of com.intellij.util.xml.XmlName in project android by JetBrains.

the class AttributeProcessingUtil method processAttributes.

/**
   * Enumerate attributes that are available for the given XML tag, represented by {@link AndroidDomElement},
   * and "return" them via {@link AttributeProcessor}.
   *
   * Primary user is {@link AndroidDomExtender}, which uses it to provide code completion facilities when
   * editing XML files in text editor.
   *
   * Implementation of the method implements {@link Styleable} annotation handling and dispatches on tag type
   * using instanceof checks for adding attributes that don't come from styleable definitions with statically
   * known names.
   *
   * @param processAllExistingAttrsFirst whether already existing attributes should be returned first
   */
public static void processAttributes(@NotNull AndroidDomElement element, @NotNull AndroidFacet facet, boolean processAllExistingAttrsFirst, @NotNull AttributeProcessor callback) {
    XmlTag tag = element.getXmlTag();
    final Set<XmlName> skippedAttributes = processAllExistingAttrsFirst ? registerExistingAttributes(facet, tag, element, callback) : new HashSet<>();
    if (element instanceof ManifestElement) {
        processManifestAttributes(tag, element, callback);
    } else if (element instanceof LayoutElement) {
        processLayoutAttributes(facet, tag, (LayoutElement) element, skippedAttributes, callback);
    } else if (element instanceof XmlResourceElement) {
        processXmlAttributes(facet, tag, (XmlResourceElement) element, skippedAttributes, callback);
    } else if (element instanceof XmlRawResourceElement) {
        processRawAttributes(tag, callback);
    }
    // If DOM element is annotated with @Styleable annotation, load a styleable definition
    // from Android framework with the name provided in annotation and register all attributes
    // from it for code highlighting and completion.
    final Styleable styleableAnnotation = element.getAnnotation(Styleable.class);
    if (styleableAnnotation == null) {
        return;
    }
    final SystemResourceManager manager = facet.getSystemResourceManager();
    if (manager == null) {
        return;
    }
    final AttributeDefinitions definitions = manager.getAttributeDefinitions();
    if (definitions == null) {
        return;
    }
    if (element instanceof MenuItem) {
        processMenuItemAttributes(facet, element, skippedAttributes, callback);
        return;
    }
    for (String styleableName : styleableAnnotation.value()) {
        final StyleableDefinition styleable = definitions.getStyleableByName(styleableName);
        if (styleable == null) {
            // DOM element is annotated with @Styleable annotation, but styleable definition with
            // provided name is not there in Android framework. This is a bug, so logging it as a warning.
            getLog().warn(String.format("@Styleable(%s) annotation doesn't point to existing styleable", styleableName));
        } else {
            registerStyleableAttributes(element, styleable, ANDROID_URI, callback, skippedAttributes);
        }
    }
    // TODO: figure it out how to make it DRY without introducing new method with lots of arguments
    if (element instanceof InterpolatorElement) {
        final String styleableName = InterpolatorDomFileDescription.getInterpolatorStyleableByTagName(tag.getName());
        if (styleableName != null) {
            final StyleableDefinition styleable = definitions.getStyleableByName(styleableName);
            if (styleable == null) {
                getLog().warn(String.format("%s doesn't point to existing styleable for interpolator", styleableName));
            } else {
                registerStyleableAttributes(element, styleable, ANDROID_URI, callback, skippedAttributes);
            }
        }
    }
}
Also used : ManifestElement(org.jetbrains.android.dom.manifest.ManifestElement) XmlResourceElement(org.jetbrains.android.dom.xml.XmlResourceElement) MenuItem(org.jetbrains.android.dom.menu.MenuItem) XmlRawResourceElement(org.jetbrains.android.dom.raw.XmlRawResourceElement) InterpolatorElement(org.jetbrains.android.dom.animation.InterpolatorElement) XmlName(com.intellij.util.xml.XmlName) SystemResourceManager(org.jetbrains.android.resourceManagers.SystemResourceManager) XmlTag(com.intellij.psi.xml.XmlTag)

Example 14 with XmlName

use of com.intellij.util.xml.XmlName in project android by JetBrains.

the class AttributeProcessingUtil method registerStyleableAttributes.

private static void registerStyleableAttributes(@NotNull DomElement element, @NotNull StyleableDefinition styleable, @Nullable String namespace, @NotNull AttributeProcessor callback, @NotNull Set<XmlName> skippedAttributes) {
    for (AttributeDefinition attrDef : styleable.getAttributes()) {
        String attrName = attrDef.getName();
        final XmlName xmlName = new XmlName(attrName, namespace);
        if (!skippedAttributes.contains(xmlName)) {
            skippedAttributes.add(xmlName);
            registerAttribute(attrDef, styleable.getName(), namespace, element, callback);
        }
    }
}
Also used : XmlName(com.intellij.util.xml.XmlName)

Example 15 with XmlName

use of com.intellij.util.xml.XmlName in project android by JetBrains.

the class AttributeProcessingUtil method registerToolsAttribute.

private static void registerToolsAttribute(@NotNull String attributeName, @NotNull AttributeProcessor callback) {
    final AttributeDefinition definition = ToolsAttributeUtil.getAttrDefByName(attributeName);
    if (definition != null) {
        final XmlName name = new XmlName(attributeName, TOOLS_URI);
        final DomExtension domExtension = callback.processAttribute(name, definition, null);
        final ResolvingConverter converter = ToolsAttributeUtil.getConverter(definition);
        if (domExtension != null && converter != null) {
            domExtension.setConverter(converter);
        }
    } else {
        getLog().warn("No attribute definition for tools attribute " + attributeName);
    }
}
Also used : DomExtension(com.intellij.util.xml.reflect.DomExtension) ResolvingConverter(com.intellij.util.xml.ResolvingConverter) XmlName(com.intellij.util.xml.XmlName)

Aggregations

XmlName (com.intellij.util.xml.XmlName)15 EvaluatedXmlName (com.intellij.util.xml.EvaluatedXmlName)3 DomExtension (com.intellij.util.xml.reflect.DomExtension)3 XmlAttribute (com.intellij.psi.xml.XmlAttribute)2 XmlFile (com.intellij.psi.xml.XmlFile)2 XmlTag (com.intellij.psi.xml.XmlTag)2 EvaluatedXmlNameImpl (com.intellij.util.xml.EvaluatedXmlNameImpl)2 ResolvingConverter (com.intellij.util.xml.ResolvingConverter)2 CustomDomChildrenDescription (com.intellij.util.xml.reflect.CustomDomChildrenDescription)2 ManifestElement (org.jetbrains.android.dom.manifest.ManifestElement)2 SystemResourceManager (org.jetbrains.android.resourceManagers.SystemResourceManager)2 NotNull (org.jetbrains.annotations.NotNull)2 Nullable (org.jetbrains.annotations.Nullable)2 AndroidModuleModel (com.android.tools.idea.gradle.project.model.AndroidModuleModel)1 NullableComputable (com.intellij.openapi.util.NullableComputable)1 RecursionGuard (com.intellij.openapi.util.RecursionGuard)1 PsiClass (com.intellij.psi.PsiClass)1 PsiElement (com.intellij.psi.PsiElement)1 XmlElementType (com.intellij.psi.xml.XmlElementType)1 Converter (com.intellij.util.xml.Converter)1