public static void buildKeysForZipContents( PyPublicTreeMap<ModulesKey, ModulesKey> keys, ZipContents zipContents) { for (String filePathInZip : zipContents.foundFileZipPaths) { String modName = StringUtils.stripExtension(filePathInZip).replace('/', '.'); if (DEBUG_ZIP) { System.out.println("Found in zip:" + modName); } ModulesKey k = new ModulesKeyForZip(modName, zipContents.zipFile, filePathInZip, true); keys.put(k, k); if (zipContents.zipContentsType == ZipContents.ZIP_CONTENTS_TYPE_JAR) { // folder modules are only created for jars (because for python files, the __init__.py is // required). for (String s : new FullRepIterable( FullRepIterable.getWithoutLastPart( modName))) { // the one without the last part was already added k = new ModulesKeyForZip(s, zipContents.zipFile, s.replace('.', '/'), false); keys.put(k, k); } } } }
/** * Change the pythonpath (used for both: system and project) * * @param project: may be null * @param defaultSelectedInterpreter: may be null */ public void changePythonPath( String pythonpath, final IProject project, IProgressMonitor monitor) { pythonPathHelper.setPythonPath(pythonpath); ModulesFoundStructure modulesFound = pythonPathHelper.getModulesFoundStructure(monitor); // now, on to actually filling the module keys ModulesKeyTreeMap<ModulesKey, ModulesKey> keys = new ModulesKeyTreeMap<ModulesKey, ModulesKey>(); int j = 0; FastStringBuffer buffer = new FastStringBuffer(); // now, create in memory modules for all the loaded files (empty modules). for (Iterator<Map.Entry<File, String>> iterator = modulesFound.regularModules.entrySet().iterator(); iterator.hasNext() && monitor.isCanceled() == false; j++) { Map.Entry<File, String> entry = iterator.next(); File f = entry.getKey(); String m = entry.getValue(); if (j % 15 == 0) { // no need to report all the time (that's pretty fast now) buffer.clear(); monitor.setTaskName(buffer.append("Module resolved: ").append(m).toString()); monitor.worked(1); } if (m != null) { // we don't load them at this time. ModulesKey modulesKey = new ModulesKey(m, f); // no conflict (easy) if (!keys.containsKey(modulesKey)) { keys.put(modulesKey, modulesKey); } else { // we have a conflict, so, let's resolve which one to keep (the old one or this one) if (PythonPathHelper.isValidSourceFile(f.getName())) { // source files have priority over other modules (dlls) -- if both are source, there is // no real way to resolve // this priority, so, let's just add it over. keys.put(modulesKey, modulesKey); } } } } for (ZipContents zipContents : modulesFound.zipContents) { if (monitor.isCanceled()) { break; } for (String filePathInZip : zipContents.foundFileZipPaths) { String modName = StringUtils.stripExtension(filePathInZip).replace('/', '.'); if (DEBUG_ZIP) { System.out.println("Found in zip:" + modName); } ModulesKey k = new ModulesKeyForZip(modName, zipContents.zipFile, filePathInZip, true); keys.put(k, k); if (zipContents.zipContentsType == ZipContents.ZIP_CONTENTS_TYPE_JAR) { // folder modules are only created for jars (because for python files, the __init__.py is // required). for (String s : new FullRepIterable( FullRepIterable.getWithoutLastPart( modName))) { // the one without the last part was already added k = new ModulesKeyForZip(s, zipContents.zipFile, s.replace('.', '/'), false); keys.put(k, k); } } } } onChangePythonpath(keys); // assign to instance variable this.setModules(keys); }
/** @see {@link ILocalScope#getPossibleClassesForActivationToken(String)} */ public List<String> getPossibleClassesForActivationToken(String actTok) { ArrayList<String> ret = new ArrayList<String>(); Iterator<SimpleNode> it = this.scope.topDownIterator(); if (!it.hasNext()) { return ret; } SimpleNode element = it.next(); // ok, that's the scope we have to analyze // Search for docstrings. String typeForParameter = NodeUtils.getTypeForParameterFromDocstring(actTok, element); if (typeForParameter != null) { ret.add(typeForParameter); } // Search for assert isinstance(). SequencialASTIteratorVisitor visitor = SequencialASTIteratorVisitor.create(element); Iterator<ASTEntry> iterator = visitor.getIterator(); ArrayList<Object> lst = new ArrayList<Object>(); Name nameDefinition = null; while (iterator.hasNext()) { ASTEntry entry = iterator.next(); if (entry.node.specialsAfter != null) { lst.addAll(entry.node.specialsAfter); } if (entry.node.specialsBefore != null) { lst.addAll(entry.node.specialsBefore); } if (!(entry.node instanceof Assert)) { if (entry.node instanceof Str) { lst.add(entry.node); } if (entry.node instanceof Name) { Name name = (Name) entry.node; if (name.ctx == Name.Load) { if (actTok.equals(name.id)) { nameDefinition = name; } } } continue; } Assert ass = (Assert) entry.node; if (ass.test instanceof Call) { Call call = (Call) ass.test; String rep = NodeUtils.getFullRepresentationString(call.func); if (rep == null) { continue; } Integer classIndex = ISINSTANCE_POSSIBILITIES.get(FullRepIterable.getLastPart(rep).toLowerCase()); if (classIndex != null) { if (call.args != null && (call.args.length >= Math.max(classIndex, 1))) { // in all cases, the instance is the 1st parameter. String foundActTok = NodeUtils.getFullRepresentationString(call.args[0]); if (foundActTok != null && foundActTok.equals(actTok)) { if (classIndex > 0) { exprType type = call.args[classIndex - 1]; if (type instanceof Tuple) { // case: isinstance(obj, (Class1,Class2)) Tuple tuple = (Tuple) type; for (exprType expr : tuple.elts) { addRepresentationIfPossible(ret, expr); } } else { // case: isinstance(obj, Class) addRepresentationIfPossible(ret, type); } } else { // zope case Interface.implementedBy(obj) -> Interface added ret.add(FullRepIterable.getWithoutLastPart(rep)); } } } } } } if (nameDefinition != null) { int s = lst.size(); for (int i = 0; i < s; i++) { Object object = lst.get(i); if (object instanceof commentType) { commentType commentType = (commentType) object; // according to http://sphinx-doc.org/ext/autodoc.html#directive-autoattribute, // to be a valid comment must be before the definition or in the same line. if (Math.abs(commentType.beginLine - nameDefinition.beginLine) <= 2) { if (commentType.id != null) { String trim = commentType.id.trim(); if (trim.startsWith("#")) { trim = trim.substring(1).trim(); } if (trim.startsWith(":")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim.substring(1)); if (type != null) { ret.add(type); } } else if (trim.startsWith("@")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim); if (type != null) { ret.add(type); } } } } } else if (object instanceof Str) { Str str = (Str) object; if (Math.abs(str.beginLine - nameDefinition.beginLine) <= 2) { if (str.s != null) { String trim = str.s.trim(); if (trim.startsWith("#")) { trim = trim.substring(1).trim(); } if (trim.startsWith(":")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim.substring(1)); if (type != null) { ret.add(type); } } else if (trim.startsWith("@")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim); if (type != null) { ret.add(type); } } } } } } } return ret; }
@Override public void addProps( MarkerAnnotationAndPosition markerAnnotation, IAnalysisPreferences analysisPreferences, String line, PySelection ps, int offset, IPythonNature nature, PyEdit edit, List<ICompletionProposal> props) throws BadLocationException, CoreException { if (nature == null) { return; } ICodeCompletionASTManager astManager = nature.getAstManager(); if (astManager == null) { return; } if (markerAnnotation.position == null) { return; } IMarker marker = markerAnnotation.markerAnnotation.getMarker(); Integer id = (Integer) marker.getAttribute(AnalysisRunner.PYDEV_ANALYSIS_TYPE); int start = markerAnnotation.position.offset; int end = start + markerAnnotation.position.length; ps.setSelection(start, end); String markerContents; try { markerContents = ps.getSelectedText(); } catch (Exception e1) { return; // Selection may be wrong. } IDocument doc = ps.getDoc(); List<String> parametersAfterCall = ps.getParametersAfterCall(end); switch (id) { case IAnalysisPreferences.TYPE_UNDEFINED_VARIABLE: addCreateClassOption(ps, edit, props, markerContents, parametersAfterCall); addCreateMethodOption(ps, edit, props, markerContents, parametersAfterCall); break; case IAnalysisPreferences.TYPE_UNDEFINED_IMPORT_VARIABLE: // Say we had something as: // import sys // sys.Bar // in which case 'Bar' is undefined // in this situation, the activationTokenAndQual would be "sys." and "Bar" // and we want to get the definition for "sys" String[] activationTokenAndQual = ps.getActivationTokenAndQual(true); if (activationTokenAndQual[0].endsWith(".")) { ArrayList<IDefinition> selected = findDefinitions(nature, edit, start - 2, doc); for (IDefinition iDefinition : selected) { IModule module = iDefinition.getModule(); if (module.getFile() != null) { Definition definition = (Definition) iDefinition; File file = module.getFile(); if (definition.ast == null) { // if we have no ast in the definition, it means the module itself was found (global // scope) // Add option to create class at the given module! addCreateClassOption(ps, edit, props, markerContents, parametersAfterCall, file); addCreateMethodOption(ps, edit, props, markerContents, parametersAfterCall, file); } else if (definition.ast instanceof ClassDef) { ClassDef classDef = (ClassDef) definition.ast; // Ok, we should create a field or method in this case (accessing a classmethod or // staticmethod) PyCreateMethodOrField pyCreateMethod = new PyCreateMethodOrField(); String className = NodeUtils.getNameFromNameTok(classDef.name); pyCreateMethod.setCreateInClass(className); pyCreateMethod.setCreateAs(PyCreateMethodOrField.CLASSMETHOD); addCreateClassmethodOption( ps, edit, props, markerContents, parametersAfterCall, pyCreateMethod, file, className); } } } } break; case IAnalysisPreferences.TYPE_UNRESOLVED_IMPORT: // This case is the following: from other_module4 import Foo // with 'Foo' being undefined. // So, we have to suggest creating a Foo class/method in other_module4 PyImportsHandling importsHandling = new PyImportsHandling(ps.getDoc(), false); int offsetLine = ps.getLineOfOffset(start); String selectedText = ps.getSelectedText(); Tuple<IModule, String> found = null; String foundFromImportStr = null; boolean isImportFrom = false; OUT: for (ImportHandle handle : importsHandling) { if (handle.startFoundLine == offsetLine || handle.endFoundLine == offsetLine || (handle.startFoundLine < offsetLine && handle.endFoundLine > offsetLine)) { List<ImportHandleInfo> importInfo = handle.getImportInfo(); for (ImportHandleInfo importHandleInfo : importInfo) { String fromImportStr = importHandleInfo.getFromImportStr(); List<String> importedStr = importHandleInfo.getImportedStr(); for (String imported : importedStr) { if (selectedText.equals(imported)) { if (fromImportStr != null) { foundFromImportStr = fromImportStr + "." + imported; isImportFrom = true; } else { // if fromImportStr == null, it's not a from xxx import yyy (i.e.: simple // import) foundFromImportStr = imported; } try { String currentModule = nature.resolveModule(edit.getEditorFile()); ICompletionState state = CompletionStateFactory.getEmptyCompletionState( nature, new CompletionCache()); found = nature .getAstManager() .findModule( foundFromImportStr, currentModule, state, new SourceModule( currentModule, edit.getEditorFile(), edit.getAST(), null)); } catch (Exception e) { Log.log(e); } break OUT; } } } break OUT; } } boolean addOptionToCreateClassOrMethod = isImportFrom; if (found != null && found.o1 != null) { // Ok, we found a module, now, it may be that we still have to create some intermediary // modules // or just create a class or method at the end. if (found.o1 instanceof SourceModule) { // if all was found, there's nothing left to create. if (found.o2 != null && found.o2.length() > 0) { SourceModule sourceModule = (SourceModule) found.o1; File file = sourceModule.getFile(); if (found.o2.indexOf('.') != -1) { // We have to create some intermediary structure. if (!addOptionToCreateClassOrMethod) { // Cannot create class or method from the info (only the module structure). if (sourceModule.getName().endsWith(".__init__")) { File f = getFileStructure(file.getParentFile(), found.o2); addCreateModuleOption(ps, edit, props, markerContents, f); } } else { // Ok, the leaf may be a class or method. if (sourceModule.getName().endsWith(".__init__")) { String moduleName = FullRepIterable.getWithoutLastPart(sourceModule.getName()); String withoutLastPart = FullRepIterable.getWithoutLastPart(found.o2); moduleName += "." + withoutLastPart; String classOrMethodName = FullRepIterable.getLastPart(found.o2); File f = getFileStructure(file.getParentFile(), withoutLastPart); addCreateClassInNewModuleOption( ps, edit, props, classOrMethodName, moduleName, parametersAfterCall, f); addCreateMethodInNewModuleOption( ps, edit, props, classOrMethodName, moduleName, parametersAfterCall, f); } } } else { // Ok, it's all there, we just have to create the leaf. if (!addOptionToCreateClassOrMethod || sourceModule.getName().endsWith(".__init__")) { // Cannot create class or method from the info (only the module structure). if (sourceModule.getName().endsWith(".__init__")) { File f = new File( file.getParent(), found.o2 + FileTypesPreferencesPage.getDefaultDottedPythonExtension()); addCreateModuleOption(ps, edit, props, markerContents, f); } } else { // Ok, the leaf may be a class or method. addCreateClassOption(ps, edit, props, markerContents, parametersAfterCall, file); addCreateMethodOption(ps, edit, props, markerContents, parametersAfterCall, file); } } } } } else if (foundFromImportStr != null) { // We couldn't find anything there, so, we have to create the modules structure as needed // and // maybe create a class or module at the end (but only if it's an import from). // Ok, it's all there, we just have to create the leaf. // Discover the source folder where we should create the structure. File editorFile = edit.getEditorFile(); String onlyProjectPythonPathStr = nature.getPythonPathNature().getOnlyProjectPythonPathStr(false); List<String> split = StringUtils.splitAndRemoveEmptyTrimmed(onlyProjectPythonPathStr, '|'); for (int i = 0; i < split.size(); i++) { String fullPath = FileUtils.getFileAbsolutePath(split.get(i)); fullPath = PythonPathHelper.getDefaultPathStr(fullPath); split.set(i, fullPath); } HashSet<String> projectSourcePath = new HashSet<String>(split); if (projectSourcePath.size() == 0) { return; // No source folder for editor... this shouldn't happen (code analysis wouldn't // even run on it). } String fullPath = FileUtils.getFileAbsolutePath(editorFile); fullPath = PythonPathHelper.getDefaultPathStr(fullPath); String foundSourceFolderFullPath = null; if (projectSourcePath.size() == 1) { foundSourceFolderFullPath = projectSourcePath.iterator().next(); } else { for (String string : projectSourcePath) { if (fullPath.startsWith(string)) { // Use this as the source folder foundSourceFolderFullPath = string; break; } } } if (foundSourceFolderFullPath != null) { if (!addOptionToCreateClassOrMethod) { // Cannot create class or method from the info (only the module structure). File f = getFileStructure(new File(foundSourceFolderFullPath), foundFromImportStr); addCreateModuleOption(ps, edit, props, foundFromImportStr, f); } else { // Ok, the leaf may be a class or method. String moduleName = FullRepIterable.getWithoutLastPart(foundFromImportStr); File file = getFileStructure(new File(foundSourceFolderFullPath), moduleName); String lastPart = FullRepIterable.getLastPart(foundFromImportStr); addCreateClassInNewModuleOption( ps, edit, props, lastPart, moduleName, parametersAfterCall, file); addCreateMethodInNewModuleOption( ps, edit, props, lastPart, moduleName, parametersAfterCall, file); } } } break; } }