예제 #1
0
  /** IPyDevCompletionParticipant */
  @SuppressWarnings("unchecked")
  public Collection getCompletionsForMethodParameter(
      ICompletionState state, ILocalScope localScope, Collection<IToken> interfaceForLocal) {
    ArrayList<IToken> ret = new ArrayList<IToken>();
    String qual = state.getQualifier();
    if (qual.length()
        >= CodeCompletionPreferencesPage
            .getCharsForContextInsensitiveGlobalTokensCompletion()) { // at least n characters

      List<IInfo> tokensStartingWith;
      try {
        tokensStartingWith =
            AdditionalProjectInterpreterInfo.getTokensStartingWith(
                qual, state.getNature(), AbstractAdditionalInterpreterInfo.INNER);
      } catch (MisconfigurationException e) {
        PydevPlugin.log(e);
        return ret;
      }
      for (IInfo info : tokensStartingWith) {
        ret.add(
            new SourceToken(
                null, info.getName(), null, null, info.getDeclaringModuleName(), info.getType()));
      }
    }
    return ret;
  }
예제 #2
0
  /**
   * Generates the cached tokens in the needed structure for a 'fast' search given a token
   * representation (creates a map with the name of the token --> token).
   */
  private Map<String, IToken> internalGenerateCachedTokens(
      IPythonNature nature,
      ICompletionCache completionCache,
      String activationToken,
      boolean searchSameLevelMods)
      throws CompletionRecursionException {

    Map<String, IToken> cachedTokens = new HashMap<String, IToken>();

    // if still not found, we have to get all the tokens, including regular and wild imports
    ICompletionState state =
        CompletionStateFactory.getEmptyCompletionState(nature, completionCache);
    ICodeCompletionASTManager astManager = nature.getAstManager();
    state.setActivationToken(activationToken);

    // we don't want to gather builtins in this case.
    state.setBuiltinsGotten(true);
    IToken[] globalTokens = astManager.getCompletionsForModule(this, state, searchSameLevelMods);
    for (IToken token : globalTokens) {
      String rep = token.getRepresentation();
      IToken t = cachedTokens.get(rep);
      if (t != null) {
        // only override tokens if it's a getattr that's not defined in the builtin module
        if (rep.equals("__getattribute__") || rep.equals("__getattr__")) {
          if (!isTokenFromBuiltins(token)) {
            cachedTokens.put(rep, token);
          }
        }
      } else {
        cachedTokens.put(rep, token);
      }
    }
    return cachedTokens;
  }
예제 #3
0
  /**
   * @param request this is the request for the completion
   * @param theList OUT - returned completions are added here. (IToken instances)
   * @param getOnlySupers whether we should only get things from super classes (in this case, we
   *     won't get things from the current class)
   * @param checkIfInCorrectScope if true, we'll first check if we're in a scope that actually has a
   *     method with 'self' or 'cls'
   * @return true if we actually tried to get the completions for self or cls.
   * @throws MisconfigurationException
   */
  @SuppressWarnings("unchecked")
  public static boolean getSelfOrClsCompletions(
      CompletionRequest request,
      List theList,
      ICompletionState state,
      boolean getOnlySupers,
      boolean checkIfInCorrectScope,
      String lookForRep)
      throws MisconfigurationException {

    SimpleNode s =
        PyParser.reparseDocument(
                new PyParser.ParserInfo(request.doc, true, request.nature, state.getLine()))
            .o1;
    if (s != null) {
      FindScopeVisitor visitor = new FindScopeVisitor(state.getLine(), 0);
      try {
        s.accept(visitor);
        if (checkIfInCorrectScope) {
          boolean scopeCorrect = false;

          FastStack<SimpleNode> scopeStack = visitor.scope.getScopeStack();
          for (Iterator<SimpleNode> it = scopeStack.topDownIterator();
              scopeCorrect == false && it.hasNext(); ) {
            SimpleNode node = it.next();
            if (node instanceof FunctionDef) {
              FunctionDef funcDef = (FunctionDef) node;
              if (funcDef.args != null
                  && funcDef.args.args != null
                  && funcDef.args.args.length > 0) {
                // ok, we have some arg, let's check for self or cls
                String rep = NodeUtils.getRepresentationString(funcDef.args.args[0]);
                if (rep != null && (rep.equals("self") || rep.equals("cls"))) {
                  scopeCorrect = true;
                }
              }
            }
          }
          if (!scopeCorrect) {
            return false;
          }
        }
        if (lookForRep.equals("self")) {
          state.setLookingFor(ICompletionState.LOOKING_FOR_INSTANCED_VARIABLE);
        } else {
          state.setLookingFor(ICompletionState.LOOKING_FOR_CLASSMETHOD_VARIABLE);
        }
        getSelfOrClsCompletions(visitor.scope, request, theList, state, getOnlySupers);
      } catch (Exception e1) {
        PydevPlugin.log(e1);
      }
      return true;
    }
    return false;
  }
