protected boolean writeClassFileCheck(IFile file, String fileName, byte[] newBytes) throws CoreException { try { byte[] oldBytes = Util.getResourceContentsAsByteArray(file); notEqual: if (newBytes.length == oldBytes.length) { for (int i = newBytes.length; --i >= 0; ) if (newBytes[i] != oldBytes[i]) break notEqual; return false; // bytes are identical so skip them } URI location = file.getLocationURI(); if (location == null) return false; // unable to determine location of this class file String filePath = location.getSchemeSpecificPart(); ClassFileReader reader = new ClassFileReader(oldBytes, filePath.toCharArray()); // ignore local types since they're only visible inside a single method if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) { if (JavaBuilder.DEBUG) System.out.println("Type has structural changes " + fileName); // $NON-NLS-1$ addDependentsOf(new Path(fileName), true); this.newState.wasStructurallyChanged(fileName); } } catch (ClassFormatException e) { addDependentsOf(new Path(fileName), true); this.newState.wasStructurallyChanged(fileName); } return true; }
protected void removeClassFile(IPath typePath, IContainer outputFolder) throws CoreException { if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type this.newState.removeQualifiedTypeName(typePath.toString()); // add dependents even when the type thinks it does not exist to be on the safe side if (JavaBuilder.DEBUG) System.out.println("Found removed type " + typePath); // $NON-NLS-1$ addDependentsOf( typePath, true); // when member types are removed, their enclosing type is structurally changed } IFile classFile = outputFolder.getFile(typePath.addFileExtension(SuffixConstants.EXTENSION_class)); if (classFile.exists()) { if (JavaBuilder.DEBUG) System.out.println("Deleting class file of removed type " + typePath); // $NON-NLS-1$ classFile.delete(IResource.FORCE, null); } }
protected void deleteGeneratedFiles(IFile[] deletedGeneratedFiles) { // delete generated files and recompile any affected source files try { for (int j = deletedGeneratedFiles.length; --j >= 0; ) { IFile deletedFile = deletedGeneratedFiles[j]; if (deletedFile.exists()) continue; // only delete .class files for source files that were actually deleted SourceFile sourceFile = findSourceFile(deletedFile, false); String typeLocator = sourceFile.typeLocator(); int mdSegmentCount = sourceFile.sourceLocation.sourceFolder.getFullPath().segmentCount(); IPath typePath = sourceFile .resource .getFullPath() .removeFirstSegments(mdSegmentCount) .removeFileExtension(); addDependentsOf(typePath, true); // add dependents of the source file since its now deleted this.previousSourceFiles = null; // existing source files did not see it as deleted since they were compiled before // it was char[][] definedTypeNames = this.newState.getDefinedTypeNamesFor(typeLocator); if (definedTypeNames == null) { // defined a single type matching typePath removeClassFile(typePath, sourceFile.sourceLocation.binaryFolder); } else { if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type IPath packagePath = typePath.removeLastSegments(1); for (int d = 0, l = definedTypeNames.length; d < l; d++) removeClassFile( packagePath.append(new String(definedTypeNames[d])), sourceFile.sourceLocation.binaryFolder); } } this.newState.removeLocator(typeLocator); } } catch (CoreException e) { // must continue with compile loop so just log the CoreException Util.log( e, "JavaBuilder logging CompilationParticipant's CoreException to help debugging"); //$NON-NLS-1$ } }
/** * @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 } } }