📄 tablemaker.java
字号:
* @throws <code>SymbolTableException</code>
* @see #addImports()
* @see #setSuperclass()
* @see #addInterfaces()
*/
public void finish() throws SymbolTableException {
if ( _node != null ) {
addImports();
setSuperclass();
addInterfaces();
}
}
/**
* Adds all packages and classes that are imported by this class
* to the class for later reference
*/
private void addImports() throws ClassImportException {
IPackage java = new ExternalPackage("java", null);
IPackage lang = new ExternalPackage("lang", java);
java.addDefinition(lang);
_def.importPackage(lang);
Vector unprocessedImports = _def.getUnprocessedImports();
for ( int i = 0; i < unprocessedImports.size(); i++ ) {
SymTabAST importNode = (SymTabAST)unprocessedImports.get(i);
SymTabAST imported = (SymTabAST)importNode.getFirstChild();
SymTabAST lastPart = (SymTabAST)imported.getFirstChild().getNextSibling();
DotIterator it = new DotIterator(imported);
SymTabAST current = null;
String className = null;
IClass importedClass = null;
// attempt at each token to find the class
// first in source
// then on classpath
//
// if there are more tokens left
// continue until you hit the last token
// if it's a star
// import all inner classes
// else
// import the explicitly named inner class
// else import the class
//
// if no classes were found, import the package
while(it.hasNext()) {
current = it.nextNode();
if (className == null) {
className = current.getText();
}
else {
if (!current.getText().equals("*")) {
className += "." + current.getText();
}
else {
break;
}
}
importedClass = findOrLoadClass(className, importedClass);
if (importedClass != null) {
break;
}
}
if (it.hasNext()) {
boolean isImported = false;
while(it.hasNext()) {
current = it.nextNode();
if (current.getText().equals("*")) {
importInnerClasses(importedClass);
isImported = true;
}
else {
className += "$" + current.getText();
importedClass = findOrLoadClass(className, importedClass);
}
}
if (!isImported) {
_def.importClass(importedClass);
}
}
else {
if (importedClass != null) {
_def.importClass(importedClass);
}
else {
if (current != null && current.getText().equals("*")) {
IPackage pkg = symbolTable.getPackage(className);
if (pkg == null) {
pkg = getPackage(className);
}
_def.importPackage(pkg);
}
else {
//TODO: can we safely ignore this?
//throw new ClassImportException(className);
;
}
}
}
// now set definitions where appropriate
imported.ignoreChildren();
if ((lastPart.getType() == TokenTypes.IDENT)
//TODO: guard added for class not loaded
//This is OK for single file processing, but not
//multiple files.
&& (importedClass != null)
)
{
lastPart.setDefinition(importedClass, null, true);
lastPart.setMeaningfulness(true);
}
}
}
/**
* creates <code>ExternalPackage</code>
* @param packageName name of the package
* @return <code>ExternalPackage</code>
* @see net.sourceforge.transmogrify.symtab.ExternalPackage
*/
private ExternalPackage getPackage(String packageName) {
return new ExternalPackage(packageName, null);
}
/**
* stores the inner classes in the approriate ClassDef
* @param outerClass
* @return <code>void</code>
*/
private void importInnerClasses(IClass outerClass) {
IClass[] innerClasses = outerClass.getInnerClasses();
for (int i = 0; i < innerClasses.length; i++) {
_def.importClass(innerClasses[i]);
}
}
/**
* creates <code>ExternalClass</code> based on a java class
* @param className class to be loaded
* @return <code>IClass</code>
* @see net.sourceforge.transmogrify.symtab.ExternalClass
*/
private IClass loadClass(String className) {
IClass result = null;
try {
Class javaClass
= ClassManager.getClassLoader().loadClass(className);
result = new ExternalClass(javaClass);
}
catch (ClassNotFoundException ignoreMe) {}
return result;
}
/**
* find a class from <code>BaseCode</code> or its parent
* @param className name of the class to be load or found
* @param parentClass its parent class
* @return <code>IClass</code>
* @see net.sourceforge.transmogrify.symtab.SymbolTable
* @see net.sourceforge.transmogrify.symtab.IClass
* @see #loadClass(String)
*/
private IClass findOrLoadClass(String className, IClass parentClass) {
IClass result = null;
if (parentClass == null) {
result = symbolTable.getBaseScope().getClassDefinition(className);
}
else {
int index = className.lastIndexOf("$");
if (index < 0) {
index = className.lastIndexOf(".");
}
result = parentClass.getClassDefinition(className.substring(index + 1));
}
if (result == null) {
result = loadClass(className);
}
return result;
}
/**
*
* If the class has a super class a reference to this super class
* is added to this class.
* @return <code>void</code>
* @see net.sourceforge.transmogrify.symtab.ClassDef
*/
private void setSuperclass() {
if (_def.getTreeNode().getType() == TokenTypes.CLASS_DEF) {
SymTabAST extendsNode = getExtendsNode(_def);
if ( extendsNode != null ) {
String superclassName = ASTUtil.constructDottedName(extendsNode);
IClass superclass = _def.getClassDefinition(superclassName);
if ( superclass != null ) {
_def.setSuperclass( superclass );
superclass.addSubclass( _def );
}
}
else {
_def.setSuperclass(new ExternalClass(Object.class));
}
}
else {
_def.setSuperclass(new ExternalClass(Object.class));
}
}
/**
*
* If the class implements an interface a reference to this interface
* is added to this class.
* @return <code>void</code>
* @see net.sourceforge.transmogrify.symtab.ClassDef
*/
private void addInterfaces() {
SymTabAST implementsClause = null;
if (_def.getTreeNode().getType() == TokenTypes.CLASS_DEF) {
implementsClause
= _node.findFirstToken(TokenTypes.IMPLEMENTS_CLAUSE);
}
else {
implementsClause
= _node.findFirstToken(TokenTypes.EXTENDS_CLAUSE);
}
if ( implementsClause != null ) {
SymTabAST interfaceNode = (SymTabAST)implementsClause.getFirstChild();
while ( interfaceNode != null ) {
IClass implemented =
_def.getClassDefinition(interfaceNode.getText());
if ( implemented != null ) {
_def.addInterface( implemented );
implemented.addImplementor( _def );
}
interfaceNode = (SymTabAST)(interfaceNode.getNextSibling());
}
}
}
}
/**
*
* Completes a Variable by setting all required references
*
*/
class VariableFinisher extends DefinitionFinisher {
VariableDef _def = null;
/**
*
* Constructor. Creates a VariableFinishes from the <code>Definition</code>
* @param def VariableDef to be finished
* @see net.sourceforge.transmogrify.symtab.VariableDef
*/
public VariableFinisher( Definition def ) {
super( def );
_def = (VariableDef)def;
}
/**
*
* Finishes the variable by setting the Type
* @return <code>void</code>
* @see #getType(Definition, SymTabAST)
* @see net.sourceforge.transmogrify.symtab.VariableDef
*/
public void finish() {
SymTabAST typeNode = _node.findFirstToken(TokenTypes.TYPE);
SymTabAST typeTextNode = (SymTabAST)(typeNode.getFirstChild());
if ( typeTextNode.getType() == TokenTypes.ARRAY_DECLARATOR ) {
typeTextNode = (SymTabAST)(typeTextNode.getFirstChild());
}
typeTextNode.setLine(ASTUtil.getLine( _def.getTreeNode() ));
IClass varType = getType(_def, typeNode);
_def.setType( varType );
}
}
/**
*
* Completes a Variable by setting all required references
*
*/
class MethodFinisher extends DefinitionFinisher {
MethodDef _def = null;
/**
*
* Creates a MethodFinisher from a <code> Definition <code>
* @param def MethodDef to be finished
* @see net.sourceforge.transmogrify.symtab.MethodDef
*/
public MethodFinisher( Definition def ) {
super( def );
_def = (MethodDef)def;
}
/**
*
* Completes a method by setting all references to return types,
* signatures and exceptions.
* @return <code>void</code>
* @see #setReturnType()
* @see #setSignature()
* @see #setExceptionsThrown()
*/
public void finish() {
setReturnType();
setSignature();
setExceptionsThrown();
}
/**
*
* setReturnType adds a reference to the methods return type
* to the method definition
* @return <code>void</code>
* @see net.sourceforge.transmogrify.symtab.MethodDef
* @see #getType(Definition, SymTabAST)
* @see #getTypeNode()
*/
private void setReturnType() {
IClass type = null;
if ( isConstructor() ) {
type = _def.getEnclosingClass();
}
else {
type = getType(_def, getTypeNode());
}
_def.setType(type);
}
/**
*
* setSignature adds a reference to the methods paramaters
* to the method definition
* @return <code>void</code>
* @see #makeVariableDef(SymTabAST, Definition)
* @see VariableFinisher
* @see net.sourceforge.transmogrify.symtab.MethodDef
*/
private void setSignature() {
SymTabAST parametersNode
= _node.findFirstToken(TokenTypes.PARAMETERS);
SymTabAST parameterNode = (SymTabAST)(parametersNode.getFirstChild());
while ( parameterNode != null ) {
if (parameterNode.getType() == TokenTypes.PARAMETER_DEF) {
VariableDef parameter = makeVariableDef( parameterNode, _def );
new VariableFinisher( parameter ).finish();
_def.addParameter( parameter );
}
parameterNode = (SymTabAST)(parameterNode.getNextSibling());
}
}
/**
*
* setExceptionsThrown adds a reference to the methods Exceptions
* to the method definition
* @return <code>void</code>
* @see net.sourceforge.transmogrify.symtab.SymbolTable
* @see net.sourceforge.transmogrify.symtab.PackageDef
* @see net.sourceforge.transmogrify.symtab.MethodDef
*/
private void setExceptionsThrown() {
IClass exception = null;
SymTabAST throwsNode
= _node.findFirstToken(TokenTypes.LITERAL_THROWS);
if ( throwsNode != null ) {
SymTabAST exceptionNode = (SymTabAST)(throwsNode.getFirstChild());
while (exceptionNode != null ) {
if (exceptionNode.getType() == TokenTypes.DOT) {
PackageDef pkg = symbolTable.getPackage(ASTUtil.constructPackage(exceptionNode));
if ( pkg != null ) {
exception = pkg.getClassDefinition(ASTUtil.constructClass(exceptionNode));
}
}
else {
exception = _def.getClassDefinition(exceptionNode.getText());
}
_def.addException(exception);
exceptionNode = (SymTabAST)(exceptionNode.getNextSibling());
}
}
}
/**
*
* isConstructor sets the flag in the method definition to indicate
* whether it is a constructor or not
* @return <code>boolean</code> <code>true</code> if a node has no return type
* <code>false</code> if a node has a return type
* @see #getTypeNode()
*/
private boolean isConstructor() {
boolean result = false;
if ( getTypeNode() == null ) {
result = true;
}
return result;
}
/**
*
* getTypeNode returnss the <code> SymTabAST</code> node that is the
* return type of this method
*
* @return <code>SymTabAST</code>
*/
private SymTabAST getTypeNode() {
return _node.findFirstToken(TokenTypes.TYPE);
}
}
class CatchFinisher extends DefinitionFinisher {
BlockDef _def = null;
/**
* constructor that takes a <code>BlockDef</code>
* @param def <code>BlockDef</code> for the catch block
*/
public CatchFinisher(BlockDef def) {
super(def);
_def = def;
}
/**
* finishes definition creation
* @return <code>void</code>
* @see #createExceptionVariable()
*/
public void finish() {
createExceptionVariable();
}
/**
* creates <code>VariableDef<code> and finishes creation definition for
* arguments in the catch clause
* @return <code>void</code>
* @see net.sourceforge.transmogrify.symtab.VariableDef
* @see #makeVariableDef(SymTabAST, Definition)
* @see VariableFinisher
*/
private void createExceptionVariable() {
SymTabAST exceptionNode
= _def.getTreeNode().findFirstToken(TokenTypes.PARAMETER_DEF);
VariableDef exception = makeVariableDef(exceptionNode, _def);
new VariableFinisher(exception).finish();
_def.addDefinition(exception);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -