String codeString = new String(codeText);
String updatedCodeString = codeString;
// Load the qualification map
Element qualificationMapElement = XMLPersistenceHelper.getChildElement(codeElement, CodeQualificationMap.QUALIFICATION_MAP_TAG);
CodeQualificationMap qualificationMap = new CodeQualificationMap();
if (qualificationMapElement != null) {
qualificationMap.loadFromXML(codeElement);
}
if (category != SourceIdentifier.Category.MODULE_NAME) {
QualifiedName qualificationMapEntry = qualificationMap.getQualifiedName(oldName.getUnqualifiedName(), category);
if (oldName.equals(qualificationMapEntry)) {
// The old name is in the qualification map. This means there might be an unqualified reference to the symbol that when
// renamed might clash with one of the arguments. Let's check for that now.
// First, load the arguments
Element argsElement = (childElems.size() < 4) ? null : (Element) childElems.get(3);
XMLPersistenceHelper.checkIsElement(argsElement);
XMLPersistenceHelper.checkTag(argsElement, GemPersistenceConstants.CODE_GEM_ARGUMENTS_TAG);
// We'll create both a list (for easy iteration) and a set (for easy membership checks).
List<Element> argNodes = XMLPersistenceHelper.getChildElements(argsElement, GemPersistenceConstants.CODE_GEM_ARGUMENT_TAG);
int numArgs = argNodes.size();
String[] argNames = new String[numArgs];
for (int i = 0; i < numArgs; i++) {
Element argNode = argNodes.get(i);
argNames[i] = argNode.getAttribute(GemPersistenceConstants.CODE_GEM_ARGUMENT_NAME_ATTR);
}
List<String> argNamesList = Arrays.asList(argNames);
Set<String> argNamesSet = new HashSet<String>(argNamesList);
// Next, loop over the arguments and look for the conflict..
for (int i = 0, n = argNamesList.size(); i < n; i++) {
String argName = argNamesList.get(i);
if (argName.equals(newName.getUnqualifiedName())) {
// Here we are. The new name is going to collide with this argument's name.
// We are going to have to rename this argument.
QualifiedName oldArgName = QualifiedName.make(moduleName, argName);
// Figure out a suitable new name for the argument that does not conflict with anything else.
int suffix = 1;
QualifiedName newArgName;
while (true) {
String potentialName = argName + suffix;
// Make sure that the new potential name is not the name of another argument and is not in the qualification map
if (!argNamesSet.contains(potentialName) &&
(qualificationMap.getQualifiedName(
potentialName, SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD) == null)) {
newArgName = QualifiedName.make(moduleName, potentialName);
break;
}
suffix++;
}
// Update the reference to the argument in the code expression
updatedCodeString = typeChecker.calculateUpdatedCodeExpression(codeString, moduleName, moduleNameResolver, qualificationMap, oldArgName, newArgName, SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD, null);
// Create a new argument node and replace the old one with it.
Element oldArgNode = argNodes.get(i);
Element newArgNode = document.createElement(GemPersistenceConstants.CODE_GEM_ARGUMENT_TAG);
newArgNode.setAttribute(GemPersistenceConstants.CODE_GEM_ARGUMENT_NAME_ATTR, newArgName.getUnqualifiedName());
argsElement.replaceChild(newArgNode, oldArgNode);
changesMade = true;
break;
}
}
}
}
// Update the code expression
updatedCodeString = typeChecker.calculateUpdatedCodeExpression(updatedCodeString, moduleName, moduleNameResolver, qualificationMap, oldName, newName, category, null);
if (!updatedCodeString.equals(codeString)) {
CDATASection newCodeChild = XMLPersistenceHelper.createCDATASection(document, updatedCodeString);
codeElement.replaceChild(newCodeChild, codeChild);
changesMade = true;
}
// Update the qualification map
if (qualificationMap != null) {
if (updateQualificationMap(qualificationMap)) {
codeElement.removeChild(qualificationMapElement);
qualificationMap.saveToXML(codeElement);
changesMade = true;
}
}
return changesMade;
}