/** * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ /* * Created on 07/09/2005 */ package com.python.pydev.analysis.additionalinfo; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.text.Document; import org.python.pydev.core.DeltaSaver; import org.python.pydev.core.IInterpreterManager; import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.ModulesKey; import org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule; import org.python.pydev.editor.codecompletion.revisited.modules.SourceModule; import org.python.pydev.parser.jython.ast.ClassDef; import org.python.pydev.parser.jython.ast.FunctionDef; import org.python.pydev.parser.jython.ast.NameTok; import org.python.pydev.plugin.nature.ProjectStub2; import org.python.pydev.shared_core.callbacks.ICallbackListener; import org.python.pydev.shared_core.io.FileUtils; import org.python.pydev.shared_core.structure.Tuple; import org.python.pydev.ui.interpreters.PythonInterpreterManager; import org.python.pydev.ui.pythonpathconf.InterpreterInfo; import com.python.pydev.analysis.system_info_builder.InterpreterInfoBuilder; public class AdditionalInterpreterInfoTest extends AdditionalInfoTestsBase { private AdditionalProjectInterpreterInfo info; private File baseDir; public static void main(String[] args) { try { AdditionalInterpreterInfoTest test = new AdditionalInterpreterInfoTest(); test.setUp(); // test.testCompleteIndex(); test.tearDown(); junit.textui.TestRunner.run(AdditionalInterpreterInfoTest.class); } catch (Throwable e) { e.printStackTrace(); } } @Override public void setUp() throws Exception { super.setUp(); ProjectStub2 project = new ProjectStub2("empty"); info = new AdditionalProjectInterpreterInfo(project) { @Override protected File getPersistingLocation() { return null; } @Override protected File getPersistingFolder() { return null; } @Override protected Set<String> getPythonPathFolders() { return new HashSet<>(Arrays.asList(baseDir.getAbsolutePath())); } @Override protected String getUIRepresentation() { return "Stub for: " + baseDir; } @Override protected DeltaSaver<Object> createDeltaSaver() { return null; } }; baseDir = FileUtils.getTempFileAt(new File("."), "data_temp_additional_info_test"); if (baseDir.exists()) { FileUtils.deleteDirectoryTree(baseDir); } baseDir.mkdir(); } @Override public void tearDown() throws Exception { if (baseDir.exists()) { FileUtils.deleteDirectoryTree(baseDir); } super.tearDown(); } public void testMap() { FuncInfo info2 = new FuncInfo(((NameTok) createFuncDef("metz").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("metZ").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("met9").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("met0").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("meta").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("metA").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); Collection<IInfo> tokensStartingWith = info .getTokensStartingWith("met", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(6, tokensStartingWith.size()); Collection<IInfo> tokensEqualTo = info.getTokensEqualTo("metz", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(1, tokensEqualTo.size()); } public void testMap2() { FuncInfo info2 = new FuncInfo(((NameTok) createFuncDef("m").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("mm").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("mmm").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("mmmm").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); Collection<IInfo> tokensStartingWith = info.getTokensStartingWith("m", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(4, tokensStartingWith.size()); tokensStartingWith = info.getTokensStartingWith("mm", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(3, tokensStartingWith.size()); tokensStartingWith = info.getTokensStartingWith("mmm", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(2, tokensStartingWith.size()); tokensStartingWith = info.getTokensStartingWith("mmmm", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(1, tokensStartingWith.size()); } public void testAddFunc() { FuncInfo info2 = new FuncInfo(((NameTok) createFuncDef("met1").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("met2").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("func1").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); info2 = new FuncInfo(((NameTok) createFuncDef("func2").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); Collection<IInfo> tokensStartingWith = info.getTokensStartingWith("me", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(2, tokensStartingWith.size()); assertIsIn("met1", tokensStartingWith); assertIsIn("met2", tokensStartingWith); tokensStartingWith = info.getTokensStartingWith("func", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(2, tokensStartingWith.size()); assertIsIn("func1", tokensStartingWith); assertIsIn("func2", tokensStartingWith); for (IInfo info : tokensStartingWith) { assertEquals("mod1", info.getDeclaringModuleName()); } } public void testAddClass() { ClassInfo info1 = new ClassInfo(((NameTok) createClassDef("cls1").name).id, "mod1", null, null); info.add(info1, AbstractAdditionalTokensInfo.TOP_LEVEL); ClassInfo info2 = new ClassInfo(((NameTok) createClassDef("cls2").name).id, "mod1", null, null); info.add(info2, AbstractAdditionalTokensInfo.TOP_LEVEL); ClassInfo info3 = new ClassInfo(((NameTok) createClassDef("class1").name).id, "mod2", null, null); info.add(info3, AbstractAdditionalTokensInfo.TOP_LEVEL); ClassInfo info4 = new ClassInfo(((NameTok) createClassDef("class2").name).id, "mod2", null, null); info.add(info4, AbstractAdditionalTokensInfo.TOP_LEVEL); Collection<IInfo> tokensStartingWith = info .getTokensStartingWith("cls", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(2, tokensStartingWith.size()); assertIsIn("cls1", tokensStartingWith); assertIsIn("cls2", tokensStartingWith); info.removeInfoFromModule("mod2", false); tokensStartingWith = info.getTokensStartingWith("class", AbstractAdditionalTokensInfo.TOP_LEVEL); assertEquals(0, tokensStartingWith.size()); } public void testAddInner() throws MisconfigurationException { String doc = "class Test:\n" + " def m1(self):\n" + " pass"; SourceModule module = AbstractModule.createModuleFromDoc("test", null, new Document(doc), nature, true); info.addAstInfo(module.getAst(), module.getModulesKey(), false); Collection<IInfo> tokensStartingWith = info.getTokensStartingWith("Tes", AbstractAdditionalTokensInfo.TOP_LEVEL | AbstractAdditionalTokensInfo.INNER); assertEquals(1, tokensStartingWith.size()); assertIsIn("Test", tokensStartingWith); tokensStartingWith = info.getTokensStartingWith("m1", AbstractAdditionalTokensInfo.TOP_LEVEL | AbstractAdditionalTokensInfo.INNER); assertEquals(1, tokensStartingWith.size()); assertIsIn("m1", tokensStartingWith); IInfo i = tokensStartingWith.iterator().next(); assertEquals("Test", i.getPath()); } public void testAddAttrs() throws MisconfigurationException { String doc = "GLOBAL_ATTR = 1\n" + "GLOBAL2.IGNORE_THIS = 2\n" + "" + "class Test:\n" + " test_attr = 1\n" + " test_attr.ignore = 2\n" + " test_attr2.ignore_this = 3\n" + "" + " class Test2:\n" + " def mmm(self):\n" + " self.attr1 = 10"; SourceModule module = AbstractModule.createModuleFromDoc("test", null, new Document(doc), nature, true); info.addAstInfo(module.getAst(), module.getModulesKey(), false); Collection<IInfo> tokensStartingWith = null; IInfo i = null; tokensStartingWith = info.getTokensStartingWith("global", AbstractAdditionalTokensInfo.TOP_LEVEL | AbstractAdditionalTokensInfo.INNER); // assertEquals(2, tokensStartingWith.size()); assertIsIn("GLOBAL_ATTR", tokensStartingWith); assertIsIn("GLOBAL2", tokensStartingWith); tokensStartingWith = info.getTokensStartingWith("", AbstractAdditionalTokensInfo.TOP_LEVEL | AbstractAdditionalTokensInfo.INNER); // assertEquals(2, tokensStartingWith.size()); i = assertIsIn("Test", tokensStartingWith); assertEquals(null, i.getPath()); i = assertIsIn("Test2", tokensStartingWith); assertEquals("Test", i.getPath()); i = assertIsIn("test_attr", tokensStartingWith); assertEquals("Test", i.getPath()); i = assertIsIn("test_attr2", tokensStartingWith); assertEquals("Test", i.getPath()); i = assertIsIn("attr1", tokensStartingWith); assertEquals("Test.Test2.mmm", i.getPath()); } public void testAddInner2() throws MisconfigurationException { String doc = "class Test:\n" + " class Test2:\n" + " def mmm(self):\n" + " pass"; SourceModule module = AbstractModule.createModuleFromDoc("test", null, new Document(doc), nature, true); info.addAstInfo(module.getAst(), module.getModulesKey(), false); Collection<IInfo> tokensStartingWith = null; tokensStartingWith = info.getTokensStartingWith("m", AbstractAdditionalTokensInfo.TOP_LEVEL | AbstractAdditionalTokensInfo.INNER); assertEquals(1, tokensStartingWith.size()); assertIsIn("mmm", tokensStartingWith); IInfo i = tokensStartingWith.iterator().next(); assertEquals("Test.Test2", i.getPath()); tokensStartingWith = info.getTokensStartingWith("Test", AbstractAdditionalTokensInfo.TOP_LEVEL | AbstractAdditionalTokensInfo.INNER); assertEquals(2, tokensStartingWith.size()); i = assertIsIn("Test", tokensStartingWith); assertEquals(null, i.getPath()); i = assertIsIn("Test2", tokensStartingWith); assertEquals("Test", i.getPath()); } // Not working with lucene searches (test must be fixed). // // public void testCompleteIndex() throws Exception { // String doc = "class Test:\n" + // " class Test2:\n" + // " def mmm(self):\n" + // " a = mmm1\n" // + // " print mmm1"; // File tempFileAt = FileUtils.getTempFileAt(baseDir, "data_temporary_file_on_additional_interpreter_info_test", // ".py"); // FileUtils.writeStrToFile(doc, tempFileAt); // try { // SourceModule module = AbstractModule.createModuleFromDoc("test", tempFileAt, new Document( // doc), nature, true); // info.addAstInfo(module.getAst(), new ModulesKey("test", tempFileAt), false); // // List<ModulesKey> modulesWithTokensStartingWith = null; // // modulesWithTokensStartingWith = info.getModulesWithToken("mmm", null); // assertEquals(1, modulesWithTokensStartingWith.size()); // // modulesWithTokensStartingWith = info.getModulesWithToken("mmm1", null); // assertEquals(1, modulesWithTokensStartingWith.size()); // // modulesWithTokensStartingWith = info.getModulesWithToken("mmm4", null); // assertEquals(0, modulesWithTokensStartingWith.size()); // // synchronized (this) { // wait(1000); // } // // doc = "new contents"; // FileUtils.writeStrToFile(doc, tempFileAt); // // info.removeInfoFromModule("test", true); // info.addAstInfo(new ModulesKey("test", tempFileAt), true); // modulesWithTokensStartingWith = info.getModulesWithToken("mmm", null); // assertEquals(0, modulesWithTokensStartingWith.size()); // // modulesWithTokensStartingWith = info.getModulesWithToken("contents", null); // assertEquals(1, modulesWithTokensStartingWith.size()); // } finally { // tempFileAt.delete(); // } // } @SuppressWarnings("unchecked") public void testForcedBuiltinsInAdditionalInfo() throws Exception { IInterpreterManager interpreterManager = getInterpreterManager(); String defaultInterpreter = interpreterManager.getDefaultInterpreterInfo(false).getExecutableOrJar(); AbstractAdditionalDependencyInfo additionalSystemInfo = AdditionalSystemInterpreterInfo .getAdditionalSystemInfo(interpreterManager, defaultInterpreter); checkItertoolsToken(additionalSystemInfo, false); InterpreterInfo defaultInterpreterInfo = (InterpreterInfo) interpreterManager.getDefaultInterpreterInfo(false); HashSet<String> set = new HashSet<>(Arrays.asList(defaultInterpreterInfo.getBuiltins())); assertTrue(set.contains("itertools")); //Now, update the information to contain the builtin tokens! new InterpreterInfoBuilder().syncInfoToPythonPath(new NullProgressMonitor(), defaultInterpreterInfo); checkItertoolsToken(additionalSystemInfo, true); //Remove and re-update to check if it's fixed. additionalSystemInfo.removeInfoFromModule("itertools", false); checkItertoolsToken(additionalSystemInfo, false); new InterpreterInfoBuilder().syncInfoToPythonPath(new NullProgressMonitor(), defaultInterpreterInfo); checkItertoolsToken(additionalSystemInfo, true); int indexSize = additionalSystemInfo.completeIndex.keys().size(); AdditionalSystemInterpreterInfo newAdditionalInfo = new AdditionalSystemInterpreterInfo(interpreterManager, defaultInterpreter); AdditionalSystemInterpreterInfo.setAdditionalSystemInfo((PythonInterpreterManager) interpreterManager, defaultInterpreter, newAdditionalInfo); newAdditionalInfo.load(); assertEquals(indexSize, newAdditionalInfo.completeIndex.keys().size()); final List<ModulesKey> added = new ArrayList<>(); final List<ModulesKey> removed = new ArrayList<>(); ICallbackListener listener = new ICallbackListener() { @Override public Object call(Object obj) { Tuple t = (Tuple) obj; added.addAll((List<ModulesKey>) t.o1); removed.addAll((List<ModulesKey>) t.o2); return null; } }; AbstractAdditionalDependencyInfo.modulesAddedAndRemoved.registerListener(listener); try { new InterpreterInfoBuilder().syncInfoToPythonPath(new NullProgressMonitor(), defaultInterpreterInfo); } finally { AbstractAdditionalDependencyInfo.modulesAddedAndRemoved.unregisterListener(listener); } if (added.size() > 0) { throw new AssertionError( "Expected no modules to be added as we just loaded from a clean save. Found: " + added); } if (removed.size() > 0) { throw new AssertionError( "Expected no modules to be removed as we just loaded from a clean save. Found: " + removed); } checkItertoolsToken(newAdditionalInfo, true); } private void checkItertoolsToken(AbstractAdditionalDependencyInfo additionalSystemInfo, boolean expect) { Collection<IInfo> tokensStartingWith; tokensStartingWith = additionalSystemInfo.getTokensStartingWith("izip_longest", AbstractAdditionalTokensInfo.TOP_LEVEL); if (expect) { assertEquals(1, tokensStartingWith.size()); } else { assertEquals(0, tokensStartingWith.size()); } } private ClassDef createClassDef(String name) { return new ClassDef(new NameTok(name, NameTok.FunctionName), null, null, null, null, null, null); } private IInfo assertIsIn(String req, Collection<IInfo> tokensStartingWith) { for (IInfo info : tokensStartingWith) { if (info.getName().equals(req)) { return info; } } fail("The token requested (" + req + ") was not found."); return null; } private FunctionDef createFuncDef(String metName) { return new FunctionDef(new NameTok(metName, NameTok.FunctionName), null, null, null, null, false); } }