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

org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment 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.debugger.fragments;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.file.impl.FileManager;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.scope.NameHint;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnAmbiguousClosureContainer;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author ven
 */
public class GroovyCodeFragment extends GroovyFileImpl implements JavaCodeFragment, IntentionFilterOwner, GrUnAmbiguousClosureContainer {
  private PsiType myThisType;
  private PsiType mySuperType;
  private ExceptionHandler myExceptionChecker;
  private IntentionFilterOwner.IntentionActionsFilter myFilter;
  private GlobalSearchScope myResolveScope;

  /**
   * map from a class's imported name (e.g. its short name or alias) to its qualified name
   */
  private final LinkedHashMap myPseudoImports = ContainerUtil.newLinkedHashMap();
  private final ArrayList myOnDemandImports = ContainerUtil.newArrayList();
  private FileViewProvider myViewProvider = null;

  public GroovyCodeFragment(Project project, CharSequence text) {
    this(project, new LightVirtualFile("Dummy.groovy", GroovyFileType.GROOVY_FILE_TYPE, text));
  }

  public GroovyCodeFragment(Project project, VirtualFile virtualFile) {
    super(new SingleRootFileViewProvider(PsiManager.getInstance(project), virtualFile, true));
    ((SingleRootFileViewProvider)getViewProvider()).forceCachedPsi(this);
  }

  @Override
  public void setThisType(PsiType thisType) {
    myThisType = thisType;
  }

  @Override
  public PsiType getSuperType() {
    return mySuperType;
  }

  @Override
  public void setSuperType(PsiType superType) {
    mySuperType = superType;
  }

  @Override
  @NotNull
  public FileViewProvider getViewProvider() {
    if (myViewProvider != null) return myViewProvider;
    return super.getViewProvider();
  }

  @Override
  public boolean isValid() {
    if (!super.isValid()) return false;
    PsiElement context = getContext();
    return context == null || context.isValid();
  }

  /**
   * @return list of imports in format "qname[:imported_name](,qname[:imported_name])*"
   */
  @Override
  public String importsToString() {
    if (myPseudoImports.isEmpty()) return "";

    StringBuilder buffer = new StringBuilder();
    for (Map.Entry entry : myPseudoImports.entrySet()) {
      final String importedName = entry.getKey();
      final GrImportStatement anImport = entry.getValue();


      //buffer.append(anImport.isStatic() ? "+" : "-");
      final String qname = anImport.getImportReference().getClassNameText();

      buffer.append(qname);
      buffer.append(':').append(importedName);
      buffer.append(',');
    }

    for (GrImportStatement anImport : myOnDemandImports) {
      //buffer.append(anImport.isStatic() ? "+" : "-");

      String packName = anImport.getImportReference().getClassNameText();
      buffer.append(packName);
      buffer.append(',');
    }
    buffer.deleteCharAt(buffer.length() - 1);
    return buffer.toString();
  }

  @Override
  public void addImportsFromString(String imports) {
    for (String anImport : imports.split(",")) {
      int colon = anImport.indexOf(':');

      if (colon >= 0) {
        String qname = anImport.substring(0, colon);
        String importedName = anImport.substring(colon + 1);
        myPseudoImports.put(importedName, createSingleImport(qname, importedName));
      }
      else {
        myOnDemandImports.add(createImportOnDemand(anImport));
      }
    }
  }

  @Override
  public void setVisibilityChecker(JavaCodeFragment.VisibilityChecker checker) {
  }

  @Override
  public VisibilityChecker getVisibilityChecker() {
    return VisibilityChecker.EVERYTHING_VISIBLE;
  }

  @Override
  public void setExceptionHandler(ExceptionHandler checker) {
    myExceptionChecker = checker;
  }

  @Override
  public ExceptionHandler getExceptionHandler() {
    return myExceptionChecker;
  }

  @Override
  public void setIntentionActionsFilter(@NotNull IntentionActionsFilter filter) {
    myFilter = filter;
  }

  @Override
  public IntentionActionsFilter getIntentionActionsFilter() {
    return myFilter;
  }

