/******************************************************************************* * Copyright (c) 2006, 2017 Phil Muldoon 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: * Phil Muldoon <pmuldoon@redhat.com> - initial API and implementation, fixes. *******************************************************************************/ package org.eclipse.linuxtools.internal.changelog.parsers; import java.io.IOException; import java.io.InputStream; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IncludeFileContentProvider; import org.eclipse.cdt.core.parser.ParserUtil; import org.eclipse.cdt.core.parser.ScannerInfo; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.IWorkingCopyManager; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.text.ITextSelection; import org.eclipse.linuxtools.changelog.core.IParserChangeLogContrib; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IStorageEditorInput; import org.eclipse.ui.texteditor.AbstractTextEditor; /** * @author pmuldoon (Phil Muldoon) */ public class CParser implements IParserChangeLogContrib { public CParser() { super(); } @Override public String parseCurrentFunction(IEditorInput input, int offset) throws CoreException { String currentElementName; if (input instanceof IFileEditorInput) { // Get the working copy and connect to input. IWorkingCopyManager manager = CUIPlugin.getDefault() .getWorkingCopyManager(); manager.connect(input); // Retrieve the C/C++ Element in question. IWorkingCopy workingCopy = manager.getWorkingCopy(input); ICElement method = workingCopy.getElementAtOffset(offset); manager.disconnect(input); // no element selected if (method == null) return ""; // Get the current element name, to test it. currentElementName = method.getElementName(); // Element doesn't have a name. Can go no further. if (currentElementName == null) { // element doesn't have a name return ""; } // Get the Element Type to test. int elementType = method.getElementType(); switch (elementType) { case ICElement.C_FIELD: case ICElement.C_METHOD: case ICElement.C_FUNCTION: break; case ICElement.C_MODEL: return ""; // So it's not a method, field, function, or model. Where are we? default: ICElement tmpMethodType; if (((tmpMethodType = method.getAncestor(ICElement.C_FUNCTION)) == null) && ((tmpMethodType = method.getAncestor(ICElement.C_METHOD)) == null) && ((tmpMethodType = method.getAncestor(ICElement.C_CLASS)) == null)) { return ""; } else { // In a class, but not in a method. Return class name instead. method = tmpMethodType; currentElementName = method.getElementName(); } } // Build all ancestor classes. // Append all ancestor class names to string ICElement tmpParent = method.getParent(); while (tmpParent != null) { ICElement tmpParentClass = tmpParent.getAncestor(ICElement.C_CLASS); if (tmpParentClass != null) { String tmpParentClassName = tmpParentClass.getElementName(); if (tmpParentClassName == null) return currentElementName; currentElementName = tmpParentClassName + "." + currentElementName; } else return currentElementName; tmpParent = tmpParentClass.getParent(); } return currentElementName; } else if (input instanceof IStorageEditorInput) { // Get the working copy and connect to input. // don't follow inclusions currentElementName = ""; IStorageEditorInput sei = (IStorageEditorInput)input; // don't follow inclusions IncludeFileContentProvider contentProvider = IncludeFileContentProvider.getEmptyFilesProvider(); // empty scanner info IScannerInfo scanInfo= new ScannerInfo(); IStorage ancestorStorage = sei.getStorage(); if (ancestorStorage == null) return ""; InputStream stream = ancestorStorage.getContents(); byte buffer[] = new byte[100]; String data = ""; int read = 0; try { do { read = stream.read(buffer); if (read > 0) { String tmp = new String(buffer, 0, read); data = data.concat(tmp); } } while (read == 100); stream.close(); } catch (IOException e) { // do nothing } FileContent content = FileContent.create("<text>", data.toCharArray()); //$NON-NLS-1$ // determine the language ILanguage language= GPPLanguage.getDefault(); try { IASTTranslationUnit ast; int options= 0; ast= language.getASTTranslationUnit(content, scanInfo, contentProvider, null, options, ParserUtil.getParserLogService()); IASTNodeSelector n = ast.getNodeSelector(null); IASTNode node = n.findFirstContainedNode(offset, 100); while (node != null && !(node instanceof IASTTranslationUnit)) { if (node instanceof IASTFunctionDefinition) { IASTFunctionDefinition fd = (IASTFunctionDefinition)node; IASTFunctionDeclarator d = fd.getDeclarator(); currentElementName = new String(d.getName().getSimpleID()); break; } node = node.getParent(); } } catch (CoreException exc) { currentElementName = ""; CUIPlugin.log(exc); } return currentElementName; } return ""; } @Override public String parseCurrentFunction(IEditorPart editor) throws CoreException { // Check for correct editor type if (!(editor instanceof AbstractTextEditor)) return ""; // Get the editor, test selection and input. AbstractTextEditor a_editor = (AbstractTextEditor) editor; ITextSelection selection = (ITextSelection) (a_editor) .getSelectionProvider().getSelection(); IEditorInput input = a_editor.getEditorInput(); // Parse it and return the function. return parseCurrentFunction(input, selection.getOffset()); } }