예제 #4
0
 /** @return the names that are already imported in the current document */
 private HashSet<String> getImportedNames(ICompletionState state) {
   List<IToken> tokenImportedModules = state.getTokenImportedModules();
   HashSet<String> importedNames = new HashSet<String>();
   if (tokenImportedModules != null) {
     for (IToken token : tokenImportedModules) {
       importedNames.add(token.getRepresentation());
     }
   }
   return importedNames;
 }
예제 #5
0
  @Override
  public boolean isInGlobalTokens(
      String tok, IPythonNature nature, ICompletionCache completionCache) {
    // we have to override because there is no way to check if it is in some import from some other
    // place if it has dots on the tok...

    if (tok.indexOf('.') == -1) {
      return isInDirectGlobalTokens(tok, completionCache);
    } else {
      ICompletionState state =
          CompletionStateFactory.getEmptyCompletionState(nature, completionCache);
      String[] headAndTail = FullRepIterable.headAndTail(tok);
      state.setActivationToken(headAndTail[0]);
      String head = headAndTail[1];
      IToken[] globalTokens = getGlobalTokens(state, nature.getAstManager());
      for (IToken token : globalTokens) {
        if (token.getRepresentation().equals(head)) {
          return true;
        }
      }
    }
    return false;
  }
예제 #6
0
  /**
   * Does a code-completion that will retrieve the globals in the module
   *
   * @throws MisconfigurationException
   */
  private void doGlobalsCompletion(
      CompletionRequest request,
      ICodeCompletionASTManager astManager,
      List<Object> tokensList,
      ICompletionState state)
      throws CompletionRecursionException, MisconfigurationException {
    state.setActivationToken(request.activationToken);
    if (DebugSettings.DEBUG_CODE_COMPLETION) {
      Log.toLogFile(this, "astManager.getCompletionsForToken");
      Log.addLogLevel();
    }
    IToken[] comps = astManager.getCompletionsForToken(request.editorFile, request.doc, state);
    if (DebugSettings.DEBUG_CODE_COMPLETION) {
      Log.remLogLevel();
      Log.toLogFile(this, "END astManager.getCompletionsForToken");
    }

    tokensList.addAll(Arrays.asList(comps));

    tokensList.addAll(getGlobalsFromParticipants(request, state));
  }
예제 #7
0
  /**
   * Does a code-completion that will retrieve the all matches for some token in the module
   *
   * @throws MisconfigurationException
   */
  private void doTokenCompletion(
      CompletionRequest request,
      ICodeCompletionASTManager astManager,
      List<Object> tokensList,
      String trimmed,
      ICompletionState state)
      throws CompletionRecursionException, MisconfigurationException {
    if (request.activationToken.endsWith(".")) {
      request.activationToken =
          request.activationToken.substring(0, request.activationToken.length() - 1);
    }

    final String initialActivationToken = request.activationToken;
    int parI = request.activationToken.indexOf('(');
    if (parI != -1) {
      request.activationToken = request.activationToken.substring(0, parI);
    }

    char[] toks = new char[] {'.', ' '};
    List<Object> completions = new ArrayList<Object>();

    boolean lookInGlobals = true;

    if (trimmed.equals("self") || FullRepIterable.getFirstPart(trimmed, toks).equals("self")) {
      lookInGlobals = !getSelfOrClsCompletions(request, tokensList, state, false, true, "self");

    } else if (trimmed.equals("cls") || FullRepIterable.getFirstPart(trimmed, toks).equals("cls")) {
      lookInGlobals = !getSelfOrClsCompletions(request, tokensList, state, false, true, "cls");
    }

    if (lookInGlobals) {
      state.setActivationToken(initialActivationToken);

      // Ok, looking for a token in globals.
      IToken[] comps = astManager.getCompletionsForToken(request.editorFile, request.doc, state);
      tokensList.addAll(Arrays.asList(comps));
    }
    tokensList.addAll(completions);
  }
예제 #8
0
  /* (non-Javadoc)
   * @see org.python.pydev.editor.codecompletion.IPyCodeCompletion#getCodeCompletionProposals(org.eclipse.jface.text.ITextViewer, org.python.pydev.editor.codecompletion.CompletionRequest)
   */
  @SuppressWarnings("unchecked")
  public List getCodeCompletionProposals(ITextViewer viewer, CompletionRequest request)
      throws CoreException, BadLocationException, IOException, MisconfigurationException,
          PythonNatureWithoutProjectException {
    if (request.getPySelection().getCursorLineContents().trim().startsWith("#")) {
      // this may happen if the context is still not correctly computed in python
      return new PyStringCodeCompletion().getCodeCompletionProposals(viewer, request);
    }
    if (DebugSettings.DEBUG_CODE_COMPLETION) {
      Log.toLogFile(this, "Starting getCodeCompletionProposals");
      Log.addLogLevel();
      Log.toLogFile(this, "Request:" + request);
    }

    ArrayList<ICompletionProposal> ret = new ArrayList<ICompletionProposal>();

    // let's see if we should do a code-completion in the current scope...
    if (!isValidCompletionContext(request)) {
      request.showTemplates = false;
      return ret;
    }

    try {
      IPythonNature pythonNature = request.nature;
      checkPythonNature(pythonNature);

      ICodeCompletionASTManager astManager = pythonNature.getAstManager();
      if (astManager == null) {
        // we're probably still loading it.
        return ret;
      }

      // list of Object[], IToken or ICompletionProposal
      List<Object> tokensList = new ArrayList<Object>();
      lazyStartShell(request);
      String trimmed = request.activationToken.replace('.', ' ').trim();

      ImportInfo importsTipper = getImportsTipperStr(request);

      int line = request.doc.getLineOfOffset(request.documentOffset);
      IRegion region = request.doc.getLineInformation(line);

      ICompletionState state =
          new CompletionState(
              line,
              request.documentOffset - region.getOffset(),
              null,
              request.nature,
              request.qualifier);
      state.setIsInCalltip(request.isInCalltip);

      boolean importsTip = false;

      if (importsTipper.importsTipperStr.length() != 0) {
        // code completion in imports
        request.isInCalltip = false; // if found after (, but in an import, it is not a calltip!
        importsTip = doImportCompletion(request, astManager, tokensList, importsTipper);

      } else if (trimmed.length() > 0 && request.activationToken.indexOf('.') != -1) {
        // code completion for a token
        doTokenCompletion(request, astManager, tokensList, trimmed, state);

      } else {
        // go to globals
        doGlobalsCompletion(request, astManager, tokensList, state);
      }

      Map<String, IToken> alreadyChecked = new HashMap<String, IToken>();

      String lowerCaseQual = request.qualifier.toLowerCase();
      if (lowerCaseQual.length()
          >= PyCodeCompletionPreferencesPage.getArgumentsDeepAnalysisNChars()) {
        // this can take some time on the analysis, so, let's let the user choose on how many chars
        // does he
        // want to do the analysis...
        state.pushFindResolveImportMemoryCtx();
        try {
          for (Iterator<Object> it = tokensList.listIterator(); it.hasNext(); ) {
            Object o = it.next();
            if (o instanceof IToken) {
              it
                  .remove(); // always remove the tokens from the list (they'll be re-added later
                             // once they are filtered)

              IToken initialToken = (IToken) o;

              IToken token = initialToken;
              String strRep = token.getRepresentation();
              IToken prev = alreadyChecked.get(strRep);

              if (prev != null) {
                if (prev.getArgs().length() != 0) {
                  continue; // we already have a version with args... just keep going
                }
              }

              if (!strRep.toLowerCase().startsWith(lowerCaseQual)) {
                // just re-add it if we're going to actually use it (depending on the qualifier)
                continue;
              }

              while (token.isImportFrom()) {
                // we'll only add it here if it is an import from (so, set the flag to false for the
                // outer add)

                if (token.getArgs().length() > 0) {
                  // if we already have the args, there's also no reason to do it (that's what we'll
                  // do here)
                  break;
                }
                ICompletionState s =
                    state.getCopyForResolveImportWithActTok(token.getRepresentation());
                s.checkFindResolveImportMemory(token);

                IToken token2 = astManager.resolveImport(s, token);
                if (token2 != null && initialToken != token2) {
                  String args = token2.getArgs();
                  if (args.length() > 0) {
                    // put it into the map (may override previous if it didn't have args)
                    initialToken.setArgs(args);
                    initialToken.setDocStr(token2.getDocStr());
                    if (initialToken instanceof SourceToken && token2 instanceof SourceToken) {
                      SourceToken initialSourceToken = (SourceToken) initialToken;
                      SourceToken token2SourceToken = (SourceToken) token2;
                      initialSourceToken.setAst(token2SourceToken.getAst());
                    }
                    break;
                  }
                  if (token2 == null
                      || (token2.equals(token)
                          && token2.getArgs().equals(token.getArgs())
                          && token2.getParentPackage().equals(token.getParentPackage()))) {
                    break;
                  }
                  token = token2;
                } else {
                  break;
                }
              }

              alreadyChecked.put(strRep, initialToken);
            }
          }

        } finally {
          state.popFindResolveImportMemoryCtx();
        }
      }

      tokensList.addAll(alreadyChecked.values());
      changeItokenToCompletionPropostal(viewer, request, ret, tokensList, importsTip, state);
    } catch (CompletionRecursionException e) {
      if (onCompletionRecursionException != null) {
        onCompletionRecursionException.call(e);
      }
      if (DebugSettings.DEBUG_CODE_COMPLETION) {
        Log.toLogFile(e);
      }
      // PydevPlugin.log(e);
      // ret.add(new CompletionProposal("",request.documentOffset,0,0,null,e.getMessage(),
      // null,null));
    }

    if (DebugSettings.DEBUG_CODE_COMPLETION) {
      Log.remLogLevel();
      Log.toLogFile(this, "Finished completion. Returned:" + ret.size() + " completions.\r\n");
    }

    return ret;
  }
