@Override
 public Object visitImportFrom(ImportFrom node) throws Exception {
   String modRep = NodeUtils.getRepresentationString(node.module);
   if (NodeUtils.isWithin(line, col, node.module)) {
     // it is a token in the definition of a module
     int startingCol = node.module.beginColumn;
     int endingCol = startingCol;
     while (endingCol < this.col) {
       endingCol++;
     }
     int lastChar = endingCol - startingCol;
     moduleImported = modRep.substring(0, lastChar);
     int i = lastChar;
     while (i < modRep.length()) {
       if (Character.isJavaIdentifierPart(modRep.charAt(i))) {
         i++;
       } else {
         break;
       }
     }
     moduleImported += modRep.substring(lastChar, i);
   } else {
     // it was not the module, so, we have to check for each name alias imported
     for (aliasType alias : node.names) {
       // we do not check the 'as' because if it is some 'as', it will be gotten as a global in the
       // module
       if (NodeUtils.isWithin(line, col, alias.name)) {
         moduleImported = modRep + "." + NodeUtils.getRepresentationString(alias.name);
       }
     }
   }
   return super.visitImportFrom(node);
 }
Beispiel #2
0
  /**
   * @param s the scope we're checking for
   * @return if the scope passed as a parameter starts with the same scope we have here. It should
   *     not be called if the size of the scope we're checking is bigger than the size of 'this'
   *     scope.
   */
  @SuppressWarnings("unchecked")
  private boolean checkIfScopesMatch(ILocalScope s) {
    Iterator<SimpleNode> otIt = s.getScopeStack().iterator();

    for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext(); ) {
      SimpleNode element = iter.next();
      SimpleNode otElement = otIt.next();

      if (element.beginColumn != otElement.beginColumn) {
        return false;
      }

      if (element.beginLine != otElement.beginLine) {
        return false;
      }

      if (!element.getClass().equals(otElement.getClass())) {
        return false;
      }

      String rep1 = NodeUtils.getFullRepresentationString(element);
      String rep2 = NodeUtils.getFullRepresentationString(otElement);
      if (rep1 == null || rep2 == null) {
        if (rep1 != rep2) {
          return false;
        }

      } else if (!rep1.equals(rep2)) {
        return false;
      }
    }
    return true;
  }
Beispiel #3
0
  public boolean equals(Object obj) {

    MemoVisitor other = (MemoVisitor) obj;
    Iterator<SimpleNode> iter1 = other.visited.iterator();

    for (Iterator<SimpleNode> iter = visited.iterator(); iter.hasNext(); ) {
      SimpleNode n = (SimpleNode) iter.next();
      SimpleNode n1 = null;
      try {
        n1 = (SimpleNode) iter1.next();
      } catch (NoSuchElementException e) {
        throw new RuntimeException("Just received " + n, e);
      }

      if (n instanceof Expr && n1 instanceof Expr) {
        continue;
      }
      print(n.getClass());
      if (n.getClass().equals(n1.getClass()) == false) {
        print("n.getClass() != n1.getClass() " + n.getClass() + " != " + n1.getClass());
        return false;
      }
      //            if(n.beginColumn != n1.beginColumn){
      //                print("n = "+n+" n1 = "+n1);
      //                print("n = "+NodeUtils.getFullRepresentationString(n)+" n1 =
      // "+NodeUtils.getFullRepresentationString(n1));
      //                print("n.beginColumn != n1.beginColumn "+ n.beginColumn +" != "+
      // n1.beginColumn);
      //                return false;
      //            }
      //            if(n.beginLine != n1.beginLine){
      //                print("n.beginLine != n1.beginLine "+ n.beginLine +" != "+ n1.beginLine);
      //                return false;
      //            }

      String s1 = NodeUtils.getFullRepresentationString(n);
      String s2 = NodeUtils.getFullRepresentationString(n1);
      if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) {
        print("(s1 == null && s2 != null) || (s1 != null && s2 == null)");
        return false;
      }

      if (s1.equals(s2.replaceAll("\r", "")) == false) {
        print("s1 != s2 \n-->" + s1 + "<--\n!=\n-->" + s2 + "<--");
        return false;
      }
    }

    return true;
  }
  @Override
  public Object visitNameTok(NameTok node) throws Exception {
    if (node.ctx == NameTok.KeywordName) {
      if (this.line == node.beginLine) {
        String rep = NodeUtils.getRepresentationString(node);

        if (PySelection.isInside(col, node.beginColumn, rep.length())) {
          foundAsDefinition = true;
          // if it is found as a definition it is an 'exact' match, so, erase all the others.
          ILocalScope scope = new LocalScope(this.defsStack);
          for (Iterator<Definition> it = definitions.iterator(); it.hasNext(); ) {
            Definition d = it.next();
            if (!d.scope.equals(scope)) {
              it.remove();
            }
          }

          definitions.clear();

          definitionFound =
              new KeywordParameterDefinition(
                  line, node.beginColumn, rep, node, scope, module.get(), this.call.peek());
          definitions.add(definitionFound);
          throw new StopVisitingException();
        }
      }
    }
    return null;
  }
 @Override
 public Object visitGlobal(Global node) throws Exception {
   for (NameTokType n : node.names) {
     globalDeclarationsStack.peek().add(NodeUtils.getFullRepresentationString(n));
   }
   return null;
 }
 private IInfo addAssignTargets(
     ASTEntry entry, String moduleName, int doOn, String path, boolean lastIsMethod) {
   String rep = NodeUtils.getFullRepresentationString(entry.node);
   if (lastIsMethod) {
     List<String> parts = StringUtils.dotSplit(rep);
     if (parts.size() >= 2) {
       // at least 2 parts are required
       if (parts.get(0).equals("self")) {
         rep = parts.get(1);
         // no intern construct (locked in the loop that calls this method)
         AttrInfo info =
             new AttrInfo(
                 ObjectsPool.internUnsynched(rep),
                 moduleName,
                 ObjectsPool.internUnsynched(path),
                 false);
         add(info, doOn);
         return info;
       }
     }
   } else {
     // no intern construct (locked in the loop that calls this method)
     AttrInfo info =
         new AttrInfo(
             ObjectsPool.internUnsynched(FullRepIterable.getFirstPart(rep)),
             moduleName,
             ObjectsPool.internUnsynched(path),
             false);
     add(info, doOn);
     return info;
   }
   return null;
 }
Beispiel #7
0
  /**
   * Checks if some token is actually undefined and changes its representation if needed
   *
   * @return a tuple indicating if it really is undefined and the representation that should be
   *     used.
   */
  protected Tuple<Boolean, String> isActuallyUndefined(IToken token, String rep) {
    String tokenRepresentation = token.getRepresentation();
    if (tokenRepresentation != null) {
      String firstPart = FullRepIterable.getFirstPart(tokenRepresentation);
      if (this.prefs.getTokensAlwaysInGlobals().contains(firstPart)) {
        return new Tuple<Boolean, String>(
            false, firstPart); // ok firstPart in not really undefined...
      }
    }

    boolean isActuallyUndefined = true;
    if (rep == null) {
      rep = tokenRepresentation;
    }

    int i;
    if ((i = rep.indexOf('.')) != -1) {
      rep = rep.substring(0, i);
    }

    String builtinType = NodeUtils.getBuiltinType(rep);
    if (builtinType != null) {
      isActuallyUndefined = false; // this is a builtin, so, it is defined after all
    }
    return new Tuple<Boolean, String>(isActuallyUndefined, rep);
  }
Beispiel #8
0
 /**
  * @param ret the list where the representation should be added
  * @param expr the Name or Attribute that determines the class that should be added
  */
 private void addRepresentationIfPossible(ArrayList<String> ret, exprType expr) {
   if (expr instanceof Name || expr instanceof Attribute) {
     String string = NodeUtils.getFullRepresentationString(expr);
     if (string != null) {
       ret.add(string);
     }
   }
 }
  public void run(IAction action) {
    FastStringBuffer buf = new FastStringBuffer();
    try {
      PyEdit pyEdit = getPyEdit();

      PySelection pySelection = new PySelection(pyEdit);

      IPythonNature nature = pyEdit.getPythonNature();
      File editorFile = pyEdit.getEditorFile();

      if (editorFile != null) {
        if (nature != null) {
          String mod = nature.resolveModule(editorFile);
          if (mod != null) {
            buf.append(mod);

          } else {
            // Support for external files (not in PYTHONPATH).
            buf.append(FullRepIterable.getFirstPart(editorFile.getName()));
          }
        } else {
          buf.append(FullRepIterable.getFirstPart(editorFile.getName()));
        }
      }

      List<stmtType> path =
          FastParser.parseToKnowGloballyAccessiblePath(
              pySelection.getDoc(), pySelection.getStartLineIndex());
      for (stmtType stmtType : path) {
        if (buf.length() > 0) {
          buf.append('.');
        }
        buf.append(NodeUtils.getRepresentationString(stmtType));
      }

    } catch (MisconfigurationException e1) {
      Log.log(e1);
      return;
    }

    Transfer[] dataTypes = new Transfer[] {TextTransfer.getInstance()};
    Object[] data = new Object[] {buf.toString()};

    Clipboard clipboard = new Clipboard(EditorUtils.getShell().getDisplay());
    try {
      clipboard.setContents(data, dataTypes);
    } catch (SWTError e) {
      if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
        throw e;
      }
      MessageDialog.openError(
          EditorUtils.getShell(), "Error copying to clipboard.", e.getMessage());
    } finally {
      clipboard.dispose();
    }
  }
  /**
   * @param lastMayBeMethod if true, it gets the path and accepts a method (if it is the last in the
   *     stack) if false, null is returned if a method is found.
   * @param tempStack is a temporary stack object (which may be cleared)
   * @return a tuple, where the first element is the path where the entry is located (may return
   *     null). and the second element is a boolen that indicates if the last was actually a method
   *     or not.
   */
  private Tuple<String, Boolean> getPathToRoot(
      ASTEntry entry, boolean lastMayBeMethod, boolean acceptAny, FastStack<SimpleNode> tempStack) {
    if (entry.parent == null) {
      return null;
    }
    // just to be sure that it's empty
    tempStack.clear();

    boolean lastIsMethod = false;
    // if the last 'may be a method', in this case, we have to remember that it will actually be the
    // first one
    // to be analyzed.

    // let's get the stack
    while (entry.parent != null) {
      if (entry.parent.node instanceof ClassDef) {
        tempStack.push(entry.parent.node);

      } else if (entry.parent.node instanceof FunctionDef) {
        if (!acceptAny) {
          if (lastIsMethod) {
            // already found a method
            return null;
          }

          if (!lastMayBeMethod) {
            return null;
          }

          // ok, the last one may be a method... (in this search, it MUST be the first one...)
          if (tempStack.size() != 0) {
            return null;
          }
        }

        // ok, there was a class, so, let's go and set it
        tempStack.push(entry.parent.node);
        lastIsMethod = true;

      } else {
        return null;
      }
      entry = entry.parent;
    }

    // now that we have the stack, let's make it into a path...
    FastStringBuffer buf = new FastStringBuffer();
    while (tempStack.size() > 0) {
      if (buf.length() > 0) {
        buf.append(".");
      }
      buf.append(NodeUtils.getRepresentationString(tempStack.pop()));
    }
    return new Tuple<String, Boolean>(buf.toString(), lastIsMethod);
  }
Beispiel #11
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;
  }
 private IInfo addAssignTargets(
     ASTEntry entry, String moduleName, int doOn, String path, boolean lastIsMethod) {
   String rep = NodeUtils.getFullRepresentationString(entry.node);
   if (lastIsMethod) {
     List<String> parts = StringUtils.dotSplit(rep);
     if (parts.size() >= 2) {
       // at least 2 parts are required
       if (parts.get(0).equals("self")) {
         rep = parts.get(1);
         return addAttribute(rep, moduleName, doOn, path);
       }
     }
   } else {
     return addAttribute(FullRepIterable.getFirstPart(rep), moduleName, doOn, path);
   }
   return null;
 }
  /**
   * @param node the declaration node we're interested in (class or function)
   * @param name the token that represents the name of that declaration
   */
  private void checkDeclaration(SimpleNode node, NameTok name) {
    String rep = NodeUtils.getRepresentationString(node);
    if (rep.equals(tokenToFind)
        && line == name.beginLine
        && col >= name.beginColumn
        && col <= name.beginColumn + rep.length()) {
      foundAsDefinition = true;
      // if it is found as a definition it is an 'exact' match, so, erase all the others.
      ILocalScope scope = new LocalScope(this.defsStack);
      for (Iterator<Definition> it = definitions.iterator(); it.hasNext(); ) {
        Definition d = it.next();
        if (!d.scope.equals(scope)) {
          it.remove();
        }
      }

      definitionFound = new Definition(line, name.beginColumn, rep, node, scope, module.get());
      definitions.add(definitionFound);
    }
  }
Beispiel #14
0
  /** @see org.python.pydev.core.ILocalScope#getLocalTokens(int, int, boolean) */
  public IToken[] getLocalTokens(int endLine, int col, boolean onlyArgs) {
    Set<SourceToken> comps = new HashSet<SourceToken>();

    for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext(); ) {
      SimpleNode element = iter.next();

      stmtType[] body = null;
      if (element instanceof FunctionDef) {
        FunctionDef f = (FunctionDef) element;
        final argumentsType args = f.args;

        for (int i = 0; i < args.args.length; i++) {
          String s = NodeUtils.getRepresentationString(args.args[i]);
          comps.add(new SourceToken(args.args[i], s, "", "", "", IToken.TYPE_PARAM));
        }
        if (args.vararg != null) {
          String s = NodeUtils.getRepresentationString(args.vararg);
          comps.add(new SourceToken(args.vararg, s, "", "", "", IToken.TYPE_PARAM));
        }

        if (args.kwarg != null) {
          String s = NodeUtils.getRepresentationString(args.kwarg);
          comps.add(new SourceToken(args.kwarg, s, "", "", "", IToken.TYPE_PARAM));
        }
        if (args.kwonlyargs != null) {
          for (int i = 0; i < args.kwonlyargs.length; i++) {
            String s = NodeUtils.getRepresentationString(args.kwonlyargs[i]);
            comps.add(new SourceToken(args.kwonlyargs[i], s, "", "", "", IToken.TYPE_PARAM));
          }
        }

        if (onlyArgs) {
          continue;
        }
        body = f.body;
      } else if (element instanceof ClassDef && !iter.hasNext()) {
        ClassDef classDef = (ClassDef) element;
        body = classDef.body;
      }

      if (body != null) {
        try {
          for (int i = 0; i < body.length; i++) {
            GlobalModelVisitor visitor =
                new GlobalModelVisitor(GlobalModelVisitor.GLOBAL_TOKENS, "", false, true);
            stmtType stmt = body[i];
            if (stmt == null) {
              continue;
            }
            stmt.accept(visitor);
            List<IToken> t = visitor.tokens;
            for (Iterator<IToken> iterator = t.iterator(); iterator.hasNext(); ) {
              SourceToken tok = (SourceToken) iterator.next();

              // if it is found here, it is a local type
              tok.type = IToken.TYPE_LOCAL;
              if (tok.getAst().beginLine <= endLine) {
                comps.add(tok);
              }
            }
          }
        } catch (Exception e) {
          Log.log(e);
        }
      }
    }

    return comps.toArray(new SourceToken[0]);
  }
  /**
   * Decides which process should take care of the request.
   *
   * @param request
   */
  public static IRefactorRenameProcess getProcess(
      Definition definition, RefactoringRequest request) {
    if (definition instanceof AssignDefinition) {
      AssignDefinition d = (AssignDefinition) definition;
      if (d.target.indexOf('.') != -1) {
        if (d.target.startsWith("self.")) {
          // ok, it is a member and not a local
          return new PyRenameSelfAttributeProcess(definition, d.target);
        } else {
          return new PyRenameAttributeProcess(definition, d.target);
        }

      } else {
        if (definition.scope != null) {
          // classvar
          if (definition.scope.isLastClassDef()) {
            return new PyRenameAttributeProcess(definition, d.target);
          }
          FastStack scopeStack = definition.scope.getScopeStack();
          if (request.moduleName.equals(definition.module.getName())) {
            if (!scopeStack.empty()) {
              Object peek = scopeStack.peek();
              if (peek instanceof FunctionDef) {
                return new PyRenameLocalProcess(definition);
              }
            }
          }
        }
        return new PyRenameGlobalProcess(definition);
      }
    }
    if (definition.ast != null) {
      if (definition.ast instanceof ClassDef) {
        return new PyRenameClassProcess(definition);
      }

      if (definition.ast instanceof Name) {
        Name n = (Name) definition.ast;
        if (n.ctx == Name.Param || n.ctx == Attribute.KwOnlyParam) {
          return new PyRenameParameterProcess(definition);
        }
      }

      if (definition instanceof KeywordParameterDefinition) {
        return new PyRenameParameterProcess(
            (KeywordParameterDefinition) definition, request.nature);
      }

      if (definition.ast instanceof FunctionDef) {
        return new PyRenameFunctionProcess(definition);
      }
      if (NodeUtils.isImport(definition.ast)) {
        // this means that we found an import and we cannot actually map that import to a definition
        // (so, it is an unresolved import)
        return new PyRenameImportProcess(definition);
      }
    } else {
      // the definition ast is null. This should mean that it was actually an import
      // and pointed to some module
      return new PyRenameImportProcess(definition);
    }
    if (definition.scope != null) {
      // classvar
      if (definition.scope.isLastClassDef()) {
        return new PyRenameAttributeProcess(definition, definition.value);
      }

      FastStack scopeStack = definition.scope.getScopeStack();
      if (request.moduleName.equals(definition.module.getName())) {
        if (!scopeStack.empty()) {
          Object peek = scopeStack.peek();
          if (peek instanceof FunctionDef) {
            return new PyRenameLocalProcess(definition);
          }
        }
      }
    }
    return new PyRenameGlobalProcess(definition);
  }
  /**
   * Puts the found positions referente to the occurrences in the group
   *
   * @param document the document that will contain this positions
   * @param group the group that will contain this positions
   * @param ps the selection used
   * @return
   * @throws BadLocationException
   * @throws OperationCanceledException
   * @throws CoreException
   * @throws MisconfigurationException
   */
  private boolean fillWithOccurrences(
      IDocument document, LinkedPositionGroup group, IProgressMonitor monitor, PySelection ps)
      throws BadLocationException, OperationCanceledException, CoreException,
          MisconfigurationException {

    RefactoringRequest req =
        MarkOccurrencesJob.getRefactoringRequest(
            pyEdit, MarkOccurrencesJob.getRefactorAction(pyEdit), ps);
    if (monitor.isCanceled()) {
      return false;
    }

    PyRenameEntryPoint processor = new PyRenameEntryPoint(req);

    // process it to get what we need
    processor.checkInitialConditions(monitor);
    processor.checkFinalConditions(monitor, null);
    HashSet<ASTEntry> occurrences = processor.getOccurrences();

    if (monitor.isCanceled()) {
      return false;
    }

    // used so that we don't add duplicates
    Set<Tuple<Integer, Integer>> found = new HashSet<Tuple<Integer, Integer>>();
    List<ProposalPosition> groupPositions = new ArrayList<ProposalPosition>();

    if (occurrences != null) {

      // first, just sort by position (line, col)
      ArrayList<ASTEntry> sortedOccurrences = new ArrayList<ASTEntry>(occurrences);
      Collections.sort(
          sortedOccurrences,
          new Comparator<ASTEntry>() {

            public int compare(ASTEntry o1, ASTEntry o2) {
              int thisVal = o1.node.beginLine;
              int anotherVal = o2.node.beginLine;
              int ret;
              if (thisVal == anotherVal) { // if it's in the same line, let's sort by column
                thisVal = o1.node.beginColumn;
                anotherVal = o2.node.beginColumn;
                ret = (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
              } else {
                ret = (thisVal < anotherVal ? -1 : 1);
              }
              return ret;
            }
          });

      // now, gather positions to add to the group

      int i = 0;
      int firstPosition = -1;
      int absoluteCursorOffset = ps.getAbsoluteCursorOffset();

      for (ASTEntry entry : sortedOccurrences) {
        try {
          IRegion lineInformation = document.getLineInformation(entry.node.beginLine - 1);
          int colDef = NodeUtils.getClassOrFuncColDefinition(entry.node) - 1;

          int offset = lineInformation.getOffset() + colDef;
          int len = req.initialName.length();
          Tuple<Integer, Integer> foundAt = new Tuple<Integer, Integer>(offset, len);

          if (!found.contains(foundAt)) {
            i++;
            ProposalPosition proposalPosition =
                new ProposalPosition(document, offset, len, i, new ICompletionProposal[0]);
            found.add(foundAt);
            groupPositions.add(proposalPosition);
            if (offset <= absoluteCursorOffset && absoluteCursorOffset < offset + len) {
              firstPosition = i;
            }
          }
        } catch (Exception e) {
          Log.log(e);
          return false;
        }
      }

      if (firstPosition != -1) {
        ArrayList<ProposalPosition> newGroupPositions = new ArrayList<ProposalPosition>();

        // add from current to end
        for (i = firstPosition - 1; i < groupPositions.size(); i++) {
          newGroupPositions.add(groupPositions.get(i));
        }
        // and now from the start up to the current
        for (i = 0; i < firstPosition - 1; i++) {
          newGroupPositions.add(groupPositions.get(i));
        }

        groupPositions = newGroupPositions;
      }

      for (ProposalPosition proposalPosition : groupPositions) {
        group.addPosition(proposalPosition);
      }
    }
    return groupPositions.size() > 0;
  }
  /**
   * @see
   *     org.python.pydev.parser.jython.ast.VisitorBase#visitAssign(org.python.pydev.parser.jython.ast.Assign)
   */
  public Object visitAssign(Assign node) throws Exception {
    ILocalScope scope = new LocalScope(this.defsStack);
    if (foundAsDefinition
        && !scope.equals(
            definitionFound
                .scope)) { // if it is found as a definition it is an 'exact' match, so, we do not
                           // keep checking it
      return null;
    }

    for (int i = 0; i < node.targets.length; i++) {
      exprType target = node.targets[i];
      if (target instanceof Subscript) {
        continue; // assigning to an element and not the variable itself. E.g.: mydict[1] = 10
                  // (instead of mydict = 10)
      }

      if (target instanceof Tuple) {
        // if assign is xxx, yyy = 1, 2
        // let's separate those as different assigns and analyze one by one
        Tuple targetTuple = (Tuple) target;
        if (node.value instanceof Tuple) {
          Tuple valueTuple = (Tuple) node.value;
          checkTupleAssignTarget(targetTuple, valueTuple.elts);

        } else if (node.value instanceof org.python.pydev.parser.jython.ast.List) {
          org.python.pydev.parser.jython.ast.List valueList =
              (org.python.pydev.parser.jython.ast.List) node.value;
          checkTupleAssignTarget(targetTuple, valueList.elts);

        } else {
          checkTupleAssignTarget(targetTuple, new exprType[] {node.value});
        }

      } else {
        String rep = NodeUtils.getFullRepresentationString(target);

        if (tokenToFind.equals(
            rep)) { // note, order of equals is important (because one side may be null).
          exprType nodeValue = node.value;
          String value = NodeUtils.getFullRepresentationString(nodeValue);
          if (value == null) {
            value = "";
          }

          // get the line and column correspondent to the target
          int line = NodeUtils.getLineDefinition(target);
          int col = NodeUtils.getColDefinition(target);

          AssignDefinition definition =
              new AssignDefinition(value, rep, i, node, line, col, scope, module.get());

          // mark it as global (if it was found as global in some of the previous contexts).
          for (Set<String> globals : globalDeclarationsStack) {
            if (globals.contains(rep)) {
              definition.foundAsGlobal = true;
            }
          }

          definitions.add(definition);
        }
      }
    }

    return null;
  }
Beispiel #18
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;
    }
  }
Beispiel #20
0
  /**
   * @return the function name for this breakpoint.
   *     <p>A return of "None" signals that we couldn't discover the function name (so, we should
   *     try to match things in the whole file, and not only in the given context, as we don't know
   *     which context it is)
   */
  public String getFunctionName() {
    String fileStr = getFile();
    File file = fileStr != null ? new File(fileStr) : null;
    if (file == null || !file.exists()) {
      return "None";
    }

    if (file.lastModified() == lastModifiedTimeCached) {
      return functionName;
    }

    try {
      IPythonNature nature = getPythonNature();
      if (nature == null) {
        lastModifiedTimeCached = 0;
        return "None";
      }
      ICodeCompletionASTManager astManager = nature.getAstManager();
      if (astManager == null) {
        lastModifiedTimeCached = 0;
        return "None";
      }
      // Only mark it as found if we were able to get the python nature (otherwise, this could
      // change later
      // if requesting during a setup)
      if (nature.startRequests()) { // start requests, as we'll ask for resolve and get module.
        SourceModule sourceModule = null;
        try {
          String modName = nature.resolveModule(fileStr);
          if (modName != null) {
            // when all is set up, this is the most likely path we're going to use
            // so, we shouldn't have delays when the module is changed, as it's already
            // ok for use.
            IModule module = astManager.getModule(modName, nature, true);
            if (module instanceof SourceModule) {
              sourceModule = (SourceModule) module;
            }
          }
        } finally {
          nature.endRequests();
        }
        lastModifiedTimeCached = file.lastModified();

        if (sourceModule == null) {
          // the text for the breakpoint requires the function name, and it may be requested before
          // the ast manager is actually restored (so, modName is None, and we have little
          // alternative
          // but making a parse to get the function name)
          IDocument doc = getDocument();
          sourceModule = AbstractModule.createModuleFromDoc("", null, doc, nature, true);
        }

        int lineToUse = getLineNumber() - 1;

        if (sourceModule == null || sourceModule.getAst() == null || lineToUse < 0) {
          functionName = "None";
          return functionName;
        }

        SimpleNode ast = sourceModule.getAst();

        functionName = NodeUtils.getContextName(lineToUse, ast);
        if (functionName == null) {
          functionName = ""; // global context
        }
        return functionName;
      }
      // If it was found, it would've already returned. So, match anything as we couldn't determine
      // it.
      functionName = "None";

    } catch (Exception e) {
      // Some error happened determining it. Match anything.
      Log.log(
          "Error determining breakpoint context. Breakpoint at: "
              + file
              + " will match any context.",
          e);
      functionName = "None";
    }
    return functionName;
  }
Beispiel #21
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);
          }
        }
      }
    }
  }
Beispiel #22
0
  public Collection<IToken> getInterfaceForLocal(
      String activationToken, boolean addAttributeAccess, boolean addLocalsFromHasAttr) {
    Set<SourceToken> comps = new HashSet<SourceToken>();

    Iterator<SimpleNode> it = this.scope.topDownIterator();
    if (!it.hasNext()) {
      return new ArrayList<IToken>();
    }

    SimpleNode element = it.next();

    String dottedActTok = activationToken + '.';
    // ok, that's the scope we have to analyze
    SequencialASTIteratorVisitor visitor = SequencialASTIteratorVisitor.create(element);

    ArrayList<Class> classes = new ArrayList<Class>(2);
    if (addAttributeAccess) {
      classes.add(Attribute.class);
    }
    if (addLocalsFromHasAttr) {
      classes.add(Call.class);
    }
    Iterator<ASTEntry> iterator = visitor.getIterator(classes.toArray(new Class[classes.size()]));

    while (iterator.hasNext()) {
      ASTEntry entry = iterator.next();
      if (entry.node instanceof Attribute) {
        String rep = NodeUtils.getFullRepresentationString(entry.node);
        if (rep.startsWith(dottedActTok)) {
          rep = rep.substring(dottedActTok.length());
          if (NodeUtils.isValidNameRepresentation(
              rep)) { // that'd be something that can happen when trying to recreate the parsing
            comps.add(
                new SourceToken(
                    entry.node,
                    FullRepIterable.getFirstPart(rep),
                    "",
                    "",
                    "",
                    IToken.TYPE_OBJECT_FOUND_INTERFACE));
          }
        }
      } else if (entry.node instanceof Call) {
        Call call = (Call) entry.node;
        if ("hasattr".equals(NodeUtils.getFullRepresentationString(call.func))
            && call.args != null
            && call.args.length == 2) {
          String rep = NodeUtils.getFullRepresentationString(call.args[0]);
          if (rep.equals(activationToken)) {
            exprType node = call.args[1];
            if (node instanceof Str) {
              Str str = (Str) node;
              String attrName = str.s;
              if (NodeUtils.isValidNameRepresentation(attrName)) {
                comps.add(
                    new SourceToken(
                        node, attrName, "", "", "", IToken.TYPE_OBJECT_FOUND_INTERFACE));
              }
            }
          }
        }
      }
    }
    return new ArrayList<IToken>(comps);
  }
