/******************************************************************************* * Copyright (c) 2000, 2015 QNX Software Systems 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: * QNX Software Systems - Initial API and implementation * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.ui.text; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.reconciler.IReconciler; import org.eclipse.jface.text.reconciler.MonoReconciler; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.jface.text.rules.RuleBasedScanner; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IPathEditorInput; import org.eclipse.ui.editors.text.ILocationProvider; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.ui.ide.ResourceUtil; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.AssemblyLanguage; import org.eclipse.cdt.core.model.IAsmLanguage; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.ILanguageUI; import org.eclipse.cdt.internal.ui.editor.asm.AsmCodeScanner; import org.eclipse.cdt.internal.ui.editor.asm.AsmPreprocessorScanner; import org.eclipse.cdt.internal.ui.editor.asm.AsmReconcilingStrategy; import org.eclipse.cdt.internal.ui.text.CCommentScanner; import org.eclipse.cdt.internal.ui.text.PartitionDamager; import org.eclipse.cdt.internal.ui.text.SingleTokenCScanner; import org.eclipse.cdt.internal.ui.text.TokenStore; /** * Configuration for a source viewer which shows Assembly code. * <p> * This class may be instantiated; it is not intended to be subclassed. * </p> * * @noextend This class is not intended to be subclassed by clients. * * @since 5.1 */ public class AsmSourceViewerConfiguration extends TextSourceViewerConfiguration { private ITextEditor fTextEditor; /** * The code scanner. */ private AbstractCScanner fCodeScanner; /** * The C multi-line comment scanner. */ private AbstractCScanner fMultilineCommentScanner; /** * The C single-line comment scanner. */ private AbstractCScanner fSinglelineCommentScanner; /** * The C string scanner. */ private AbstractCScanner fStringScanner; /** * The preprocessor scanner. */ private AbstractCScanner fPreprocessorScanner; /** * The color manager. */ private IColorManager fColorManager; /** * The document partitioning. */ private String fDocumentPartitioning; /** * Creates a new assembly source viewer configuration for viewers in the given editor * using the given preference store, the color manager and the specified document partitioning. * * @param colorManager the color manager * @param preferenceStore the preference store, can be read-only * @param editor the editor in which the configured viewer(s) will reside, or <code>null</code> if none * @param partitioning the document partitioning for this configuration, or <code>null</code> for the default partitioning */ public AsmSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore preferenceStore, ITextEditor editor, String partitioning) { super(preferenceStore); fColorManager= colorManager; fTextEditor= editor; fDocumentPartitioning= partitioning; initializeScanners(); } /** * Initializes the scanners. */ private void initializeScanners() { fMultilineCommentScanner= new CCommentScanner(getTokenStoreFactory(), ICColorConstants.C_MULTI_LINE_COMMENT); fSinglelineCommentScanner= new CCommentScanner(getTokenStoreFactory(), ICColorConstants.C_SINGLE_LINE_COMMENT); fStringScanner= new SingleTokenCScanner(getTokenStoreFactory(), ICColorConstants.C_STRING); } /** * Returns the ASM multiline comment scanner for this configuration. * * @return the ASM multiline comment scanner */ public RuleBasedScanner getMultilineCommentScanner() { return fMultilineCommentScanner; } /** * Returns the ASM singleline comment scanner for this configuration. * * @return the ASM singleline comment scanner */ public RuleBasedScanner getSinglelineCommentScanner() { return fSinglelineCommentScanner; } /** * Returns the ASM string scanner for this configuration. * * @return the ASM string scanner */ public RuleBasedScanner getStringScanner() { return fStringScanner; } /** * Returns the assembly preprocessor scanner for this configuration. * @param language * * @return the assembly preprocessor scanner */ public RuleBasedScanner getPreprocessorScanner(ILanguage language) { if (fPreprocessorScanner != null) { return fPreprocessorScanner; } AbstractCScanner scanner= null; if (language instanceof IAsmLanguage) { scanner= new AsmPreprocessorScanner(getTokenStoreFactory(), (IAsmLanguage)language); } if (scanner == null) { scanner= new AsmPreprocessorScanner(getTokenStoreFactory(), AssemblyLanguage.getDefault()); } fPreprocessorScanner= scanner; return fPreprocessorScanner; } /** * @param language * @return the assembly code scanner for the given language */ public RuleBasedScanner getCodeScanner(ILanguage language) { if (fCodeScanner != null) { return fCodeScanner; } RuleBasedScanner scanner= null; if (language instanceof IAsmLanguage) { IAsmLanguage asmLang= (IAsmLanguage)language; scanner = new AsmCodeScanner(getTokenStoreFactory(), asmLang); } else if (language != null) { ILanguageUI languageUI = language.getAdapter(ILanguageUI.class); if (languageUI != null) scanner = languageUI.getCodeScanner(); } if (scanner == null) { scanner = new AsmCodeScanner(getTokenStoreFactory(), AssemblyLanguage.getDefault()); } if (scanner instanceof AbstractCScanner) { fCodeScanner= (AbstractCScanner)scanner; } return scanner; } /* * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredDocumentPartitioning(org.eclipse.jface.text.source.ISourceViewer) */ @Override public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) { if (fDocumentPartitioning != null) return fDocumentPartitioning; return super.getConfiguredDocumentPartitioning(sourceViewer); } /* * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getPresentationReconciler(org.eclipse.jface.text.source.ISourceViewer) */ @Override public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { PresentationReconciler reconciler= new PresentationReconciler(); ILanguage language= getLanguage(); DefaultDamagerRepairer dr= new DefaultDamagerRepairer(getCodeScanner(language)); reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); dr= new DefaultDamagerRepairer(getMultilineCommentScanner()); reconciler.setDamager(dr, ICPartitions.C_MULTI_LINE_COMMENT); reconciler.setRepairer(dr, ICPartitions.C_MULTI_LINE_COMMENT); dr= new DefaultDamagerRepairer(getSinglelineCommentScanner()); reconciler.setDamager(dr, ICPartitions.C_SINGLE_LINE_COMMENT); reconciler.setRepairer(dr, ICPartitions.C_SINGLE_LINE_COMMENT); dr= new DefaultDamagerRepairer(getStringScanner()); reconciler.setDamager(dr, ICPartitions.C_STRING); reconciler.setRepairer(dr, ICPartitions.C_STRING); dr= new DefaultDamagerRepairer(getStringScanner()); reconciler.setDamager(dr, ICPartitions.C_CHARACTER); reconciler.setRepairer(dr, ICPartitions.C_CHARACTER); dr= new DefaultDamagerRepairer(getPreprocessorScanner(language)); reconciler.setDamager(new PartitionDamager(), ICPartitions.C_PREPROCESSOR); reconciler.setRepairer(dr, ICPartitions.C_PREPROCESSOR); reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); return reconciler; } /* * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredContentTypes(org.eclipse.jface.text.source.ISourceViewer) */ @Override public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { return new String[] { IDocument.DEFAULT_CONTENT_TYPE, ICPartitions.C_MULTI_LINE_COMMENT, ICPartitions.C_SINGLE_LINE_COMMENT, ICPartitions.C_STRING, ICPartitions.C_CHARACTER, ICPartitions.C_PREPROCESSOR}; } /* * @see org.eclipse.ui.editors.text.TextSourceViewerConfiguration#getReconciler(org.eclipse.jface.text.source.ISourceViewer) */ @Override public IReconciler getReconciler(ISourceViewer sourceViewer) { if (fTextEditor != null) { MonoReconciler reconciler= new MonoReconciler(new AsmReconcilingStrategy(fTextEditor), false); reconciler.setIsIncrementalReconciler(false); reconciler.setProgressMonitor(new NullProgressMonitor()); reconciler.setDelay(500); return reconciler; } return super.getReconciler(sourceViewer); } /** * Determines whether the preference change encoded by the given event * changes the behavior of one of its contained components. * * @param event the event to be investigated * @return <code>true</code> if event causes a behavioral change */ public boolean affectsTextPresentation(PropertyChangeEvent event) { if (fMultilineCommentScanner.affectsBehavior(event) || fSinglelineCommentScanner.affectsBehavior(event) || fStringScanner.affectsBehavior(event)) { return true; } if (fCodeScanner != null && fCodeScanner.affectsBehavior(event)) { return true; } if (fPreprocessorScanner != null && fPreprocessorScanner.affectsBehavior(event)) { return true; } return false; } /** * Adapts the behavior of the contained components to the change * encoded in the given event. * <p> * Clients are not allowed to call this method if the old setup with * text tools is in use. * </p> * * @param event the event to which to adapt * @see CSourceViewerConfiguration#CSourceViewerConfiguration(IColorManager, IPreferenceStore, ITextEditor, String) */ public void handlePropertyChangeEvent(PropertyChangeEvent event) { if (fCodeScanner != null && fCodeScanner.affectsBehavior(event)) fCodeScanner.adaptToPreferenceChange(event); if (fMultilineCommentScanner.affectsBehavior(event)) fMultilineCommentScanner.adaptToPreferenceChange(event); if (fSinglelineCommentScanner.affectsBehavior(event)) fSinglelineCommentScanner.adaptToPreferenceChange(event); if (fStringScanner.affectsBehavior(event)) fStringScanner.adaptToPreferenceChange(event); if (fPreprocessorScanner != null && fPreprocessorScanner.affectsBehavior(event)) fPreprocessorScanner.adaptToPreferenceChange(event); } /** * Returns the color manager for this configuration. * * @return the color manager */ public IColorManager getColorManager() { return fColorManager; } public ILanguage getLanguage() { if (fTextEditor == null) { return AssemblyLanguage.getDefault(); } ICElement element = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fTextEditor.getEditorInput()); if (element instanceof ITranslationUnit) { try { return ((ITranslationUnit)element).getLanguage(); } catch (CoreException e) { CUIPlugin.log(e); } } else { // compute the language from the plain editor input IContentType contentType = null; IEditorInput input = fTextEditor.getEditorInput(); IFile file = ResourceUtil.getFile(input); if (file != null) { contentType = CCorePlugin.getContentType(file.getProject(), file.getName()); } else if (input instanceof IPathEditorInput) { IPath path = ((IPathEditorInput)input).getPath(); contentType = CCorePlugin.getContentType(path.lastSegment()); } else { ILocationProvider locationProvider = input.getAdapter(ILocationProvider.class); if (locationProvider != null) { IPath path = locationProvider.getPath(input); contentType = CCorePlugin.getContentType(path.lastSegment()); } } if (contentType != null) { return LanguageManager.getInstance().getLanguage(contentType); } } // fallback return AssemblyLanguage.getDefault(); } /** * Reset cached language dependent scanners. */ public void resetScanners() { fCodeScanner= null; fPreprocessorScanner= null; } private ITokenStoreFactory getTokenStoreFactory() { return new ITokenStoreFactory() { @Override public ITokenStore createTokenStore(String[] propertyColorNames) { return new TokenStore(getColorManager(), fPreferenceStore, propertyColorNames); } }; } }