@SuppressWarnings("unchecked")
  protected static StatementSequence findEnclosingStatementSequence(
      IFortranAST ast, ITextSelection selection) {
    Token firstToken = findFirstTokenAfter(ast, selection.getOffset());
    Token lastToken = findLastTokenBefore(ast, selection.getOffset() + selection.getLength());
    if (firstToken == null || lastToken == null) return null;

    IASTListNode<? extends IASTNode> listContainingFirstToken =
        firstToken.findNearestAncestor(IASTListNode.class);
    IASTListNode<? extends IASTNode> listContainingLastToken =
        lastToken.findNearestAncestor(IASTListNode.class);
    if (listContainingFirstToken == null
        || listContainingLastToken == null
        || listContainingFirstToken != listContainingLastToken) return null;

    IASTListNode<? extends IASTNode> listContainingStmts = listContainingFirstToken;
    int startIndex = -1;
    int endIndex = -1;
    for (int i = 0; i < listContainingStmts.size(); i++) {
      IASTNode node = listContainingStmts.get(i);
      if (contains(node, firstToken)) startIndex = i;
      if (contains(node, lastToken)) endIndex = i;
    }
    if (startIndex < 0 || endIndex < 0 || endIndex < startIndex)
      throw new Error(
          "INTERNAL ERROR: Unable to locate selected statements in IASTListNode"); //$NON-NLS-1$

    return new StatementSequence(
        listContainingStmts.findNearestAncestor(ScopingNode.class),
        listContainingStmts,
        startIndex,
        endIndex);
  }
 private static Token findLastTokenBefore(IFortranAST ast, final int targetFileOffset) {
   Token previousToken = null;
   for (Token token : new IterableWrapper<Token>(ast)) {
     if (token.isOnOrAfterFileOffset(targetFileOffset)) return previousToken;
     else previousToken = token;
   }
   return null;
 }
 protected static <T extends IASTNode> T getNode(
     Token firstToken, Token lastToken, Class<T> node) {
   assert (firstToken != null);
   assert (lastToken != null);
   T firstTokenNode = firstToken.findNearestAncestor(node);
   T lastTokenNode = lastToken.findNearestAncestor(node);
   if (firstTokenNode == null || lastTokenNode == null || firstTokenNode != lastTokenNode)
     return null;
   return firstTokenNode;
   // return null;
 }
  protected static IASTNode findEnclosingNode(IFortranAST ast, ITextSelection selection) {
    Token firstToken = findFirstTokenAfter(ast, selection.getOffset());
    Token lastToken =
        findLastTokenBefore(
            ast, OffsetLength.getPositionPastEnd(selection.getOffset(), selection.getLength()));
    if (firstToken == null || lastToken == null) return null;

    for (IASTNode parent = lastToken.getParent(); parent != null; parent = parent.getParent())
      if (contains(parent, firstToken)) return parent;

    return null;
  }
  protected static Definition findUnambiguousDeclaration(Token t) {
    if (t == null) return null;

    List<Definition> defs = t.resolveBinding();
    if (defs.size() <= 0 || defs.size() > 1) return null;
    return defs.get(0);
  }
 protected static Token findEnclosingToken(IFortranAST ast, final ITextSelection selection) {
   Token prevToken = null;
   for (Token token : new IterableWrapper<Token>(ast)) {
     if (OffsetLength.contains(
         token.getFileOffset(), token.getLength(),
         selection.getOffset(), selection.getLength())) {
       String tokenText = token.getText();
       // If we get whitespace, that means we want the previous token (cursor was put AFTER
       // the identifier we want to rename
       if (tokenText.length() == 1 && Character.isWhitespace(tokenText.charAt(0))) {
         return prevToken;
       } else return token;
     }
     prevToken = token;
   }
   return null;
 }
  private Set<ASTCallStmtNode> getCallSites() {
    List<Definition> subroutineDefinitions =
        selectedSubroutine.getSubroutineName().getSubroutineName().resolveBinding();
    HashSet<ASTCallStmtNode> result = new HashSet<ASTCallStmtNode>();

    if (subroutineDefinitions.size() != 1)
      return result; // probably should throw an error of some sort!

    for (PhotranTokenRef tokenRef : subroutineDefinitions.get(0).findAllReferences(true)) {
      Token token = tokenRef.findToken();

      ASTCallStmtNode callStmtNode = token.findNearestAncestor(ASTCallStmtNode.class);

      if (callStmtNode != null) result.add(callStmtNode);
    }

    return result;
  }
    private void checkIfReferenceBindingWillChange(
        IConflictingBindingCallback callback,
        PhotranTokenRef ref,
        boolean shouldReferenceRenamedDefinition) {
      pm.subTask(
          Messages.bind(
              Messages.FortranResourceRefactoring_CheckingForBindingConflictsIn,
              PhotranVPG.lastSegmentOfFilename(ref.getFilename())));

      Token reference = ref.findToken();

      if (definitionToCheck != null) {
        ScopingNode scopeOfDefinitionToRename =
            reference.findScopeDeclaringOrImporting(definitionToCheck);
        if (scopeOfDefinitionToRename == null) return;

        for (String newName : newNames) {
          for (PhotranTokenRef existingBinding :
              new FakeToken(reference, newName).manuallyResolveBinding()) {
            ScopingNode scopeOfExistingBinding = existingBinding.findToken().getEnclosingScope();

            boolean willReferenceRenamedDefinition =
                scopeOfExistingBinding.isParentScopeOf(scopeOfDefinitionToRename);
            if (shouldReferenceRenamedDefinition != willReferenceRenamedDefinition)
              callback.addReferenceWillChangeError(newName, reference);
          }
        }
      } else {
        if (scopeOfDefinitionToCheck == reference.getLocalScope()
            || scopeOfDefinitionToCheck.isParentScopeOf(reference.getLocalScope())) {
          for (String newName : newNames) {
            for (PhotranTokenRef existingBinding :
                new FakeToken(reference, newName).manuallyResolveBinding()) {
              ScopingNode scopeOfExistingBinding = existingBinding.findToken().getEnclosingScope();

              boolean willReferenceRenamedDefinition =
                  scopeOfExistingBinding.isParentScopeOf(scopeOfDefinitionToCheck);
              if (shouldReferenceRenamedDefinition != willReferenceRenamedDefinition)
                callback.addReferenceWillChangeError(newName, reference);
            }
          }
        }
      }
    }
 private ASTSubroutineArgNode getActualArgFromCallStmt(
     ASTCallStmtNode callStmt, Token desiredParName, int desiredParIndex) {
   for (int i = 0; i < callStmt.getArgList().size(); i++) {
     ASTSubroutineArgNode argument = callStmt.getArgList().get(i);
     if (argument.getName() == null || desiredParName == null) {
       if (i == desiredParIndex) return argument;
     } else {
       String argumentName = PhotranVPG.canonicalizeIdentifier(argument.getName().getText());
       String parameterName = PhotranVPG.canonicalizeIdentifier(desiredParName.getText());
       if (argumentName.equals(parameterName)) return argument;
     }
   }
   return null;
 }
  protected void swapComments() {
    Token outerLoopDoToken = outerLoop.getLoopHeader().findFirstToken();
    Token innerLoopDoToken = innerLoop.getLoopHeader().findFirstToken();

    String outerLoopWhiteText = outerLoopDoToken.getWhiteBefore();
    String innerLoopWhiteText = innerLoopDoToken.getWhiteBefore();

    innerLoopDoToken.setWhiteBefore(outerLoopWhiteText);
    outerLoopDoToken.setWhiteBefore(innerLoopWhiteText);
  }
 public void setEndName(org.eclipse.photran.internal.core.lexer.Token newValue) {
   this.endName = newValue;
   if (newValue != null) newValue.setParent(this);
 }
 public void setLabel(org.eclipse.photran.internal.core.lexer.Token newValue) {
   this.label = newValue;
   if (newValue != null) newValue.setParent(this);
 }
 public void setImpliedDoVariable(org.eclipse.photran.internal.core.lexer.Token newValue) {
   this.impliedDoVariable = newValue;
   if (newValue != null) newValue.setParent(this);
 }
 protected static boolean isUniquelyDefinedIdentifer(Token t) {
   return isBoundIdentifier(t) && t.resolveBinding().size() == 1;
 }
 protected static boolean isBoundIdentifier(Token t) {
   return isIdentifier(t) && !t.resolveBinding().isEmpty();
 }
 protected static String describeToken(Token token) {
   return "\"" + token.getText() + "\" " + describeTokenPos(token); // $NON-NLS-1$ //$NON-NLS-2$
 }
 protected static boolean isIdentifier(Token token) {
   return token != null && token.getTerminal() == Terminal.T_IDENT;
 }
 /**
  * @return the whitespace preceding the given token. Note that {@link Token#getWhiteBefore()} may
  *     return comments and line continuations, while this method only returns everything
  *     <i>following</i> the last <tt>\n</tt> (if any), so those will be omitted.
  */
 protected String extractWhitespacePreceding(Token token) {
   String result = token.getWhiteBefore();
   return result.substring(result.lastIndexOf('\n') + 1);
 }
 public void setBlockDataToken(org.eclipse.photran.internal.core.lexer.Token newValue) {
   this.blockDataToken = newValue;
   if (newValue != null) newValue.setParent(this);
 }
 protected RefactoringStatusContext createContext(Token token) {
   return createContext(token.getTokenRef());
 }
 private static Token findFirstTokenAfter(IFortranAST ast, final int targetFileOffset) {
   for (Token token : new IterableWrapper<Token>(ast))
     if (token.isOnOrAfterFileOffset(targetFileOffset)) return token;
   return null;
 }
 private static boolean contains(IASTNode target, Token token) {
   for (IASTNode node = token.getParent(); node != null; node = node.getParent())
     if (node == target) return true;
   return false;
 }
 protected static boolean isPreprocessed(Token token) {
   return token.getPreprocessorDirective() != null;
 }
 protected static String describeTokenPos(Token token) {
   return Messages.bind(
       Messages.FortranResourceRefactoring_LineColumn, token.getLine(), token.getCol());
 }