All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.org.eclipse.jdt.internal.core.search.IndexSelector Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * 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 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Nikolay Botev - Bug 348507
 *******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.core.search;

import static org.aspectj.org.eclipse.jdt.internal.core.JavaModelManager.trace;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.aspectj.org.eclipse.jdt.core.IClasspathEntry;
import org.aspectj.org.eclipse.jdt.core.IJavaElement;
import org.aspectj.org.eclipse.jdt.core.IJavaModel;
import org.aspectj.org.eclipse.jdt.core.IJavaProject;
import org.aspectj.org.eclipse.jdt.core.IMethod;
import org.aspectj.org.eclipse.jdt.core.IPackageFragmentRoot;
import org.aspectj.org.eclipse.jdt.core.IType;
import org.aspectj.org.eclipse.jdt.core.ITypeHierarchy;
import org.aspectj.org.eclipse.jdt.core.ITypeRoot;
import org.aspectj.org.eclipse.jdt.core.JavaModelException;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.core.search.IJavaSearchScope;
import org.aspectj.org.eclipse.jdt.core.search.SearchPattern;
import org.aspectj.org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.aspectj.org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.aspectj.org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.aspectj.org.eclipse.jdt.internal.core.JavaModel;
import org.aspectj.org.eclipse.jdt.internal.core.JavaModelManager;
import org.aspectj.org.eclipse.jdt.internal.core.JavaProject;
import org.aspectj.org.eclipse.jdt.internal.core.builder.ReferenceCollection;
import org.aspectj.org.eclipse.jdt.internal.core.builder.State;
import org.aspectj.org.eclipse.jdt.internal.core.index.IndexLocation;
import org.aspectj.org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.aspectj.org.eclipse.jdt.internal.core.search.indexing.QualifierQuery;
import org.aspectj.org.eclipse.jdt.internal.core.search.matching.MatchLocator;
import org.aspectj.org.eclipse.jdt.internal.core.search.matching.MethodPattern;
import org.aspectj.org.eclipse.jdt.internal.core.search.matching.ModulePattern;
import org.aspectj.org.eclipse.jdt.internal.core.search.processing.JobManager;

/**
 * Selects the indexes that correspond to projects in a given search scope
 * and that are dependent on a given focus element.
 */
public class IndexSelector {

	//TODO: Bug 386113: "Search references" and "Type hierarchy" show inconsistent results with "External Plug-in Libraries" project
	public static final int PROJECT_CAN_SEE_FOCUS= 0;
	public static final int PROJECT_SOURCE_CAN_NOT_SEE_FOCUS= 1;
	public static final int PROJECT_CAN_NOT_SEE_FOCUS= 2;

	IJavaSearchScope searchScope;
	SearchPattern pattern;
	IndexLocation[] indexLocations; // cache of the keys for looking index up

public IndexSelector(
		IJavaSearchScope searchScope,
		SearchPattern pattern) {

	this.searchScope = searchScope;
	this.pattern = pattern;
}
/**
 * Returns whether elements of the given project or jar can see the given focus (an IJavaProject or
 * a JarPackageFragmentRot) either because the focus is part of the project or the jar, or because it is
 * accessible throught the project's classpath
 */
public static int canSeeFocus(SearchPattern pattern, IPath projectOrJarPath) {
	try {
		IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
		IJavaProject project = getJavaProject(projectOrJarPath, model);
		IJavaElement[] focuses = getFocusedElementsAndTypes(pattern, project, null);
		if (focuses.length == 0) return PROJECT_CAN_NOT_SEE_FOCUS;
		if (project != null) {
			return canSeeFocus(focuses, (JavaProject) project, null);
		}

		// projectOrJarPath is a jar
		// it can see the focus only if it is on the classpath of a project that can see the focus
		int result = PROJECT_CAN_NOT_SEE_FOCUS;
		IJavaProject[] allProjects = model.getJavaProjects();
		for (int i = 0, length = allProjects.length; i < length; i++) {
			JavaProject otherProject = (JavaProject) allProjects[i];
			IClasspathEntry entry = otherProject.getClasspathEntryFor(projectOrJarPath);
			if (entry != null && entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
				int canSeeFocus = canSeeFocus(focuses, otherProject, null);
				if (canSeeFocus == PROJECT_CAN_SEE_FOCUS)
					return PROJECT_CAN_SEE_FOCUS;
				if (canSeeFocus == PROJECT_SOURCE_CAN_NOT_SEE_FOCUS)
					result = PROJECT_SOURCE_CAN_NOT_SEE_FOCUS;
			}
		}
		return result;
	} catch (JavaModelException e) {
		return PROJECT_CAN_NOT_SEE_FOCUS;
	}
}
private static int canSeeFocus(IJavaElement[] focuses, JavaProject javaProject, char[][][] focusQualifiedNames) {
	int result = PROJECT_CAN_NOT_SEE_FOCUS;
	int length = focuses.length;
	for (int i=0; i values = projectState.getReferences().values();
						for (ReferenceCollection references : values) {
							if (references == null) continue;
							if (references.includes(focusQualifiedNames, null, null)) {
								return PROJECT_CAN_SEE_FOCUS;
							}
						}
						return PROJECT_SOURCE_CAN_NOT_SEE_FOCUS;
					}
				}
				return PROJECT_CAN_SEE_FOCUS;
			}
		}
		return PROJECT_CAN_NOT_SEE_FOCUS;
	} catch (JavaModelException e) {
		return PROJECT_CAN_NOT_SEE_FOCUS;
	}
}

