/******************************************************************************* * Copyright (c) 2005, 2009 IBM Corporation 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: * IBM Corporation - initial API and implementation * QNX Software System * Anton Leherbauer (Wind River Systems) * Andrew Ferguson (Symbian) *******************************************************************************/ package org.eclipse.cdt.internal.ui.compare; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.eclipse.compare.IEncodedStreamContentAccessor; import org.eclipse.compare.ISharedDocumentAdapter; import org.eclipse.compare.IStreamContentAccessor; import org.eclipse.compare.ResourceNode; import org.eclipse.compare.contentmergeviewer.IDocumentRange; import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; import org.eclipse.compare.structuremergeviewer.IStructureComparator; import org.eclipse.compare.structuremergeviewer.StructureCreator; import org.eclipse.compare.structuremergeviewer.StructureRootNode; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentPartitioner; import org.eclipse.jface.text.Position; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; 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.text.ICPartitions; import org.eclipse.cdt.ui.text.doctools.IDocCommentOwner; import org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager; /** * A structure creator for C/C++ translation units. */ public class CStructureCreator extends StructureCreator { private static final String NAME = "CStructureCreator.name"; //$NON-NLS-1$ public CStructureCreator() { } public String getName() { return CUIPlugin.getResourceString(NAME); } /* * @see IStructureCreator#getContents */ public String getContents(Object node, boolean ignoreWhitespace) { if (node instanceof IDocumentRange) { IDocumentRange documentRange= (IDocumentRange)node; final Position range = documentRange.getRange(); try { return documentRange.getDocument().get(range.getOffset(), range.getLength()); } catch (BadLocationException exc) { } } if (node instanceof IStreamContentAccessor) { IStreamContentAccessor sca = (IStreamContentAccessor) node; try { return readString(sca); } catch (CoreException ex) { } } return null; } /* * @see org.eclipse.compare.structuremergeviewer.StructureCreator#createStructureComparator(java.lang.Object, org.eclipse.jface.text.IDocument, org.eclipse.compare.ISharedDocumentAdapter, org.eclipse.core.runtime.IProgressMonitor) */ @Override protected IStructureComparator createStructureComparator(Object element, IDocument document, ISharedDocumentAdapter sharedDocumentAdapter, IProgressMonitor monitor) throws CoreException { DocumentRangeNode root= new StructureRootNode(document, element, this, sharedDocumentAdapter); // don't follow inclusions IncludeFileContentProvider contentProvider = IncludeFileContentProvider.getEmptyFilesProvider(); // empty scanner info IScannerInfo scanInfo= new ScannerInfo(); FileContent content = FileContent.create("<text>", document.get().toCharArray()); //$NON-NLS-1$ // determine the language boolean isSource[]= {false}; ILanguage language= determineLanguage(element, isSource); try { IASTTranslationUnit ast; int options= isSource[0] ? ILanguage.OPTION_IS_SOURCE_UNIT : 0; ast= language.getASTTranslationUnit(content, scanInfo, contentProvider, null, options, ParserUtil.getParserLogService()); CStructureCreatorVisitor structureCreator= new CStructureCreatorVisitor(root); // build structure ast.accept(structureCreator); } catch (CoreException exc) { CUIPlugin.log(exc); } return root; } /** * Try to determine the <code>ILanguage</code> for the given input element. * * @param element * @return a language instance */ private ILanguage determineLanguage(Object element, boolean[] isSource) { ILanguage language= null; if (element instanceof ResourceNode) { IResource resource= ((ResourceNode)element).getResource(); if (resource.getType() == IResource.FILE) { ITranslationUnit tUnit= (ITranslationUnit)CoreModel.getDefault().create(resource); if (tUnit != null) { try { language= tUnit.getLanguage(); isSource[0]= tUnit.isSourceUnit(); } catch (CoreException exc) { // silently ignored } } } } if (language == null) { language= GPPLanguage.getDefault(); } return language; } @Override protected String getDocumentPartitioning() { return ICPartitions.C_PARTITIONING; } @Override protected IDocumentPartitioner getDocumentPartitioner() { // use workspace default for highlighting doc comments in compare viewer IDocCommentOwner owner= DocCommentOwnerManager.getInstance().getWorkspaceCommentOwner(); return CUIPlugin.getDefault().getTextTools().createDocumentPartitioner(owner); } private static String readString(IStreamContentAccessor sa) throws CoreException { InputStream is= sa.getContents(); if (is != null) { String encoding= null; if (sa instanceof IEncodedStreamContentAccessor) { try { encoding= ((IEncodedStreamContentAccessor) sa).getCharset(); } catch (Exception e) { } } if (encoding == null) encoding= ResourcesPlugin.getEncoding(); return readString(is, encoding); } return null; } private static String readString(InputStream is, String encoding) { if (is == null) return null; BufferedReader reader= null; try { StringBuffer buffer= new StringBuffer(); char[] part= new char[2048]; int read= 0; reader= new BufferedReader(new InputStreamReader(is, encoding)); while ((read= reader.read(part)) != -1) buffer.append(part, 0, read); return buffer.toString(); } catch (IOException ex) { // NeedWork } finally { if (reader != null) { try { reader.close(); } catch (IOException ex) { // silently ignored } } } return null; } }