/** * @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 } } }
/** * 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; }