blob: 693047caac61cea1676fc74877dda5a80ed60c1e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.core.search.indexing;
import org.eclipse.dltk.compiler.CharOperation;
import org.eclipse.dltk.compiler.ISourceElementRequestor;
import org.eclipse.dltk.core.DLTKCore;
/**
* This class is used by the JavaParserIndexer. When parsing thescriptfile, the
* requestor recognises thescriptelements (methods, fields, ...) and add them to
* an index.
*/
public class SourceIndexerRequestor implements ISourceElementRequestor,
IIndexConstants {
protected SourceIndexer indexer;
// char[] packageName = CharOperation.NO_CHAR;
protected char[][] enclosingTypeNames = new char[5][];
protected int depth = 0;
protected int methodDepth = 0;
protected char[] pkgName = CharOperation.NO_CHAR;
public SourceIndexerRequestor(SourceIndexer indexer) {
this.indexer = indexer;
}
public SourceIndexerRequestor() {
}
public void setIndexer(SourceIndexer indexer) {
this.indexer = indexer;
}
/**
* @see ISourceElementRequestor#acceptFieldReference(char[], int)
*/
public void acceptFieldReference(char[] fieldName, int sourcePosition) {
this.indexer.addFieldReference(fieldName);
}
/**
* @see ISourceElementRequestor#acceptImport(int, int, char[][], boolean,
* int)
*/
public void acceptImport(int declarationStart, int declarationEnd,
char[][] tokens, boolean onDemand, int modifiers) {
// imports have already been reported while creating the ImportRef node
// (see
// SourceElementParser#comsume*ImportDeclarationName() methods)
}
/**
* @see ISourceElementRequestor#acceptLineSeparatorPositions(int[])
*/
public void acceptLineSeparatorPositions(int[] positions) {
// implements interface method
}
/**
* @see ISourceElementRequestor#acceptMethodReference(char[], int, int, int)
*/
public void acceptMethodReference(char[] methodName, int argCount,
int sourcePosition, int sourceEndPosition) {
this.indexer.addMethodReference(methodName, argCount);
}
// /**
// * @see ISourceElementRequestor#acceptPackage(int, int, char[])
// */
// public void acceptPackage(int declarationStart, int declarationEnd,
// char[] name) {
// this.packageName = name;
// }
/**
* @see ISourceElementRequestor#acceptTypeReference(char[][], int, int)
*/
public void acceptTypeReference(char[][] typeName, int sourceStart,
int sourceEnd) {
int length = typeName.length;
for (int i = 0; i < length - 1; i++)
acceptUnknownReference(typeName[i], 0); // ?
acceptTypeReference(typeName[length - 1], 0);
}
/**
* @see ISourceElementRequestor#acceptTypeReference(char[], int)
*/
public void acceptTypeReference(char[] simpleTypeName, int sourcePosition) {
this.indexer.addTypeReference(simpleTypeName);
}
/**
* @see ISourceElementRequestor#acceptUnknownReference(char[][], int, int)
*/
public void acceptUnknownReference(char[][] name, int sourceStart,
int sourceEnd) {
for (int i = 0; i < name.length; i++) {
acceptUnknownReference(name[i], 0);
}
}
/**
* @see ISourceElementRequestor#acceptUnknownReference(char[], int)
*/
public void acceptUnknownReference(char[] name, int sourcePosition) {
this.indexer.addNameReference(name);
}
/*
* Rebuild the proper qualification for the current source type:
*
* java.lang.Object ---> null java.util.Hashtable$Entry --> [Hashtable]
* x.y.A$B$C --> [A, B]
*/
public char[][] enclosingTypeNames() {
if (depth == 0)
return null;
char[][] qualification = new char[this.depth][];
System.arraycopy(this.enclosingTypeNames, 0, qualification, 0,
this.depth);
return qualification;
}
public void enterType(TypeInfo typeInfo) {
// eliminate possible qualifications, given they need to be fully
// resolved again
if (typeInfo.superclasses != null) {
// typeInfo.superclasses = typeInfo.superclasses;
for (int i = 0, length = typeInfo.superclasses.length; i < length; i++) {
typeInfo.superclasses[i] = new String(
getSimpleName(typeInfo.superclasses[i].toCharArray()));
}
// add implicit constructor reference to default constructor
if (DLTKCore.DEBUG) {
System.err.println("TODO: Add constructore references...");
}
// this.indexer.addConstructorReference(typeInfo.superclasss, 0);
}
char[][] typeNames;
if (this.methodDepth > 0) {
typeNames = ONE_ZERO_CHAR;
} else {
typeNames = this.enclosingTypeNames();
}
this.indexer.addTypeDeclaration(typeInfo.modifiers, this.pkgName,
typeInfo.name, typeNames, typeInfo.superclasses);
this.pushTypeName(typeInfo.name.toCharArray());
}
public void enterConstructor(MethodInfo methodInfo) {
this.indexer.addConstructorDeclaration(methodInfo.name,
methodInfo.parameterNames, methodInfo.exceptionTypes);
this.methodDepth++;
}
/**
* @see ISourceElementRequestor#enterField(FieldInfo)
*/
public void enterField(FieldInfo fieldInfo) {
this.indexer.addFieldDeclaration(fieldInfo.name.toCharArray());
this.methodDepth++;
}
/**
* @see ISourceElementRequestor#enterMethod(MethodInfo)
*/
public void enterMethod(MethodInfo methodInfo) {
this.indexer.addMethodDeclaration(methodInfo.name,
methodInfo.parameterNames, methodInfo.exceptionTypes);
this.methodDepth++;
}
/**
* @see ISourceElementRequestor#exitType(int)
*/
public void exitType(int declarationEnd) {
popTypeName();
}
/*
* Returns the unqualified name without parameters from the given type name.
*/
private char[] getSimpleName(char[] typeName) {
int lastDot = -1, lastGenericStart = -1;
int depthCount = 0;
int length = typeName.length;
lastDotLookup: for (int i = length - 1; i >= 0; i--) {
switch (typeName[i]) {
case '.':
if (depthCount == 0) {
lastDot = i;
break lastDotLookup;
}
break;
case '<':
depthCount--;
if (depthCount == 0)
lastGenericStart = i;
break;
case '>':
depthCount++;
break;
}
}
if (lastGenericStart < 0) {
if (lastDot < 0) {
return typeName;
}
return CharOperation.subarray(typeName, lastDot + 1, length);
}
return CharOperation.subarray(typeName, lastDot + 1, lastGenericStart);
}
public void popTypeName() {
if (depth > 0) {
// System.out.println("POPNAME:" + new String( enclosingTypeNames[depth-1]));
enclosingTypeNames[--depth] = null;
}
// else if (JobManager.VERBOSE) {
// // dump a trace so it can be tracked down
// try {
// enclosingTypeNames[-1] = null;
// } catch (ArrayIndexOutOfBoundsException e) {
// e.printStackTrace();
// }
// }
}
public void pushTypeName(char[] typeName) {
if (depth == enclosingTypeNames.length)
System.arraycopy(enclosingTypeNames, 0,
enclosingTypeNames = new char[depth * 2][], 0, depth);
enclosingTypeNames[depth++] = typeName;
}
public void enterMethodRemoveSame(MethodInfo info) {
if (DLTKCore.DEBUG) {
System.out.println("TODO: Add replace method code.");
}
}
public void enterModule() {
}
public void exitField(int declarationEnd) {
this.methodDepth--;
}
public void exitMethod(int declarationEnd) {
this.methodDepth--;
}
public void exitModule(int declarationEnd) {
}
public void setPackageName(String pkgName) {
this.pkgName = pkgName.toCharArray();
}
public void acceptPackage(int declarationStart, int declarationEnd,
char[] name) {
}
public boolean enterFieldCheckDuplicates(FieldInfo info) {
this.indexer.addFieldDeclaration(info.name.toCharArray());
this.methodDepth++;
return true;
}
public boolean enterMethodWithParentType(MethodInfo info,
String parentName, String delimiter) {
this.enterMethod(info);
// this.methodDepth++;
return true;
}
public boolean enterFieldWithParentType(FieldInfo info, String parentName,
String delimiter) {
this.indexer.addFieldDeclaration(info.name.toCharArray());
this.methodDepth++;
return true;
}
public boolean enterTypeAppend(TypeInfo info, String fullName,
String delimiter) {
enterType(info);
return true;
}
public void enterModuleRoot() {
// TODO Auto-generated method stub
}
public boolean enterTypeAppend(String fullName, String delimiter) {
return false;
}
public void exitModuleRoot() {
}
}