/******************************************************************************* * Copyright (c) 2006, 2010 Wind River Systems, Inc. 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: * Markus Schorn - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.indexer; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; abstract public class IndexerASTVisitor extends ASTVisitor { private static class Definition { Definition(IASTName name, IASTNode node) { fName= name; fNode= node; } IASTName fName; IASTNode fNode; } private IASTName fDefinitionName; private IASTNode fDefinitionNode; private ArrayList<Definition> fStack= new ArrayList<Definition>(); private ArrayList<IASTProblem> fProblems= new ArrayList<IASTProblem>(); public IndexerASTVisitor(boolean visitImplicitNames) { shouldVisitNames= true; shouldVisitImplicitNames = visitImplicitNames; shouldVisitDeclarations= true; shouldVisitInitializers= true; shouldVisitDeclSpecifiers= true; shouldVisitProblems= true; shouldVisitExpressions= true; } public List<IASTProblem> getProblems() { return fProblems; } abstract public void visit(IASTName name, IASTName definitionName); @Override final public int visit(IASTName name) { if (!(name instanceof ICPPASTQualifiedName)) { if (name != fDefinitionName) { visit(name, fDefinitionName); } } return PROCESS_CONTINUE; } private void push(IASTName name, IASTNode node) { if (fDefinitionName != null) { fStack.add(new Definition(fDefinitionName, fDefinitionNode)); } name = getLastInQualified(name); fDefinitionName= name; fDefinitionNode= node; } private IASTName getLastInQualified(IASTName name) { if (name instanceof ICPPASTQualifiedName) { name= ((ICPPASTQualifiedName) name).getLastName(); } return name; } private void pop(IASTNode node) { if (node == fDefinitionNode) { if (fStack.isEmpty()) { fDefinitionName= null; fDefinitionNode= null; } else { Definition old= fStack.remove(fStack.size()-1); fDefinitionName= old.fName; fDefinitionNode= old.fNode; } } } // functions and methods @Override public int visit(IASTDeclaration decl) { if (decl instanceof IASTFunctionDefinition) { IASTFunctionDefinition fdef= (IASTFunctionDefinition) decl; final IASTFunctionDeclarator declarator= fdef.getDeclarator(); IASTDeclarator nestedDeclarator= declarator; while (nestedDeclarator.getNestedDeclarator() != null) { nestedDeclarator= nestedDeclarator.getNestedDeclarator(); } IASTName name= getLastInQualified(nestedDeclarator.getName()); visit(name, fDefinitionName); push(name, decl); } else if (decl instanceof IASTSimpleDeclaration) { IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) decl; if (sdecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) { IASTDeclarator[] declarators= sdecl.getDeclarators(); for (IASTDeclarator declarator : declarators) { if (declarator.getPointerOperators().length == 0 && declarator.getNestedDeclarator() == null) { IASTName name= getLastInQualified(declarator.getName()); visit(name, fDefinitionName); push(name, decl); } } } } return PROCESS_CONTINUE; } @Override public int leave(IASTDeclaration decl) { pop(decl); return PROCESS_CONTINUE; } // class definitions, typedefs @Override public int visit(IASTDeclSpecifier declspec) { if (declspec instanceof ICPPASTCompositeTypeSpecifier) { ICPPASTCompositeTypeSpecifier cts= (ICPPASTCompositeTypeSpecifier) declspec; IASTName name = getLastInQualified(cts.getName()); visit(name, fDefinitionName); push(name, declspec); } if (declspec instanceof ICASTCompositeTypeSpecifier) { ICASTCompositeTypeSpecifier cts= (ICASTCompositeTypeSpecifier) declspec; IASTName name = cts.getName(); visit(name, fDefinitionName); push(name, declspec); } return PROCESS_CONTINUE; } @Override public int leave(IASTDeclSpecifier declspec) { pop(declspec); return PROCESS_CONTINUE; } @Override public int visit(IASTProblem problem) { fProblems.add(problem); return PROCESS_SKIP; } // variable and field initializers @Override public int visit(IASTInitializer initializer) { if (!(fDefinitionNode instanceof IASTFunctionDefinition)) { IASTNode cand= initializer.getParent(); if (cand instanceof IASTDeclarator) { cand= ASTQueries.findInnermostDeclarator((IASTDeclarator) cand); push(((IASTDeclarator) cand).getName(), initializer); } } return PROCESS_CONTINUE; } @Override public int leave(IASTInitializer initializer) { pop(initializer); return PROCESS_CONTINUE; } // Lambda expressions @Override public int visit(IASTExpression expr) { if (expr instanceof ICPPASTLambdaExpression) { return visit((ICPPASTLambdaExpression) expr); } return PROCESS_CONTINUE; } private int visit(final ICPPASTLambdaExpression lambdaExpr) { // Captures for (ICPPASTCapture cap : lambdaExpr.getCaptures()) { if (!cap.accept(this)) return PROCESS_ABORT; } // Definition of closure type final IASTName closureName = lambdaExpr.getClosureTypeName(); visit(closureName, fDefinitionName); // Definition of call operator IASTName callOp= lambdaExpr.getFunctionCallOperatorName(); visit(callOp, closureName); push(callOp, lambdaExpr); ICPPASTFunctionDeclarator dtor = lambdaExpr.getDeclarator(); if (dtor != null && !dtor.accept(this)) return PROCESS_ABORT; IASTCompoundStatement body = lambdaExpr.getBody(); if (body != null && !body.accept(this)) return PROCESS_ABORT; pop(lambdaExpr); return PROCESS_SKIP; } }