private void runAfterCommitActions(@NotNull Document document) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    List<Runnable> list;
    synchronized (ACTION_AFTER_COMMIT) {
      list = document.getUserData(ACTION_AFTER_COMMIT);
      if (list != null) {
        list = new ArrayList<Runnable>(list);
        document.putUserData(ACTION_AFTER_COMMIT, null);
      }
    }
    if (list != null) {
      for (final Runnable runnable : list) {
        runnable.run();
      }
    }

    if (!hasUncommitedDocuments() && !actionsWhenAllDocumentsAreCommitted.isEmpty()) {
      List<Object> keys = new ArrayList<Object>(actionsWhenAllDocumentsAreCommitted.keySet());
      for (Object key : keys) {
        Runnable action = actionsWhenAllDocumentsAreCommitted.remove(key);
        myDocumentCommitProcessor.log("Running after commit runnable: ", null, false, key, action);
        action.run();
      }
    }
  }
  public static void replaceMovedMemberTypeParameters(
      final PsiElement member,
      final Iterable<PsiTypeParameter> parametersIterable,
      final PsiSubstitutor substitutor,
      final GroovyPsiElementFactory factory) {
    final Map<PsiElement, PsiElement> replacement = new LinkedHashMap<PsiElement, PsiElement>();
    for (PsiTypeParameter parameter : parametersIterable) {
      PsiType substitutedType = substitutor.substitute(parameter);
      if (substitutedType == null) {
        substitutedType = TypeConversionUtil.erasure(factory.createType(parameter));
      }

      PsiElement scopeElement = member instanceof GrField ? member.getParent() : member;
      for (PsiReference reference :
          ReferencesSearch.search(parameter, new LocalSearchScope(scopeElement))) {
        final PsiElement element = reference.getElement();
        final PsiElement parent = element.getParent();
        if (parent instanceof PsiTypeElement) {
          replacement.put(parent, factory.createTypeElement(substitutedType));
        } else if (element instanceof GrCodeReferenceElement
            && substitutedType instanceof PsiClassType) {
          replacement.put(
              element, factory.createReferenceElementByType((PsiClassType) substitutedType));
        }
      }
    }

    for (PsiElement element : replacement.keySet()) {
      if (element.isValid()) {
        element.replace(replacement.get(element));
      }
    }
  }
Пример #3
0
  protected void addLookupItem(
      Set<LookupElement> set,
      TailType tailType,
      @NotNull Object completion,
      final PsiFile file,
      final CompletionVariant variant) {
    LookupElement ret = objectToLookupItem(completion);
    if (ret == null) return;
    if (!(ret instanceof LookupItem)) {
      set.add(ret);
      return;
    }

    LookupItem item = (LookupItem) ret;

    final InsertHandler insertHandler = variant.getInsertHandler();
    if (insertHandler != null && item.getInsertHandler() == null) {
      item.setInsertHandler(insertHandler);
      item.setTailType(TailType.UNKNOWN);
    } else if (tailType != TailType.NONE) {
      item.setTailType(tailType);
    }
    final Map<Object, Object> itemProperties = variant.getItemProperties();
    for (final Object key : itemProperties.keySet()) {
      item.setAttribute(key, itemProperties.get(key));
    }

    set.add(ret);
  }
  /**
   * @param type
   * @param min
   * @param createDef
   * @param manager - must not be null if min is not null
   * @param scope - must not be null if min is not null
   */
  private GrTypeComboBox(
      @Nullable PsiType type,
      @Nullable PsiType min,
      boolean createDef,
      @Nullable PsiManager manager,
      @Nullable GlobalSearchScope scope) {
    LOG.assertTrue(min == null || manager != null);
    LOG.assertTrue(min == null || scope != null);

    if (type instanceof PsiDisjunctionType) type = ((PsiDisjunctionType) type).getLeastUpperBound();

    Map<String, PsiType> types = Collections.emptyMap();
    if (type != null) {
      types = getCompatibleTypeNames(type, min, manager, scope);
    }

    if (createDef || types.isEmpty()) {
      addItem(new PsiTypeItem(null));
    }

    for (String typeName : types.keySet()) {
      addItem(new PsiTypeItem(types.get(typeName)));
    }

    if (createDef && getItemCount() > 1) {
      setSelectedIndex(1);
    }
  }
  private static void fillFromSchema(PsiFile file, ElementNames names) {
    if (!(file instanceof XmlFile)) return;
    final XmlFile f = (XmlFile) file;
    final XmlDocument d = f.getDocument();
    if (d == null) return;
    final XmlTag rootTag = d.getRootTag();
    if (rootTag == null) return;

    //noinspection unchecked
    names.dependencies.add(new NSDeclTracker(rootTag));

    try {
      final Map<String, String> namespaceDeclarations = rootTag.getLocalNamespaceDeclarations();
      final Collection<String> prefixes = namespaceDeclarations.keySet();

      //noinspection unchecked
      final Set<XmlElementDescriptor> history = new THashSet<XmlElementDescriptor>();

      final XmlElementFactory ef = XmlElementFactory.getInstance(file.getProject());
      int noSchemaNamespaces = 0;
      for (String prefix : prefixes) {
        final String namespace = namespaceDeclarations.get(prefix);
        if (isIgnoredNamespace(prefix, namespace)) continue;

        final XmlTag tag =
            ef.createTagFromText("<dummy-tag xmlns='" + namespace + "' />", XMLLanguage.INSTANCE);
        final XmlDocument document = PsiTreeUtil.getParentOfType(tag, XmlDocument.class);
        final XmlNSDescriptor rootDescriptor = tag.getNSDescriptor(tag.getNamespace(), true);
        if (rootDescriptor == null
            || (rootDescriptor instanceof XmlNSDescriptorImpl
                && ((XmlNSDescriptorImpl) rootDescriptor).getTag() == null)
            || !rootDescriptor.getDeclaration().isPhysical()) {
          final QName any = QNameUtil.createAnyLocalName(namespace);
          names.elementNames.add(any);
          names.attributeNames.add(any);
          noSchemaNamespaces++;
          continue;
        }

        //noinspection unchecked
        names.dependencies.add(rootDescriptor.getDescriptorFile());

        final XmlElementDescriptor[] e = rootDescriptor.getRootElementsDescriptors(document);
        for (XmlElementDescriptor descriptor : e) {
          processElementDescriptors(descriptor, tag, names, history);
        }
      }

      names.validateNames = names.elementNames.size() > noSchemaNamespaces;

      //            final QName any = QNameUtil.createAnyLocalName("");
      //            names.elementNames.add(any);
      //            names.attributeNames.add(any);
    } catch (IncorrectOperationException e) {
      Logger.getInstance(XsltContextProvider.class.getName()).error(e);
    }
  }
