public Collection getVariants()

in android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java [182:284]


  public Collection<? extends ResourceValue> getVariants(@NotNull ConvertContext context) {
    Module module = context.getModule();
    if (module == null || module.isDisposed()) return Collections.emptySet();
    AndroidFacet facet = AndroidFacet.getInstance(module);
    if (facet == null) return Collections.emptySet();

    Set<ResourceValue> result = new HashSet<>();
    Set<ResourceType> recommendedTypes = getResourceTypes(context);

    if (recommendedTypes.contains(ResourceType.BOOL) && recommendedTypes.size() < VALUE_RESOURCE_TYPES.size()) {
      // Is this resource reference expected to be a @bool reference? Specifically
      // check that it's not allowed to be *all* resource types since that's a fallback
      // for when we don't have metadata, and we don't want to show true and false
      // as possible completions for things like com.google.android.gms.version
      result.add(ResourceValue.literal(VALUE_TRUE));
      result.add(ResourceValue.literal(VALUE_FALSE));
    }

    // hack to check if it is a real id attribute
    if (recommendedTypes.contains(ResourceType.ID) && recommendedTypes.size() == 1) {
      result.add(ResourceValue.reference(NEW_ID_PREFIX));
    }

    XmlElement element = context.getXmlElement();
    if (element == null) return result;
    String value = getValue(element);
    assert value != null;

    boolean startsWithRefChar = StringUtil.startsWithChar(value, '@');
    if (!myQuiet || startsWithRefChar) {
      ResourceNamespace namespace = null;
      String namespacePrefix = null;
      // Retrieve the system prefix depending on the prefix settings ("@android:" or "android:")
      Matcher matcher = (myWithPrefix ? PREFIX_NAMESPACE_COLON : NAMESPACE_COLON).matcher(value);
      if (matcher.matches()) {
        ResourceNamespaceContext namespacesContext = IdeResourcesUtil.getNamespacesContext(element);
        namespacePrefix = matcher.group(1);
        if (namespacesContext != null) {
          namespace = ResourceNamespace.fromNamespacePrefix(namespacePrefix,
                                                            namespacesContext.getCurrentNs(),
                                                            namespacesContext.getResolver());
        } else {
          namespace = ResourceNamespace.fromPackageName(namespacePrefix);
        }
      }
      else {
        // We don't offer framework resources in completion, unless the string already starts with the framework namespace. But we do offer
        // the right prefix, which will cause the framework resources to show up as follow-up completion. These variants are later handled
        // in createLookupElement below.
        ResourceNamespace.Resolver resolver = IdeResourcesUtil.getNamespaceResolver(element);
        String frameworkPrefix = firstNonNull(resolver.uriToPrefix(ResourceNamespace.ANDROID.getXmlNamespaceUri()),
                                              ResourceNamespace.ANDROID.getPackageName());
        result.add(ResourceValue.literal(myWithPrefix || startsWithRefChar
                                         ? '@' + frameworkPrefix + ':'
                                         : frameworkPrefix + ':'));
      }
      char prefix = myWithPrefix || startsWithRefChar ? '@' : 0;

      if (value.startsWith(NEW_ID_PREFIX)) {
        addVariantsForIdDeclaration(context, facet, prefix, value, result);
      }

      if (myExpandedCompletionSuggestion) {
        // We will add the resource type (e.g. @style/) if the current value starts like a reference using @
        boolean explicitResourceType = startsWithRefChar || myWithExplicitResourceType;
        for (ResourceType type : recommendedTypes) {
          // If getResourceTypes decided SAMPLE_DATA belongs here, then this is one of the few exceptions where it can be referenced.
          if (type.getCanBeReferenced() || type == ResourceType.SAMPLE_DATA) {
            addResourceReferenceValues(facet, element, prefix, type, namespace, result, explicitResourceType, myIncludeDynamicFeatures);
          }
        }
      }
      else {
        Set<ResourceType> filteringSet =
            namespace == ResourceNamespace.ANDROID ? EnumSet.allOf(ResourceType.class) : getResourceTypesInCurrentModule(facet);

        for (ResourceType resourceType : ResourceType.values()) {
          if (!resourceType.getCanBeReferenced()) {
            continue;
          }

          String typePrefix = getTypePrefix(namespacePrefix, resourceType);
          if (value.startsWith(typePrefix)) {
            addResourceReferenceValues(facet, element, prefix, resourceType, namespace, result, true, myIncludeDynamicFeatures);
          }
          else if (recommendedTypes.contains(resourceType) && filteringSet.contains(resourceType)) {
            result.add(ResourceValue.literal(typePrefix));
          }
        }
      }
    }
    if (myAllowAttributeReferences) {
      completeAttributeReferences(value, facet, result);
    }
    ResolvingConverter<String> additionalConverter = getAdditionalConverter(context);

    if (additionalConverter != null) {
      for (String variant : additionalConverter.getVariants(context)) {
        result.add(ResourceValue.literal(variant));
      }
    }
    return result;
  }