/*
 * Create the list of focused jars or projects.
 */
private static IJavaElement[] getFocusedElementsAndTypes(SearchPattern pattern, IJavaElement focusElement, ObjectVector superTypes) throws JavaModelException {
	if (pattern instanceof MethodPattern) {
		// For method pattern, it needs to walk along the focus type super hierarchy
		// and add jars/projects of all the encountered types.
		IType type = (IType) pattern.focus.getAncestor(IJavaElement.TYPE);
		MethodPattern methodPattern = (MethodPattern) pattern;
		String selector = new String(methodPattern.selector);
		int parameterCount = methodPattern.parameterCount;
		ITypeHierarchy superHierarchy = type.newSupertypeHierarchy(null);
		IType[] allTypes = superHierarchy.getAllSupertypes(type);
		int length = allTypes.length;
		SimpleSet focusSet = new SimpleSet(length+1);
		if (focusElement != null) focusSet.add(focusElement);
		for (int i=0; i= 0;) {
			if (values[i] != null) {
				focuses[count++] = (IJavaElement) values[i];
			}
		}
		return focuses;
	}
	if (focusElement == null) return new IJavaElement[0];
	return new IJavaElement[] { focusElement };
}

/*
 *  Compute the list of paths which are keying index files.
 */
private void initializeIndexLocations() {
	IPath[] projectsAndJars = this.searchScope.enclosingProjectsAndJars();
	IndexManager manager = JavaModelManager.getIndexManager();
	// use a linked set to preserve the order during search: see bug 348507
	LinkedHashSet locations = new LinkedHashSet<>();
	IJavaElement focus = this.pattern instanceof ModulePattern ? null : MatchLocator.projectOrJarFocus(this.pattern);
	if (focus == null) {
		for (int i = 0; i < projectsAndJars.length; i++) {
			IPath path = projectsAndJars[i];
			Object target = JavaModel.getTarget(path, false/*don't check existence*/);
			if (target instanceof IFolder) // case of an external folder
				path = ((IFolder) target).getFullPath();
			locations.add(manager.computeIndexLocation(path));
		}
	} else {
		try {
			// See whether the state builder might be used to reduce the number of index locations

			// find the projects from projectsAndJars that see the focus then walk those projects looking for the jars from projectsAndJars
			int length = projectsAndJars.length;
			JavaProject[] projectsCanSeeFocus = new JavaProject[length];
			SimpleSet visitedProjects = new SimpleSet(length);
			int projectIndex = 0;
			SimpleSet externalLibsToCheck = new SimpleSet(length);
			ObjectVector superTypes = new ObjectVector();
			IJavaElement[] focuses = getFocusedElementsAndTypes(this.pattern, focus, superTypes);
			char[][][] focusQualifiedNames = null;
			boolean isAutoBuilding = ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding();
			if (isAutoBuilding && focus instanceof IJavaProject) {
				focusQualifiedNames = getQualifiedNames(superTypes);
			}
			IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
			for (int i = 0; i < length; i++) {
				IPath path = projectsAndJars[i];
				JavaProject project = (JavaProject) getJavaProject(path, model);
				if (project != null) {
					visitedProjects.add(project);
					int canSeeFocus = canSeeFocus(focuses, project, focusQualifiedNames);
					if (canSeeFocus == PROJECT_CAN_SEE_FOCUS) {
						locations.add(manager.computeIndexLocation(path));
					}
					if (canSeeFocus != PROJECT_CAN_NOT_SEE_FOCUS) {
						projectsCanSeeFocus[projectIndex++] = project;
					}
				} else {
					externalLibsToCheck.add(path);
				}
			}
			for (int i = 0; i < projectIndex && externalLibsToCheck.elementSize > 0; i++) {
				IClasspathEntry[] entries = projectsCanSeeFocus[i].getResolvedClasspath();
				for (int j = entries.length; --j >= 0;) {
					IClasspathEntry entry = entries[j];
					if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
						IPath path = entry.getPath();
						if (externalLibsToCheck.remove(path) != null) {
							Object target = JavaModel.getTarget(path, false/*don't check existence*/);
							if (target instanceof IFolder) // case of an external folder
								path = ((IFolder) target).getFullPath();
							locations.add(manager.computeIndexLocation(path));
						}
					}
				}
			}
			// jar files can be included in the search scope without including one of the projects that references them, so scan all projects that have not been visited
			if (externalLibsToCheck.elementSize > 0) {
				IJavaProject[] allProjects = model.getJavaProjects();
				for (int i = 0, l = allProjects.length; i < l && externalLibsToCheck.elementSize > 0; i++) {
					JavaProject project = (JavaProject) allProjects[i];
					if (!visitedProjects.includes(project)) {
						IClasspathEntry[] entries = project.getResolvedClasspath();
						for (int j = entries.length; --j >= 0;) {
							IClasspathEntry entry = entries[j];
							if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
								IPath path = entry.getPath();
								if (externalLibsToCheck.remove(path) != null) {
									Object target = JavaModel.getTarget(path, false/*don't check existence*/);
									if (target instanceof IFolder) // case of an external folder
										path = ((IFolder) target).getFullPath();
									locations.add(manager.computeIndexLocation(path));
								}
							}
						}
					}
				}
			}
		} catch (JavaModelException e) {
			// ignored
		}
	}

	locations.remove(null); // Ensure no nulls
	this.indexLocations = locations.toArray(new IndexLocation[locations.size()]);
}