Пример #6
0
  /**
   * Should typically be called when there is no MPS facet left in the project. We don't want to put
   * any load on Idea in this case. We only keep tracking facet notifications, to react when MPS
   * facet is back.
   */
  private void deactivate() {
    synchronized (LOCK) {
      workerConnection.disconnect();

      // remove all our solutions
      for (Module mod : myModulesToSolutions.keySet()) {
        untrackModule(mod, false);
      }

      myIsActivated = false;
    }
  }
 private static void rebindExternalReferences(
     PsiElement element,
     Map<PsiClass, PsiElement> oldToNewMap,
     Set<PsiElement> rebindExpressions) {
   final LocalSearchScope searchScope = new LocalSearchScope(element);
   for (PsiClass aClass : oldToNewMap.keySet()) {
     final PsiElement newClass = oldToNewMap.get(aClass);
     for (PsiReference reference : ReferencesSearch.search(aClass, searchScope)) {
       rebindExpressions.add(reference.bindToElement(newClass));
     }
   }
 }
 private void addToResult(Map<PsiExpression, PsiType> map) {
   if (myResult == null) {
     myResult = new THashMap<>(map, ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY);
   } else {
     final Iterator<PsiExpression> iterator = myResult.keySet().iterator();
     while (iterator.hasNext()) {
       PsiExpression psiExpression = iterator.next();
       if (!myResult.get(psiExpression).equals(map.get(psiExpression))) {
         iterator.remove();
       }
     }
   }
 }
