blob: d1ec2c1a91295241b5818a10e332eff2db339b3e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2017 NumberFour AG 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
*
* Contributors:
* NumberFour AG - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.core.tests.search;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.internal.environment.LocalEnvironment;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.TypeNameMatch;
import org.eclipse.dltk.core.search.TypeNameMatchRequestor;
import org.eclipse.dltk.core.tests.ProjectSetup;
import org.eclipse.dltk.core.tests.model.ModelTestsPlugin;
import org.eclipse.dltk.internal.core.BuildpathEntry;
import org.eclipse.dltk.internal.core.search.DLTKSearchScope;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
* Test for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=387751
* <p>
* Tests for {@link DLTKSearchScope#projectFragment(String)} method with scope
* containing external source modules are performed indirectly via
* {@link SearchEngine#searchAllTypeNames()} method, which also uses it.
* </p>
*/
public class Bug387751Test extends Assert {
@Rule
public final ProjectSetup project = new ProjectSetup(
ModelTestsPlugin.WORKSPACE, "bug387751");
@Rule
public final TemporaryFolder temp = new TemporaryFolder();
/**
* Precondition: validates the model of the test file
*/
@Test
public void validateTestModuleContents() throws ModelException {
final ISourceModule module = project.getSourceModule("", "test.txt");
assertNotNull(module);
assertTrue(module.exists());
final IModelElement[] types = module.getChildren();
assertEquals(1, types.length);
final IType type = (IType) types[0];
assertEquals("Foo", type.getElementName());
final IModelElement[] methods = type.getChildren();
assertEquals(1, methods.length);
final IMethod method = (IMethod) methods[0];
assertEquals("bar", method.getElementName());
assertEquals(0, method.getChildren().length);
}
/**
* Precondition: validates that {@link SearchEngine#searchAllTypeNames()}
* works
*/
@Test
public void searchProject() throws IOException, CoreException {
final List<IType> types = searchAllTypeNames(
SearchEngine.createSearchScope(project.getScriptProject()),
"Foo");
assertEquals(1, types.size());
assertEquals(project.getSourceModule("", "test.txt"),
types.get(0).getSourceModule());
}
/**
* Validates that search works in external folders when scope is created for
* the project
*/
@Test
public void searchExternalLibraryProjectScope()
throws IOException, CoreException {
final IFile file = project.getFile("test.txt");
addExternalLibraryFromFile(file, file.getName());
file.delete(true, null);
final List<ISourceModule> modules = listModules();
assertEquals(1, modules.size());
final ISourceModule module = modules.get(0);
final List<IType> types = searchAllTypeNames(
SearchEngine.createSearchScope(project.getScriptProject()),
"Foo");
assertEquals(1, types.size());
assertEquals(module, types.get(0).getSourceModule());
}
/**
* Validates that search works in external folders when scope is created for
* the external module
*/
@Test
public void searchExternalLibraryModuleScope()
throws IOException, CoreException {
final IFile file = project.getFile("test.txt");
addExternalLibraryFromFile(file, file.getName());
file.delete(true, null);
final List<ISourceModule> modules = listModules();
assertEquals(1, modules.size());
final ISourceModule module = modules.get(0);
final List<IType> types = searchAllTypeNames(
SearchEngine.createSearchScope(module), "Foo");
assertEquals(1, types.size());
assertEquals(module, types.get(0).getSourceModule());
}
/**
* Validates that search works in external folders when scope is created for
* the project - more complicated setup with 2 entries and exclude patterns.
*/
@Test
public void searchExternalLibraryModuleScopeWithExcludes()
throws IOException, CoreException {
final IFile file = project.getFile("test.txt");
temp.newFolder("tests");
addExternalLibraryFromFile(file, "tests/" + file.getName());
file.delete(true, null);
addBuildpathEntry(project.getScriptProject(), DLTKCore.newLibraryEntry(
getFullPath(temp.getRoot()), IBuildpathEntry.NO_ACCESS_RULES,
IBuildpathEntry.NO_EXTRA_ATTRIBUTES, BuildpathEntry.INCLUDE_ALL,
new IPath[] { new Path("tests/") }, false /* not exported */,
true));
final List<ISourceModule> modules = listModules();
assertEquals(1, modules.size());
final ISourceModule module = modules.get(0);
final List<IType> types = searchAllTypeNames(
SearchEngine.createSearchScope(module), "Foo");
assertEquals(1, types.size());
assertEquals(module, types.get(0).getSourceModule());
}
private List<IType> searchAllTypeNames(final IDLTKSearchScope scope,
final String name) throws ModelException {
final List<IType> types = new ArrayList<>();
new SearchEngine((WorkingCopyOwner) null).searchAllTypeNames(null, 0,
name.toCharArray(),
SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
IDLTKSearchConstants.TYPE, scope, new TypeNameMatchRequestor() {
@Override
public void acceptTypeNameMatch(TypeNameMatch match) {
types.add(match.getType());
}
}, IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);
return types;
}
private List<ISourceModule> listModules() throws ModelException {
final List<ISourceModule> modules = new ArrayList<>();
project.getScriptProject().accept(element -> {
if (element instanceof ISourceModule) {
modules.add((ISourceModule) element);
}
return element.getElementType() < IModelElement.SOURCE_MODULE;
});
return modules;
}
private void addExternalLibraryFromFile(IFile file, String filename)
throws IOException, CoreException {
final File externalFile = new File(temp.getRoot(), filename);
try (final InputStream input = file.getContents()) {
Util.copy(externalFile, input);
}
addBuildpathEntry(project.getScriptProject(), DLTKCore
.newExtLibraryEntry(getFullPath(externalFile.getParentFile())));
}
private IPath getFullPath(File file) {
return EnvironmentPathUtils.getFullPath(LocalEnvironment.getInstance(),
new Path(file.getAbsolutePath()));
}
private void addBuildpathEntry(IScriptProject scriptProject,
IBuildpathEntry entry) throws ModelException {
final List<IBuildpathEntry> buildpath = new ArrayList<>();
buildpath.add(entry);
Collections.addAll(buildpath, scriptProject.getRawBuildpath());
scriptProject.setRawBuildpath(
buildpath.toArray(new IBuildpathEntry[buildpath.size()]), null);
}
}