Changeset 1230
- Timestamp:
- 07/14/08 04:58:09 (2 months ago)
- Files:
-
- trunk/descent.building/integrate (added)
- trunk/descent.building/integrate/src (added)
- trunk/descent.building/integrate/src/descent (added)
- trunk/descent.building/integrate/src/descent/internal (added)
- trunk/descent.building/integrate/src/descent/internal/building (added)
- trunk/descent.building/integrate/src/descent/internal/building/debuild (added)
- trunk/descent.building/integrate/src/descent/internal/building/debuild/ConditionalEvaluator.java (added)
- trunk/descent.building/integrate/src/descent/internal/building/debuild/RecursiveDependancyCollector.java (added)
- trunk/descent.building/src/descent/building/compiler/BuildException.java (added)
- trunk/descent.building/src/descent/building/compiler/IBuildManager.java (modified) (1 diff)
- trunk/descent.building/src/descent/building/compiler/ICompileManager.java (modified) (1 diff)
- trunk/descent.building/src/descent/building/compiler/ICompilerInterface.java (modified) (3 diffs)
- trunk/descent.building/src/descent/building/compiler/IErrorReporter.java (added)
- trunk/descent.building/src/descent/building/compiler/IExecutionMonitor.java (added)
- trunk/descent.building/src/descent/building/compiler/IObjectFile.java (modified) (1 diff)
- trunk/descent.building/src/descent/internal/building/compiler/DmdCompileManager.java (added)
- trunk/descent.building/src/descent/internal/building/compiler/DmdCompilerInterface.java (modified) (3 diffs)
- trunk/descent.building/src/descent/internal/building/compiler/DmdfeCompilerInterface.java (modified) (1 diff)
- trunk/descent.building/src/descent/internal/building/debuild/BuildManager.java (added)
- trunk/descent.building/src/descent/internal/building/debuild/BuildRequest.java (modified) (6 diffs)
- trunk/descent.building/src/descent/internal/building/debuild/ConditionalEvaluator.java (deleted)
- trunk/descent.building/src/descent/internal/building/debuild/DebuildBuilder.java (modified) (9 diffs)
- trunk/descent.building/src/descent/internal/building/debuild/DebuildException.java (deleted)
- trunk/descent.building/src/descent/internal/building/debuild/IncrementalConsistencyManager.java (modified) (3 diffs)
- trunk/descent.building/src/descent/internal/building/debuild/ObjectFileFactory.java (modified) (6 diffs)
- trunk/descent.building/src/descent/internal/building/debuild/RecursiveDependancyCollector.java (deleted)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/descent.building/src/descent/building/compiler/IBuildManager.java
r1197 r1230 1 1 package descent.building.compiler; 2 2 3 /** 4 * Class representing the state of the internal builder, which the 5 * {@link ICompileManager} should use to gain information on the state of the 6 * build and to perform various tasks. 7 * 8 * <b>This class is not intended to be implemented by clients.</b> 9 * 10 * @see ICompileManager 11 * @author Robert Fraser 12 */ 3 13 public interface IBuildManager 4 14 { trunk/descent.building/src/descent/building/compiler/ICompileManager.java
r1197 r1230 1 1 package descent.building.compiler; 2 2 3 import org.eclipse.core.runtime.IProgressMonitor; 4 5 /** 6 * The build process contains some processes that are compiler-ambivalent, and 7 * others that depend on the compiler being used. The compiler-ambivalent parts 8 * are managed internally by the builder, and an instance of this class is used 9 * to manage compiler-specific parts. The lifecycle of a build involves 10 * cooperation between this class and the builder (accessed via an 11 * {@link IBuildManager}), with multiple calls made back and forth between the 12 * two components. From the perspective of the compiler implementer, the 13 * lifecycle works roughly like this: 14 * 15 * <ol> 16 * <li>For each build, this class will be constructed via the 17 * {@link ICompilerInterface#getCompileManager(IBuildManager)} class.</li> 18 * 19 * <li>When an object file needs to be compiled, the 20 * {@link #compile(IObjectFile)} method will be called.</li> 21 * 22 * <li>During the course of building, methods on the {@link IBuildManager} 23 * should be called to handle things like executing specific commands, 24 * reporting errors, or getting build information.</li> 25 * 26 * <li>TODO linking</li> 27 * </ol> 28 * 29 * <b>This class should be implemented by clients providing a compiler interface.</b> 30 * 31 * @author Robert Fraser 32 */ 3 33 public interface ICompileManager 4 34 { 35 /** 36 * Compiles the given object files. If multiple files are passed, they may 37 * be built together. If 38 * {@link ICompilerInterface#supportsInternalDependancyAnalysis()} returns 39 * <code>true</code> for this compiler type, this class should return a 40 * non-null array of the names of all modules imported by the given object 41 * files (whether or not these files need to be built should be decided by 42 * the builder). If supportsInternalDependancyAnalysis() is 43 * <code>false</code>, the return of this method will be ignored. 44 * 45 * @param objectFiles the object files to be built 46 * @param pm a monitor to rack the progress of the operation 47 * @return a list of files imported by the given targets 48 */ 49 public String[] compile(IObjectFile[] objectFiles, IProgressMonitor pm); 5 50 } trunk/descent.building/src/descent/building/compiler/ICompilerInterface.java
r1197 r1230 2 2 3 3 import descent.building.compiler.ui.CompilerOption; 4 5 4 6 5 /** … … 17 16 * TODO document how it is used 18 17 * 18 * <b>This class should be implemented by clients providing a compiler interface.</b> 19 * 19 20 * @author Robert Fraser 20 21 */ 21 22 public interface ICompilerInterface 22 { 23 { 23 24 /** 24 25 * Gets the compiler options which should be presented in the UI. … … 28 29 // TODO comment about what sorts of options should be included etc 29 30 public CompilerOption[] getOptions(); 31 32 /** 33 * Checks whether this type of compiler supports internal compiler analysis. 34 * Internal dependency analysis means that during the compile step it is 35 * possible to retrieve a list of dependencies after building an object file. 36 * For example, DMD output can be parsed for imports. If this returns false, 37 * the descent builder will use internal dependency analysis. This method can 38 * be slower and could potentially have issues if the semantics are slightly 39 * different than the compiler, so if it is possible to support internal 40 * dependency analysis, it should be done. 41 * 42 * @return true if and only if this compiler supports internal dependency 43 * analysis 44 */ 45 public boolean supportsInternalDependancyAnalysis(); 46 47 /** 48 * Gets a new instance of a compile manager that should cooperate with the 49 * given build manager. 50 * 51 * @param buildManager the build manager the compile manager should work 52 * with 53 * @return an instance of a compiler manager to be used for a 54 * build 55 * @see ICompileManager 56 */ 57 public ICompileManager getCompileManager(IBuildManager buildManager); 30 58 } trunk/descent.building/src/descent/building/compiler/IObjectFile.java
r1216 r1230 3 3 import java.io.File; 4 4 5 /** 6 * Ties together an input file (a D module) and an output file (the target .obj 7 * file). Instances of this interface represent fully-qualified D modules with 8 * their target outputs from a build. 9 * 10 * There should be only one of this class for any given module in or referenced by 11 * a build. The {@link #equals(Object)} method should return <code>true</true> for 12 * two object file if they refer to the same module. 13 * 14 * <b>This class is not intended to be implemented by clients.</b> 15 * 16 * @author Robert Fraser 17 */ 5 18 public interface IObjectFile 6 19 { 20 /** 21 * Gets the name of the D module to which this refers. 22 */ 23 public String getName(); 24 25 /** 26 * Gets the D file which is the module's source code. This file should 27 * exist, but be sure to check for existence before use. 28 */ 7 29 public File getInputFile(); 30 31 /** 32 * Gets the object file (which may or may not exist) which is the target 33 * output for a compile execution. 34 */ 8 35 public File getOutputFile(); 36 37 /** 38 * Checks whether this module is local to the project/workspace or is 39 * referenced from a source library. 40 */ 9 41 public boolean isLibraryFile(); 10 42 } trunk/descent.building/src/descent/internal/building/compiler/DmdCompilerInterface.java
r1197 r1230 5 5 import java.util.regex.Pattern; 6 6 7 import descent.building.compiler.IBuildManager; 8 import descent.building.compiler.ICompileManager; 7 9 import descent.building.compiler.IResponseInterpreter; 8 10 import descent.building.compiler.ui.CompilerOption; … … 11 13 12 14 public final class DmdCompilerInterface extends DmdfeCompilerInterface 13 { 14 protected static final boolean DEBUG = true; 15 16 //-------------------------------------------------------------------------- 17 // Response interpreter 18 protected static class DmdResponseInterpreter implements IResponseInterpreter 19 { 20 private static final Pattern ERROR_WITH_FILENAME = Pattern.compile( 21 "([^\\(\\:]*)" + // Filename 22 "(?:\\((\\d*)\\))?" + // Line number 23 "\\:\\s(.*)$" // Message 24 ); 25 26 /* (non-Javadoc) 27 * @see descent.launching.compiler.IResponseInterpreter#interpret(java.lang.String) 28 */ 29 public void interpret(String line) 30 { 31 // TODO finish & test 32 33 if(DEBUG) 34 System.out.println("OUT => " + line); 35 36 /* 37 Matcher m = ERROR_WITH_FILENAME.matcher(line); 38 if(m.find()) 39 { 40 String file = m.group(1); 41 String lineStr = m.group(2); 42 String message = m.group(3); 43 int lineNum = null != lineStr ? Integer.parseInt(lineStr) : -1; 44 resp.addError(new BuildError(message, file, lineNum)); 45 return; 46 } 47 */ 48 } 49 50 /* (non-Javadoc) 51 * @see descent.launching.compiler.IResponseInterpreter#interpretError(java.lang.String) 52 */ 53 public void interpretError(String line) 54 { 55 if(DEBUG) 56 System.out.println("ERR => " + line); 57 58 // Keep all the interpretation in one method 59 // TODO interpret(line); 60 } 61 } 62 15 { 63 16 //-------------------------------------------------------------------------- 64 17 // UI Options … … 95 48 uiOptions = options.toArray(new CompilerOption[options.size()]); 96 49 } 50 51 @Override 52 public ICompileManager getCompileManager(IBuildManager buildManager) 53 { 54 return new DmdCompileManager(); 55 } 97 56 } trunk/descent.building/src/descent/internal/building/compiler/DmdfeCompilerInterface.java
r1197 r1230 1 1 package descent.internal.building.compiler; 2 2 3 import descent.building.compiler.IBuildManager; 4 import descent.building.compiler.ICompileManager; 3 5 import descent.building.compiler.ICompilerInterface; 4 6 5 7 public abstract class DmdfeCompilerInterface implements ICompilerInterface 6 8 { 9 public ICompileManager getCompileManager(IBuildManager buildManager) 10 { 11 // TODO Auto-generated method stub 12 return null; 13 } 14 15 public boolean supportsInternalDependancyAnalysis() 16 { 17 return true; 18 } 7 19 } trunk/descent.building/src/descent/internal/building/debuild/BuildRequest.java
r1229 r1230 20 20 import descent.internal.building.BuilderUtil; 21 21 import descent.launching.IVMInstall; 22 import descent.building.compiler.BuildException; 22 23 import descent.building.compiler.ICompilerInterface; 23 24 … … 59 60 catch(CoreException e) 60 61 { 61 throw new DebuildException("Could not get compiler for project " +62 throw new BuildException("Could not get compiler for project " + 62 63 project.getElementName()); 63 64 } … … 109 110 110 111 if(handles.isEmpty()) 111 throw new DebuildException("No target modules defined");112 throw new BuildException("No target modules defined"); 112 113 113 114 List<ICompilationUnit> modules = … … 146 147 147 148 if(modules.isEmpty()) 148 throw new DebuildException("None of the modules to be built exist in the project.");149 throw new BuildException("None of the modules to be built exist in the project."); 149 150 150 151 return modules.toArray(new ICompilationUnit[modules.size()]); … … 199 200 catch(JavaModelException e) 200 201 { 201 throw new DebuildException(e);202 throw new BuildException(e); 202 203 } 203 204 } … … 214 215 215 216 if(null == project) 216 throw new DebuildException(String.format("Cannot find project %1$s", projectName));217 throw new BuildException(String.format("Cannot find project %1$s", projectName)); 217 218 218 219 return project; trunk/descent.building/src/descent/internal/building/debuild/DebuildBuilder.java
r1229 r1230 4 4 import java.util.ArrayList; 5 5 import java.util.HashSet; 6 import java.util.Iterator; 6 7 import java.util.List; 7 8 import java.util.Set; … … 14 15 15 16 import descent.core.IClasspathEntry; 17 import descent.core.ICompilationUnit; 16 18 import descent.core.IJavaModel; 17 19 import descent.core.IJavaProject; … … 19 21 import descent.internal.building.BuilderUtil; 20 22 import descent.building.IDBuilder; 23 import descent.building.compiler.BuildException; 24 import descent.building.compiler.ICompileManager; 25 import descent.building.compiler.ICompilerInterface; 21 26 import descent.building.compiler.IObjectFile; 22 27 … … 27 32 private BuildRequest req; 28 33 private ErrorReporter err; 34 private BuildManager buildMgr; 35 private ObjectFileFactory objFactory; 36 29 37 private List<File> importPath; 30 38 … … 44 52 req = new BuildRequest(config); 45 53 err = new ErrorReporter(req.getProject()); 54 buildMgr = new BuildManager(); 55 objFactory = new ObjectFileFactory(req); 46 56 pm.worked(5); // 5 57 58 // Check whether this build is even possible 59 // NEXTVERSION support internal dependency analysis 60 ICompilerInterface compilerInterface = req.getCompilerInterface(); 61 if(null == compilerInterface || 62 !compilerInterface.supportsInternalDependancyAnalysis()) 63 throw new BuildException("This compiler type is not supported in " + 64 "this version of Descent."); 47 65 48 66 // If the launch configuration has changed, clear the output folder … … 60 78 return null; 61 79 62 // Collect dependancies and create the associated object files 63 ObjectFileFactory objFactory = new ObjectFileFactory(req); 64 RecursiveDependancyCollector collector = 65 new RecursiveDependancyCollector(req, objFactory); 66 IObjectFile[] objectFiles = collector.getModules( 67 new SubProgressMonitor(pm, 35)); // 50 68 69 // TODO 70 return null; 80 doCompile(new SubProgressMonitor(pm, 60)); // 85 81 if(pm.isCanceled()) 82 return null; 83 84 return doLink(new SubProgressMonitor(pm, 15)); // 100 71 85 } 72 catch( DebuildException e)86 catch(BuildException e) 73 87 { 74 88 err.projectError(e.getMessage()); … … 92 106 } 93 107 108 //-------------------------------------------------------------------------- 109 // Import path management 110 94 111 private void createImportPath() 95 112 { … … 104 121 catch(JavaModelException e) 105 122 { 106 throw new DebuildException(e.getMessage());123 throw new BuildException(e.getMessage()); 107 124 } 108 125 } … … 139 156 } 140 157 } 158 159 //-------------------------------------------------------------------------- 160 // Compile management 161 162 private void doCompile(IProgressMonitor pm) 163 { 164 try 165 { 166 // TODO what to do about progress monitoring? 167 pm.beginTask("Compiling object files", 1000); 168 169 ICompileManager compileMgr = req.getCompilerInterface(). 170 getCompileManager(buildMgr); 171 Set<IObjectFile> pending = new HashSet<IObjectFile>(); 172 Set<IObjectFile> completed = new HashSet<IObjectFile>(); 173 174 // Add the initial/seed objects 175 for(ICompilationUnit cu : req.getModules()) 176 { 177 pending.add(objFactory.create(cu.getFullyQualifiedName())); 178 if(pm.isCanceled()) 179 return; 180 } 181 182 while(!pending.isEmpty()) 183 { 184 // Remove any object files that should not be built 185 Iterator<IObjectFile> iter = pending.iterator(); 186 objects: while(iter.hasNext()) 187 { 188 IObjectFile obj = iter.next(); 189 190 // Check if it's already been built during this run 191 if(completed.contains(obj)) 192 { 193 iter.remove(); 194 continue objects; 195 } 196 197 // Check if the file has already been built during another 198 // run and is still up-to-date 199 if((obj.getInputFile().exists()) && 200 (obj.getOutputFile().exists()) && 201 (obj.getOutputFile().lastModified() >= 202 obj.getInputFile().lastModified())) 203 { 204 completed.add(obj); 205 iter.remove(); 206 continue objects; 207 } 208 } 209 210 if(pending.isEmpty()) 211 break; 212 if(pm.isCanceled()) 213 return; 214 215 // Compile the rest 216 String[] dependancies = compileMgr.compile( 217 pending.toArray(new IObjectFile[pending.size()]), 218 new SubProgressMonitor(pm, 10)); 219 if(pm.isCanceled()) 220 return; 221 222 // Flush the pending list into the completed list and put any 223 // dependencies into the pending list 224 completed.addAll(pending); 225 pending.clear(); 226 for(String moduleName : dependancies) 227 { 228 IObjectFile obj = objFactory.create(moduleName); 229 if(null != obj) 230 pending.add(obj); 231 if(pm.isCanceled()) 232 return; 233 } 234 } 235 } 236 finally 237 { 238 pm.done(); 239 } 240 } 241 242 //-------------------------------------------------------------------------- 243 // Link management 244 245 private String doLink(IProgressMonitor pm) 246 { 247 try 248 { 249 pm.beginTask("Linking output file", 100); 250 251 return null; 252 } 253 finally 254 { 255 pm.done(); 256 } 257 } 141 258 } trunk/descent.building/src/descent/internal/building/debuild/IncrementalConsistencyManager.java
r1229 r1230 8 8 import org.eclipse.debug.core.ILaunchConfiguration; 9 9 10 import descent.building.compiler.BuildException; 10 11 import descent.internal.building.BuilderUtil; 11 12 … … 103 104 catch(CoreException e) 104 105 { 105 throw new DebuildException(String.format(106 throw new BuildException(String.format( 106 107 "Error preparing output folder: %1$s", e.getMessage())); 107 108 } … … 145 146 catch(CoreException e) 146 147 { 147 throw new DebuildException(String.format(148 throw new BuildException(String.format( 148 149 "Error deleting resource %1$s: %2$s", 149 150 file.getFullPath().toString(), e.getMessage())); trunk/descent.building/src/descent/internal/building/debuild/ObjectFileFactory.java
r1229 r1230 2 2 3 3 import java.io.File; 4 4 import java.util.HashMap; 5 import java.util.HashSet; 6 import java.util.Map; 7 import java.util.Set; 8 9 import descent.building.compiler.BuildException; 5 10 import descent.building.compiler.IObjectFile; 6 11 import descent.core.ICompilationUnit; 12 import descent.core.IJavaModel; 13 import descent.core.IJavaProject; 14 import descent.core.IPackageFragment; 15 import descent.core.IPackageFragmentRoot; 16 import descent.core.JavaModelException; 7 17 import descent.internal.building.BuilderUtil; 8 18 … … 11 21 private static final class ObjectFile implements IObjectFile 12 22 { 23 private final String name; 13 24 private final File inputFile; 14 25 private final File outputFile; 15 26 private final boolean isLibraryFile; 16 27 17 public ObjectFile(File inputFile, File outputFile, 28 public ObjectFile(String name, 29 File inputFile, File outputFile, 18 30 boolean isLibraryFile) 19 31 { 32 this.name = name; 20 33 this.inputFile = inputFile; 21 34 this.outputFile = outputFile; 22 35 this.isLibraryFile = isLibraryFile; 23 36 } 37 38 public String getName() 39 { 40 return name; 41 } 24 42 25 43 public File getInputFile() … … 37 55 return isLibraryFile; 38 56 } 57 58 @Override 59 public boolean equals(Object other) 60 { 61 return ((null != other) && 62 (other instanceof ObjectFile) && 63 (((ObjectFile) other).name.equals(this.name))); 64 } 65 66 @Override 67 public int hashCode() 68 { 69 return name.hashCode(); 70 } 71 72 @Override 73 public String toString() 74 { 75 StringBuilder str = new StringBuilder(); 76 77 str.append(getName()); 78 if(isLibraryFile()) 79 str.append(" (ExTERNAL)"); 80 81 str.append("\n "); 82 str.append("Input file: "); 83 str.append(getInputFile()); 84 85 str.append("\n "); 86 str.append("Output file: "); 87 str.append(getOutputFile()); 88 89 return str.toString(); 90 } 39 91 } 40 92 … … 42 94 43 95 private final BuildRequest req; 96 private Map<String, IObjectFile> cached = 97 new HashMap<String, IObjectFile>(); 98 99 // Since findModule() is called quite a bit, creating 100 // a new hash set every time sounds like a horrible thrashing of the GC. 101 // Instead, we'll just keep clearing out these set. They can't be static 102 // to maintain the threadsafe nature of the builder as a whole, however 103 private final Set<IJavaProject> visitedProjectAccumulator = 104 new HashSet<IJavaProject>(); 44 105 45 106 public ObjectFileFactory(BuildRequest req) … … 48 109 } 49 110 50 public IObjectFile create(ICompilationUnit cu, 51 boolean isLibraryFile) 111 public IObjectFile create(String moduleName) 112 { 113 // If there's a cached version, return that one 114 if(cached.containsKey(moduleName)) 115 return cached.get(moduleName); 116 117 // If we shouldn't be building it, return null 118 for(String ignored : req.getIgnoredModules()) 119 if(moduleName.startsWith(ignored)) 120 return null; 121 122 try 123 { 124 // Use a one-element array to get pointer semantics 125 boolean[] _isLibraryFile = new boolean[1]; 126 ICompilationUnit cu = findModule(moduleName, _isLibraryFile); 127 if(null == cu) 128 return null; 129 boolean isLibraryFile = _isLibraryFile[0]; 130 IObjectFile obj = getInstance(moduleName, cu, isLibraryFile); 131 cached.put(moduleName, obj); 132 return obj; 133 } 134 catch(JavaModelException e) 135 { 136 throw new BuildException(e); 137 } 138 } 139 140 private IObjectFile getInstance(String moduleName, 141 ICompilationUnit cu, boolean isLibraryFile) 52 142 { 53 143 File inputFile = new File(BuilderUtil.getAbsolutePath(cu.getResource(). … … 55 145 File outputFile = new File(req.getOutputLocation().getAbsolutePath() + 56 146 File.separator + getOutputFilename(cu)); 57 return new ObjectFile(inputFile, outputFile, isLibraryFile); 58 } 147 return new ObjectFile(moduleName, inputFile, outputFile, isLibraryFile); 148 } 149 150 private ICompilationUnit findModule(String moduleName, boolean[] isLibraryFile) 151 throws JavaModelException 152 { 153 visitedProjectAccumulator.clear(); 154 return findModuleInProject(req.getProject(), moduleName, isLibraryFile); 155 } 156 157 private ICompilationUnit findModuleInProject( 158 IJavaProject project, 159 String moduleName, 160 boolean[] isLibraryFile) 161 throws JavaModelException 162 { 163 if (visitedProjectAccumulator.contains(project)) 164 return null; 165 166 int index = moduleName.lastIndexOf('.'); 167 String packagePart = index > 0 ? moduleName.substring(0, index) : ""; 168 String modulePart = (index > 0 ? moduleName.substring(index + 1) : 169 moduleName) + ".d"; 170 171 ICompilationUnit module = null; 172 boolean libraryFile = false; 173 for(IPackageFragmentRoot root : project.getPackageFragmentRoots()) 174 { 175 IPackageFragment pkg = root.getPackageFragment(packagePart); 176 if (pkg.exists()) 177 { 178 // Check if it's in the package... 179 module = pkg.getCompilationUnit(modulePart); 180 181 // If not, check if it's a class file 182 if (!module.exists()) 183 { 184 module = pkg.getClassFile(modulePart); 185 libraryFile = true; 186 } 187 188 if(module.exists()) 189 { 190 break; 191 } 192 } 193 } 194 195 if(null != module && module.exists()) 196 { 197 // Note: existance must be tested since an ICompilationUnit may 198 // be returned for non-existant modules 199 isLibraryFile[0] = libraryFile; 200 return module; 201 } 202 203 visitedProjectAccumulator.add(project); 204 IJavaModel javaModel= project.getJavaModel(); 205 String[] requiredProjectNames= project.getRequiredProjectNames(); 206 for (int i= 0; i < requiredProjectNames.length; i++) 207 { 208 IJavaProject requiredProject= javaModel.getJavaProject(requiredProjectNames[i]); 209 if (requiredProject.exists()) 210 { 211 module = findModuleInProject(requiredProject, moduleName, isLibraryFile); 212 if (module != null) 213 return module; 214 } 215 } 216 return null; 217 } 59 218 60 219 private static String getOutputFilename(ICompilationUnit cu) 61 220 { 62 String name = cu.getFullyQualifiedName().replace('.', '-') + "." +221 String name = cu.getFullyQualifiedName().replace('.', '-') + 63 222 BuilderUtil.EXTENSION_OBJECT_FILE; 64 223 int len = name.length();
