/**
  * @see
  *     org.eclipse.jdt.internal.core.builder.AbstractImageBuilder#writeClassFileContents(org.eclipse.jdt.internal.compiler.ClassFile,
  *     org.eclipse.core.resources.IFile, java.lang.String, boolean,
  *     org.eclipse.jdt.internal.core.builder.SourceFile)
  */
 protected void writeClassFileContents(
     ClassFile classfile,
     IFile file,
     String qualifiedFileName,
     boolean isTopLevelType,
     SourceFile compilationUnit)
     throws CoreException {
   // Before writing out the class file, compare it to the previous file
   // If structural changes occurred then add dependent source files
   byte[] bytes = classfile.getBytes();
   if (file.exists()) {
     if (writeClassFileCheck(file, qualifiedFileName, bytes)
         || compilationUnit.updateClassFile) { // see 46093
       if (JavaBuilder.DEBUG)
         System.out.println("Writing changed class file " + file.getName()); // $NON-NLS-1$
       if (!file.isDerived()) file.setDerived(true, null);
       file.setContents(new ByteArrayInputStream(bytes), true, false, null);
     } else if (JavaBuilder.DEBUG) {
       System.out.println("Skipped over unchanged class file " + file.getName()); // $NON-NLS-1$
     }
   } else {
     if (isTopLevelType) addDependentsOf(new Path(qualifiedFileName), true); // new type
     if (JavaBuilder.DEBUG)
       System.out.println("Writing new class file " + file.getName()); // $NON-NLS-1$
     try {
       file.create(new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null);
     } catch (CoreException e) {
       if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
         IStatus status = e.getStatus();
         if (status instanceof IResourceStatus) {
           IPath oldFilePath = ((IResourceStatus) status).getPath();
           char[] oldTypeName = oldFilePath.removeFileExtension().lastSegment().toCharArray();
           char[][] previousTypeNames =
               this.newState.getDefinedTypeNamesFor(compilationUnit.typeLocator());
           boolean fromSameFile = false;
           if (previousTypeNames == null) {
             fromSameFile = CharOperation.equals(compilationUnit.getMainTypeName(), oldTypeName);
           } else {
             for (int i = 0, l = previousTypeNames.length; i < l; i++) {
               if (CharOperation.equals(previousTypeNames[i], oldTypeName)) {
                 fromSameFile = true;
                 break;
               }
             }
           }
           if (fromSameFile) {
             // file is defined by the same compilationUnit, but won't be deleted until later so do
             // it now
             IFile collision = file.getParent().getFile(new Path(oldFilePath.lastSegment()));
             collision.delete(true, false, null);
             boolean success = false;
             try {
               file.create(
                   new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null);
               success = true;
             } catch (CoreException ignored) {
               // ignore the second exception
             }
             if (success) return;
           }
         }
         // catch the case that a type has been renamed and collides on disk with an
         // as-yet-to-be-deleted type
         throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedFileName));
       }
       throw e; // rethrow
     }
   }
 }
예제 #2
0
  /**
   * Creates the text changes for all the affected files. Updates all the include statements in the
   * current file and all the includes in the "including " files. In case of folders, creates the
   * changes recursively
   *
   * @param pm - progress monitor
   * @param rootChange - the root change that the new changes are added to
   * @param sourceResources
   * @return the root change after the additions
   * @throws CoreException
   */
  private Change createTextChanges(
      IProgressMonitor pm,
      CompositeChange rootChange,
      Set<IFile> phpFiles,
      IResource[] sourceResources)
      throws CoreException {
    List<ProgramFileChange> changes = new ArrayList<ProgramFileChange>();
    try {
      pm.beginTask(PhpRefactoringCoreMessages.getString("MoveDelegate.1"), 100); // $NON-NLS-1$

      // creat text changes:
      // for each file that will be moved, update its includes
      // and update all the files that include it,

      IResource[] uniqueSourceResources = removeDuplicateResources(sourceResources);

      for (Iterator<IFile> it = phpFiles.iterator(); it.hasNext(); ) {
        IFile currentMovedResource = it.next();

        Map<IFile, Program> participantFiles = collectReferencingFiles(currentMovedResource, pm);

        for (Entry<IFile, Program> entry : participantFiles.entrySet()) {
          final IFile file = entry.getKey();
          if (phpFiles.contains(file)) {
            continue;
          }
          final Program program = entry.getValue();

          final ChangeIncludePath rename =
              new ChangeIncludePath(
                  currentMovedResource, file, fMainDestinationPath, false, uniqueSourceResources);
          // aggregate the changes identifiers
          program.accept(rename);

          if (pm.isCanceled()) throw new OperationCanceledException();

          pm.worked(1);

          if (rename.hasChanges()) {
            ProgramFileChange change = new ProgramFileChange(file.getName(), file, program);
            change.setEdit(new MultiTextEdit());
            change.setTextType("php"); // $NON-NLS-1$

            changes.add(change);
            rename.updateChange(change);
          }
        }

        ISourceModule sourceModule = DLTKCore.createSourceModuleFrom(currentMovedResource);

        if (sourceModule instanceof ISourceModule) {

          Program program = null;
          try {
            program = ASTUtils.createProgramFromSource(sourceModule);
          } catch (Exception e) {
          }

          if (program != null) {
            final ChangeIncludePath rename =
                new ChangeIncludePath(
                    currentMovedResource,
                    currentMovedResource,
                    fMainDestinationPath,
                    true,
                    uniqueSourceResources);

            // aggregate the changes identifiers
            program.accept(rename);

            if (pm.isCanceled()) throw new OperationCanceledException();

            pm.worked(1);

            if (rename.hasChanges()) {
              ProgramFileChange change =
                  new ProgramFileChange(
                      currentMovedResource.getName(), currentMovedResource, program);
              change.setEdit(new MultiTextEdit());
              change.setTextType("php"); // $NON-NLS-1$

              changes.add(change);
              rename.updateChange(change);
            }
          }
        }
      }
      pm.worked(70);

    } finally {
      pm.done();
    } // getChildren()

    Map<IFile, List<TextEdit>> changeMap = new HashMap<IFile, List<TextEdit>>();
    Map<IFile, ProgramFileChange> fileMap = new HashMap<IFile, ProgramFileChange>();
    for (ProgramFileChange programFileChange : changes) {
      List<TextEdit> list = changeMap.get(programFileChange.getFile());
      if (list == null) {
        list = new ArrayList<TextEdit>();
        changeMap.put(programFileChange.getFile(), list);
        fileMap.put(programFileChange.getFile(), programFileChange);
      } else {

      }
      list.addAll(Arrays.asList(programFileChange.getEdit().getChildren()));
    }
    for (IFile file : changeMap.keySet()) {
      ProgramFileChange change =
          new ProgramFileChange(file.getName(), file, fileMap.get(file).getProgram());
      change.setEdit(new MultiTextEdit());
      change.setTextType("php"); // $NON-NLS-1$

      List<TextEdit> list = changeMap.get(file);
      Collections.sort(
          list,
          new Comparator<TextEdit>() {
            public int compare(TextEdit o1, TextEdit o2) {
              return o2.getOffset() - o1.getOffset();
            }
          });

      for (TextEdit textEdit : list) {
        if (textEdit instanceof ReplaceEdit) {
          ReplaceEdit replaceEdit = (ReplaceEdit) textEdit;
          change.addEdit(
              new ReplaceEdit(
                  replaceEdit.getOffset(), replaceEdit.getLength(), replaceEdit.getText()));
        }
      }
      rootChange.add(change);
    }
    return rootChange;
  }