/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.text;
import com.google.dart.tools.core.DartCoreDebug;
import com.google.dart.tools.ui.DartToolsPlugin;
import com.google.dart.tools.ui.DartX;
import com.google.dart.tools.ui.actions.DartEditorActionDefinitionIds;
import com.google.dart.tools.ui.internal.text.correction.DartCorrectionAssistant_NEW;
import com.google.dart.tools.ui.internal.text.correction.DartCorrectionAssistant_OLD;
import com.google.dart.tools.ui.internal.text.dart.ContentAssistProcessor;
import com.google.dart.tools.ui.internal.text.dart.DartAutoIndentStrategy_NEW;
import com.google.dart.tools.ui.internal.text.dart.DartAutoIndentStrategy_OLD;
import com.google.dart.tools.ui.internal.text.dart.DartCodeScanner;
import com.google.dart.tools.ui.internal.text.dart.DartCompletionProcessor;
import com.google.dart.tools.ui.internal.text.dart.DartDocDoubleClickStrategy;
import com.google.dart.tools.ui.internal.text.dart.DartDoubleClickSelector_NEW;
import com.google.dart.tools.ui.internal.text.dart.DartDoubleClickSelector_OLD;
import com.google.dart.tools.ui.internal.text.dart.DartReconcilingEditor;
import com.google.dart.tools.ui.internal.text.dart.DartReconcilingStrategy;
import com.google.dart.tools.ui.internal.text.dart.DartStringAutoIndentStrategy;
import com.google.dart.tools.ui.internal.text.dart.DartStringDoubleClickSelector_NEW;
import com.google.dart.tools.ui.internal.text.dart.DartStringDoubleClickSelector_OLD;
import com.google.dart.tools.ui.internal.text.dart.SmartSemicolonAutoEditStrategy;
import com.google.dart.tools.ui.internal.text.dartdoc.DartDocAutoIndentStrategy;
import com.google.dart.tools.ui.internal.text.dartdoc.DartDocScanner;
import com.google.dart.tools.ui.internal.text.dartdoc.LineDocAutoIndentStrategy;
import com.google.dart.tools.ui.internal.text.editor.DartHover;
import com.google.dart.tools.ui.internal.text.functions.AbstractDartScanner;
import com.google.dart.tools.ui.internal.text.functions.ContentAssistPreference;
import com.google.dart.tools.ui.internal.text.functions.DartCommentScanner;
import com.google.dart.tools.ui.internal.text.functions.DartElementProvider;
import com.google.dart.tools.ui.internal.text.functions.DartMultilineStringScanner;
import com.google.dart.tools.ui.internal.text.functions.DartOutlineElementProvider;
import com.google.dart.tools.ui.internal.text.functions.DartOutlineElementProvider_NEW;
import com.google.dart.tools.ui.internal.text.functions.DartOutlineInformationControl;
import com.google.dart.tools.ui.internal.text.functions.DartOutlineInformationControl_NEW;
import com.google.dart.tools.ui.internal.text.functions.DartPresentationReconciler;
import com.google.dart.tools.ui.internal.text.functions.HTMLAnnotationHover;
import com.google.dart.tools.ui.internal.text.functions.PreferencesAdapter;
import com.google.dart.tools.ui.internal.text.functions.SingleTokenDartScanner;
import com.google.dart.tools.ui.internal.typehierarchy.HierarchyInformationControl_NEW;
import com.google.dart.tools.ui.internal.typehierarchy.HierarchyInformationControl_OLD;
import com.google.dart.tools.ui.internal.util.CodeFormatterUtil;
import com.google.dart.tools.ui.text.editor.tmp.JavaScriptCore;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.internal.text.html.HTMLTextPresenter;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.ITextDoubleClickStrategy;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter;
import org.eclipse.jface.text.hyperlink.IHyperlinkPresenter;
import org.eclipse.jface.text.information.IInformationPresenter;
import org.eclipse.jface.text.information.IInformationProvider;
import org.eclipse.jface.text.information.InformationPresenter;
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.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.RuleBasedScanner;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.ITextEditor;
import java.util.Arrays;
import java.util.Map;
/**
* Configuration for a source viewer which shows Dart code.
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
* Provisional API: This class/interface is part of an interim API that is still under development
* and expected to change significantly before reaching stability. It is being made available at
* this early stage to solicit feedback from pioneering adopters on the understanding that any code
* that uses this API will almost certainly be broken (repeatedly) as the API evolves.
*/
@SuppressWarnings("restriction")
public class DartSourceViewerConfiguration extends TextSourceViewerConfiguration {
/**
* Creates and returns a preference store which combines the preference stores from the text tools
* and which is read-only.
*
* @param javaTextTools the Dart text tools
* @return the combined read-only preference store
*/
@SuppressWarnings("unused")
private static final IPreferenceStore createPreferenceStore(DartTextTools javaTextTools) {
Assert.isNotNull(javaTextTools);
IPreferenceStore generalTextStore = EditorsUI.getPreferenceStore();
if (javaTextTools.getCorePreferenceStore() == null) {
return new ChainedPreferenceStore(new IPreferenceStore[] {
javaTextTools.getPreferenceStore(), generalTextStore});
}
return new ChainedPreferenceStore(new IPreferenceStore[] {
javaTextTools.getPreferenceStore(),
new PreferencesAdapter(javaTextTools.getCorePreferenceStore()), generalTextStore});
}
private static IInformationControlCreator getHierarchyPresenterControlCreator(
ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
int shellStyle = SWT.RESIZE;
int treeStyle = SWT.V_SCROLL | SWT.H_SCROLL;
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
return new HierarchyInformationControl_NEW(parent, shellStyle, treeStyle);
} else {
return new HierarchyInformationControl_OLD(parent, shellStyle, treeStyle);
}
}
};
}
private DartTextTools fJavaTextTools;
private ITextEditor fTextEditor;
/**
* The document partitioning.
*/
private String fDocumentPartitioning;
/**
* The Dart source code scanner.
*/
private AbstractDartScanner fCodeScanner;
/**
* The Dart multi-line comment scanner.
*/
private AbstractDartScanner fMultilineCommentScanner;
/**
* The Dart single-line comment scanner.
*/
private AbstractDartScanner fSinglelineCommentScanner;
/**
* The Dart string scanner.
*/
private AbstractDartScanner fStringScanner;
/**
* The Dart multi-line scanner
*/
private AbstractDartScanner fMultilineStringScanner;
/**
* The Doc scanner.
*/
private AbstractDartScanner fJavaDocScanner;
/**
* The color manager.
*/
private IColorManager fColorManager;
/**
* The double click strategy.
*/
private DartDoubleClickSelector_OLD fJavaDoubleClickSelector_OLD;
/**
* The double click strategy.
*/
private DartDoubleClickSelector_NEW fJavaDoubleClickSelector_NEW;
/**
* Creates a new Dart source viewer configuration for viewers in the given editor using the given
* preference store, the color manager and the specified document partitioning.
* <p>
* Creates a Dart source viewer configuration in the new setup without text tools. Clients are
* allowed to call
* {@link DartSourceViewerConfiguration#handlePropertyChangeEvent(PropertyChangeEvent)} on the
* resulting Dart source viewer configuration.
* </p>
*
* @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 DartSourceViewerConfiguration(IColorManager colorManager,
IPreferenceStore preferenceStore, ITextEditor editor, String partitioning) {
super(preferenceStore);
fColorManager = colorManager;
fTextEditor = editor;
fDocumentPartitioning = partitioning;
initializeScanners();
}
/**
* 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) {
return fCodeScanner.affectsBehavior(event) || fMultilineCommentScanner.affectsBehavior(event)
|| fSinglelineCommentScanner.affectsBehavior(event)
|| fStringScanner.affectsBehavior(event) || fJavaDocScanner.affectsBehavior(event)
|| fMultilineStringScanner.affectsBehavior(event);
}
@Override
public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
return new HTMLAnnotationHover() {
@Override
protected boolean isIncluded(Annotation annotation) {
return isShowInVerticalRuler(annotation);
}
};
}
@Override
public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
DartX.todo("indent");
String partitioning = getConfiguredDocumentPartitioning(sourceViewer);
if (DartPartitions.DART_DOC.equals(contentType)
|| DartPartitions.DART_MULTI_LINE_COMMENT.equals(contentType)) {
return new IAutoEditStrategy[] {new DartDocAutoIndentStrategy(partitioning)};
} else if (DartPartitions.DART_SINGLE_LINE_DOC.equals(contentType)) {
return new IAutoEditStrategy[] {new LineDocAutoIndentStrategy(partitioning)};
} else if (DartPartitions.DART_MULTI_LINE_STRING.equals(contentType)) {
return new IAutoEditStrategy[] {
new SmartSemicolonAutoEditStrategy(partitioning),
new DartStringAutoIndentStrategy(partitioning)};
} else if (DartPartitions.DART_STRING.equals(contentType)) {
return new IAutoEditStrategy[] {
new SmartSemicolonAutoEditStrategy(partitioning),
new DartStringAutoIndentStrategy(partitioning)};
} else if (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)) {
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
return new IAutoEditStrategy[] {
new SmartSemicolonAutoEditStrategy(partitioning),
new DartAutoIndentStrategy_NEW(partitioning, sourceViewer)};
} else {
return new IAutoEditStrategy[] {
new SmartSemicolonAutoEditStrategy(partitioning),
new DartAutoIndentStrategy_OLD(partitioning, sourceViewer)};
}
} else {
return new IAutoEditStrategy[] {new DartAutoIndentStrategy_OLD(partitioning, sourceViewer)};
}
}
@Override
public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
return new String[] {
IDocument.DEFAULT_CONTENT_TYPE, DartPartitions.DART_DOC,
DartPartitions.DART_MULTI_LINE_COMMENT, DartPartitions.DART_SINGLE_LINE_COMMENT,
DartPartitions.DART_SINGLE_LINE_DOC, DartPartitions.DART_STRING,
DartPartitions.DART_MULTI_LINE_STRING};
}
@Override
public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
if (fDocumentPartitioning != null) {
return fDocumentPartitioning;
}
return super.getConfiguredDocumentPartitioning(sourceViewer);
}
@Override
public int[] getConfiguredTextHoverStateMasks(ISourceViewer sourceViewer, String contentType) {
return new int[] {0};
// return super.getConfiguredTextHoverStateMasks(sourceViewer, contentType);
// JavaEditorTextHoverDescriptor[] hoverDescs =
// DartToolsPlugin.getDefault().getJavaEditorTextHoverDescriptors();
// int stateMasks[] = new int[hoverDescs.length];
// int stateMasksLength = 0;
// for (int i = 0; i < hoverDescs.length; i++) {
// if (hoverDescs[i].isEnabled()) {
// int j = 0;
// int stateMask = hoverDescs[i].getStateMask();
// while (j < stateMasksLength) {
// if (stateMasks[j] == stateMask)
// break;
// j++;
// }
// if (j == stateMasksLength)
// stateMasks[stateMasksLength++] = stateMask;
// }
// }
// if (stateMasksLength == hoverDescs.length)
// return stateMasks;
//
// int[] shortenedStateMasks = new int[stateMasksLength];
// System.arraycopy(stateMasks, 0, shortenedStateMasks, 0,
// stateMasksLength);
// return shortenedStateMasks;
}
@Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
if (getEditor() != null) {
ContentAssistant assistant = new DartEditorContentAssistant(sourceViewer);
assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
IContentAssistProcessor javaProcessor = new DartCompletionProcessor(
getEditor(),
assistant,
IDocument.DEFAULT_CONTENT_TYPE);
assistant.setContentAssistProcessor(javaProcessor, IDocument.DEFAULT_CONTENT_TYPE);
ContentAssistProcessor singleLineProcessor = new DartCompletionProcessor(
getEditor(),
assistant,
DartPartitions.DART_SINGLE_LINE_COMMENT);
assistant.setContentAssistProcessor(
singleLineProcessor,
DartPartitions.DART_SINGLE_LINE_COMMENT);
// TODO temporary, see docProcessor below
assistant.setContentAssistProcessor(singleLineProcessor, DartPartitions.DART_SINGLE_LINE_DOC);
ContentAssistProcessor stringProcessor = new DartCompletionProcessor(
getEditor(),
assistant,
DartPartitions.DART_STRING);
assistant.setContentAssistProcessor(stringProcessor, DartPartitions.DART_STRING);
assistant.setContentAssistProcessor(stringProcessor, DartPartitions.DART_MULTI_LINE_STRING);
ContentAssistProcessor multiLineProcessor = new DartCompletionProcessor(
getEditor(),
assistant,
DartPartitions.DART_MULTI_LINE_COMMENT);
assistant.setContentAssistProcessor(
multiLineProcessor,
DartPartitions.DART_MULTI_LINE_COMMENT);
// TODO temporary, see docProcessor below
assistant.setContentAssistProcessor(multiLineProcessor, DartPartitions.DART_DOC);
// TODO Code completion in doc comments
// ContentAssistProcessor docProcessor = new DartDocCompletionProcessor(getEditor(), assistant);
// assistant.setContentAssistProcessor(docProcessor, DartPartitions.DART_DOC);
// assistant.setContentAssistProcessor(docProcessor, DartPartitions.DART_SINGLE_LINE_DOC);
ContentAssistPreference.configure(assistant, fPreferenceStore);
assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
return assistant;
}
return null;
}
@Override
public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
// final MultiPassContentFormatter formatter = new MultiPassContentFormatter(
// getConfiguredDocumentPartitioning(sourceViewer),
// IDocument.DEFAULT_CONTENT_TYPE);
//
// formatter.setMasterStrategy(new DartFormattingStrategy());
// formatter.setSlaveStrategy(new CommentFormattingStrategy(), DartPartitions.DART_DOC);
// formatter.setSlaveStrategy(
// new CommentFormattingStrategy(),
// DartPartitions.DART_SINGLE_LINE_COMMENT);
// formatter.setSlaveStrategy(new CommentFormattingStrategy(), DartPartitions.DART_SINGLE_LINE_DOC);
// formatter.setSlaveStrategy(
// new CommentFormattingStrategy(),
// DartPartitions.DART_MULTI_LINE_COMMENT);
//
// return formatter;
return null;
}
@Override
public String[] getDefaultPrefixes(ISourceViewer sourceViewer, String contentType) {
if (DartPartitions.DART_SINGLE_LINE_DOC.equals(contentType)) {
return new String[] {"///", ""}; //$NON-NLS-1$ //$NON-NLS-2$
}
return new String[] {"//", ""}; //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer,
String contentType) {
if (DartPartitions.DART_DOC.equals(contentType)
|| DartPartitions.DART_SINGLE_LINE_DOC.equals(contentType)) {
return new DartDocDoubleClickStrategy();
}
if (DartPartitions.DART_MULTI_LINE_COMMENT.equals(contentType)
|| DartPartitions.DART_SINGLE_LINE_COMMENT.equals(contentType)) {
return new DefaultTextDoubleClickStrategy();
} else if (DartPartitions.DART_STRING.equals(contentType)
|| DartPartitions.DART_MULTI_LINE_STRING.equals(contentType)) {
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
return new DartStringDoubleClickSelector_NEW();
} else {
return new DartStringDoubleClickSelector_OLD();
}
}
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
if (fJavaDoubleClickSelector_NEW == null) {
fJavaDoubleClickSelector_NEW = new DartDoubleClickSelector_NEW();
fJavaDoubleClickSelector_NEW.setSourceVersion(fPreferenceStore.getString(JavaScriptCore.COMPILER_SOURCE));
}
return fJavaDoubleClickSelector_NEW;
} else {
if (fJavaDoubleClickSelector_OLD == null) {
fJavaDoubleClickSelector_OLD = new DartDoubleClickSelector_OLD();
fJavaDoubleClickSelector_OLD.setSourceVersion(fPreferenceStore.getString(JavaScriptCore.COMPILER_SOURCE));
}
return fJavaDoubleClickSelector_OLD;
}
}
/**
* Returns the hierarchy presenter which will determine and shown type hierarchy information
* requested for the current cursor position.
*
* @param sourceViewer the source viewer to be configured by this configuration
* @param doCodeResolve a boolean which specifies whether code resolve should be used to compute
* the Dart element
* @return an information presenter
*/
public IInformationPresenter getHierarchyPresenter(ISourceViewer sourceViewer,
boolean doCodeResolve) {
IInformationControlCreator hierarchyPresenterControlCreator = getHierarchyPresenterControlCreator(sourceViewer);
InformationPresenter presenter = new InformationPresenter(hierarchyPresenterControlCreator);
presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
IInformationProvider provider = new DartElementProvider(getEditor(), doCodeResolve);
presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
presenter.setInformationProvider(provider, DartPartitions.DART_DOC);
presenter.setInformationProvider(provider, DartPartitions.DART_MULTI_LINE_COMMENT);
presenter.setInformationProvider(provider, DartPartitions.DART_SINGLE_LINE_COMMENT);
presenter.setInformationProvider(provider, DartPartitions.DART_STRING);
presenter.setInformationProvider(provider, DartPartitions.DART_MULTI_LINE_STRING);
presenter.setSizeConstraints(50, 20, true, false);
return presenter;
}
/**
* Returns the hyperlink presenter for the given source viewer. This implementation always returns
* the {@link DefaultHyperlinkPresenter}.
*
* @param sourceViewer the source viewer to be configured by this configuration
* @return the hyperlink presenter or <code>null</code> if no hyperlink support should be
* installed
* @since 3.1
*/
@Override
public IHyperlinkPresenter getHyperlinkPresenter(ISourceViewer sourceViewer) {
return new DefaultHyperlinkPresenter(fColorManager.getColor("dart_doc_link"));
}
@Override
public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) {
return super.getIndentPrefixes(sourceViewer, contentType);
// DartProject project = getProject();
// final int tabWidth = CodeFormatterUtil.getTabWidth(project);
// final int indentWidth = CodeFormatterUtil.getIndentWidth(project);
// boolean allowTabs = tabWidth <= indentWidth;
//
// String indentMode;
// if (project == null)
// indentMode =
// JavaScriptCore.getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR);
// else
// indentMode = project.getOption(
// DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, true);
//
// boolean useSpaces = JavaScriptCore.SPACE.equals(indentMode)
// || DefaultCodeFormatterConstants.MIXED.equals(indentMode);
//
// Assert.isLegal(allowTabs || useSpaces);
//
// if (!allowTabs) {
// char[] spaces = new char[indentWidth];
// Arrays.fill(spaces, ' ');
// return new String[]{new String(spaces), ""}; //$NON-NLS-1$
// } else if (!useSpaces)
// return getIndentPrefixesForTab(tabWidth);
// else
// return getIndentPrefixesForSpaces(tabWidth);
}
@Override
public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, new HTMLTextPresenter(true));
}
};
}
@Override
public IInformationPresenter getInformationPresenter(ISourceViewer sourceViewer) {
return super.getInformationPresenter(sourceViewer);
// InformationPresenter presenter = new InformationPresenter(
// getInformationPresenterControlCreator(sourceViewer));
// presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
//
// // Register information provider
// IInformationProvider provider = new JavaInformationProvider(getEditor());
// String[] contentTypes = getConfiguredContentTypes(sourceViewer);
// for (int i = 0; i < contentTypes.length; i++)
// presenter.setInformationProvider(provider, contentTypes[i]);
//
// presenter.setSizeConstraints(60, 10, true, true);
// return presenter;
}
/**
* Returns the outline presenter which will determine and shown information requested for the
* current cursor position.
*
* @param sourceViewer the source viewer to be configured by this configuration
* @param doCodeResolve a boolean which specifies whether code resolve should be used to compute
* the Dart element
* @return an information presenter
*/
@SuppressWarnings("deprecation")
public IInformationPresenter getOutlinePresenter(ISourceViewer sourceViewer, boolean doCodeResolve) {
InformationPresenter presenter;
if (doCodeResolve) {
presenter = new InformationPresenter(getOutlinePresenterControlCreator(
sourceViewer,
DartEditorActionDefinitionIds.OPEN_STRUCTURE));
} else {
presenter = new InformationPresenter(getOutlinePresenterControlCreator(
sourceViewer,
DartEditorActionDefinitionIds.SHOW_OUTLINE));
}
presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
IInformationProvider provider;
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
provider = new DartOutlineElementProvider_NEW(getEditor());
} else {
provider = new DartOutlineElementProvider(getEditor());
}
presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
presenter.setInformationProvider(provider, DartPartitions.DART_DOC);
presenter.setInformationProvider(provider, DartPartitions.DART_MULTI_LINE_COMMENT);
presenter.setInformationProvider(provider, DartPartitions.DART_SINGLE_LINE_COMMENT);
presenter.setInformationProvider(provider, DartPartitions.DART_SINGLE_LINE_DOC);
presenter.setInformationProvider(provider, DartPartitions.DART_STRING);
presenter.setInformationProvider(provider, DartPartitions.DART_MULTI_LINE_STRING);
presenter.setInformationProvider(provider, DartPartitions.JAVA_CHARACTER);
presenter.setSizeConstraints(50, 20, true, false);
return presenter;
}
@Override
public IAnnotationHover getOverviewRulerAnnotationHover(ISourceViewer sourceViewer) {
return new HTMLAnnotationHover() {
@Override
protected boolean isIncluded(Annotation annotation) {
return isShowInOverviewRuler(annotation);
}
};
}
@Override
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
PresentationReconciler reconciler = new DartPresentationReconciler();
reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getCodeScanner());
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
dr = new DefaultDamagerRepairer(getJavaDocScanner());
reconciler.setDamager(new DartIndiscriminateDamager(), DartPartitions.DART_DOC);
reconciler.setRepairer(dr, DartPartitions.DART_DOC);
reconciler.setDamager(new DartIndiscriminateDamager(), DartPartitions.DART_SINGLE_LINE_DOC);
reconciler.setRepairer(dr, DartPartitions.DART_SINGLE_LINE_DOC);
dr = new DefaultDamagerRepairer(getMultilineCommentScanner());
reconciler.setDamager(dr, DartPartitions.DART_MULTI_LINE_COMMENT);
reconciler.setRepairer(dr, DartPartitions.DART_MULTI_LINE_COMMENT);
dr = new DefaultDamagerRepairer(getSinglelineCommentScanner());
reconciler.setDamager(dr, DartPartitions.DART_SINGLE_LINE_COMMENT);
reconciler.setRepairer(dr, DartPartitions.DART_SINGLE_LINE_COMMENT);
dr = new DefaultDamagerRepairer(getStringScanner());
reconciler.setDamager(dr, DartPartitions.DART_STRING);
reconciler.setRepairer(dr, DartPartitions.DART_STRING);
dr = new DefaultDamagerRepairer(getMultilineStringScanner());
reconciler.setDamager(dr, DartPartitions.DART_MULTI_LINE_STRING);
reconciler.setRepairer(dr, DartPartitions.DART_MULTI_LINE_STRING);
return reconciler;
}
@Override
public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
ITextEditor editor = getEditor();
if (editor != null) {
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
DartCorrectionAssistant_NEW assistant = new DartCorrectionAssistant_NEW(editor);
assistant.setRestoreCompletionProposalSize(getSettings("quick_assist_proposal_size")); //$NON-NLS-1$
return assistant;
} else {
DartCorrectionAssistant_OLD assistant = new DartCorrectionAssistant_OLD(editor);
assistant.setRestoreCompletionProposalSize(getSettings("quick_assist_proposal_size")); //$NON-NLS-1$
return assistant;
}
}
return null;
}
@Override
public IReconciler getReconciler(ISourceViewer sourceViewer) {
DartX.todo("spelling");
final ITextEditor editor = getEditor();
if (editor instanceof DartReconcilingEditor) {
DartReconcilingEditor dartEditor = (DartReconcilingEditor) editor;
IReconcilingStrategy strategy = new DartReconcilingStrategy(dartEditor);
MonoReconciler reconciler = new MonoReconciler(strategy, true);
reconciler.setIsIncrementalReconciler(true);
reconciler.setIsAllowedToModifyDocument(false);
reconciler.setProgressMonitor(new NullProgressMonitor());
reconciler.setDelay(500);
return reconciler;
}
return null;
}
@Override
public int getTabWidth(ISourceViewer sourceViewer) {
return CodeFormatterUtil.getTabWidth();
}
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
return getTextHover(sourceViewer, contentType, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
}
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType, int stateMask) {
return new DartHover(fTextEditor, sourceViewer, this);
// JavaEditorTextHoverDescriptor[] hoverDescs =
// DartToolsPlugin.getDefault().getJavaEditorTextHoverDescriptors();
// int i = 0;
// while (i < hoverDescs.length) {
// if (hoverDescs[i].isEnabled()
// && hoverDescs[i].getStateMask() == stateMask)
// return new JavaEditorTextHoverProxy(hoverDescs[i], getEditor());
// i++;
// }
//
// return null;
}
/**
* 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 DartSourceViewerConfiguration#JavaSourceViewerConfiguration(IColorManager,
* IPreferenceStore, ITextEditor, String)
*/
public void handlePropertyChangeEvent(PropertyChangeEvent event) {
Assert.isTrue(isNewSetup());
if (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 (fMultilineStringScanner.affectsBehavior(event)) {
fMultilineStringScanner.adaptToPreferenceChange(event);
}
if (fJavaDocScanner.affectsBehavior(event)) {
fJavaDocScanner.adaptToPreferenceChange(event);
}
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
if (fJavaDoubleClickSelector_NEW != null
&& JavaScriptCore.COMPILER_SOURCE.equals(event.getProperty())) {
if (event.getNewValue() instanceof String) {
fJavaDoubleClickSelector_NEW.setSourceVersion((String) event.getNewValue());
}
}
} else {
if (fJavaDoubleClickSelector_OLD != null
&& JavaScriptCore.COMPILER_SOURCE.equals(event.getProperty())) {
if (event.getNewValue() instanceof String) {
fJavaDoubleClickSelector_OLD.setSourceVersion((String) event.getNewValue());
}
}
}
}
/**
* Made public for visibility outside of the package.
*/
@Override
public boolean isShownInText(Annotation annotation) {
return super.isShownInText(annotation);
}
/**
* Returns the Dart source code scanner for this configuration.
*
* @return the Dart source code scanner
*/
protected RuleBasedScanner getCodeScanner() {
return fCodeScanner;
}
/**
* Returns the color manager for this configuration.
*
* @return the color manager
*/
protected IColorManager getColorManager() {
return fColorManager;
}
/**
* Returns the editor in which the configured viewer(s) will reside.
*
* @return the enclosing editor
*/
protected ITextEditor getEditor() {
return fTextEditor;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
Map targets = super.getHyperlinkDetectorTargets(sourceViewer);
targets.put("com.google.dart.tools.ui.dartCode", fTextEditor); //$NON-NLS-1$
return targets;
}
/**
* Returns the JavaDoc scanner for this configuration.
*
* @return the JavaDoc scanner
*/
protected RuleBasedScanner getJavaDocScanner() {
return fJavaDocScanner;
}
/**
* Returns the Dart multi-line comment scanner for this configuration.
*
* @return the Dart multi-line comment scanner
*/
protected RuleBasedScanner getMultilineCommentScanner() {
return fMultilineCommentScanner;
}
/**
* Returns the Dart multi-line string scanner for this configuration.
*
* @return the Dart multi-line string scanner
*/
protected RuleBasedScanner getMultilineStringScanner() {
return fMultilineStringScanner;
}
/**
* Returns the Dart single-line comment scanner for this configuration.
*
* @return the Dart single-line comment scanner
*/
protected RuleBasedScanner getSinglelineCommentScanner() {
return fSinglelineCommentScanner;
}
/**
* Returns the Dart string scanner for this configuration.
*
* @return the Dart string scanner
*/
protected RuleBasedScanner getStringScanner() {
return fStringScanner;
}
/**
* Computes and returns the indent prefixes for space indentation and the given
* <code>tabWidth</code>.
*
* @param tabWidth the display tab width
* @return the indent prefixes
* @see #getIndentPrefixes(ISourceViewer, String)
*/
@SuppressWarnings("unused")
private String[] getIndentPrefixesForSpaces(int tabWidth) {
String[] indentPrefixes = new String[tabWidth + 2];
indentPrefixes[0] = getStringWithSpaces(tabWidth);
for (int i = 0; i < tabWidth; i++) {
String spaces = getStringWithSpaces(i);
if (i < tabWidth) {
indentPrefixes[i + 1] = spaces + '\t';
} else {
indentPrefixes[i + 1] = new String(spaces);
}
}
indentPrefixes[tabWidth + 1] = ""; //$NON-NLS-1$
return indentPrefixes;
}
/**
* Returns the information presenter control creator. The creator is a factory creating the
* presenter controls for the given source viewer. This implementation always returns a creator
* for <code>DefaultInformationControl</code> instances.
*
* @param sourceViewer the source viewer to be configured by this configuration
* @return an information control creator
*/
@SuppressWarnings("unused")
private IInformationControlCreator getInformationPresenterControlCreator(
ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
@SuppressWarnings("deprecation")
@Override
public IInformationControl createInformationControl(Shell parent) {
int shellStyle = SWT.RESIZE | SWT.TOOL;
int style = SWT.V_SCROLL | SWT.H_SCROLL;
return new DefaultInformationControl(
parent,
shellStyle,
style,
new HTMLTextPresenter(false));
}
};
}
/**
* Returns the outline presenter control creator. The creator is a factory creating outline
* presenter controls for the given source viewer. This implementation always returns a creator
* for <code>DartOutlineInformationControl</code> instances.
*
* @param sourceViewer the source viewer to be configured by this configuration
* @param commandId the ID of the command that opens this control
* @return an information control creator
*/
private IInformationControlCreator getOutlinePresenterControlCreator(ISourceViewer sourceViewer,
final String commandId) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
int shellStyle = SWT.RESIZE;
if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
return new DartOutlineInformationControl_NEW(parent, shellStyle, fTextEditor);
} else {
return new DartOutlineInformationControl(parent, shellStyle, fTextEditor);
}
}
};
}
/**
* Returns the settings for the given section.
*
* @param sectionName the section name
* @return the settings
*/
private IDialogSettings getSettings(String sectionName) {
IDialogSettings settings = DartToolsPlugin.getDefault().getDialogSettings().getSection(
sectionName);
if (settings == null) {
settings = DartToolsPlugin.getDefault().getDialogSettings().addNewSection(sectionName);
}
return settings;
}
/**
* Creates and returns a String with <code>count</code> spaces.
*
* @param count the space count
* @return the string with the spaces
*/
private String getStringWithSpaces(int count) {
char[] spaceChars = new char[count];
Arrays.fill(spaceChars, ' ');
return new String(spaceChars);
}
/**
* Initializes the scanners.
*/
private void initializeScanners() {
Assert.isTrue(isNewSetup());
fCodeScanner = new DartCodeScanner(getColorManager(), fPreferenceStore);
fMultilineCommentScanner = new DartCommentScanner(
getColorManager(),
fPreferenceStore,
IDartColorConstants.JAVA_MULTI_LINE_COMMENT);
fSinglelineCommentScanner = new DartCommentScanner(
getColorManager(),
fPreferenceStore,
IDartColorConstants.JAVA_SINGLE_LINE_COMMENT);
fStringScanner = new SingleTokenDartScanner(
getColorManager(),
fPreferenceStore,
IDartColorConstants.JAVA_STRING);
fMultilineStringScanner = new DartMultilineStringScanner(
getColorManager(),
fPreferenceStore,
IDartColorConstants.DART_MULTI_LINE_STRING);
fJavaDocScanner = new DartDocScanner(getColorManager(), fPreferenceStore);
}
/**
* @return <code>true</code> iff the new setup without text tools is in use.
*/
private boolean isNewSetup() {
return fJavaTextTools == null;
}
}