예제 #9
0
  /**
   * Get self completions when you already have a scope
   *
   * @throws MisconfigurationException
   */
  @SuppressWarnings("unchecked")
  public static void getSelfOrClsCompletions(
      ILocalScope scope,
      CompletionRequest request,
      List theList,
      ICompletionState state,
      boolean getOnlySupers)
      throws BadLocationException, MisconfigurationException {
    for (Iterator<SimpleNode> it = scope.iterator(); it.hasNext(); ) {
      SimpleNode node = it.next();
      if (node instanceof ClassDef) {
        ClassDef d = (ClassDef) node;

        if (getOnlySupers) {
          List gottenComps = new ArrayList();
          for (int i = 0; i < d.bases.length; i++) {
            if (d.bases[i] instanceof Name) {
              Name n = (Name) d.bases[i];
              state.setActivationToken(n.id);
              IToken[] completions;
              try {
                completions =
                    request
                        .nature
                        .getAstManager()
                        .getCompletionsForToken(request.editorFile, request.doc, state);
                gottenComps.addAll(Arrays.asList(completions));
              } catch (CompletionRecursionException e) {
                // ok...
              }
            }
          }
          theList.addAll(gottenComps);
        } else {
          // ok, get the completions for the class, only thing we have to take care now is that we
          // may
          // not have only 'self' for completion, but something like self.foo.
          // so, let's analyze our activation token to see what should we do.

          String trimmed = request.activationToken.replace('.', ' ').trim();
          String[] actTokStrs = trimmed.split(" ");
          if (actTokStrs.length == 0
              || (!actTokStrs[0].equals("self") && !actTokStrs[0].equals("cls"))) {
            throw new AssertionError(
                "We need to have at least one token (self or cls) for doing completions in the class.");
          }

          if (actTokStrs.length == 1) {
            // ok, it's just really self, let's get on to get the completions
            state.setActivationToken(NodeUtils.getNameFromNameTok((NameTok) d.name));
            try {
              theList.addAll(
                  Arrays.asList(
                      request
                          .nature
                          .getAstManager()
                          .getCompletionsForToken(request.editorFile, request.doc, state)));
            } catch (CompletionRecursionException e) {
              // ok
            }

          } else {
            // it's not only self, so, first we have to get the definition of the token
            // the first one is self, so, just discard it, and go on, token by token to know what is
            // the last
            // one we are completing (e.g.: self.foo.bar)
            int line = request.doc.getLineOfOffset(request.documentOffset);
            IRegion region = request.doc.getLineInformationOfOffset(request.documentOffset);
            int col = request.documentOffset - region.getOffset();

            // ok, try our best shot at getting the module name of the current buffer used in the
            // request.
            String modName = "";
            File requestFile = request.editorFile;
            if (request.editorFile != null) {
              String resolveModule = request.nature.resolveModule(requestFile);
              if (resolveModule != null) {
                modName = resolveModule;
              }
            }

            IModule module =
                AbstractModule.createModuleFromDoc(
                    modName, requestFile, request.doc, request.nature, line);

            AbstractASTManager astMan = ((AbstractASTManager) request.nature.getAstManager());
            theList.addAll(
                new AssignAnalysis()
                    .getAssignCompletions(
                        astMan,
                        module,
                        new CompletionState(
                            line, col, request.activationToken, request.nature, request.qualifier))
                    .completions);
          }
        }
      }
    }
  }
