1 33 34 package edu.rice.cs.drjava.model.compiler; 35 36 import java.io.File ; 37 import java.io.IOException ; 38 39 import java.util.List ; 40 import java.util.ArrayList ; 41 import java.util.Arrays ; 42 import java.util.Collections ; 43 import java.util.HashSet ; 44 import java.util.LinkedList ; 45 import java.util.Iterator ; 46 import java.util.StringTokenizer ; 47 48 import edu.rice.cs.drjava.DrJava; 49 import edu.rice.cs.drjava.config.OptionConstants; 50 51 import edu.rice.cs.drjava.model.GlobalModel; 52 import edu.rice.cs.drjava.model.OpenDefinitionsDocument; 53 import edu.rice.cs.drjava.model.definitions.InvalidPackageException; 54 55 import edu.rice.cs.plt.io.IOUtil; 56 import edu.rice.cs.util.ClassPathVector; 57 import edu.rice.cs.util.swing.Utilities; 58 import edu.rice.cs.util.UnexpectedException; 59 60 61 import edu.rice.cs.javalanglevels.*; 62 import edu.rice.cs.javalanglevels.parser.*; 63 import edu.rice.cs.javalanglevels.tree.*; 64 65 69 public class DefaultCompilerModel implements CompilerModel { 70 71 72 private final CompilerEventNotifier _notifier = new CompilerEventNotifier(); 73 74 75 private final GlobalModel _model; 76 77 78 private CompilerErrorModel _compilerErrorModel; 79 80 81 private File _workDir; 82 83 84 private Object _compilerLock = new Object (); 85 86 89 public DefaultCompilerModel(GlobalModel m) { 90 _model = m; 91 _compilerErrorModel = new CompilerErrorModel(new CompilerError[0], _model); 92 _workDir = _model.getWorkingDirectory(); 93 } 94 95 97 98 public Object getCompilerLock() { return _compilerLock; } 99 100 102 107 public void addListener(CompilerListener listener) { _notifier.addListener(listener); } 108 109 115 public void removeListener(CompilerListener listener) { _notifier.removeListener(listener); } 116 117 118 public void removeAllListeners() { _notifier.removeAllListeners(); } 119 120 122 123 137 public void compileAll() throws IOException { 138 if (_prepareForCompile()) { 139 _doCompile(_model.getOpenDefinitionsDocuments()); 140 } 141 } 142 143 157 public void compileProject() throws IOException { 158 if (! _model.isProjectActive()) 159 throw new UnexpectedException("compileProject invoked when DrJava is not in project mode"); 160 161 if (_prepareForCompile()) { 162 _doCompile(_model.getProjectDocuments()); 163 } 164 } 165 166 180 public void compile(List <OpenDefinitionsDocument> defDocs) throws IOException { 181 if (_prepareForCompile()) { 182 _doCompile(defDocs); 183 } 184 } 185 186 200 public void compile(OpenDefinitionsDocument doc) throws IOException { 201 if (_prepareForCompile()) { 202 _doCompile(Arrays.asList(doc)); 203 } 204 } 205 206 209 private boolean _prepareForCompile() { 210 if (_model.hasModifiedDocuments()) _notifier.saveBeforeCompile(); 211 return !_model.hasModifiedDocuments(); 213 } 214 215 216 private void _doCompile(List <OpenDefinitionsDocument> docs) throws IOException { 217 ArrayList <File > filesToCompile = new ArrayList <File >(); 218 ArrayList <File > excludedFiles = new ArrayList <File >(); 219 for (OpenDefinitionsDocument doc : docs) { 220 if (doc.isSourceFile()) { 221 File f = doc.getFile(); 222 if (f != null) { filesToCompile.add(f); } 224 doc.setCachedClassFile(null); } 226 else excludedFiles.add(doc.getFile()); 227 } 228 229 File buildDir = _model.getBuildDirectory(); 230 if ((buildDir!=null) && !buildDir.exists() && !buildDir.mkdirs()) { 231 throw new IOException ("Could not create build directory: "+buildDir); 232 } 233 234 File workDir = _model.getWorkingDirectory(); 235 if ((workDir != null) && ! workDir.exists() && ! workDir.mkdirs()) { 236 throw new IOException ("Could not create working directory: "+workDir); 237 } 238 239 _notifier.compileStarted(); 240 try { _compileFiles(filesToCompile, buildDir); } 241 catch (Throwable t) { 242 CompilerError err = new CompilerError(t.toString(), false); 243 _distributeErrors(Arrays.asList(err)); 244 } 245 finally { _notifier.compileEnded(workDir, excludedFiles); } 246 } 247 248 249 251 252 private LinkedList <CompilerError> _parseExceptions2CompilerErrors(LinkedList <JExprParseException> pes) { 253 LinkedList <CompilerError> errors = new LinkedList <CompilerError>(); 254 Iterator <JExprParseException> iter = pes.iterator(); 255 while (iter.hasNext()) { 256 JExprParseException pe = iter.next(); 257 errors.addLast(new CompilerError(pe.getFile(), pe.currentToken.beginLine-1, pe.currentToken.beginColumn-1, pe.getMessage(), false)); 258 } 259 return errors; 260 } 261 262 263 private LinkedList <CompilerError> _visitorErrors2CompilerErrors(LinkedList <Pair<String , JExpressionIF>> visitorErrors) { 264 LinkedList <CompilerError> errors = new LinkedList <CompilerError>(); 265 Iterator <Pair<String , JExpressionIF>> iter = visitorErrors.iterator(); 266 while (iter.hasNext()) { 267 Pair<String , JExpressionIF> pair = iter.next(); 268 String message = pair.getFirst(); 269 JExpressionIF jexpr = pair.getSecond(); 271 272 SourceInfo si; 273 if (jexpr == null) si = JExprParser.NO_SOURCE_INFO; 274 else si = pair.getSecond().getSourceInfo(); 275 276 errors.addLast(new CompilerError(si.getFile(), si.getStartLine()-1, si.getStartColumn()-1, message, false)); 277 } 278 return errors; 279 } 280 281 290 private void _compileFiles(List <? extends File > files, File buildDir) throws IOException { 291 if (!files.isEmpty()) { 292 293 if (buildDir != null) buildDir = IOUtil.attemptCanonicalFile(buildDir); 294 295 List <File > classPath = _model.getClassPath().asFileVector(); 296 297 List <File > bootClassPath = null; 299 if (System.getProperty("drjava.bootclasspath") != null) { 300 bootClassPath = new LinkedList <File >(); 301 StringTokenizer st = new StringTokenizer (System.getProperty("drjava.bootclasspath"), File.pathSeparator); 302 while (st.hasMoreTokens()) { 303 bootClassPath.add(new File (st.nextToken())); 304 } 305 } 306 307 List <CompilerError> errors = new LinkedList <CompilerError>(); 308 309 List <? extends File > preprocessedFiles = _compileLanguageLevelsFiles(files, errors); 310 311 if (errors.isEmpty()) { 312 CompilerInterface compiler = CompilerRegistry.ONLY.getActiveCompiler(); 313 314 synchronized(_compilerLock) { 315 if (preprocessedFiles == null) { 316 errors.addAll(compiler.compile(files, classPath, null, buildDir, bootClassPath, null, true)); 317 } 318 else { 319 320 errors.addAll(compiler.compile(preprocessedFiles, classPath, null, buildDir, bootClassPath, null, false)); 321 } 322 } 323 } 324 _distributeErrors(errors); 325 } 326 else { 327 _distributeErrors(Collections.<CompilerError>emptyList()); 329 } 330 } 331 332 333 337 private List <? extends File > _compileLanguageLevelsFiles(List <? extends File > files, List <? super CompilerError> errors) { 338 LanguageLevelConverter llc = new LanguageLevelConverter(getActiveCompiler().getName()); 340 Pair<LinkedList <JExprParseException>, LinkedList <Pair<String , JExpressionIF>>> llErrors = 341 llc.convert(files.toArray(new File [0])); 342 343 348 HashSet <File > javaFileSet = new HashSet <File >(); 349 boolean containsLanguageLevels = false; 350 for (File f : files) { 351 File canonicalFile = IOUtil.attemptCanonicalFile(f); 352 String fileName = canonicalFile.getPath(); 353 int lastIndex = fileName.lastIndexOf(".dj"); 354 if (lastIndex != -1) { 355 containsLanguageLevels = true; 356 javaFileSet.add(new File (fileName.substring(0, lastIndex) + ".java")); 357 } 358 else { javaFileSet.add(canonicalFile); } 359 } 360 files = new LinkedList <File >(javaFileSet); 361 362 errors.addAll(_parseExceptions2CompilerErrors(llErrors.getFirst())); 363 errors.addAll(_visitorErrors2CompilerErrors(llErrors.getSecond())); 364 if (containsLanguageLevels) { return files; } 365 else { return null; } 366 } 367 368 371 private void _distributeErrors(List <? extends CompilerError> errors) throws IOException { 372 _compilerErrorModel = new CompilerErrorModel(errors.toArray(new CompilerError[0]), _model); 374 _model.setNumCompErrors(_compilerErrorModel.getNumCompErrors()); } 376 377 379 380 public CompilerErrorModel getCompilerErrorModel() { return _compilerErrorModel; } 381 382 383 public int getNumErrors() { return getCompilerErrorModel().getNumErrors(); } 384 385 386 public int getNumCompErrors() { return getCompilerErrorModel().getNumCompErrors(); } 387 388 389 public int getNumWarnings() { return getCompilerErrorModel().getNumWarnings(); } 390 391 392 public void resetCompilerErrors() { 393 _compilerErrorModel = new CompilerErrorModel(new CompilerError[0], _model); 395 } 396 397 399 410 public CompilerInterface[] getAvailableCompilers() { 411 return CompilerRegistry.ONLY.getAvailableCompilers(); 412 } 413 414 420 public CompilerInterface getActiveCompiler() { 421 return CompilerRegistry.ONLY.getActiveCompiler(); 422 } 423 424 432 public void setActiveCompiler(CompilerInterface compiler) { 433 CompilerRegistry.ONLY.setActiveCompiler(compiler); 434 } 435 } 436 | Popular Tags |