001: package tide.sources;
002:
003: import snow.texteditor.SimpleDocument;
004: import tide.editor.MainEditorFrame;
005: import java.util.*;
006: import snow.utils.storage.StorageVector;
007:
008: /** Important part of tIDE. Each sourcefile contains an instance of this class,
009: * contains the dependences (bidirectional) with other sources in the project.
010: * Must be updated when the source changed.
011: * At best before compiling so we can augment the files to be compiled with their dependencies
012: * {see TreeFunctions.createDetectDependenciesThread()}
013: * {see DependenciesDetector.updateDependencies()}
014: * TODO: also store here the names here of the inner classes
015: */
016: public final class SourceFileDependencies {
017: /* these are the sources used by this file. These sources are notified that this source uses them.
018: so a recompilation of one of them must also cause a recompilation of this file.
019: Example: if this is "File", classesUsedBy contains "String"
020: */
021: private final Set<SourceFile> classesUsedBy = new HashSet<SourceFile>();
022:
023: // DON'T MODIFY !
024: public final Set<SourceFile> getClassesUsedBy_REF_() {
025: return classesUsedBy;
026: }
027:
028: /* these are really the files depending on this file, i.e. changes in this
029: must cause a recompilation of them ! (to detect errors !) */
030: private final Set<SourceFile> classesUsingThis = new HashSet<SourceFile>();
031:
032: public final Set<SourceFile> getClassesUsingThis_REF_() {
033: return classesUsingThis;
034: }
035:
036: /* keep trace of the declared types, relative names starting from this included
037: for example an inner class will be Name.InnerClass, a private top level class not inner
038: will have ItsName stored. => the associated class file will be named package + "."+name.repl(. , $) */
039: private final Set<String> declaredTypesNames = new HashSet<String>();
040:
041: public Set<String> getDeclaredTypesNames_REF_() {
042: return declaredTypesNames;
043: }
044:
045: // this is used to know if the dependencies are uptodate
046: private long detectedForSourceLength = -1;
047:
048: public boolean hasStaticMain = false;
049:
050: // a link
051: private final SourceFile this Source;
052:
053: SourceFileDependencies(SourceFile this Source) {
054: this .this Source = this Source;
055: }
056:
057: /** Sets the resolved dependencies found in this source file.
058: * The source file must have been stored ! (to know its length)
059: */
060: public void setDependenciesOnOtherSources_(
061: final Collection<SourceFile> deps) {
062: // this uses deps as for example: "File" use "String"
063:
064: if (deps.size() < classesUsedBy.size()) {
065: MainEditorFrame
066: .debugOut("setDependenciesOnOtherSources reducing from "
067: + classesUsedBy.size()
068: + " to "
069: + deps.size() + " srcs for " + this Source);
070: //MainEditorFrame.debugOut(new Throwable("zero deps for "+thisSource+" (prior was "+classesUsedBy.size()+")"));
071: }
072:
073: // allow to know if actual
074: detectedForSourceLength = this Source.javaFile.length();
075:
076: // makes no sense.
077: //deps.remove(thisSource);
078:
079: // for all old deps, remove them from the targets
080: for (SourceFile sf : classesUsedBy) {
081: sf.sourceFileDependencies.classesUsingThis
082: .remove(this Source);
083: }
084:
085: // set the new
086: classesUsedBy.clear();
087: classesUsedBy.addAll(deps);
088:
089: // update the refs
090: for (SourceFile sf : classesUsedBy) {
091: sf.sourceFileDependencies.classesUsingThis.add(this Source);
092: }
093: }
094:
095: public void reset_() {
096: // sometimes equals "?#"
097: /*if(!thisSource.getJavaName().equals("?#"))
098: {
099: MainEditorFrame.debugOut("reset deps for "+thisSource.getJavaName()+" "+thisSource.getFileOrDirectory());
100: }*/
101: classesUsedBy.clear();
102: classesUsingThis.clear();
103: detectedForSourceLength = -1;
104: }
105:
106: /** Uses the actual source length and the stored one to compare.
107: */
108: public boolean areDependenciesActual() {
109: if (this Source.javaFile == null)
110: return true; // ??? ok (directories)
111:
112: // test file existence to avoid crashes ?
113: return this Source.javaFile.length() == detectedForSourceLength;
114: }
115:
116: /** This clears the dependencies.
117: */
118: public void fileHasBeenDeletedOrIsIgnored() {
119:
120: // for all old deps, remove them from the targets
121: for (final SourceFile sf : classesUsedBy) {
122: sf.sourceFileDependencies.classesUsingThis
123: .remove(this Source);
124: }
125:
126: for (final SourceFile sf : classesUsingThis) {
127: sf.sourceFileDependencies.classesUsedBy.remove(this Source);
128: // [Jan2007] was missing
129: sf.setIsCompiled(false);
130: }
131:
132: reset_();
133:
134: }
135:
136: //
137: // persistence (impl within sourcefile)
138: //
139:
140: public StorageVector getVectorRep() {
141: StorageVector rep = new StorageVector();
142: rep.add(1); // 0, version
143: rep.add(detectedForSourceLength); // 1
144:
145: StorageVector cusing = new StorageVector();
146: rep.add(cusing); // 2
147: for (SourceFile sf : this .classesUsingThis) {
148: cusing.add(sf.getJavaName());
149: }
150:
151: StorageVector cused = new StorageVector();
152: rep.add(cused); // 3
153: for (SourceFile sf : this .classesUsedBy) {
154: cused.add(sf.getJavaName());
155: }
156:
157: rep.add(hasStaticMain); // 4
158:
159: rep.add(new ArrayList<String>(declaredTypesNames)); // 5
160:
161: return rep;
162: }
163:
164: /** Called only from SourceFile !
165: */
166: @SuppressWarnings("unchecked")
167: public void restoreFromVectorRep(StorageVector rep,
168: SourcesTreeModel model) {
169: detectedForSourceLength = (Long) rep.get(1);
170:
171: List<String> cusing = (List<String>) rep.get(2);
172: this .classesUsingThis.clear();
173: for (String jn : cusing) {
174: SourceFile sf = model.getSourceFile(jn, "");
175: if (sf != null) {
176: classesUsingThis.add(sf);
177: } else {
178: System.out.println("" + this Source
179: + ": Cl using not found: " + jn);
180: // invalidate
181: detectedForSourceLength = -1;
182: }
183: }
184:
185: List<String> cused = (List<String>) rep.get(3);
186: this .classesUsedBy.clear();
187: for (String jn : cused) {
188: SourceFile sf = model.getSourceFile(jn, "");
189: if (sf != null) {
190: classesUsedBy.add(sf);
191: } else {
192: System.out.println("" + this Source
193: + ": Cl used by not found: " + jn);
194: // invalidate
195: detectedForSourceLength = -1;
196: }
197: }
198:
199: if (rep.size() > 4) {
200: hasStaticMain = (Boolean) rep.get(4);
201: } else {
202: // sorry, invalidate
203: detectedForSourceLength = -1;
204: }
205:
206: if (rep.size() > 5) {
207: declaredTypesNames.addAll((List<String>) rep.get(5));
208: }
209:
210: /*if(thisSource.getJavaName().equals("ZTrTTW90"))
211: {
212: new Throwable().printStackTrace();
213: System.out.println(""+this);
214: }*/
215:
216: }
217:
218: @Override
219: public final String toString() {
220: StringBuilder sb = new StringBuilder();
221: sb.append("Deps of " + this .this Source + ": uses "
222: + classesUsedBy.size() + ", is used by "
223: + classesUsingThis.size());
224: if (!areDependenciesActual())
225: sb.append(" NOT ACTUAL");
226: return sb.toString();
227: }
228:
229: public void writeDependencies(final SimpleDocument doc) {
230: SourceFile src = this .this Source;
231: doc.append("=== Source dependencies for " + src.getJavaName()
232: + " === (" + classesUsedBy.size() + ", "
233: + classesUsingThis.size() + ")");
234: if (!areDependenciesActual()) {
235: doc.append(" NOT ACTUAL");
236: }
237: doc.append("\r\n");
238: if (classesUsedBy.isEmpty()) {
239: doc.appendLine("Uses no other classes in the project");
240: } else {
241: doc.appendLine("Uses "
242: + src.sourceFileDependencies.classesUsedBy.size()
243: + " class"
244: + (classesUsedBy.size() == 1 ? "" : "es") + ":");
245: for (SourceFile sf : classesUsedBy) {
246: doc.appendLine(" " + sf.getJavaName() + ".java:");
247: }
248: }
249:
250: doc.appendLine("");
251:
252: if (classesUsingThis.isEmpty()) {
253: doc
254: .appendLine("Is used by no other classes in the project");
255: } else {
256: doc.appendLine("Is used by " + classesUsingThis.size()
257: + " class"
258: + (classesUsingThis.size() == 1 ? "" : "es") + ":");
259: for (SourceFile sf : classesUsingThis) {
260: doc.appendLine(" " + sf.getJavaName() + ".java:");
261: }
262: }
263:
264: doc.appendLine("");
265: }
266:
267: }
|