public IndexLocation[] getIndexLocations() {
	if (this.indexLocations == null) {
		initializeIndexLocations();
	}

	IndexLocation[] filtered = this.indexLocations;
	if(this.pattern != null && this.pattern.indexQualifierQuery != null && this.pattern.indexQualifierQuery.length > 0) {
		Optional> indexNamesResult = JavaModelManager.getIndexManager()
				.findMatchingIndexNames(QualifierQuery.fromEncodedQuery(this.pattern.indexQualifierQuery));
		if(indexNamesResult.isPresent()) {
			Set indexNames = indexNamesResult.get();
			filtered = Stream.of(this.indexLocations).filter(l -> indexNames.contains(l.fileName()))
					.toArray(IndexLocation[]::new);
			if (filtered.length == 0) {
				if (JobManager.VERBOSE) {
					trace(String.format(
							"-> current index selection and qualifying indexes has no intersection, " + //$NON-NLS-1$
									"to keep search backward compatible using selected index locations - %s", //$NON-NLS-1$
							this.toString()));
				}
				filtered = this.indexLocations;
			}
		}
	}
	if (JobManager.VERBOSE) {
		trace(String.format("-> selected %s indexes out of total indexes %s after qualify filtering - %s",  //$NON-NLS-1$
				filtered.length, this.indexLocations.length, this.toString()));
	}
	return filtered;
}

/**
 * Returns the java project that corresponds to the given path.
 * Returns null if the path doesn't correspond to a project.
 */
private static IJavaProject getJavaProject(IPath path, IJavaModel model) {
	String lastSeg = path.lastSegment();
	if (lastSeg == null) {
		lastSeg = path.toOSString();
	}
	IJavaProject project = model.getJavaProject(lastSeg);
	if (project.exists()) {
		return project;
	}
	return null;
}

private char[][][] getQualifiedNames(ObjectVector types) {
	final int size = types.size;
	char[][][] focusQualifiedNames = null;
	IJavaElement javaElement = this.pattern.focus;
	int index = 0;
	while (javaElement != null && !(javaElement instanceof ITypeRoot)) {
		javaElement = javaElement.getParent();
	}
	if (javaElement != null) {
		IType primaryType = ((ITypeRoot) javaElement).findPrimaryType();
		if (primaryType != null) {
			focusQualifiedNames = new char[size+1][][];
			focusQualifiedNames[index++] = CharOperation.splitOn('.', primaryType.getFullyQualifiedName().toCharArray());
		}
	}
	if (focusQualifiedNames == null) {
		focusQualifiedNames = new char[size][][];
	}
	for (int i = 0; i < size; i++) {
		focusQualifiedNames[index++] = CharOperation.splitOn('.', ((IType)(types.elementAt(i))).getFullyQualifiedName().toCharArray());
	}
	return focusQualifiedNames.length == 0 ? null : ReferenceCollection.internQualifiedNames(focusQualifiedNames, true);
}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy