/* * Copyright 2015 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.robotframework.ide.eclipse.main.plugin.tableeditor.source; import static com.google.common.collect.Lists.newArrayList; import java.util.List; import org.eclipse.jface.bindings.keys.KeySequence; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.text.AbstractReusableInformationControlCreator; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.TextAttribute; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.IContentAssistant; import org.eclipse.jface.text.formatter.IContentFormatter; import org.eclipse.jface.text.formatter.MultiPassContentFormatter; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.jface.text.hyperlink.IHyperlinkPresenter; import org.eclipse.jface.text.hyperlink.MultipleHyperlinkPresenter; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.quickassist.IQuickAssistAssistant; import org.eclipse.jface.text.quickassist.QuickAssistAssistant; import org.eclipse.jface.text.reconciler.IReconciler; import org.eclipse.jface.text.reconciler.IReconcilingStrategy; import org.eclipse.jface.text.reconciler.MonoReconciler; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.ITokenScanner; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.source.DefaultAnnotationHover; import org.eclipse.jface.text.source.IAnnotationHover; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Shell; import org.rf.ide.core.executor.RedSystemProperties; import org.rf.ide.core.testdata.model.RobotFileOutput; import org.robotframework.ide.eclipse.main.plugin.RedPlugin; import org.robotframework.ide.eclipse.main.plugin.RedPreferences; import org.robotframework.ide.eclipse.main.plugin.RedPreferences.ColoringPreference; import org.robotframework.ide.eclipse.main.plugin.hyperlink.detectors.SourceHyperlinksToFilesDetector; import org.robotframework.ide.eclipse.main.plugin.hyperlink.detectors.SourceHyperlinksToKeywordsDetector; import org.robotframework.ide.eclipse.main.plugin.hyperlink.detectors.SourceHyperlinksToVariablesDetector; import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile; import org.robotframework.ide.eclipse.main.plugin.preferences.SyntaxHighlightingCategory; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.CodeReservedWordsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.CombinedAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.CycledContentAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.CycledContentAssistProcessor.AssitantCallbacks; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.GeneralSettingsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.ImportsInCodeAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.ImportsInSettingsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.KeywordCallsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.KeywordCallsInSettingsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.LibrariesImportAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.ResourcesImportAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.SectionsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.SettingsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.SuiteSourceAssistantContext; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.VariablesAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.VariablesDefinitionsAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.VariablesImportAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.assist.WithNameAssistProcessor; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.CaseNameRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.CommentRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.ExecutableRowCallRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.GherkinPrefixRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.ISyntaxColouringRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.InTokenRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.KeywordNameRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.KeywordSettingsCallRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.KeywordSettingsRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.MatchEverythingRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.RedCachingScanner; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.RedTokenScanner; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.RedTokensStore; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.SectionHeaderRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.SettingRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.SettingsCallRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.TestCaseSettingsCallRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.TestCaseSettingsRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.VariableDefinitionRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.VariableUsageRule; import org.robotframework.ide.eclipse.main.plugin.tableeditor.source.colouring.WithNameRule; import org.robotframework.red.graphics.ColorsManager; import com.google.common.base.Supplier; class SuiteSourceEditorConfiguration extends SourceViewerConfiguration { private final SuiteSourceEditor editor; private IReconciler reconciler; public SuiteSourceEditorConfiguration(final SuiteSourceEditor editor) { this.editor = editor; } @Override public IAnnotationHover getAnnotationHover(final ISourceViewer sourceViewer) { return new DefaultAnnotationHover(); } @Override public ITextHover getTextHover(final ISourceViewer sourceViewer, final String contentType) { return new SuiteSourceHoverSupport(editor.getFileModel()); } @Override public IHyperlinkPresenter getHyperlinkPresenter(final ISourceViewer sourceViewer) { return new MultipleHyperlinkPresenter(new RGB(0, 0, 255)); } @Override public IHyperlinkDetector[] getHyperlinkDetectors(final ISourceViewer sourceViewer) { final RobotSuiteFile model = editor.getFileModel(); return new IHyperlinkDetector[] { new SourceHyperlinksToVariablesDetector(model), new SourceHyperlinksToKeywordsDetector(model), new SourceHyperlinksToFilesDetector(model) }; } @Override public IAutoEditStrategy[] getAutoEditStrategies(final ISourceViewer sourceViewer, final String contentType) { final boolean isTsv = "tsv".equals(editor.fileModel.getFileExtension()); final List<IAutoEditStrategy> strategies = newArrayList(); strategies.add(new SuiteSourceIndentLineEditStrategy(isTsv)); strategies.add(new SuiteSourceInsertLineContinuationStrategy(isTsv)); if (contentType.equals(SuiteSourcePartitionScanner.KEYWORDS_SECTION) || contentType.equals(SuiteSourcePartitionScanner.TEST_CASES_SECTION) || contentType.equals(IDocument.DEFAULT_CONTENT_TYPE)) { strategies.add(new SuiteSourceIndentLineAfterDefinitionStrategy(isTsv)); } return strategies.toArray(new IAutoEditStrategy[0]); } @Override public IContentAssistant getContentAssistant(final ISourceViewer sourceViewer) { final ContentAssistant contentAssistant = new ContentAssistant(); contentAssistant.enableColoredLabels(true); contentAssistant.enableAutoInsert(false); contentAssistant .enableAutoActivation(RedPlugin.getDefault().getPreferences().isAssistantAutoActivationEnabled()); contentAssistant .setAutoActivationDelay(RedPlugin.getDefault().getPreferences().getAssistantAutoActivationDelay()); contentAssistant.setEmptyMessage("No proposals"); contentAssistant.setShowEmptyList(true); contentAssistant.setStatusLineVisible(true); contentAssistant.setRepeatedInvocationMode(true); contentAssistant .setRepeatedInvocationTrigger(KeySequence.getInstance(KeyStroke.getInstance(SWT.CTRL, SWT.SPACE))); setupAssistantProcessors(contentAssistant); contentAssistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_BELOW); contentAssistant.setInformationControlCreator(new AbstractReusableInformationControlCreator() { @Override protected IInformationControl doCreateInformationControl(final Shell parent) { return new DefaultInformationControl(parent, true); } }); return contentAssistant; } private void setupAssistantProcessors(final ContentAssistant contentAssistant) { final AssitantCallbacks assistantAccessor = new AssitantCallbacks() { @Override public void setStatus(final String title) { contentAssistant.setStatusMessage(title); } @Override public void openCompletionProposals() { contentAssistant.showPossibleCompletions(); } }; final Supplier<RobotSuiteFile> modelSupplier = new Supplier<RobotSuiteFile>() { @Override public RobotSuiteFile get() { final RobotSuiteFile suiteModel = editor.getFileModel(); suiteModel.dispose(); try { final RobotDocument document = (RobotDocument) editor.getDocument(); final RobotFileOutput fileOutput = document.getNewestFileOutput(); suiteModel.link(fileOutput); } catch (final InterruptedException e) { // ok we'll return not-yet-parsed version } return suiteModel; } }; createSettingsAssist(contentAssistant, modelSupplier, assistantAccessor); createVariablesAssist(contentAssistant, modelSupplier, assistantAccessor); createKeywordsAssist(contentAssistant, modelSupplier, assistantAccessor); createTestCasesAssist(contentAssistant, modelSupplier, assistantAccessor); createDefaultAssist(contentAssistant, modelSupplier, assistantAccessor); } private void createSettingsAssist(final ContentAssistant contentAssistant, final Supplier<RobotSuiteFile> modelSupplier, final AssitantCallbacks assistantAccessor) { final SuiteSourceAssistantContext assistContext = new SuiteSourceAssistantContext(modelSupplier); final GeneralSettingsAssistProcessor settingNamesProcessor = new GeneralSettingsAssistProcessor(assistContext); final VariablesAssistProcessor variablesAssistProcessor = new VariablesAssistProcessor(assistContext); final CombinedAssistProcessor combinedProcessor = new CombinedAssistProcessor( new WithNameAssistProcessor(assistContext), new LibrariesImportAssistProcessor(assistContext), new VariablesImportAssistProcessor(assistContext), new ResourcesImportAssistProcessor(assistContext), new SectionsAssistProcessor(assistContext), settingNamesProcessor, new KeywordCallsInSettingsAssistProcessor(assistContext), new ImportsInSettingsAssistProcessor(assistContext), variablesAssistProcessor); final CycledContentAssistProcessor cycledProcessor = new CycledContentAssistProcessor(assistContext, assistantAccessor); cycledProcessor.addProcessor(combinedProcessor); cycledProcessor.addProcessor(settingNamesProcessor); cycledProcessor.addProcessor(variablesAssistProcessor); contentAssistant.setContentAssistProcessor(cycledProcessor, SuiteSourcePartitionScanner.SETTINGS_SECTION); contentAssistant.addCompletionListener(cycledProcessor); } private void createVariablesAssist(final ContentAssistant contentAssistant, final Supplier<RobotSuiteFile> modelSupplier, final AssitantCallbacks assistantAccessor) { final SuiteSourceAssistantContext assistContext = new SuiteSourceAssistantContext(modelSupplier); final VariablesAssistProcessor variablesAssistProcessor = new VariablesAssistProcessor(assistContext); final CombinedAssistProcessor combinedProcessor = new CombinedAssistProcessor( new VariablesDefinitionsAssistProcessor(assistContext), new SectionsAssistProcessor(assistContext), variablesAssistProcessor); final CycledContentAssistProcessor cycledProcessor = new CycledContentAssistProcessor(assistContext, assistantAccessor); cycledProcessor.addProcessor(combinedProcessor); cycledProcessor.addProcessor(variablesAssistProcessor); contentAssistant.setContentAssistProcessor(cycledProcessor, SuiteSourcePartitionScanner.VARIABLES_SECTION); contentAssistant.addCompletionListener(cycledProcessor); } private void createTestCasesAssist(final ContentAssistant contentAssistant, final Supplier<RobotSuiteFile> modelSupplier, final AssitantCallbacks assistantAccessor) { final SuiteSourceAssistantContext assistContext = new SuiteSourceAssistantContext(modelSupplier); final KeywordCallsAssistProcessor keywordCallsAssistProcessor = new KeywordCallsAssistProcessor(assistContext); final VariablesAssistProcessor variablesAssistProcessor = new VariablesAssistProcessor(assistContext); final CombinedAssistProcessor combinedProcessor = new CombinedAssistProcessor( new SectionsAssistProcessor(assistContext), new SettingsAssistProcessor(assistContext), new CodeReservedWordsAssistProcessor(assistContext), keywordCallsAssistProcessor, new ImportsInCodeAssistProcessor(assistContext), variablesAssistProcessor); final CycledContentAssistProcessor cycledProcessor = new CycledContentAssistProcessor(assistContext, assistantAccessor); cycledProcessor.addProcessor(combinedProcessor); cycledProcessor.addProcessor(keywordCallsAssistProcessor); cycledProcessor.addProcessor(variablesAssistProcessor); contentAssistant.setContentAssistProcessor(cycledProcessor, SuiteSourcePartitionScanner.TEST_CASES_SECTION); contentAssistant.addCompletionListener(cycledProcessor); } private void createKeywordsAssist(final ContentAssistant contentAssistant, final Supplier<RobotSuiteFile> modelSupplier, final AssitantCallbacks assistantAccessor) { final SuiteSourceAssistantContext assistContext = new SuiteSourceAssistantContext(modelSupplier); final KeywordCallsAssistProcessor keywordCallsAssistProcessor = new KeywordCallsAssistProcessor(assistContext); final VariablesAssistProcessor variablesAssistProcessor = new VariablesAssistProcessor(assistContext); final CombinedAssistProcessor combinedProcessor = new CombinedAssistProcessor( new SectionsAssistProcessor(assistContext), new SettingsAssistProcessor(assistContext), new CodeReservedWordsAssistProcessor(assistContext), keywordCallsAssistProcessor, new ImportsInCodeAssistProcessor(assistContext), variablesAssistProcessor); final CycledContentAssistProcessor cycledProcessor = new CycledContentAssistProcessor(assistContext, assistantAccessor); cycledProcessor.addProcessor(combinedProcessor); cycledProcessor.addProcessor(keywordCallsAssistProcessor); cycledProcessor.addProcessor(variablesAssistProcessor); contentAssistant.setContentAssistProcessor(cycledProcessor, SuiteSourcePartitionScanner.KEYWORDS_SECTION); contentAssistant.addCompletionListener(cycledProcessor); } private void createDefaultAssist(final ContentAssistant contentAssistant, final Supplier<RobotSuiteFile> modelSupplier, final AssitantCallbacks assistantAccessor) { // we are adding all the assistants for default content type. Most of them (excluding // section headers assistant) are working in default content type only at the very last // position in file (this position always has default content type, but it can be actually // prepended with some valid meaningful content type final SuiteSourceAssistantContext assistContext = new SuiteSourceAssistantContext(modelSupplier); final GeneralSettingsAssistProcessor generalSettingProcessor = new GeneralSettingsAssistProcessor( assistContext); final KeywordCallsAssistProcessor keywordCallsProcessor = new KeywordCallsAssistProcessor(assistContext); final VariablesAssistProcessor variablesProcessor = new VariablesAssistProcessor(assistContext); final CombinedAssistProcessor combinedProcessor = new CombinedAssistProcessor( new VariablesDefinitionsAssistProcessor(assistContext), new WithNameAssistProcessor(assistContext), new LibrariesImportAssistProcessor(assistContext), new VariablesImportAssistProcessor(assistContext), new ResourcesImportAssistProcessor(assistContext), new SectionsAssistProcessor(assistContext), generalSettingProcessor, new SettingsAssistProcessor(assistContext), new CodeReservedWordsAssistProcessor(assistContext), new KeywordCallsInSettingsAssistProcessor(assistContext), keywordCallsProcessor, new ImportsInSettingsAssistProcessor(assistContext), new ImportsInCodeAssistProcessor(assistContext), variablesProcessor); final CycledContentAssistProcessor cycledProcessor = new CycledContentAssistProcessor(assistContext, assistantAccessor); cycledProcessor.addProcessor(combinedProcessor); cycledProcessor.addProcessor(generalSettingProcessor); cycledProcessor.addProcessor(keywordCallsProcessor); cycledProcessor.addProcessor(variablesProcessor); contentAssistant.setContentAssistProcessor(cycledProcessor, IDocument.DEFAULT_CONTENT_TYPE); contentAssistant.addCompletionListener(cycledProcessor); } @Override public IQuickAssistAssistant getQuickAssistAssistant(final ISourceViewer sourceViewer) { final IQuickAssistAssistant assistant = new QuickAssistAssistant(); final SuiteSourceQuickAssistProcessor processor = new SuiteSourceQuickAssistProcessor(editor.getFileModel(), sourceViewer); assistant.setQuickAssistProcessor(processor); assistant.addCompletionListener(processor); sourceViewer.getTextWidget().addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(final DisposeEvent e) { assistant.removeCompletionListener(processor); } }); assistant.setInformationControlCreator(new AbstractReusableInformationControlCreator() { @Override protected IInformationControl doCreateInformationControl(final Shell parent) { return new DefaultInformationControl(parent, true); } }); return assistant; } @Override public String[] getConfiguredContentTypes(final ISourceViewer sourceViewer) { final List<String> legal = newArrayList(SuiteSourcePartitionScanner.LEGAL_CONTENT_TYPES); legal.add(0, IDocument.DEFAULT_CONTENT_TYPE); return legal.toArray(new String[0]); } @Override public IPresentationReconciler getPresentationReconciler(final ISourceViewer sourceViewer) { final PresentationReconciler reconciler = new PresentationReconciler(); final RedPreferences preferences = RedPlugin.getDefault().getPreferences(); final ColoringPreference sectionPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.SECTION_HEADER); final IToken section = new Token(createAttribute(sectionPref)); final ColoringPreference commentPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.COMMENT); final IToken comment = new Token(createAttribute(commentPref)); final ColoringPreference definitionPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.DEFINITION); final IToken definition = new Token(createAttribute(definitionPref)); final ColoringPreference variablePref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.VARIABLE); final IToken variable = new Token(createAttribute(variablePref)); final ColoringPreference callPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.KEYWORD_CALL); final IToken call = new Token(createAttribute(callPref)); final ColoringPreference settingPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.SETTING); final IToken setting = new Token(createAttribute(settingPref)); final ColoringPreference gherkinPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.GHERKIN); final IToken gherkin = new Token(createAttribute(gherkinPref)); final ColoringPreference specialTokenPref = preferences.getSyntaxColoring(SyntaxHighlightingCategory.SPECIAL); final IToken specialToken = new Token(createAttribute(specialTokenPref)); final ColoringPreference garbagePref = preferences .getSyntaxColoring(SyntaxHighlightingCategory.DEFAULT_SECTION); final IToken defaultSection = new Token(createAttribute(garbagePref)); final ISyntaxColouringRule[] defaultRules = new ISyntaxColouringRule[] { new SectionHeaderRule(section), new CommentRule(comment), new MatchEverythingRule(defaultSection) }; final RedTokensStore store = new RedTokensStore(); sourceViewer.addTextInputListener(store); createDamageRepairer(reconciler, IDocument.DEFAULT_CONTENT_TYPE, store, defaultRules); final ISyntaxColouringRule[] testCasesRules = new ISyntaxColouringRule[] { new SectionHeaderRule(section), new CaseNameRule(definition), new TestCaseSettingsRule(setting), new TestCaseSettingsCallRule(call), new GherkinPrefixRule(gherkin), new ExecutableRowCallRule(call), new CommentRule(comment), new VariableUsageRule(variable), new InTokenRule(specialToken) }; createDamageRepairer(reconciler, SuiteSourcePartitionScanner.TEST_CASES_SECTION, store, testCasesRules); final ISyntaxColouringRule[] keywordsRules = new ISyntaxColouringRule[] { new SectionHeaderRule(section), new KeywordNameRule(definition, variable), new KeywordSettingsRule(setting), new KeywordSettingsCallRule(call), new GherkinPrefixRule(gherkin), new ExecutableRowCallRule(call), new CommentRule(comment), new VariableUsageRule(variable), new InTokenRule(specialToken) }; createDamageRepairer(reconciler, SuiteSourcePartitionScanner.KEYWORDS_SECTION, store, keywordsRules); final ISyntaxColouringRule[] settingsRules = new ISyntaxColouringRule[] { new SectionHeaderRule(section), new SettingRule(setting), new SettingsCallRule(call), new CommentRule(comment), new VariableUsageRule(variable), new WithNameRule(specialToken) }; createDamageRepairer(reconciler, SuiteSourcePartitionScanner.SETTINGS_SECTION, store, settingsRules); final ISyntaxColouringRule[] variablesRules = new ISyntaxColouringRule[] { new SectionHeaderRule(section), new VariableDefinitionRule(variable), new CommentRule(comment), new VariableUsageRule(variable) }; createDamageRepairer(reconciler, SuiteSourcePartitionScanner.VARIABLES_SECTION, store, variablesRules); return reconciler; } private TextAttribute createAttribute(final ColoringPreference sectionPref) { return new TextAttribute(ColorsManager.getColor(sectionPref.getRgb()), null, sectionPref.getFontStyle()); } private void createDamageRepairer(final PresentationReconciler reconciler, final String contentType, final RedTokensStore store, final ISyntaxColouringRule[] rules) { final boolean useDirectScanner = RedSystemProperties.shouldUseDirectScanner(); final RedTokenScanner tokenScanner = new RedTokenScanner(rules); final ITokenScanner scanner = useDirectScanner ? tokenScanner : new RedCachingScanner(tokenScanner, store); final DefaultDamagerRepairer damagerRepairer = useDirectScanner ? new DefaultDamagerRepairer(scanner) : new RedDamagerRepairer(scanner, editor.getViewer()); reconciler.setDamager(damagerRepairer, contentType); reconciler.setRepairer(damagerRepairer, contentType); } @Override public IReconciler getReconciler(final ISourceViewer sourceViewer) { if (reconciler == null) { reconciler = new MonoReconciler(getReconcilingStrategy(), true); } return reconciler; } private IReconcilingStrategy getReconcilingStrategy() { return new SuiteSourceReconcilingStrategy(editor); } @Override public IContentFormatter getContentFormatter(final ISourceViewer sourceViewer) { final MultiPassContentFormatter formatter = new MultiPassContentFormatter( getConfiguredDocumentPartitioning(sourceViewer), IDocument.DEFAULT_CONTENT_TYPE); formatter.setMasterStrategy(new SuiteSourceFormattingStrategy()); return formatter; } }