rootdocimpl.java
来自「linux下建立JAVA虚拟机的源码KAFFE」· Java 代码 · 共 1,314 行 · 第 1/3 页
JAVA
1,314 行
classDocMap.put(cd.qualifiedName(), cd); } public void addClassDocRecursive(ClassDoc cd) { classDocMap.put(cd.qualifiedName(), cd); ClassDoc[] innerClasses = cd.innerClasses(false); for (int i=0; i<innerClasses.length; ++i) { addClassDocRecursive(innerClasses[i]); } } public void addPackageDoc(PackageDoc pd) { packageDocMap.put(pd.name(), pd); } public PackageDocImpl getPackageDoc(String name) { return (PackageDocImpl)packageDocMap.get(name); } public ClassDocImpl getClassDoc(String qualifiedName) { return (ClassDocImpl)classDocMap.get(qualifiedName); } class ScheduledClass { ClassDoc contextClass; String qualifiedName; ScheduledClass(ClassDoc contextClass, String qualifiedName) { this.contextClass=contextClass; this.qualifiedName=qualifiedName; } public String toString() { return "ScheduledClass{"+qualifiedName+"}"; } } public void scheduleClass(ClassDoc context, String qualifiedName) throws ParseException, IOException { if (classDocMap.get(qualifiedName)==null) { //Debug.log(9,"Scheduling "+qualifiedName+", context "+context+"."); //System.err.println("Scheduling " + qualifiedName + ", context " + context); scheduledClasses.add(new ScheduledClass(context, qualifiedName)); } } /** * Load all classes that were implictly referenced by the classes * (already loaded) that the user explicitly specified on the * command line. * * For example, if the user generates Documentation for his simple * 'class Test {}', which of course 'extends java.lang.Object', * then 'java.lang.Object' is implicitly referenced because it is * the base class of Test. * * Gjdoc needs a ClassDocImpl representation of all classes * implicitly referenced through derivation (base class), * or implementation (interface), or field type, method argument * type, or method return type. * * The task of this method is to ensure that Gjdoc has all this * information at hand when it exits. * * */ public void loadScheduledClasses(Parser parser) throws ParseException, IOException { // Because the referenced classes could in turn reference other // classes, this method runs as long as there are still unloaded // classes. while (!scheduledClasses.isEmpty()) { // Make a copy of scheduledClasses and empty it. This // prevents any Concurrent Modification issues. // As the copy won't need to grow (as it won't change) // we make it an Array for performance reasons. ScheduledClass[] scheduledClassesArr = (ScheduledClass[])scheduledClasses.toArray(new ScheduledClass[0]); scheduledClasses.clear(); // Load each class specified in our array copy for (int i=0; i<scheduledClassesArr.length; ++i) { // The name of the class we are looking for. This name // needs not be fully qualified. String scheduledClassName=scheduledClassesArr[i].qualifiedName; // The ClassDoc in whose context the scheduled class was looked for. // This is necessary in order to resolve non-fully qualified // class names. ClassDoc scheduledClassContext=scheduledClassesArr[i].contextClass; // If there already is a class doc with this name, skip. There's // nothing to do for us. if (classDocMap.get(scheduledClassName)!=null) { continue; } try { // Try to load the class //printNotice("Trying to load " + scheduledClassName); loadScheduledClass(parser, scheduledClassName, scheduledClassContext); } catch (ParseException e) { /********************************************************** // Check whether the following is necessary at all. if (scheduledClassName.indexOf('.')>0) { // Maybe the dotted notation doesn't mean a package // name but instead an inner class, as in 'Outer.Inner'. // so let's assume this and try to load the outer class. String outerClass=""; for (StringTokenizer st=new StringTokenizer(scheduledClassName,"."); st.hasMoreTokens(); ) { if (outerClass.length()>0) outerClass+="."; outerClass+=st.nextToken(); if (!st.hasMoreTokens()) break; try { loadClass(outerClass); //FIXME: shouldn't this be loadScheduledClass(outerClass, scheduledClassContext); ??? continue; } catch (Exception ee) { // Ignore: try next level } } } **********************************************************/ // If we arrive here, the class could not be found printWarning("Couldn't load class "+scheduledClassName+" referenced by "+scheduledClassContext); //FIXME: shouldn't this be throw new Error("cannot load: "+scheduledClassName); } } } } private void loadScheduledClass(Parser parser, String scheduledClassName, ClassDoc scheduledClassContext) throws ParseException, IOException { ClassDoc loadedClass=(ClassDoc)scheduledClassContext.findClass(scheduledClassName); if (loadedClass==null || loadedClass instanceof ClassDocProxy) { ClassDoc classDoc = findScheduledClassFile(scheduledClassName, scheduledClassContext); if (null != classDoc) { if (classDoc instanceof ClassDocReflectedImpl) { Main.getRootDoc().addClassDocRecursive(classDoc); } if (Main.DESCEND_SUPERCLASS && null != classDoc.superclass() && (classDoc.superclass() instanceof ClassDocProxy)) { scheduleClass(classDoc, classDoc.superclass().qualifiedName()); } } else { // It might be an inner class of one of the outer/super classes. // But we can only check that when they are all fully loaded. boolean retryLater = false; int numberOfProcessedFilesBefore = parser.getNumberOfProcessedFiles(); ClassDoc cc = scheduledClassContext.containingClass(); while (cc != null && !retryLater) { ClassDoc sc = cc.superclass(); while (sc != null && !retryLater) { if (sc instanceof ClassDocProxy) { ((ClassDocImpl)cc).resolve(); retryLater = true; } sc = sc.superclass(); } cc = cc.containingClass(); } // Now that outer/super references have been resolved, try again // to find the class. loadedClass = (ClassDoc)scheduledClassContext.findClass(scheduledClassName); int numberOfProcessedFilesAfter = parser.getNumberOfProcessedFiles(); boolean filesWereProcessed = numberOfProcessedFilesAfter > numberOfProcessedFilesBefore; // Only re-schedule class if additional files have been processed // If there haven't, there's no point in re-scheduling. // Will avoid infinite loops of re-scheduling if (null == loadedClass && retryLater && filesWereProcessed) scheduleClass(scheduledClassContext, scheduledClassName); /* A warning needn't be emitted - this is normal, can happen if the scheduled class is in a package which is not included on the command line. else if (null == loadedClass) printWarning("Can't find scheduled class '" + scheduledClassName + "' in context '" + scheduledClassContext.qualifiedName() + "'"); */ } } } private static interface ResolvedImport { public String match(String name); public boolean mismatch(String name); public ClassDoc tryFetch(String name); } private class ResolvedImportNotFound implements ResolvedImport { private String importSpecifier; private String name; ResolvedImportNotFound(String importSpecifier) { this.importSpecifier = importSpecifier; int ndx = importSpecifier.lastIndexOf('.'); if (ndx >= 0) { this.name = importSpecifier.substring(ndx + 1); } else { this.name = importSpecifier; } } public String toString() { return "ResolvedImportNotFound{" + importSpecifier + "}"; } public String match(String name) { if (name.equals(this.name)) return this.name; // FIXME: note that we don't handle on-demand imports here. return null; } public boolean mismatch(String name) { return true; // FIXME! } public ClassDoc tryFetch(String name) { return null; } } private class ResolvedImportPackageFile implements ResolvedImport { private Set topLevelClassNames; private File packageFile; private String packageName; private Map cache = new HashMap(); ResolvedImportPackageFile(File packageFile, String packageName) { this.packageFile = packageFile; this.packageName = packageName; topLevelClassNames = new HashSet(); File[] files = packageFile.listFiles(); for (int i=0; i<files.length; ++i) { if (!files[i].isDirectory() && files[i].getName().endsWith(".java")) { String topLevelClassName = files[i].getName(); topLevelClassName = topLevelClassName.substring(0, topLevelClassName.length() - 5); topLevelClassNames.add(topLevelClassName); } } } public String match(String name) { ClassDoc loadedClass = classNamed(packageName + "." + name); if (null != loadedClass) { return loadedClass.qualifiedName(); } else { String topLevelName = name; int ndx = topLevelName.indexOf('.'); String innerClassName = null; if (ndx > 0) { innerClassName = topLevelName.substring(ndx + 1); topLevelName = topLevelName.substring(0, ndx); } if (topLevelClassNames.contains(topLevelName)) { //System.err.println(this + ".match returns " + packageName + "." + name); return packageName + "." + name; } // FIXME: inner classes else { return null; } } } public boolean mismatch(String name) { return null == match(name); } public ClassDoc tryFetch(String name) { ClassDoc loadedClass = classNamed(packageName + "." + name); if (null != loadedClass) { return loadedClass; } else if (null != match(name)) { String topLevelName = name; int ndx = topLevelName.indexOf('.'); String innerClassName = null; if (ndx > 0) { innerClassName = topLevelName.substring(ndx + 1); topLevelName = topLevelName.substring(0, ndx); } ClassDoc topLevelClass = (ClassDoc)cache.get(topLevelName); if (null == topLevelClass) { File classFile = new File(packageFile, topLevelName + ".java"); try { // FIXME: inner classes topLevelClass = parser.processSourceFile(classFile, false, sourceEncoding, null); } catch (Exception ignore) { printWarning("Could not parse source file " + classFile); } cache.put(topLevelName, topLevelClass); } if (null == innerClassName) { return topLevelClass; } else { return getInnerClass(topLevelClass, innerClassName); } } else { return null; } } public String toString() { return "ResolvedImportPackageFile{" + packageFile + "," + packageName + "}"; } } private ClassDoc getInnerClass(ClassDoc topLevelClass, String innerClassName) { StringTokenizer st = new StringTokenizer(innerClassName, "."); outer: while (st.hasMoreTokens()) { String innerClassNameComponent = st.nextToken(); ClassDoc[] innerClasses = topLevelClass.innerClasses(); for (int i=0; i<innerClasses.length; ++i) { if (innerClasses[i].name().equals(innerClassNameComponent)) { topLevelClass = innerClasses[i]; continue outer; } } printWarning("Could not find inner class " + innerClassName + " in class " + topLevelClass.qualifiedName()); return null; } return topLevelClass; } private class ResolvedImportClassFile implements ResolvedImport { private File classFile; private String innerClassName; private String name; private ClassDoc classDoc; private boolean alreadyFetched; private String qualifiedName; ResolvedImportClassFile(File classFile, String innerClassName, String name, String qualifiedName) { this.classFile = classFile; this.innerClassName = innerClassName; this.name = name; this.qualifiedName = qualifiedName; } public String toString() { return "ResolvedImportClassFile{" + classFile + "," + innerClassName + "}"; } public String match(String name) { String topLevelName = name; int ndx = topLevelName.indexOf('.'); String _innerClassName = null; if (ndx > 0) { _innerClassName = topLevelName.substring(ndx + 1); topLevelName = topLevelName.substring(0, ndx); } if (this.name.equals(topLevelName)) { if (null == _innerClassName) { return qualifiedName; } else { return qualifiedName + "." + _innerClassName; } } else { return null; } } public boolean mismatch(String name) { return null == match(name); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?