| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.core.search.indexing; |
| |
| import java.util.Stack; |
| |
| import org.eclipse.dltk.compiler.IBinaryElementRequestor; |
| import org.eclipse.dltk.compiler.ISourceElementRequestor; |
| import org.eclipse.dltk.compiler.ISourceElementRequestorExtension; |
| import org.eclipse.dltk.compiler.SourceElementRequestorMode; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.ISearchFactory; |
| import org.eclipse.dltk.core.ISearchPatternProcessor; |
| |
| /** |
| * 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, IBinaryElementRequestor, |
| IIndexConstants, ISourceElementRequestorExtension { |
| protected AbstractIndexer indexer; |
| // char[] packageName = CharOperation.NO_CHAR; |
| protected String[] enclosingTypeNames = new String[5]; |
| protected int depth = 0; |
| protected int methodDepth = 0; |
| // protected String pkgName = Util.EMPTY_STRING; |
| |
| protected ISearchFactory searchFactory; |
| protected ISearchPatternProcessor searchPatternProcessor; |
| private Stack<String[]> namespaces = new Stack<>(); |
| |
| public SourceIndexerRequestor(AbstractIndexer indexer) { |
| this.indexer = indexer; |
| } |
| |
| public SourceIndexerRequestor() { |
| } |
| |
| public void setIndexer(AbstractIndexer indexer) { |
| this.indexer = indexer; |
| } |
| |
| public void setSearchFactory(ISearchFactory searchFactory) { |
| this.searchFactory = searchFactory; |
| if (searchFactory != null) { |
| searchPatternProcessor = searchFactory |
| .createSearchPatternProcessor(); |
| } else { |
| searchPatternProcessor = null; |
| } |
| } |
| |
| /** |
| * @see ISourceElementRequestor#acceptFieldReference(char[], int) |
| * @since 2.0 |
| */ |
| @Override |
| public void acceptFieldReference(String fieldName, int sourcePosition) { |
| this.indexer.addFieldReference(fieldName); |
| } |
| |
| /** |
| * @see ISourceElementRequestor#acceptLineSeparatorPositions(int[]) |
| */ |
| public void acceptLineSeparatorPositions(int[] positions) { |
| // implements interface method |
| } |
| |
| /** |
| * @see ISourceElementRequestor#acceptMethodReference(char[], int, int, int) |
| * @since 2.0 |
| */ |
| @Override |
| public void acceptMethodReference(String 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) |
| */ |
| @Override |
| public void acceptTypeReference(String simpleTypeName, int sourcePosition) { |
| this.indexer.addTypeReference(simpleTypeName); |
| } |
| |
| /** |
| * @see ISourceElementRequestor#acceptUnknownReference(char[], int) |
| */ |
| public void acceptUnknownReference(String 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] |
| */ |
| protected String[] enclosingTypeNames() { |
| if (depth == 0) |
| return null; |
| String[] qualification = new String[this.depth]; |
| System.arraycopy(this.enclosingTypeNames, 0, qualification, 0, |
| this.depth); |
| |
| return qualification; |
| } |
| |
| protected String[] namespace() { |
| return !namespaces.isEmpty() ? namespaces.peek() : null; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| 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] = getSimpleName( |
| typeInfo.superclasses[i]); |
| } |
| // add implicit constructor reference to default constructor |
| if (DLTKCore.DEBUG) { |
| System.err.println("TODO: Add constructore references..."); //$NON-NLS-1$ |
| } |
| // this.indexer.addConstructorReference(typeInfo.superclasss, 0); |
| } |
| String[] typeNames; |
| if (this.methodDepth > 0) { |
| typeNames = ONE_ZERO_CHAR_STRINGS; |
| } else { |
| typeNames = this.enclosingTypeNames(); |
| } |
| this.indexer.addTypeDeclaration(typeInfo.modifiers, namespace(), |
| typeInfo.name, typeNames, typeInfo.superclasses); |
| this.pushTypeName(typeInfo.name); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public void enterConstructor(MethodInfo methodInfo) { |
| this.indexer.addConstructorDeclaration(methodInfo.name, |
| methodInfo.parameterNames, methodInfo.exceptionTypes); |
| this.methodDepth++; |
| } |
| |
| /** |
| * @see ISourceElementRequestor#enterField(FieldInfo) |
| * @since 2.0 |
| */ |
| @Override |
| public void enterField(FieldInfo fieldInfo) { |
| this.indexer.addFieldDeclaration(fieldInfo.name, fieldInfo.type); |
| this.methodDepth++; |
| } |
| |
| /** |
| * @see ISourceElementRequestor#enterMethod(MethodInfo) |
| * @since 2.0 |
| */ |
| @Override |
| public void enterMethod(MethodInfo methodInfo) { |
| this.indexer.addMethodDeclaration(methodInfo.modifiers, namespace(), |
| this.enclosingTypeNames(), methodInfo.name, |
| methodInfo.parameterNames, methodInfo.exceptionTypes); |
| if (methodInfo.returnType != null) { |
| this.indexer.addTypeReference(methodInfo.returnType); |
| } |
| if (methodInfo.parameterTypes != null) { |
| for (String type : methodInfo.parameterTypes) { |
| if (type != null) { |
| this.indexer.addTypeReference(type); |
| } |
| } |
| } |
| this.methodDepth++; |
| } |
| |
| /** |
| * @see ISourceElementRequestor#exitType(int) |
| */ |
| @Override |
| public void exitType(int declarationEnd) { |
| popTypeName(); |
| } |
| |
| /* |
| * Returns the unqualified name without parameters from the given type name. |
| */ |
| private String getSimpleName(String typeName) { |
| if (searchPatternProcessor != null) { |
| return searchPatternProcessor.extractTypeChars(typeName); |
| } else { |
| return typeName; |
| } |
| } |
| |
| 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(String typeName) { |
| if (depth == enclosingTypeNames.length) |
| System.arraycopy(enclosingTypeNames, 0, |
| enclosingTypeNames = new String[depth * 2], 0, depth); |
| enclosingTypeNames[depth++] = typeName; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public void enterMethodRemoveSame(MethodInfo info) { |
| if (DLTKCore.DEBUG) { |
| System.out.println("TODO: Add replace method code."); //$NON-NLS-1$ |
| } |
| } |
| |
| @Override |
| public void enterModule() { |
| } |
| |
| @Override |
| public void exitField(int declarationEnd) { |
| this.methodDepth--; |
| } |
| |
| @Override |
| public void exitMethod(int declarationEnd) { |
| this.methodDepth--; |
| } |
| |
| @Override |
| public void exitModule(int declarationEnd) { |
| indexer.ensureDocumentAdded(); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public void acceptPackage(int declarationStart, int declarationEnd, |
| String name) { |
| // this.pkgName = name; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public boolean enterFieldCheckDuplicates(FieldInfo info) { |
| this.indexer.addFieldDeclaration(info.name, info.type); |
| this.methodDepth++; |
| return true; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public boolean enterTypeAppend(TypeInfo info, String fullName, |
| String delimiter) { |
| enterType(info); |
| return true; |
| } |
| |
| @Override |
| public void enterModuleRoot() { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| @Override |
| public boolean enterTypeAppend(String fullName, String delimiter) { |
| return false; |
| } |
| |
| @Override |
| public void exitModuleRoot() { |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public void acceptImport(ImportInfo importInfo) { |
| } |
| |
| @Override |
| public void enterNamespace(String[] namespace) { |
| namespaces.push(namespace); |
| } |
| |
| @Override |
| public void exitNamespace() { |
| namespaces.pop(); |
| } |
| |
| @Override |
| public SourceElementRequestorMode getMode() { |
| return SourceElementRequestorMode.INDEX; |
| } |
| |
| } |