Skip to content

Commit 958f548

Browse files
author
kevinmontrose
committed
implementing fix for task 154200 Project Main Document Heuristics should not be hard-coded. XML and old-style project files now store main-class name instead of main-class file. Opening old project files will result in an attempted fix-up of the old data, which may not always succeed; but will not result in an error. Confirmed all tests pass.
git-svn-id: file:///tmp/test-svn/trunk@4782 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent e997230 commit 958f548

17 files changed

+256
-93
lines changed

drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,9 @@ public void setFileGroupingState(FileGroupingState state) {
410410
}
411411

412412
protected FileGroupingState
413-
makeProjectFileGroupingState(File pr, File main, File bd, File wd, File project, File[] srcFiles, File[] auxFiles,
413+
makeProjectFileGroupingState(File pr, String main, File bd, File wd, File project, File[] srcFiles, File[] auxFiles,
414414
File[] excludedFiles, Iterable<File> cp, File cjf, int cjflags, boolean refresh) {
415+
415416
return new ProjectFileGroupingState(pr, main, bd, wd, project, srcFiles, auxFiles, excludedFiles, cp, cjf, cjflags,
416417
refresh);
417418
}
@@ -455,14 +456,52 @@ public void setProjectChanged(boolean changed) {
455456
public boolean inProjectPath(OpenDefinitionsDocument doc) { return _state.inProjectPath(doc); }
456457

457458
/** Sets the class with the project's main method. */
458-
public void setMainClass(File f) {
459+
public void setMainClass(String f) {
459460
_state.setMainClass(f);
460461
_notifier.projectRunnableChanged();
461462
setProjectChanged(true);
462463
}
463464

464465
/** @return the class with the project's main method. */
465-
public File getMainClass() { return _state.getMainClass(); }
466+
public String getMainClass() { return _state.getMainClass(); }
467+
468+
private static edu.rice.cs.util.Log Log = new edu.rice.cs.util.Log("mainClassFile.txt", true);
469+
470+
/** @return the file containing the project's main class. */
471+
public File getMainClassContainingFile(){
472+
String path = getMainClass();
473+
474+
Log.log("For path: "+path+"\n");
475+
476+
if(path == null){
477+
Log.log("\tnull\n");
478+
return null;
479+
}
480+
481+
if(path.toLowerCase().endsWith(".java")){
482+
Log.log("\t"+(new File(getProjectFile().getParent(), path)).getAbsolutePath()+"\n");
483+
return new File(getProjectFile().getParent(), path);
484+
}//if
485+
486+
path = path.replace('.', File.separatorChar);
487+
File tempFile = new File(getProjectFile().getParent(), path+".java");
488+
489+
while(path.length() > 0){
490+
if(tempFile.exists()){
491+
Log.log("\t"+tempFile.getAbsolutePath()+"\n");
492+
return tempFile;
493+
}//if
494+
495+
if(path.indexOf(File.separatorChar) == -1)
496+
break;
497+
498+
path = path.substring(0, path.lastIndexOf(File.separatorChar));
499+
tempFile = new File(getProjectFile().getParent(), path+".java");
500+
}
501+
502+
Log.log("\tnull\n");
503+
return null;
504+
}
466505

467506
/** Sets the create jar file of the project. */
468507
public void setCreateJarFile(File f) {
@@ -554,7 +593,7 @@ protected static String getPackageName(String classname) {
554593
class ProjectFileGroupingState implements FileGroupingState {
555594

556595
volatile File _projRoot;
557-
volatile File _mainFile;
596+
volatile String _mainClass;
558597
volatile File _buildDir;
559598
volatile File _workDir;
560599
volatile File _projectFile;
@@ -575,10 +614,10 @@ class ProjectFileGroupingState implements FileGroupingState {
575614
IterUtil.<File>empty(), null, 0, false);
576615
}
577616

578-
ProjectFileGroupingState(File pr, File main, File bd, File wd, File project, File[] srcFiles, File[] auxFiles,
617+
ProjectFileGroupingState(File pr, String main, File bd, File wd, File project, File[] srcFiles, File[] auxFiles,
579618
File[] excludedFiles, Iterable<File> cp, File cjf, int cjflags, boolean refreshStatus) {
580619
_projRoot = pr;
581-
_mainFile = main;
620+
_mainClass = main;
582621
_buildDir = bd;
583622
_workDir = wd;
584623
_projectFile = project;
@@ -721,9 +760,9 @@ public void setExcludedFiles(File[] fs) {
721760

722761
public void setWorkingDirectory(File f) { _workDir = f; }
723762

724-
public File getMainClass() { return _mainFile; }
763+
public String getMainClass() { return _mainClass; }
725764

726-
public void setMainClass(File f) { _mainFile = f; }
765+
public void setMainClass(String f) { _mainClass = f; }
727766

728767
public void setCreateJarFile(File f) { _createJarFile = f; }
729768

@@ -911,8 +950,8 @@ public void remAuxFile(File f) { }
911950
public void setWorkingDirectory(File f) { }
912951
public File[] getProjectFiles() { return new File[0]; }
913952
public boolean inProject(File f) { return false; }
914-
public File getMainClass() { return null; }
915-
public void setMainClass(File f) { }
953+
public String getMainClass() { return null; }
954+
public void setMainClass(String f) { }
916955
public void setCreateJarFile(File f) { }
917956
public File getCreateJarFile() { return FileOps.NULL_FILE; }
918957
public void setCreateJarFlags(int f) { }
@@ -1515,7 +1554,7 @@ else if (doc.isAuxiliaryFile()) {
15151554
if (wd != FileOps.NULL_FILE) builder.setWorkingDirectory(wd);
15161555

15171556
// add jar main class
1518-
File mainClass = getMainClass();
1557+
String mainClass = getMainClass();
15191558
if (mainClass != null) builder.setMainClass(mainClass);
15201559

15211560
// add create jar file
@@ -1567,7 +1606,7 @@ public void saveProject(File file, HashMap<OpenDefinitionsDocument, DocumentInfo
15671606
// for (File f: builder.getAuxiliaryFiles()) { _auxiliaryFiles.add(f); }
15681607
// }
15691608

1570-
setFileGroupingState(makeProjectFileGroupingState(builder.getProjectRoot(), builder.getMainClass (),
1609+
setFileGroupingState(makeProjectFileGroupingState(builder.getProjectRoot(), builder.getMainClass(),
15711610
builder.getBuildDirectory(), builder.getWorkingDirectory(), file,
15721611
builder.getSourceFiles(), builder.getAuxiliaryFiles(),
15731612
builder.getExcludedFiles(),
@@ -1633,7 +1672,7 @@ private void _loadProject(final ProjectFileIR ir) throws IOException {
16331672
final File projectRoot = pr;
16341673
final File buildDir = ir.getBuildDirectory ();
16351674
final File workDir = ir.getWorkingDirectory();
1636-
final File mainClass = ir.getMainClass();
1675+
final String mainClass = ir.getMainClass();
16371676
final Iterable<File> projectClassPaths = ir.getClassPaths();
16381677
final File createJarFile = ir.getCreateJarFile ();
16391678
int createJarFlags = ir.getCreateJarFlags();
@@ -3016,7 +3055,7 @@ public void startCompile() throws IOException {
30163055
}
30173056

30183057
/** throws UnsupportedOperationException */
3019-
public void runMain() throws IOException, ClassNameNotFoundException {
3058+
public void runMain(String className) throws IOException, ClassNameNotFoundException {
30203059
throw new UnsupportedOperationException("AbstractGlobalModel does not support running");
30213060
}
30223061

drjava/src/edu/rice/cs/drjava/model/DefaultGlobalModel.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,16 +432,26 @@ public void startCompile() throws IOException {
432432
* up to date. Fires an event to signal when execution is about to begin.
433433
* NOTE: this code normally runs in the event thread; it cannot block waiting for an event that is triggered by
434434
* event thread execution!
435+
*
436+
* @param qualifiedClassName - the qualified name of the class (in this document) to run. If NULL, it is the name of the top level class.
437+
*
435438
* @exception ClassNameNotFoundException propagated from getFirstTopLevelClass()
436439
* @exception IOException propagated from GlobalModel.compileAll()
437440
*/
438-
public void runMain() throws ClassNameNotFoundException, IOException {
441+
public void runMain(String qualifiedClassName) throws ClassNameNotFoundException, IOException {
439442
assert EventQueue.isDispatchThread();
440443

441444
_notifier.prepareForRun(ConcreteOpenDefDoc.this);
442445

446+
String tempClassName = null;
447+
448+
if(qualifiedClassName == null)
449+
tempClassName = getDocument().getQualifiedClassName();
450+
else
451+
tempClassName = qualifiedClassName;
452+
443453
// Get the class name for this document, the first top level class in the document.
444-
final String className = getDocument().getQualifiedClassName();
454+
final String className = tempClassName;
445455
final InteractionsDocument iDoc = _interactionsModel.getDocument();
446456
if (! checkIfClassFileInSync()) {
447457
iDoc.insertBeforeLastPrompt(DOCUMENT_OUT_OF_SYNC_MSG, InteractionsDocument.ERROR_STYLE);

drjava/src/edu/rice/cs/drjava/model/DummyGlobalModel.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,11 +437,15 @@ public void setWorkingDirectory(File f) {
437437
throw new UnsupportedOperationException("Tried to call setWorkingDirectory on a Dummy");
438438
}
439439

440-
public void setMainClass(File f) {
440+
public void setMainClass(String f) {
441441
throw new UnsupportedOperationException("Tried to call setMainClass on a Dummy");
442442
}
443443

444-
public File getMainClass() {
444+
public String getMainClass() {
445+
throw new UnsupportedOperationException("Tried to call getMainClass on a Dummy");
446+
}
447+
448+
public File getMainClassContainingFile(){
445449
throw new UnsupportedOperationException("Tried to call getMainClass on a Dummy");
446450
}
447451

drjava/src/edu/rice/cs/drjava/model/DummyOpenDefDoc.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public String getFirstTopLevelClassName() throws ClassNameNotFoundException {
121121

122122
public void startCompile() throws IOException { throw new UnsupportedOperationException("Dummy method"); }
123123

124-
public void runMain() throws IOException { throw new UnsupportedOperationException("Dummy method"); }
124+
public void runMain(String className) throws IOException { throw new UnsupportedOperationException("Dummy method"); }
125125

126126
public boolean revertIfModifiedOnDisk() throws IOException {
127127
throw new UnsupportedOperationException("Dummy method");

drjava/src/edu/rice/cs/drjava/model/FileGroupingState.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,15 @@ public interface FileGroupingState {
100100
/** Sets the current working directory for the interactions pane. */
101101
public void setWorkingDirectory(File f);
102102

103-
/** Returns the source file that has the main method of the project
103+
/** Returns the name of the class that has the main method of the project
104104
* @return null if no build directory is specified
105105
*/
106-
public File getMainClass();
106+
public String getMainClass();
107107

108-
/** Sets the file that has the main method of the project
108+
/** Sets the name of the class that has the main method of the project
109109
* (Note: should point to the sourcefile of the document, not the class file)
110110
*/
111-
public void setMainClass(File f);
111+
public void setMainClass(String f);
112112

113113
/** Sets the create jar file of the project. */
114114
public void setCreateJarFile(File f);

drjava/src/edu/rice/cs/drjava/model/GlobalModel.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,13 @@ public InteractionsScriptModel loadHistoryAsScript(FileOpenSelector selector)
444444
public void setWorkingDirectory(File f);
445445

446446
/** Sets the main file of the project. */
447-
public void setMainClass(File f);
447+
public void setMainClass(String f);
448448

449449
/** Return the main file for the project If not in project mode, returns null. */
450-
public File getMainClass();
450+
public String getMainClass();
451+
452+
/** Return the File that contains the Main-Class. */
453+
public File getMainClassContainingFile();
451454

452455
/** Returns only the project's extra classpaths.
453456
* @return The classpath entries loaded along with the project

drjava/src/edu/rice/cs/drjava/model/GlobalModelOtherTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ public void testRunMainMethod() throws Exception {
536536
final OpenDefinitionsDocument doc = doCompile(FOO_CLASS, file);
537537
Utilities.invokeAndWait(new Runnable() {
538538
public void run() {
539-
try { doc.runMain(); }
539+
try { doc.runMain(null); }
540540
catch(Exception e) { throw new UnexpectedException(e); }
541541
}
542542
});
@@ -547,7 +547,7 @@ public void run() {
547547

548548
Utilities.invokeAndWait(new Runnable() {
549549
public void run() {
550-
try { doc.runMain(); }
550+
try { doc.runMain(null); }
551551
catch(Exception e) { throw new UnexpectedException(e); }
552552
}
553553
});

drjava/src/edu/rice/cs/drjava/model/OpenDefinitionsDocument.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,12 @@ public interface OpenDefinitionsDocument extends DJDocument, Finalizable<Definit
209209

210210
/** Runs the main method in this document in the interactions pane. Demands that the definitions be saved
211211
* and compiled before proceeding. Fires an event to signal when execution is about to begin.
212+
*
213+
* @param qualifiedClassName - the fully qualified name of the class contained in this document to run the main(String[]) method of
212214
* @exception ClassNameNotFoundException propagated from getFirstTopLevelClass()
213215
* @exception IOException propagated from GlobalModel.compileAll()
214216
*/
215-
public void runMain() throws ClassNameNotFoundException, IOException;
217+
public void runMain(String qualifiedClassName) throws ClassNameNotFoundException, IOException;
216218

217219
/** Starts testing the source using JUnit. Demands that the definitions be saved and compiled before proceeding
218220
* with testing. Fires the appropriate events as the testing proceeds and finishes.

drjava/src/edu/rice/cs/drjava/project/ProjectFileIR.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,11 @@ public interface ProjectFileIR {
7272
/** @return an array full of all the classpath path elements in the classpath for this project file */
7373
public Iterable<File> getClassPaths();
7474

75-
/** @return the name of the file that holds the Jar main class associated with this project */
76-
public File getMainClass();
75+
/** @return the fully qualified name of the class that holds the Jar main class associated with this project */
76+
public String getMainClass();
77+
78+
/** @return the File that contains the class specified by getMainClass() */
79+
public File getMainClassContainingFile();
7780

7881
/** @return the project file for this project. */
7982
public File getProjectFile();
@@ -105,7 +108,7 @@ public interface ProjectFileIR {
105108
public void setClassPaths(Iterable<? extends File> cp);
106109
public void setBuildDirectory(File dir);
107110
public void setWorkingDirectory(File dir);
108-
public void setMainClass(File main);
111+
public void setMainClass(String main);
109112
public void setProjectRoot(File root);
110113
public void setCreateJarFile(File createJarFile);
111114
public void setCreateJarFlags(int createJarFlags);

drjava/src/edu/rice/cs/drjava/project/ProjectFileParser.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,20 @@ else if (name.compareToIgnoreCase("classpaths") == 0) {
157157
pfir.setClassPaths(fList);
158158
}
159159
else if (name.compareToIgnoreCase("main-class") == 0) {
160-
List<DocFile> fList = exp.getRest().accept(flv);
161-
if (fList.size() > 1) throw new PrivateProjectException("Cannot have multiple main classes");
162-
else if (fList.size() == 0) pfir.setMainClass(null);
163-
else pfir.setMainClass(fList.get(0));
160+
try{
161+
List<DocFile> fList = exp.getRest().accept(flv);
162+
if(fList.size() == 1){
163+
String main = fList.get(0).getPath().replace(File.separatorChar,'.');
164+
main = main.substring(0, main.length() - 5);
165+
166+
pfir.setMainClass(main);
167+
168+
return;
169+
}
170+
}catch(Exception exc){}
171+
172+
String mainClass = exp.getRest().accept(NameVisitor.ONLY);
173+
pfir.setMainClass(mainClass);
164174
}
165175
else if (name.compareToIgnoreCase("create-jar-file") == 0) {
166176
List<DocFile> fList = exp.getRest().accept(flv);

0 commit comments

Comments
 (0)