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

org.jetbrains.plugins.groovy.lang.psi.impl.statements.arguments.GrArgumentLabelImpl Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition groovy-psi 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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.arguments;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.extensions.GroovyNamedArgumentProvider;
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrParenthesizedExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;

import java.util.Map;

/**
 * @author ilyas
 */
public class GrArgumentLabelImpl extends GroovyPsiElementImpl implements GrArgumentLabel {

  public GrArgumentLabelImpl(@NotNull ASTNode node) {
    super(node);
  }

  @Override
  public void accept(GroovyElementVisitor visitor) {
    visitor.visitArgumentLabel(this);
  }

  public String toString() {
    return "Argument label";
  }

  @Nullable
  private PsiPolyVariantReference getReferenceFromNamedArgumentProviders() {
    PsiElement namedArgument = getParent();
    if (!(namedArgument instanceof GrNamedArgument)) return null;

    PsiElement nameElement = getNameElement();
    if (!(nameElement instanceof LeafPsiElement)) return null;

    IElementType elementType = ((LeafPsiElement)nameElement).getElementType();
    if (elementType != GroovyTokenTypes.mIDENT && !CommonClassNames.JAVA_LANG_STRING.equals(TypesUtil.getBoxedTypeName(elementType))) {
      return null;
    }

    GrCall call = PsiUtil.getCallByNamedParameter((GrNamedArgument)namedArgument);
    if (call == null) return null;

    String labelName = getName();

    Map providers = GroovyNamedArgumentProvider.getNamedArgumentsFromAllProviders(call, labelName, false);
    if (providers != null) {
      NamedArgumentDescriptor descr = providers.get(labelName);
      if (descr != null) {
        PsiPolyVariantReference res = descr.createReference(this);
        if (res != null) {
          return res;
        }
      }
    }

    return null;
  }

  @NotNull
  private PsiPolyVariantReference getRealReference() {
    PsiReference[] otherReferences = ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);
    PsiPolyVariantReference reference = getReferenceFromNamedArgumentProviders();

    if (otherReferences.length == 0) {
      if (reference != null) {
        return reference;
      }
      else {
        return new PsiPolyVariantReferenceBase(this) {

          @NotNull
          @Override
          public Object[] getVariants() {
            return ArrayUtil.EMPTY_OBJECT_ARRAY;
          }

          @NotNull
          @Override
          public ResolveResult[] multiResolve(boolean incompleteCode) {
            return ResolveResult.EMPTY_ARRAY;
          }
        };
      }
    }
    else {
      if (reference != null) {
        PsiReference[] refs = new PsiReference[otherReferences.length + 1];
        refs[0] = reference;
        //noinspection ManualArrayCopy
        for (int i = 0; i < otherReferences.length; i++) {
          refs[i + 1] = otherReferences[i];
        }

        otherReferences = refs;
      }

      return new PsiMultiReference(otherReferences, this);
    }
  }

  @Override
  public PsiReference getReference() {
    final PsiElement name = getNameElement();
    return name instanceof GrLiteral || name instanceof LeafPsiElement ? this : null;
  }

  @Override
  @Nullable
  public String getName() {
    final PsiElement element = getNameElement();
    if (element instanceof GrLiteral) {
      return convertToString(((GrLiteral)element).getValue());
    }
    if (element instanceof GrExpression) {
      final Object value = JavaPsiFacade.getInstance(getProject()).getConstantEvaluationHelper().computeConstantExpression(element);
      if (value instanceof String) {
        return (String)value;
      }
    }

    final IElementType elemType = element.getNode().getElementType();
    if (GroovyTokenTypes.mIDENT == elemType || TokenSets.KEYWORDS.contains(elemType)) {
      return element.getText();
    }

    return convertToString(GrLiteralImpl.getLiteralValue(element));
  }

  private static String convertToString(Object value) {
    if (value instanceof String) {
      return (String)value;
    }

    if (value instanceof Number) {
      return value.toString();
    }
    return null;
  }

  @Override
  public PsiElement getElement() {
    return this;
  }

  @Override
  public TextRange getRangeInElement() {
    return new TextRange(0, getTextLength());
  }

  @Override
  @Nullable
  public PsiElement resolve() {
    return advancedResolve().getElement();
  }

  @NotNull
  @Override
  public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
    final ResolveResult[] results = getRealReference().multiResolve(incompleteCode);
    if (results instanceof GroovyResolveResult[]) {
      return (GroovyResolveResult[])results;
    }
    else {
      final GroovyResolveResult[] results1 = new GroovyResolveResult[results.length];
      for (int i = 0; i < results.length; i++) {
        ResolveResult result = results[i];
        final PsiElement element = result.getElement();
        if (element == null) {
          results1[i] = GroovyResolveResult.EMPTY_RESULT;
        }
        else {
          results1[i] = new GroovyResolveResultImpl(element, true);
        }
      }
      return results1;
    }
  }

  @NotNull
  @Override
  public GroovyResolveResult advancedResolve() {
    return PsiImplUtil.extractUniqueResult(multiResolve(false));
  }

  @Override
  @NotNull
  public String getCanonicalText() {
    PsiElement resolved = resolve();
    if (resolved instanceof PsiMember && resolved instanceof PsiNamedElement) {
      PsiClass clazz = ((PsiMember) resolved).getContainingClass();
      if (clazz != null) {
        String qName = clazz.getQualifiedName();
        if (qName != null) {
          return qName + "." + ((PsiNamedElement) resolved).getName();
        }
      }
    }

    return getText();
  }

  @Override
  public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
    return getRealReference().handleElementRename(newElementName);
  }

  @Override
  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
    return getRealReference().bindToElement(element);
  }

  @Override
  public boolean isReferenceTo(PsiElement element) {
    return getRealReference().isReferenceTo(element);
  }

  @Override
  @NotNull
  public Object[] getVariants() {
    return ArrayUtil.EMPTY_OBJECT_ARRAY;
  }

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

  @Override
  @NotNull
  public PsiElement getNameElement() {
    final PsiElement element = getFirstChild();
    assert element != null;
    return element;
  }

  @Override
  public GrExpression getExpression() {
    final PsiElement nameElement = getNameElement();
    if (nameElement instanceof GrParenthesizedExpression) return ((GrParenthesizedExpression)nameElement).getOperand();
    return null;
  }

  @Override
  @Nullable
  public PsiType getExpectedArgumentType() { // TODO use GroovyNamedArgumentProvider to determinate expected argument type.
    return null;
  }

  @Override
  public PsiType getLabelType() {
    PsiElement el = getNameElement();
    if (el instanceof GrParenthesizedExpression) {
      return ((GrParenthesizedExpression)el).getType();
    }

    final ASTNode node = el.getNode();
    if (node == null) {
      return null;
    }

    PsiType nodeType = TypesUtil.getPsiType(el, node.getElementType());
    if (nodeType != null) {
      return nodeType;
    }
    return TypesUtil.createType(CommonClassNames.JAVA_LANG_STRING, this);
  }

  @Override
  public GrNamedArgument getNamedArgument() {
    final PsiElement parent = getParent();
    assert parent instanceof GrNamedArgument;
    return (GrNamedArgument)parent;
  }

  @Override
  public PsiElement setName(@NotNull String newName) {
    PsiImplUtil.setName(newName, getNameElement());
    return this;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy