All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.codeInsight.hint.api.impls.XmlParameterInfoHandler Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition xml library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2014 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 com.intellij.codeInsight.hint.api.impls;

import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.MutableLookupElement;
import com.intellij.lang.parameterInfo.*;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlToken;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.Function;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.Comparator;

/**
 * @author Maxim.Mossienko
 */
public class XmlParameterInfoHandler implements ParameterInfoHandler {
  private static final Comparator COMPARATOR = new Comparator() {
    @Override
    public int compare(final XmlAttributeDescriptor o1, final XmlAttributeDescriptor o2) {
      return o1.getName().compareTo(o2.getName());
    }
  };

  @Override
  public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
    if (!(item instanceof MutableLookupElement)) return null;
    final Object lookupItem = item.getObject();
    if (lookupItem instanceof XmlElementDescriptor) return new Object[]{lookupItem};
    return null;
  }

  @Override
  public Object[] getParametersForDocumentation(final XmlElementDescriptor p, final ParameterInfoContext context) {
    return getSortedDescriptors(p);
  }

  public static XmlAttributeDescriptor[] getSortedDescriptors(final XmlElementDescriptor p) {
    final XmlAttributeDescriptor[] xmlAttributeDescriptors = p.getAttributesDescriptors(null);
    Arrays.sort(xmlAttributeDescriptors, COMPARATOR);
    return xmlAttributeDescriptors;
  }

  @Override
  public boolean couldShowInLookup() {
    return true;
  }

  @Override
  public XmlTag findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
    final XmlTag tag = findXmlTag(context.getFile(), context.getOffset());
    final XmlElementDescriptor descriptor = tag != null ? tag.getDescriptor() : null;

    if (descriptor == null) {
      DaemonCodeAnalyzer.getInstance(context.getProject()).updateVisibleHighlighters(context.getEditor());
      return null;
    }

    context.setItemsToShow(new Object[] {descriptor});
    return tag;
  }

  @Override
  public void showParameterInfo(final @NotNull XmlTag element, @NotNull final CreateParameterInfoContext context) {
    context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
  }

  @Override
  public XmlTag findElementForUpdatingParameterInfo(@NotNull final UpdateParameterInfoContext context) {
    final XmlTag tag = findXmlTag(context.getFile(), context.getOffset());
    if (tag != null) {
      final PsiElement currentXmlTag = context.getParameterOwner();
      if (currentXmlTag == null || currentXmlTag == tag) return tag;
    }

    return null;
  }

  @Override
  public void updateParameterInfo(@NotNull final XmlTag parameterOwner, @NotNull final UpdateParameterInfoContext context) {
    if (context.getParameterOwner() == null || parameterOwner.equals(context.getParameterOwner())) {
      context.setParameterOwner(parameterOwner);
    } else {
      context.removeHint();
    }
  }

  @Override
  public String getParameterCloseChars() {
    return null;
  }

  @Override
  public boolean tracksParameterIndex() {
    return false;
  }

  @Nullable
  private static XmlTag findXmlTag(PsiFile file, int offset){
    if (!(file instanceof XmlFile)) return null;

    PsiElement element = file.findElementAt(offset);
    if (element == null) return null;
    element = element.getParent();

    while (element != null) {
      if (element instanceof XmlTag) {
        XmlTag tag = (XmlTag)element;

        final PsiElement[] children = tag.getChildren();

        if (offset <= children[0].getTextRange().getStartOffset()) return null;

        for (PsiElement child : children) {
          final TextRange range = child.getTextRange();
          if (range.getStartOffset() <= offset && range.getEndOffset() > offset) return tag;

          if (child instanceof XmlToken) {
            XmlToken token = (XmlToken)child;
            if (token.getTokenType() == XmlTokenType.XML_TAG_END) return null;
          }
        }

        return null;
      }

      element = element.getParent();
    }

    return null;
  }

  @Override
  public void updateUI(XmlElementDescriptor o, @NotNull final ParameterInfoUIContext context) {
    updateElementDescriptor(
      o,
      context,
      new Function() {
        final XmlTag parameterOwner  = (XmlTag)context.getParameterOwner();

        @Override
        public Boolean fun(String s) {
          return parameterOwner != null && parameterOwner.getAttributeValue(s) != null;
        }
      });
  }

  public static void updateElementDescriptor(XmlElementDescriptor descriptor, ParameterInfoUIContext context,
                                             Function attributePresentFun) {
    final XmlAttributeDescriptor[] attributes = descriptor != null ? getSortedDescriptors(descriptor) : XmlAttributeDescriptor.EMPTY;

    StringBuilder buffer = new StringBuilder();
    int highlightStartOffset = -1;
    int highlightEndOffset = -1;

    if (attributes.length == 0) {
      buffer.append(CodeInsightBundle.message("xml.tag.info.no.attributes"));
    }
    else {
      StringBuilder text1 = new StringBuilder(" ");
      StringBuilder text2 = new StringBuilder(" ");
      StringBuilder text3 = new StringBuilder(" ");

      for (XmlAttributeDescriptor attribute : attributes) {
        if (Boolean.TRUE.equals(attributePresentFun.fun(attribute.getName()))) {
          if (!(text1.toString().equals(" "))) {
            text1.append(", ");
          }
          text1.append(attribute.getName());
        }
        else if (attribute.isRequired()) {
          if (!(text2.toString().equals(" "))) {
            text2.append(", ");
          }
          text2.append(attribute.getName());
        }
        else {
          if (!(text3.toString().equals(" "))) {
            text3.append(", ");
          }
          text3.append(attribute.getName());
        }
      }

      if (!text1.toString().equals(" ") && !text2.toString().equals(" ")) {
        text1.append(", ");
      }

      if (!text2.toString().equals(" ") && !text3.toString().equals(" ")) {
        text2.append(", ");
      }

      if (!text1.toString().equals(" ") && !text3.toString().equals(" ") && text2.toString().equals(" ")) {
        text1.append(", ");
      }

      buffer.append(text1);
      highlightStartOffset = buffer.length();
      buffer.append(text2);
      highlightEndOffset = buffer.length();
      buffer.append(text3);
    }

    context.setupUIComponentPresentation(buffer.toString(), highlightStartOffset, highlightEndOffset, false,
                                         false, true, context.getDefaultParameterColor());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy