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;
 }
  /**
   * Adds ast info information for a module.
   *
   * @param m the module we want to add to the info
   */
  public List<IInfo> addAstInfo(SimpleNode node, ModulesKey key, boolean generateDelta) {
    List<IInfo> createdInfos = new ArrayList<IInfo>();
    if (node == null || key.name == null) {
      return createdInfos;
    }
    try {
      Tuple<DefinitionsASTIteratorVisitor, Iterator<ASTEntry>> tup = getInnerEntriesForAST(node);
      if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
        Log.toLogFile(this, "Adding ast info to: " + key.name);
      }

      try {
        Iterator<ASTEntry> entries = tup.o2;

        FastStack<SimpleNode> tempStack = new FastStack<SimpleNode>(10);

        synchronized (this.lock) {
          synchronized (ObjectsPool.lock) {
            key.name = ObjectsPool.internUnsynched(key.name);

            while (entries.hasNext()) {
              ASTEntry entry = entries.next();
              IInfo infoCreated = null;

              if (entry.parent == null) { // we only want those that are in the global scope
                if (entry.node instanceof ClassDef) {
                  // no intern construct (locked in this loop)
                  ClassInfo info =
                      new ClassInfo(
                          ObjectsPool.internUnsynched(((NameTok) ((ClassDef) entry.node).name).id),
                          key.name,
                          null,
                          false);
                  add(info, TOP_LEVEL);
                  infoCreated = info;

                } else if (entry.node instanceof FunctionDef) {
                  // no intern construct (locked in this loop)
                  FuncInfo info2 =
                      new FuncInfo(
                          ObjectsPool.internUnsynched(
                              ((NameTok) ((FunctionDef) entry.node).name).id),
                          key.name,
                          null,
                          false);
                  add(info2, TOP_LEVEL);
                  infoCreated = info2;

                } else {
                  // it is an assign
                  infoCreated = this.addAssignTargets(entry, key.name, TOP_LEVEL, null, false);
                }
              } else {
                if (entry.node instanceof ClassDef || entry.node instanceof FunctionDef) {
                  // ok, it has a parent, so, let's check to see if the path we got only has class
                  // definitions
                  // as the parent (and get that path)
                  Tuple<String, Boolean> pathToRoot =
                      this.getPathToRoot(entry, false, false, tempStack);
                  if (pathToRoot != null && pathToRoot.o1 != null && pathToRoot.o1.length() > 0) {
                    // if the root is not valid, it is not only classes in the path (could be a
                    // method inside
                    // a method, or something similar).

                    if (entry.node instanceof ClassDef) {
                      ClassInfo info =
                          new ClassInfo(
                              ObjectsPool.internUnsynched(
                                  ((NameTok) ((ClassDef) entry.node).name).id),
                              key.name,
                              ObjectsPool.internUnsynched(pathToRoot.o1),
                              false);
                      add(info, INNER);
                      infoCreated = info;

                    } else {
                      // FunctionDef
                      FuncInfo info2 =
                          new FuncInfo(
                              ObjectsPool.internUnsynched(
                                  ((NameTok) ((FunctionDef) entry.node).name).id),
                              key.name,
                              ObjectsPool.internUnsynched(pathToRoot.o1),
                              false);
                      add(info2, INNER);
                      infoCreated = info2;
                    }
                  }
                } else {
                  // it is an assign
                  Tuple<String, Boolean> pathToRoot =
                      this.getPathToRoot(entry, true, false, tempStack);
                  if (pathToRoot != null && pathToRoot.o1 != null && pathToRoot.o1.length() > 0) {
                    infoCreated =
                        this.addAssignTargets(entry, key.name, INNER, pathToRoot.o1, pathToRoot.o2);
                  }
                }
              }

              if (infoCreated != null) {
                createdInfos.add(infoCreated);
              }
            } // end while
          } // end lock ObjectsPool.lock
        } // end this.lock

      } catch (Exception e) {
        Log.log(e);
      }
    } catch (Exception e) {
      Log.log(e);
    }
    return createdInfos;
  }