forked from dnault/therapi-runtime-javadoc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
399 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
hs_err_pid* | ||
|
||
# IntelliJ IDEA project files | ||
out | ||
*.ipr | ||
*.iml | ||
.idea | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
therapi-runtime-javadoc/src/main/java/com/github/therapi/runtimejavadoc/ClassResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package com.github.therapi.runtimejavadoc; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
|
||
/** | ||
* Searches a list of imports for a specified class. | ||
*/ | ||
public abstract class ClassResolver implements Comparable<ClassResolver> { | ||
|
||
public static ClassResolver createClassResolverFor( String sourcePackage, Import...imports ) { | ||
return createClassResolverFor( sourcePackage, Arrays.asList(imports) ); | ||
} | ||
|
||
public static ClassResolver createClassResolverFor( String sourcePackage, List<Import> imports ) { | ||
return new CompositeClassResolver( createClassResolversFor(sourcePackage,imports) ); | ||
} | ||
|
||
|
||
private final int comparisonOrder; | ||
|
||
protected ClassResolver( int comparisonOrder ) { | ||
this.comparisonOrder = comparisonOrder; | ||
} | ||
|
||
/** | ||
* Do ones best to convert classRef into an instance of java.lang.Class. | ||
* | ||
* @return null if no match was found. | ||
*/ | ||
public abstract Class resolveClass( String classRef ); | ||
|
||
|
||
public int compareTo( ClassResolver o ) { | ||
return Integer.compare( this.comparisonOrder, o.comparisonOrder ); | ||
} | ||
|
||
|
||
private static Class fetchClass( String fqn ) { | ||
try { | ||
return Class.forName( fqn ); | ||
} catch ( ClassNotFoundException e ) { | ||
return null; | ||
} | ||
} | ||
|
||
|
||
private static List<ClassResolver> createClassResolversFor( String sourcePackage, List<Import> imports ) { | ||
List<ClassResolver> classResolvers = new ArrayList<>(); | ||
|
||
classResolvers.add( new FQNResolver() ); | ||
classResolvers.add( new FullPackageResolver(sourcePackage) ); | ||
classResolvers.add( new FullPackageResolver("java.lang") ); | ||
|
||
for ( Import declaredImport : imports ) { | ||
ClassResolver newResolver = createClassResolverFor( declaredImport ); | ||
|
||
if ( newResolver != null ) { | ||
classResolvers.add( newResolver ); | ||
} | ||
} | ||
|
||
// ensure that the fully qualified comparators appear ahead of the 'all in package' imports | ||
Collections.sort(classResolvers); | ||
|
||
return classResolvers; | ||
} | ||
|
||
private static ClassResolver createClassResolverFor( Import declaredImport ) { | ||
if ( declaredImport.getStaticMember() == null ) { | ||
if ( "*".equals(declaredImport.getClassName()) ) { | ||
return new FullPackageResolver(declaredImport.getPkg()); | ||
} else { | ||
Class importedClass = fetchClass( declaredImport.getFullyQualifiedClass() ); | ||
|
||
if ( importedClass != null ) { | ||
return new ExactClassResolver(declaredImport.getClassName(), importedClass); | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
|
||
/** | ||
* Given a list of ClassResolvers, return the result of the first one that returns a non-null | ||
* result. | ||
*/ | ||
private static class CompositeClassResolver extends ClassResolver { | ||
private List<ClassResolver> classResolvers; | ||
|
||
private CompositeClassResolver( List<ClassResolver> classResolvers ) { | ||
super(0); | ||
|
||
this.classResolvers = classResolvers; | ||
} | ||
|
||
public Class resolveClass( String classRef ) { | ||
for ( ClassResolver resolver : classResolvers ) { | ||
Class resolvedClass = resolver.resolveClass( classRef ); | ||
|
||
if ( resolvedClass != null ) { | ||
return resolvedClass; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* Resolves absolute class refs (eg x.y.Z). | ||
*/ | ||
private static class FQNResolver extends ClassResolver { | ||
public FQNResolver() { | ||
super(1); | ||
} | ||
|
||
public Class resolveClass( String ref ) { | ||
return fetchClass(ref); | ||
} | ||
} | ||
|
||
/** | ||
* Given 'import x.y.Z', match relative class refs that equal 'Z' and return the class | ||
* for x.y.Z. | ||
*/ | ||
private static class ExactClassResolver extends ClassResolver { | ||
private String targetRelativeRef; | ||
private Class explicitClass; | ||
|
||
private ExactClassResolver( String targetRelativeRef, Class matchingClass ) { | ||
super(2); | ||
|
||
this.targetRelativeRef = targetRelativeRef; | ||
this.explicitClass = matchingClass; | ||
} | ||
|
||
public Class resolveClass( String ref ) { | ||
if ( !Objects.equals(targetRelativeRef, ref) ) { | ||
return null; | ||
} | ||
|
||
return explicitClass; | ||
} | ||
} | ||
/** | ||
* Given 'import x.y.*', attempt to load any class ref as though it is within package x.y. | ||
*/ | ||
private static class FullPackageResolver extends ClassResolver { | ||
|
||
private String basePackage; | ||
|
||
private FullPackageResolver( String basePackage ) { | ||
super(3); | ||
|
||
this.basePackage = basePackage; | ||
} | ||
public Class resolveClass( String ref ) { | ||
return fetchClass(basePackage + "." + ref); | ||
} | ||
|
||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
therapi-runtime-javadoc/src/main/java/com/github/therapi/runtimejavadoc/Import.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package com.github.therapi.runtimejavadoc; | ||
|
||
import java.util.Objects; | ||
|
||
|
||
public final class Import { | ||
/** | ||
* The imported package, for example com.bar.foo. A null value means that the root package. | ||
*/ | ||
private String pkg; | ||
|
||
/** | ||
* The name of the imported class, for example Bar. If all classes in the package are to be | ||
* imported, then className will be set to '*'. className will never be set to null. | ||
*/ | ||
private String className; | ||
|
||
/** | ||
* The static field or method from the class. Will be set to null when there no static | ||
* members have been imported, and '*' when all static members of the class are to be imported. | ||
*/ | ||
private String staticMember; | ||
|
||
|
||
public Import( String pkg, String className ) { | ||
this(pkg,className,null); | ||
} | ||
|
||
public Import( String pkg, String className, String staticMember ) { | ||
this.pkg = pkg; | ||
this.className = className; | ||
this.staticMember = staticMember; | ||
} | ||
|
||
public String getPkg() { | ||
return pkg; | ||
} | ||
|
||
public String getClassName() { | ||
return className; | ||
} | ||
|
||
public String getStaticMember() { | ||
return staticMember; | ||
} | ||
|
||
public boolean importsAllClassesWithinPackage() { | ||
return "*".equals( className ); | ||
} | ||
|
||
public boolean importsAllStaticMembersWithingClass() { | ||
return "*".equals( staticMember ); | ||
} | ||
|
||
public String getFullyQualifiedClass() { | ||
if ( importsAllClassesWithinPackage() ) { | ||
return null; | ||
} | ||
|
||
return pkg == null ? className : pkg + '.' + className; | ||
} | ||
|
||
|
||
public boolean equals( Object o ) { | ||
if ( this == o ) | ||
return true; | ||
if ( o == null || getClass() != o.getClass() ) | ||
return false; | ||
Import anImport = (Import) o; | ||
return Objects.equals( pkg, anImport.pkg ) && | ||
Objects.equals( className, anImport.className ) && | ||
Objects.equals( staticMember, anImport.staticMember ); | ||
} | ||
|
||
public int hashCode() { | ||
return Objects.hash( pkg, className, staticMember ); | ||
} | ||
//TODO test other methods | ||
//TODO wire up to AST parser | ||
//TODO write to json output | ||
public String toString() { | ||
StringBuilder buf = new StringBuilder(); | ||
|
||
if ( pkg == null ) { | ||
buf.append( className ); | ||
} else { | ||
buf.append( pkg ); | ||
buf.append( '.' ); | ||
buf.append( className ); | ||
} | ||
|
||
if ( staticMember != null ) { | ||
buf.append( '.' ); | ||
buf.append( staticMember ); | ||
} | ||
|
||
return buf.toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.