예제 #10
0
  /**
   * @param findInfo
   * @see
   *     org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule#findDefinition(java.lang.String,
   *     int, int)
   */
  public Definition[] findDefinition(
      ICompletionState state, int line, int col, IPythonNature nature) throws Exception {
    String token = state.getActivationToken();

    if (TRACE_COMPILED_MODULES) {
      System.out.println("CompiledModule.findDefinition:" + token);
    }
    Definition[] found = this.definitionsFoundCache.getObj(token);
    if (found != null) {
      if (TRACE_COMPILED_MODULES) {
        System.out.println("CompiledModule.findDefinition: found in cache.");
      }
      return found;
    }

    AbstractShell shell = AbstractShell.getServerShell(nature, AbstractShell.COMPLETION_SHELL);
    synchronized (shell) {
      Tuple<String[], int[]> def =
          shell.getLineCol(
              this.name,
              token,
              nature
                  .getAstManager()
                  .getModulesManager()
                  .getCompletePythonPath(
                      nature.getProjectInterpreter(),
                      nature.getRelatedInterpreterManager())); // default
      if (def == null) {
        if (TRACE_COMPILED_MODULES) {
          System.out.println("CompiledModule.findDefinition:" + token + " = empty");
        }
        this.definitionsFoundCache.add(token, EMPTY_DEFINITION);
        return EMPTY_DEFINITION;
      }
      String fPath = def.o1[0];
      if (fPath.equals("None")) {
        if (TRACE_COMPILED_MODULES) {
          System.out.println("CompiledModule.findDefinition:" + token + " = None");
        }
        Definition[] definition =
            new Definition[] {new Definition(def.o2[0], def.o2[1], token, null, null, this)};
        this.definitionsFoundCache.add(token, definition);
        return definition;
      }
      File f = new File(fPath);
      String foundModName = nature.resolveModule(f);
      String foundAs = def.o1[1];

      IModule mod;
      if (foundModName == null) {
        // this can happen in a case where we have a definition that's found from a compiled file
        // which actually
        // maps to a file that's outside of the pythonpath known by Pydev.
        String n = FullRepIterable.getFirstPart(f.getName());
        mod = AbstractModule.createModule(n, f, nature, true);
      } else {
        mod = nature.getAstManager().getModule(foundModName, nature, true);
      }

      if (TRACE_COMPILED_MODULES) {
        System.out.println("CompiledModule.findDefinition: found at:" + mod.getName());
      }
      int foundLine = def.o2[0];
      if (foundLine == 0
          && foundAs != null
          && foundAs.length() > 0
          && mod != null
          && state.canStillCheckFindSourceFromCompiled(mod, foundAs)) {
        // TODO: The nature (and so the grammar to be used) must be defined by the file we'll parse
        // (so, we need to know the system modules manager that actually created it to know the
        // actual nature)
        IModule sourceMod =
            AbstractModule.createModuleFromDoc(
                mod.getName(), f, new Document(REF.getFileContents(f)), nature, true);
        if (sourceMod instanceof SourceModule) {
          Definition[] definitions =
              (Definition[])
                  sourceMod.findDefinition(state.getCopyWithActTok(foundAs), -1, -1, nature);
          if (definitions.length > 0) {
            this.definitionsFoundCache.add(token, definitions);
            return definitions;
          }
        }
      }
      if (mod == null) {
        mod = this;
      }
      int foundCol = def.o2[1];
      if (foundCol < 0) {
        foundCol = 0;
      }
      if (TRACE_COMPILED_MODULES) {
        System.out.println("CompiledModule.findDefinition: found compiled at:" + mod.getName());
      }
      Definition[] definitions =
          new Definition[] {new Definition(foundLine + 1, foundCol + 1, token, null, null, mod)};
      this.definitionsFoundCache.add(token, definitions);
      return definitions;
    }
  }
예제 #11
0
  /**
   * @see
   *     org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule#getGlobalTokens(java.lang.String)
   */
  public IToken[] getGlobalTokens(ICompletionState state, ICodeCompletionASTManager manager) {
    String activationToken = state.getActivationToken();
    if (activationToken.length() == 0) {
      return getGlobalTokens();
    }

    Map<String, IToken> v = cache.get(activationToken);
    if (v != null) {
      Collection<IToken> values = v.values();
      return values.toArray(new IToken[values.size()]);
    }

    IToken[] toks = new IToken[0];

    if (COMPILED_MODULES_ENABLED) {
      try {
        final IPythonNature nature = manager.getNature();

        final AbstractShell shell;
        try {
          shell = AbstractShell.getServerShell(nature, AbstractShell.COMPLETION_SHELL);
        } catch (Exception e) {
          throw new RuntimeException("Unable to create shell for CompiledModule: " + this.name, e);
        }
        synchronized (shell) {
          String act = name + '.' + activationToken;
          String tokenToCompletion = act;
          if (isPythonBuiltin) {
            String replacement = BUILTIN_REPLACEMENTS.get(activationToken);
            if (replacement != null) {
              tokenToCompletion = name + '.' + replacement;
            }
          }

          List<String[]> completions =
              shell.getImportCompletions(
                      tokenToCompletion,
                      manager
                          .getModulesManager()
                          .getCompletePythonPath(
                              nature.getProjectInterpreter(),
                              nature.getRelatedInterpreterManager()))
                  .o2;

          ArrayList<IToken> array = new ArrayList<IToken>();

          for (Iterator<String[]> iter = completions.iterator(); iter.hasNext(); ) {
            String[] element = iter.next();
            if (element.length >= 4) { // it might be a server error
              IToken t =
                  new CompiledToken(
                      element[0], element[1], element[2], act, Integer.parseInt(element[3]));
              array.add(t);
            }
          }
          toks = (CompiledToken[]) array.toArray(new CompiledToken[0]);
          HashMap<String, IToken> map = new HashMap<String, IToken>();
          for (IToken token : toks) {
            map.put(token.getRepresentation(), token);
          }
          cache.put(activationToken, map);
        }
      } catch (Exception e) {
        Log.log(
            "Error while getting info for module:"
                + this.name
                + ". Project: "
                + manager.getNature().getProject(),
            e);
      }
    }
    return toks;
  }