/**
     * Check whether the new definition will either conflict with or shadow an existing definition
     */
    private List<PhotranTokenRef> findReferencesToShadowedDefinitions() {
      List<PhotranTokenRef> referencesToShadowedDefinitions = new LinkedList<PhotranTokenRef>();

      for (String newName : newNames) {
        Token token =
            definitionToCheck == null
                ? new FakeToken(scopeOfDefinitionToCheck, newName)
                : new FakeToken(definitionToCheck.getTokenRef().findToken(), newName);

        List<PhotranTokenRef> shadowedDefinitions = scopeOfDefinitionToCheck.manuallyResolve(token);
        // TODO: Does not consider rename or only lists (need to tell if this SPECIFIC definition
        // will be imported)
        for (ScopingNode importingScope : scopeOfDefinitionToCheck.findImportingScopes()) {
          pm.subTask(
              Messages.bind(
                  Messages.FortranResourceRefactoring_CheckingForReferencesTo,
                  newName,
                  importingScope.describe()));
          shadowedDefinitions.addAll(importingScope.manuallyResolve(token));
        }

        for (PhotranTokenRef def : shadowedDefinitions) {
          Definition definition = PhotranVPG.getInstance().getDefinitionFor(def);
          if (definition != null)
            referencesToShadowedDefinitions.addAll(definition.findAllReferences(false));
        }
      }

      return referencesToShadowedDefinitions;
    }
    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 List<Conflict> findAllPotentiallyConflictingUnboundSubprogramCalls() {
      final List<Conflict> conflictingDef = new ArrayList<Conflict>();

      for (ScopingNode importingScope :
          scopeItselfAndAllScopesThatImport(scopeOfDefinitionToCheck)) {
        pm.subTask(
            Messages.bind(
                Messages.FortranResourceRefactoring_CheckingForSubprogramBindingConflictsIn,
                importingScope.describe()));

        importingScope.accept(
            new GenericASTVisitor() {
              @Override
              public void visitASTVarOrFnRefNode(ASTVarOrFnRefNode node) {
                if (node.getName() != null && node.getName().getName() != null)
                  checkForConflict(node.getName().getName());
              }

              @Override
              public void visitASTCallStmtNode(ASTCallStmtNode node) {
                if (node.getSubroutineName() != null) checkForConflict(node.getSubroutineName());
              }

              private void checkForConflict(Token name) {
                if (name.getLogicalFile() != null)
                  for (String newName : newNames)
                    if (name != null
                        && name.getText().equals(newName)
                        && name.resolveBinding().isEmpty())
                      conflictingDef.add(new Conflict(newName, name.getTokenRef()));
              }
            });
      }

      return conflictingDef;
    }
    private List<Conflict> findAllPotentiallyConflictingDefinitions() {
      List<Conflict> conflicts = new ArrayList<Conflict>();

      if (definitionToCheck != null) {
        // Cannot call a main program (or function, etc.) X if it has an internal subprogram named
        // X,
        // even if that subprogram is never used (in which case it wouldn't be caught below)
        if (definitionToCheck.isMainProgram()
            || definitionToCheck.isSubprogram()
            || definitionToCheck.isModule()) {
          findAllPotentiallyConflictingDefinitionsInScope(
              conflicts,
              definitionToCheck.getTokenRef().findToken().findNearestAncestor(ScopingNode.class),
              false);
        }
        for (String newName : newNames) {
          if (definitionToCheck.isInternalSubprogramDefinition()
              && scopeContainingInternalSubprogram().isNamed(newName)) {
            conflicts.add(
                new Conflict(
                    newName, scopeContainingInternalSubprogram().getNameToken().getTokenRef()));
          }
        }
      }

      for (ScopingNode importingScope :
          scopeItselfAndAllScopesThatImport(scopeOfDefinitionToCheck)) {
        pm.subTask(
            Messages.bind(
                Messages.FortranResourceRefactoring_CheckingForConflictingDefinitionsIn,
                importingScope.describe()));
        findAllPotentiallyConflictingDefinitionsInScope(conflicts, importingScope, true);
      }

      return conflicts;
    }
 protected ASTImplicitStmtNode findExistingImplicitStatement(final ScopingNode scope) {
   try {
     scope.accept(
         new GenericASTVisitor() {
           @Override
           public void visitASTImplicitStmtNode(ASTImplicitStmtNode node) {
             if (node.getImplicitToken().getEnclosingScope() == scope)
               throw new Notification(node);
           }
         });
   } catch (Notification n) {
     return (ASTImplicitStmtNode) n.getResult();
   }
   return null;
 }
    /**
     * Cannot call a function X if it is defined in or imported into a scope with a function X
     * already defined
     *
     * <p>The third parameter indicates whether or not we should check that the definition to check
     * is actually imported into the target scope (it may not be if there is a USE statement with a
     * Rename or ONLY list).
     */
    private void findAllPotentiallyConflictingDefinitionsInScope(
        List<Conflict> conflicts,
        ScopingNode importingScope,
        boolean shouldCheckIfDefinitionImportedIntoScope) {
      for (String newName : newNames) {
        List<PhotranTokenRef> definitionsLocalToScope = collectLocalDefinitions(importingScope);

        if (isProgramOrSubprogramOrModuleScope(importingScope)
            && shouldCheckIfDefinitionImportedIntoScope) {
          // Cannot call a variable X inside a function named X
          if (importingScope.isNamed(newName)) {
            if (definitionToCheck == null
                || definitionsLocalToScope.contains(definitionToCheck.getTokenRef())) {
              conflicts.add(new Conflict(newName, importingScope.getNameToken().getTokenRef()));
            }
          }
          // Cannot call a variable X inside a function named Y inside a module named X
          else {
            ScopingNode parent = importingScope.findNearestAncestor(ScopingNode.class);
            if (parent != null && parent.isNamed(newName)) {
              List<PhotranTokenRef> definitionsLocalToParent = collectLocalDefinitions(parent);
              if (definitionToCheck == null
                  || definitionsLocalToParent.contains(definitionToCheck.getTokenRef())) {
                conflicts.add(new Conflict(newName, parent.getNameToken().getTokenRef()));
              }
            }
          }
        }

        // Cannot call a function X if it is defined in or imported into a scope with a function X
        // already defined
        Token newNameToken =
            definitionToCheck == null
                ? new FakeToken(scopeOfDefinitionToCheck, newName)
                : new FakeToken(definitionToCheck.getTokenRef().findToken(), newName);
        for (PhotranTokenRef conflict : importingScope.manuallyResolveInLocalScope(newNameToken)) {
          if (definitionsLocalToScope.contains(conflict)) {
            if (shouldCheckIfDefinitionImportedIntoScope) {
              if (definitionToCheck == null
                  || definitionsLocalToScope.contains(definitionToCheck.getTokenRef())) {
                conflicts.add(new Conflict(newName, conflict));
              }
            } else {
              conflicts.add(new Conflict(newName, conflict));
            }
          }
        }
      }
    }
 private List<PhotranTokenRef> collectLocalDefinitions(ScopingNode importingScope) {
   List<PhotranTokenRef> definitionsLocalToScope = new ArrayList<PhotranTokenRef>();
   for (Definition def : importingScope.getAllDefinitions())
     if (def != null && !def.isIntrinsic()) definitionsLocalToScope.add(def.getTokenRef());
   return definitionsLocalToScope;
 }