Beispiel #1
0
  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);
        }
      }
    }
  }
Beispiel #2
0
  /**
   * 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);
  }
Beispiel #3
0
  /** @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;
    }
  }