Пример #9
0
 private void removeInvalidRefs() {
   synchronized (myLocalRefsMap) {
     for (Iterator<PsiReference> iterator = myLocalRefsMap.keySet().iterator();
         iterator.hasNext(); ) {
       PsiReference ref = iterator.next();
       if (!ref.getElement().isValid()) {
         PsiElement value = myLocalRefsMap.get(ref);
         iterator.remove();
         List<PsiReference> array = myLocalRefsMap.getKeysByValue(value);
         LOG.assertTrue(array != null);
         array.remove(ref);
       }
     }
   }
   for (Iterator<PsiReference> iterator = myImportStatements.keySet().iterator();
       iterator.hasNext(); ) {
     PsiReference ref = iterator.next();
     if (!ref.getElement().isValid()) {
       iterator.remove();
     }
   }
   removeInvalidFrom(myDclsUsedMap.keySet());
 }
 @Nullable
 private static String normalizeRelativeMap(Map<PsiFile, String> relativeMap) {
   String vector = null;
   for (String relativePath : relativeMap.values()) {
     if (vector == null) {
       vector = relativePath;
     } else if (vector.startsWith(relativePath + "/")) {
       vector = relativePath;
     } else if (!relativePath.startsWith(vector + "/") && !relativePath.equals(vector)) {
       return null;
     }
   }
   if (vector != null) {
     for (PsiFile psiFile : relativeMap.keySet()) {
       final String path = relativeMap.get(psiFile);
       relativeMap.put(psiFile, path.equals(vector) ? "" : path.substring(vector.length() + 1));
     }
   }
   return vector;
 }
 private PsiSubstitutor upDownSuperClassSubstitutor() {
   PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
   for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(mySourceClass)) {
     substitutor = substitutor.put(parameter, null);
   }
   final Map<PsiTypeParameter, PsiType> substitutionMap =
       TypeConversionUtil.getSuperClassSubstitutor(
               myTargetSuperClass, mySourceClass, PsiSubstitutor.EMPTY)
           .getSubstitutionMap();
   for (PsiTypeParameter parameter : substitutionMap.keySet()) {
     final PsiType type = substitutionMap.get(parameter);
     final PsiClass resolvedClass = PsiUtil.resolveClassInType(type);
     if (resolvedClass instanceof PsiTypeParameter) {
       substitutor =
           substitutor.put(
               (PsiTypeParameter) resolvedClass,
               JavaPsiFacade.getElementFactory(myProject).createType(parameter));
     }
   }
   return substitutor;
 }
  private PsiMethod createMethodToAdd() {
    ChangeContextUtil.encodeContextInfo(myMethod, true);
    try {
      final PsiManager manager = myMethod.getManager();
      final PsiElementFactory factory =
          JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();

      // correct internal references
      final PsiCodeBlock body = myMethod.getBody();
      if (body != null) {
        final Map<PsiElement, PsiElement> replaceMap = new HashMap<PsiElement, PsiElement>();
        body.accept(
            new JavaRecursiveElementVisitor() {
              @Override
              public void visitThisExpression(PsiThisExpression expression) {
                final PsiClass classReferencedByThis =
                    MoveInstanceMembersUtil.getClassReferencedByThis(expression);
                if (classReferencedByThis != null
                    && !PsiTreeUtil.isAncestor(myMethod, classReferencedByThis, false)) {
                  final PsiElementFactory factory =
                      JavaPsiFacade.getInstance(myProject).getElementFactory();
                  String paramName = getParameterNameToCreate(classReferencedByThis);
                  try {
                    final PsiExpression refExpression =
                        factory.createExpressionFromText(paramName, null);
                    replaceMap.put(expression, refExpression);
                  } catch (IncorrectOperationException e) {
                    LOG.error(e);
                  }
                }
              }

              @Override
              public void visitReferenceExpression(PsiReferenceExpression expression) {
                try {
                  final PsiExpression qualifier = expression.getQualifierExpression();
                  final PsiElement resolved = expression.resolve();
                  if (qualifier instanceof PsiReferenceExpression
                      && ((PsiReferenceExpression) qualifier).isReferenceTo(myTargetVariable)) {
                    if (resolved instanceof PsiField) {
                      for (PsiParameter parameter : myMethod.getParameterList().getParameters()) {
                        if (Comparing.strEqual(
                            parameter.getName(), ((PsiField) resolved).getName())) {
                          qualifier.replace(factory.createExpressionFromText("this", null));
                          return;
                        }
                      }
                    }
                    // Target is a field, replace target.m -> m
                    qualifier.delete();
                    return;
                  }
                  if (myTargetVariable.equals(resolved)) {
                    PsiThisExpression thisExpression =
                        RefactoringChangeUtil.createThisExpression(
                            manager,
                            PsiTreeUtil.isAncestor(
                                    myMethod,
                                    PsiTreeUtil.getParentOfType(expression, PsiClass.class),
                                    true)
                                ? myTargetClass
                                : null);
                    replaceMap.put(expression, thisExpression);
                    return;
                  } else if (myMethod.equals(resolved)) {
                  } else {
                    PsiClass classReferencedByThis =
                        MoveInstanceMembersUtil.getClassReferencedByThis(expression);
                    if (classReferencedByThis != null) {
                      final String paramName = getParameterNameToCreate(classReferencedByThis);
                      if (paramName != null) {
                        PsiReferenceExpression newQualifier =
                            (PsiReferenceExpression)
                                factory.createExpressionFromText(paramName, null);
                        expression.setQualifierExpression(newQualifier);
                        return;
                      }
                    }
                  }
                  super.visitReferenceExpression(expression);
                } catch (IncorrectOperationException e) {
                  LOG.error(e);
                }
              }

              @Override
              public void visitNewExpression(PsiNewExpression expression) {
                try {
                  final PsiExpression qualifier = expression.getQualifier();
                  if (qualifier instanceof PsiReferenceExpression
                      && ((PsiReferenceExpression) qualifier).isReferenceTo(myTargetVariable)) {
                    // Target is a field, replace target.new A() -> new A()
                    qualifier.delete();
                  } else {
                    final PsiClass classReferencedByThis =
                        MoveInstanceMembersUtil.getClassReferencedByThis(expression);
                    if (classReferencedByThis != null) {
                      if (qualifier != null) qualifier.delete();
                      final String paramName = getParameterNameToCreate(classReferencedByThis);
                      final PsiExpression newExpression =
                          factory.createExpressionFromText(
                              paramName + "." + expression.getText(), null);
                      replaceMap.put(expression, newExpression);
                    }
                  }
                  super.visitNewExpression(expression);
                } catch (IncorrectOperationException e) {
                  LOG.error(e);
                }
              }

              @Override
              public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                correctMethodCall(expression, true);
                super.visitMethodCallExpression(expression);
              }
            });
        for (PsiElement element : replaceMap.keySet()) {
          final PsiElement replacement = replaceMap.get(element);
          element.replace(replacement);
        }
      }

      final PsiMethod methodCopy = getPatternMethod();

      final List<PsiParameter> newParameters =
          Arrays.asList(methodCopy.getParameterList().getParameters());
      RefactoringUtil.fixJavadocsForParams(methodCopy, new HashSet<PsiParameter>(newParameters));
      return methodCopy;
    } catch (IncorrectOperationException e) {
      LOG.error(e);
      return myMethod;
    }
  }
  @Nullable
  public static PsiElement doCopyClasses(
      final Map<PsiFile, PsiClass[]> fileToClasses,
      @Nullable HashMap<PsiFile, String> map,
      final String copyClassName,
      final PsiDirectory targetDirectory,
      final Project project)
      throws IncorrectOperationException {
    PsiElement newElement = null;
    final Map<PsiClass, PsiElement> oldToNewMap = new HashMap<PsiClass, PsiElement>();
    for (final PsiClass[] psiClasses : fileToClasses.values()) {
      if (psiClasses != null) {
        for (PsiClass aClass : psiClasses) {
          if (aClass instanceof SyntheticElement) {
            continue;
          }
          oldToNewMap.put(aClass, null);
        }
      }
    }
    final List<PsiFile> createdFiles = new ArrayList<PsiFile>(fileToClasses.size());
    int[] choice = fileToClasses.size() > 1 ? new int[] {-1} : null;
    List<PsiFile> files = new ArrayList<PsiFile>();
    for (final Map.Entry<PsiFile, PsiClass[]> entry : fileToClasses.entrySet()) {
      final PsiFile psiFile = entry.getKey();
      final PsiClass[] sources = entry.getValue();
      if (psiFile instanceof PsiClassOwner && sources != null) {
        final PsiFile createdFile =
            copy(
                psiFile,
                targetDirectory,
                copyClassName,
                map == null ? null : map.get(psiFile),
                choice);
        if (createdFile == null) return null;
        for (final PsiClass destination : ((PsiClassOwner) createdFile).getClasses()) {
          if (destination instanceof SyntheticElement) {
            continue;
          }
          PsiClass source = findByName(sources, destination.getName());
          if (source != null) {
            final PsiClass copy = copy(source, copyClassName);
            newElement = destination.replace(copy);
            oldToNewMap.put(source, newElement);
          } else {
            destination.delete();
          }
        }
        createdFiles.add(createdFile);
      } else {
        files.add(psiFile);
      }
    }

    for (PsiFile file : files) {
      try {
        PsiDirectory finalTarget = targetDirectory;
        final String relativePath = map != null ? map.get(file) : null;
        if (relativePath != null && !relativePath.isEmpty()) {
          finalTarget =
              buildRelativeDir(targetDirectory, relativePath).findOrCreateTargetDirectory();
        }
        final PsiFile fileCopy =
            CopyFilesOrDirectoriesHandler.copyToDirectory(
                file, getNewFileName(file, copyClassName), finalTarget, choice);
        if (fileCopy != null) {
          createdFiles.add(fileCopy);
        }
      } catch (IOException e) {
        throw new IncorrectOperationException(e.getMessage());
      }
    }

    final Set<PsiElement> rebindExpressions = new HashSet<PsiElement>();
    for (PsiElement element : oldToNewMap.values()) {
      if (element == null) {
        LOG.error(oldToNewMap.keySet());
        continue;
      }
      decodeRefs(element, oldToNewMap, rebindExpressions);
    }

    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
    for (PsiFile psiFile : createdFiles) {
      if (psiFile instanceof PsiJavaFile) {
        codeStyleManager.removeRedundantImports((PsiJavaFile) psiFile);
      }
    }
    for (PsiElement expression : rebindExpressions) {
      codeStyleManager.shortenClassReferences(expression);
    }
    new OptimizeImportsProcessor(
            project, createdFiles.toArray(new PsiFile[createdFiles.size()]), null)
        .run();
    return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null;
  }
 public void doCopy(PsiElement[] elements, PsiDirectory defaultTargetDirectory) {
   FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.copyClass");
   final HashMap<PsiFile, String> relativePathsMap = new HashMap<PsiFile, String>();
   final Map<PsiFile, PsiClass[]> classes =
       convertToTopLevelClasses(elements, false, "", relativePathsMap);
   assert classes != null;
   if (defaultTargetDirectory == null) {
     final PsiFile psiFile = classes.keySet().iterator().next();
     defaultTargetDirectory = psiFile.getContainingDirectory();
     LOG.assertTrue(defaultTargetDirectory != null, psiFile);
   } else {
     Project project = defaultTargetDirectory.getProject();
     VirtualFile sourceRootForFile =
         ProjectRootManager.getInstance(project)
             .getFileIndex()
             .getSourceRootForFile(defaultTargetDirectory.getVirtualFile());
     if (sourceRootForFile == null) {
       final List<PsiElement> files = new ArrayList<PsiElement>();
       for (int i = 0, elementsLength = elements.length; i < elementsLength; i++) {
         PsiFile containingFile = elements[i].getContainingFile();
         if (containingFile != null) {
           files.add(containingFile);
         } else if (elements[i] instanceof PsiDirectory) {
           files.add(elements[i]);
         }
       }
       CopyFilesOrDirectoriesHandler.copyAsFiles(
           files.toArray(new PsiElement[files.size()]), defaultTargetDirectory, project);
       return;
     }
   }
   Project project = defaultTargetDirectory.getProject();
   Object targetDirectory = null;
   String className = null;
   boolean openInEditor = true;
   if (copyOneClass(classes)) {
     final String commonPath =
         ArrayUtil.find(elements, classes.values().iterator().next()) == -1
             ? normalizeRelativeMap(relativePathsMap)
             : null;
     CopyClassDialog dialog =
         new CopyClassDialog(
             classes.values().iterator().next()[0], defaultTargetDirectory, project, false) {
           @Override
           protected String getQualifiedName() {
             if (commonPath != null && !commonPath.isEmpty()) {
               return StringUtil.getQualifiedName(
                   super.getQualifiedName(), commonPath.replaceAll("/", "."));
             }
             return super.getQualifiedName();
           }
         };
     dialog.setTitle(RefactoringBundle.message("copy.handler.copy.class"));
     dialog.show();
     if (dialog.isOK()) {
       openInEditor = dialog.openInEditor();
       targetDirectory = dialog.getTargetDirectory();
       className = dialog.getClassName();
       if (className == null || className.length() == 0) return;
     }
   } else {
     if (ApplicationManager.getApplication().isUnitTestMode()) {
       targetDirectory = defaultTargetDirectory;
     } else {
       defaultTargetDirectory =
           CopyFilesOrDirectoriesHandler.resolveDirectory(defaultTargetDirectory);
       if (defaultTargetDirectory == null) return;
       PsiElement[] files = PsiUtilCore.toPsiFileArray(classes.keySet());
       if (classes.keySet().size() == 1) {
         // do not choose a new name for a file when multiple classes exist in one file
         final PsiClass[] psiClasses = classes.values().iterator().next();
         if (psiClasses != null) {
           files = psiClasses;
         }
       }
       final CopyFilesOrDirectoriesDialog dialog =
           new CopyFilesOrDirectoriesDialog(files, defaultTargetDirectory, project, false);
       dialog.show();
       if (dialog.isOK()) {
         targetDirectory = dialog.getTargetDirectory();
         className = dialog.getNewName();
         openInEditor = dialog.openInEditor();
       }
     }
   }
   if (targetDirectory != null) {
     copyClassesImpl(
         className,
         project,
         classes,
         relativePathsMap,
         targetDirectory,
         defaultTargetDirectory,
         RefactoringBundle.message("copy.handler.copy.class"),
         false,
         openInEditor);
   }
 }