/** * 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; }