  @Override
  public void forceResolveScope(GlobalSearchScope scope) {
    myResolveScope = scope;
  }

  @Override
  public GlobalSearchScope getForcedResolveScope() {
    return myResolveScope;
  }

  @Override
  public boolean importClass(PsiClass aClass) {
    return false;
  }

  @Override
  public PsiType getThisType() {
    return myThisType;
  }

  @Override
  protected boolean processImports(PsiScopeProcessor processor,
                                   @NotNull ResolveState state,
                                   PsiElement lastParent,
                                   @NotNull PsiElement place,
                                   @NotNull GrImportStatement[] importStatements,
                                   boolean onDemand) {
    if (!super.processImports(processor, state, lastParent, place, importStatements, onDemand)) {
      return false;
    }
    if (!processPseudoImports(processor, state, lastParent, place, onDemand)) {
      return false;
    }

    return true;
  }

  @Override
  protected GroovyCodeFragment clone() {
    final GroovyCodeFragment clone = (GroovyCodeFragment)cloneImpl((FileElement)calcTreeElement().clone());
    clone.myOriginalFile = this;
    clone.myPseudoImports.putAll(myPseudoImports);
    FileManager fileManager = ((PsiManagerEx)getManager()).getFileManager();
    SingleRootFileViewProvider cloneViewProvider = (SingleRootFileViewProvider)fileManager.createFileViewProvider(new LightVirtualFile(
      getName(),
      getLanguage(),
      getText()), false);
    cloneViewProvider.forceCachedPsi(clone);
    clone.myViewProvider = cloneViewProvider;
    return clone;
  }

  protected boolean processPseudoImports(PsiScopeProcessor processor,
                                         @NotNull ResolveState state,
                                         PsiElement lastParent,
                                         PsiElement place,
                                         boolean onDemand) {
    if (onDemand) {
      if (!processImportsOnDemand(processor, state, lastParent, place)) {
        return false;
      }
    }
    else {
      if (!processSingleImports(processor, state, lastParent, place)) {
        return false;
      }
    }
    return true;
  }

  private boolean processImportsOnDemand(PsiScopeProcessor processor, ResolveState state, PsiElement parent, PsiElement place) {
    for (GrImportStatement anImport : myOnDemandImports) {
      if (!anImport.processDeclarations(processor, state, parent, place)) {
        return false;
      }
    }
    return true;
  }

  private boolean processSingleImports(PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, PsiElement place) {
    NameHint nameHint = processor.getHint(NameHint.KEY);
    String name = nameHint != null ? nameHint.getName(state) : null;

    if (name != null) {
      final GrImportStatement anImport = myPseudoImports.get(name);
      if (anImport != null) {
        if (!anImport.processDeclarations(processor, state, lastParent, place)) {
          return false;
        }
      }
    }
    else {
      for (GrImportStatement anImport : myPseudoImports.values()) {
        if (!anImport.processDeclarations(processor, state, lastParent, place)) {
          return false;
        }
      }
    }
    return true;
  }

  @Nullable
  private GrImportStatement createImportOnDemand(@NotNull String qname) {
    final PsiClass aClass = JavaPsiFacade.getInstance(getProject()).findClass(qname, getResolveScope());
    final boolean isStatic = aClass != null;

    final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(getProject());
    try {
      return factory.createImportStatement(qname, isStatic, true, null, this);
    }
    catch (IncorrectOperationException e) {
      return null;
    }
  }

  @Nullable
  private GrImportStatement createSingleImport(@NotNull String qname, @Nullable String importedName) {
    final PsiClass aClass = JavaPsiFacade.getInstance(getProject()).findClass(qname, getResolveScope());
    final boolean isStatic = aClass == null;

    final String className = PsiNameHelper.getShortClassName(qname);
    final String alias = importedName == null || className.equals(importedName) ? null : importedName;
    final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(getProject());
    try {
      return factory.createImportStatement(qname, isStatic, false, alias, this);
    }
    catch (IncorrectOperationException e) {
      return null;
    }
  }

  public void clearImports() {
    myPseudoImports.clear();
    myOnDemandImports.clear();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy