/******************************************************************************* * Copyright (c) 2011 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Institute for Software - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.parser.util.CharArrayUtils; public class IndexToASTNameHelper { public static List<IASTName> findNamesIn(IASTTranslationUnit tu, IBinding binding, IIndex index) { BindingToAstNameMatcher visitor = new BindingToAstNameMatcher(binding, index); tu.accept(visitor); return visitor.getMatches(); } public static IASTName findMatchingASTName(IASTTranslationUnit tu, IName name, IIndex index) throws CoreException { if (name instanceof IASTName) { return (IASTName) name; } else if (!(name instanceof IIndexName)) { return null; } IndexNameToAstNameMatcher visitor = new IndexNameToAstNameMatcher(tu, (IIndexName) name, index); tu.accept(visitor); return visitor.getMatch(); } static boolean shouldConsiderName(IASTName candidate) { return !isQualifiedName(candidate) && isLastNameInQualifiedName(candidate) && !isUnnamedName(candidate); } private static boolean isLastNameInQualifiedName(IASTName name) { if (name.getParent() instanceof ICPPASTQualifiedName) { ICPPASTQualifiedName qName = (ICPPASTQualifiedName) name.getParent(); return name.equals(qName.getLastName()); } return true; } private static boolean isUnnamedName(IASTName name) { return name.getFileLocation() == null && "".equals(name.toString()); //$NON-NLS-1$ } private static boolean isQualifiedName(IASTName name) { return name instanceof ICPPASTQualifiedName; } } class IndexNameToAstNameMatcher extends ASTVisitor { private IASTName result; private IBinding bindingToFind; private char[] charNameToFind; private IIndex index; private IASTFileLocation locationToFind; public IndexNameToAstNameMatcher(IASTTranslationUnit tu, IIndexName indexName, IIndex index) throws CoreException { super(true); locationToFind = indexName.getFileLocation(); bindingToFind = index.findBinding(indexName); this.index = index; charNameToFind = bindingToFind.getNameCharArray(); shouldVisitImplicitNames = true; shouldVisitImplicitNameAlternates = true; } @Override public int visit(IASTName candidate) { if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { return PROCESS_CONTINUE; } if (isEquivalent(candidate)) { result = candidate; return PROCESS_ABORT; } return PROCESS_CONTINUE; } private boolean isEquivalent(IASTName candidate) { return matchesIndexName(candidate) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); } private boolean matchesIndexName(IASTName candidate) { IASTFileLocation candidateLocation = candidate.getFileLocation(); return locationToFind.getNodeOffset() == candidateLocation.getNodeOffset() && locationToFind.getNodeLength() == candidateLocation.getNodeLength() && locationToFind.getFileName().equals(candidateLocation.getFileName()) && CharArrayUtils.equals(candidate.getLookupKey(), charNameToFind); } public IASTName getMatch() { return result; } } class BindingToAstNameMatcher extends ASTVisitor { private List<IASTName> results = new ArrayList<IASTName>(); private IBinding bindingToFind; private char[] toFindName; private IIndex index; public BindingToAstNameMatcher(IBinding binding, IIndex index) { super(true); bindingToFind = index.adaptBinding(binding); this.index = index; toFindName = binding.getNameCharArray(); shouldVisitImplicitNames = true; shouldVisitImplicitNameAlternates = true; } @Override public int visit(IASTName candidate) { if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { return PROCESS_CONTINUE; } if (isEquivalent(candidate)) { results.add(candidate); } return PROCESS_CONTINUE; } private boolean isEquivalent(IASTName candidate) { return CharArrayUtils.equals(candidate.getSimpleID(), toFindName) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); } public List<IASTName> getMatches() { return results; } }