/******************************************************************************* * Copyright (c) 2009 Elliott Baron * 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: * Elliott Baron - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.codan.checkers; import java.text.MessageFormat; import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; 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.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; public class CloseOpenedFilesChecker extends AbstractIndexAstChecker { private static final String ERR_ID = Activator.PLUGIN_ID + ".CloseOpenedFilesProblem"; public void processAst(IASTTranslationUnit ast) { // traverse the AST using the visitor pattern CloseOpenedFilesVisitor visitor = new CloseOpenedFilesVisitor(); ast.accept(visitor); IASTName closeFD = visitor.getCloseFD(); if (closeFD != null) { IASTName openFD = visitor.getOpenFD(); if (openFD == null || !matchingFileDescriptors(closeFD.getBinding(), openFD.getBinding())) { String message = MessageFormat.format("File descriptor \"{0}\" has not been opened", closeFD.toString()); reportProblem(ERR_ID, closeFD, message); } } } private boolean matchingFileDescriptors(IBinding closeFD, IBinding openFD) { // FIXME elaborate return closeFD.equals(openFD); } class CloseOpenedFilesVisitor extends ASTVisitor { public static final String OPEN = "open"; public static final String CLOSE = "close"; private IASTName openFD; private IASTName closeFD; public CloseOpenedFilesVisitor() { shouldVisitExpressions = true; } @Override public int visit(IASTExpression expression) { if (expression instanceof IASTFunctionCallExpression) { IASTFunctionCallExpression callExpression = (IASTFunctionCallExpression) expression; IASTExpression funcName = callExpression.getFunctionNameExpression(); if (funcName instanceof IASTIdExpression) { IASTName name = ((IASTIdExpression) funcName).getName(); String simpleName = String.valueOf(name.getSimpleID()); if (simpleName.equals(OPEN)) { IASTNode parent = callExpression.getParent(); if (parent instanceof IASTInitializer) { parent = parent.getParent(); if (parent instanceof IASTDeclarator) { openFD = ((IASTDeclarator) parent).getName(); } } } else if (simpleName.equals(CLOSE)) { IASTExpression paramExpression = callExpression.getParameterExpression(); if (paramExpression instanceof IASTIdExpression) { closeFD = ((IASTIdExpression) paramExpression).getName(); } } } return PROCESS_SKIP; } else { return PROCESS_CONTINUE; } } public IASTName getOpenFD() { return openFD; } public IASTName getCloseFD() { return closeFD; } } }