Beispiel #23
-1
  /**
   * Called after the creation of any module. Used as a workaround for filling tokens that are in no
   * way available in the code-completion through the regular inspection.
   *
   * <p>The django objects class is the reason why this happens... It's structure for the creation
   * on a model class follows no real patterns for the creation of the 'objects' attribute in the
   * class, and thus, we have no real generic way of discovering it (actually, even by looking at
   * the class definition this is very obscure), so, the solution found is creating the objects by
   * decorating the module with that info.
   */
  private AbstractModule decorateModule(AbstractModule n, IPythonNature nature) {
    if (n instanceof SourceModule && "django.db.models.base".equals(n.getName())) {
      SourceModule sourceModule = (SourceModule) n;
      SimpleNode ast = sourceModule.getAst();
      for (SimpleNode node : ((Module) ast).body) {
        if (node instanceof ClassDef && "Model".equals(NodeUtils.getRepresentationString(node))) {
          Object[][] metaclassAttrs =
              new Object[][] {
                {"objects", NodeUtils.makeAttribute("django.db.models.manager.Manager()")},
                {"DoesNotExist", new Name("Exception", Name.Load, false)},
                {"MultipleObjectsReturned", new Name("Exception", Name.Load, false)},
              };

          ClassDef classDef = (ClassDef) node;
          stmtType[] newBody = new stmtType[classDef.body.length + metaclassAttrs.length];
          System.arraycopy(classDef.body, 0, newBody, metaclassAttrs.length, classDef.body.length);

          int i = 0;
          for (Object[] objAndType : metaclassAttrs) {
            // Note that the line/col is important so that we correctly acknowledge it inside the
            // "class Model" scope.
            Name name = new Name((String) objAndType[0], Name.Store, false);
            name.beginColumn = classDef.beginColumn + 4;
            name.beginLine = classDef.beginLine + 1;
            newBody[i] = new Assign(new exprType[] {name}, (exprType) objAndType[1]);
            newBody[i].beginColumn = classDef.beginColumn + 4;
            newBody[i].beginLine = classDef.beginLine + 1;

            i += 1;
          }

          classDef.body = newBody;
          break;
        }
      }
    }
    return n;
  }