blob: 6c803cc7b8dc87e5297009ff9a309769cdb21f41 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Tom Eicher (Avaloq Evolution AG) - block selection mode
* Kelly Campbell <kellyc@google.com> - [typing] String literal splitting should use formatter preferences - http://bugs.eclipse.org/48433
*******************************************************************************/
package org.eclipse.jdt.ui.text;
import java.util.Arrays;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.text.AbstractInformationControlManager;
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.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.formatter.MultiPassContentFormatter;
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.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.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.text.AbstractJavaScanner;
import org.eclipse.jdt.internal.ui.text.ContentAssistPreference;
import org.eclipse.jdt.internal.ui.text.HTMLAnnotationHover;
import org.eclipse.jdt.internal.ui.text.JavaCommentScanner;
import org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy;
import org.eclipse.jdt.internal.ui.text.JavaElementProvider;
import org.eclipse.jdt.internal.ui.text.JavaOutlineInformationControl;
import org.eclipse.jdt.internal.ui.text.JavaPresentationReconciler;
import org.eclipse.jdt.internal.ui.text.JavaReconciler;
import org.eclipse.jdt.internal.ui.text.PreferencesAdapter;
import org.eclipse.jdt.internal.ui.text.SingleTokenJavaScanner;
import org.eclipse.jdt.internal.ui.text.correction.JavaCorrectionAssistant;
import org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor;
import org.eclipse.jdt.internal.ui.text.java.JavaAutoIndentStrategy;
import org.eclipse.jdt.internal.ui.text.java.JavaCodeScanner;
import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProcessor;
import org.eclipse.jdt.internal.ui.text.java.JavaDoubleClickSelector;
import org.eclipse.jdt.internal.ui.text.java.JavaFormattingStrategy;
import org.eclipse.jdt.internal.ui.text.java.JavaMultiLineStringAutoIndentStrategy;
import org.eclipse.jdt.internal.ui.text.java.JavaStringAutoIndentStrategy;
import org.eclipse.jdt.internal.ui.text.java.JavadocDoubleClickStrategy;
import org.eclipse.jdt.internal.ui.text.java.PartitionDoubleClickSelector;
import org.eclipse.jdt.internal.ui.text.java.SmartSemicolonAutoEditStrategy;
import org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverDescriptor;
import org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy;
import org.eclipse.jdt.internal.ui.text.java.hover.JavaInformationProvider;
import org.eclipse.jdt.internal.ui.text.javadoc.JavaDocAutoIndentStrategy;
import org.eclipse.jdt.internal.ui.text.javadoc.JavaDocScanner;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocCompletionProcessor;
import org.eclipse.jdt.internal.ui.typehierarchy.HierarchyInformationControl;
/**
* Configuration for a source viewer which shows Java 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.
*/
public class JavaSourceViewerConfiguration extends TextSourceViewerConfiguration {
/**
* Preference key used to look up display tab width.
*
* @since 2.0
* @deprecated As of 3.0, replaced by {@link AbstractDecoratedTextEditorPreferenceConstants#EDITOR_TAB_WIDTH}
*/
@Deprecated
public final static String PREFERENCE_TAB_WIDTH= PreferenceConstants.EDITOR_TAB_WIDTH;
/**
* Preference key for inserting spaces rather than tabs.
*
* @since 2.0
* @deprecated as of 3.1 use {@link org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants#FORMATTER_TAB_CHAR}
*/
@Deprecated
public final static String SPACES_FOR_TABS= PreferenceConstants.EDITOR_SPACES_FOR_TABS;
private JavaTextTools fJavaTextTools;
private ITextEditor fTextEditor;
/**
* The document partitioning.
* @since 3.0
*/
private String fDocumentPartitioning;
/**
* The Java source code scanner.
* @since 3.0
*/
private AbstractJavaScanner fCodeScanner;
/**
* The Java multi-line comment scanner.
* @since 3.0
*/
private AbstractJavaScanner fMultilineCommentScanner;
/**
* The Java single-line comment scanner.
* @since 3.0
*/
private AbstractJavaScanner fSinglelineCommentScanner;
/**
* The Java string scanner.
* @since 3.0
*/
private AbstractJavaScanner fStringScanner;
/**
* The Javadoc scanner.
* @since 3.0
*/
private AbstractJavaScanner fJavaDocScanner;
/**
* The color manager.
* @since 3.0
*/
private IColorManager fColorManager;
/**
* The double click strategy.
* @since 3.1
*/
private JavaDoubleClickSelector fJavaDoubleClickSelector;
/**
* Creates a new Java 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 Java source viewer configuration in the new setup without text tools. Clients are
* allowed to call {@link JavaSourceViewerConfiguration#handlePropertyChangeEvent(PropertyChangeEvent)}
* and disallowed to call {@link JavaSourceViewerConfiguration#getPreferenceStore()} on the resulting
* Java 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
* @since 3.0
*/
public JavaSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore preferenceStore, ITextEditor editor, String partitioning) {
this(colorManager, preferenceStore, editor, partitioning, isModuleInfo(editor));
}
/**
* Creates a new Java 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 Java source viewer configuration in the new setup without text tools. Clients are
* allowed to call
* {@link JavaSourceViewerConfiguration#handlePropertyChangeEvent(PropertyChangeEvent)} and
* disallowed to call {@link JavaSourceViewerConfiguration#getPreferenceStore()} on the resulting
* Java 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
* @param isModuleInfo <code>true</code> if {@link JavaCodeScanner} should be initialized for
* module-info code
* @since 3.14
*/
public JavaSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore preferenceStore, ITextEditor editor, String partitioning, boolean isModuleInfo) {
super(preferenceStore);
fColorManager= colorManager;
fTextEditor= editor;
fDocumentPartitioning= partitioning;
initializeScanners(isModuleInfo);
}
private static boolean isModuleInfo(ITextEditor editor) {
boolean isModuleInfo= false;
if (editor != null && editor.getEditorSite() != null) {
String id= editor.getEditorSite().getId();
if (JavaUI.ID_MODULE_INFO_EDITOR.equals(id) || JavaUI.ID_MODULE_INFO_CF_EDITOR.equals(id) || JavaUI.ID_MODULE_INFO_CF_EDITOR_NO_SOURCE.equals(id)) {
isModuleInfo= true;
}
}
return isModuleInfo;
}
/**
* Creates a new Java source viewer configuration for viewers in the given editor
* using the given Java tools.
*
* @param tools the Java text tools to be used
* @param editor the editor in which the configured viewer(s) will reside, or <code>null</code> if none
* @see JavaTextTools
* @deprecated As of 3.0, replaced by {@link JavaSourceViewerConfiguration#JavaSourceViewerConfiguration(IColorManager, IPreferenceStore, ITextEditor, String)}
*/
@Deprecated
public JavaSourceViewerConfiguration(JavaTextTools tools, ITextEditor editor) {
super(createPreferenceStore(tools));
fJavaTextTools= tools;
fColorManager= tools.getColorManager();
fCodeScanner= (AbstractJavaScanner) fJavaTextTools.getCodeScanner();
fMultilineCommentScanner= (AbstractJavaScanner) fJavaTextTools.getMultilineCommentScanner();
fSinglelineCommentScanner= (AbstractJavaScanner) fJavaTextTools.getSinglelineCommentScanner();
fStringScanner= (AbstractJavaScanner) fJavaTextTools.getStringScanner();
fJavaDocScanner= (AbstractJavaScanner) fJavaTextTools.getJavaDocScanner();
fTextEditor= editor;
}
/**
* Returns the Java source code scanner for this configuration.
*
* @return the Java source code scanner
*/
protected RuleBasedScanner getCodeScanner() {
return fCodeScanner;
}
/**
* Returns the Java multi-line comment scanner for this configuration.
*
* @return the Java multi-line comment scanner
* @since 2.0
*/
protected RuleBasedScanner getMultilineCommentScanner() {
return fMultilineCommentScanner;
}
/**
* Returns the Java single-line comment scanner for this configuration.
*
* @return the Java single-line comment scanner
* @since 2.0
*/
protected RuleBasedScanner getSinglelineCommentScanner() {
return fSinglelineCommentScanner;
}
/**
* Returns the Java string scanner for this configuration.
*
* @return the Java string scanner
* @since 2.0
*/
protected RuleBasedScanner getStringScanner() {
return fStringScanner;
}
/**
* Returns the JavaDoc scanner for this configuration.
*
* @return the JavaDoc scanner
*/
protected RuleBasedScanner getJavaDocScanner() {
return fJavaDocScanner;
}
/**
* 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;
}
/**
* Returns the preference store used by this configuration to initialize
* the individual bits and pieces.
* <p>
* Clients are not allowed to call this method if the new setup without
* text tools is in use.</p>
*
* @return the preference store used to initialize this configuration
* @see JavaSourceViewerConfiguration#JavaSourceViewerConfiguration(IColorManager, IPreferenceStore, ITextEditor, String)
* @since 2.0
* @deprecated As of 3.0
*/
@Deprecated
protected IPreferenceStore getPreferenceStore() {
Assert.isTrue(!isNewSetup());
return fJavaTextTools.getPreferenceStore();
}
/**
* @return <code>true</code> iff the new setup without text tools is in use.
*
* @since 3.0
*/
private boolean isNewSetup() {
return fJavaTextTools == null;
}
/**
* Creates and returns a preference store which combines the preference
* stores from the text tools and which is read-only.
*
* @param javaTextTools the Java text tools
* @return the combined read-only preference store
* @since 3.0
*/
private static final IPreferenceStore createPreferenceStore(JavaTextTools 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 });
}
/**
* Initializes the scanners.
*
* @param isModuleInfo <code>true</code> if used for module-info code
*
* @since 3.0
*/
private void initializeScanners(boolean isModuleInfo) {
Assert.isTrue(isNewSetup());
fCodeScanner= new JavaCodeScanner(getColorManager(), fPreferenceStore, isModuleInfo);
fMultilineCommentScanner= new JavaCommentScanner(getColorManager(), fPreferenceStore, IJavaColorConstants.JAVA_MULTI_LINE_COMMENT);
fSinglelineCommentScanner= new JavaCommentScanner(getColorManager(), fPreferenceStore, IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT);
fStringScanner= new SingleTokenJavaScanner(getColorManager(), fPreferenceStore, IJavaColorConstants.JAVA_STRING);
fJavaDocScanner= new JavaDocScanner(getColorManager(), fPreferenceStore);
}
/*
* @see SourceViewerConfiguration#getPresentationReconciler(ISourceViewer)
*/
@Override
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
PresentationReconciler reconciler= new JavaPresentationReconciler();
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(dr, IJavaPartitions.JAVA_DOC);
reconciler.setRepairer(dr, IJavaPartitions.JAVA_DOC);
dr= new DefaultDamagerRepairer(getMultilineCommentScanner());
reconciler.setDamager(dr, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
reconciler.setRepairer(dr, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
dr= new DefaultDamagerRepairer(getSinglelineCommentScanner());
reconciler.setDamager(dr, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
reconciler.setRepairer(dr, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
dr= new DefaultDamagerRepairer(getStringScanner());
reconciler.setDamager(dr, IJavaPartitions.JAVA_STRING);
reconciler.setRepairer(dr, IJavaPartitions.JAVA_STRING);
dr= new DefaultDamagerRepairer(getStringScanner());
reconciler.setDamager(dr, IJavaPartitions.JAVA_CHARACTER);
reconciler.setRepairer(dr, IJavaPartitions.JAVA_CHARACTER);
dr= new DefaultDamagerRepairer(getStringScanner());
reconciler.setDamager(dr, IJavaPartitions.JAVA_MULTI_LINE_STRING);
reconciler.setRepairer(dr, IJavaPartitions.JAVA_MULTI_LINE_STRING);
return reconciler;
}
/*
* @see SourceViewerConfiguration#getContentAssistant(ISourceViewer)
*/
@Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
if (getEditor() != null) {
ContentAssistant assistant= new ContentAssistant();
assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
IContentAssistProcessor javaProcessor= new JavaCompletionProcessor(getEditor(), assistant, IDocument.DEFAULT_CONTENT_TYPE);
assistant.setContentAssistProcessor(javaProcessor, IDocument.DEFAULT_CONTENT_TYPE);
ContentAssistProcessor singleLineProcessor= new JavaCompletionProcessor(getEditor(), assistant, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
assistant.setContentAssistProcessor(singleLineProcessor, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
ContentAssistProcessor stringProcessor= new JavaCompletionProcessor(getEditor(), assistant, IJavaPartitions.JAVA_STRING);
assistant.setContentAssistProcessor(stringProcessor, IJavaPartitions.JAVA_STRING);
ContentAssistProcessor multiLineProcessor= new JavaCompletionProcessor(getEditor(), assistant, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
assistant.setContentAssistProcessor(multiLineProcessor, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
ContentAssistProcessor javadocProcessor= new JavadocCompletionProcessor(getEditor(), assistant);
assistant.setContentAssistProcessor(javadocProcessor, IJavaPartitions.JAVA_DOC);
ContentAssistProcessor multiLineStringProcessor= new JavaCompletionProcessor(getEditor(), assistant, IJavaPartitions.JAVA_MULTI_LINE_STRING);
assistant.setContentAssistProcessor(multiLineStringProcessor, IJavaPartitions.JAVA_MULTI_LINE_STRING);
ContentAssistPreference.configure(assistant, fPreferenceStore);
assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
assistant.setInformationControlCreator(new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, JavaPlugin.getAdditionalInfoAffordanceString());
}
});
return assistant;
}
return null;
}
/*
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getQuickAssistAssistant(org.eclipse.jface.text.source.ISourceViewer)
* @since 3.2
*/
@Override
public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
if (getEditor() != null) {
JavaCorrectionAssistant assistant= new JavaCorrectionAssistant(getEditor());
assistant.setRestoreCompletionProposalSize(getSettings("quick_assist_proposal_size")); //$NON-NLS-1$
return assistant;
}
return null;
}
/*
* @see SourceViewerConfiguration#getReconciler(ISourceViewer)
*/
@Override
public IReconciler getReconciler(ISourceViewer sourceViewer) {
final ITextEditor editor= getEditor();
if (editor != null && editor.isEditable()) {
JavaCompositeReconcilingStrategy strategy= new JavaCompositeReconcilingStrategy(sourceViewer, editor, getConfiguredDocumentPartitioning(sourceViewer));
JavaReconciler reconciler= new JavaReconciler(editor, strategy, false);
reconciler.setIsAllowedToModifyDocument(false);
reconciler.setDelay(500);
return reconciler;
}
return null;
}
/*
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getAutoEditStrategies(org.eclipse.jface.text.source.ISourceViewer, java.lang.String)
*/
@Override
public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
String partitioning= getConfiguredDocumentPartitioning(sourceViewer);
if (IJavaPartitions.JAVA_DOC.equals(contentType) || IJavaPartitions.JAVA_MULTI_LINE_COMMENT.equals(contentType))
return new IAutoEditStrategy[] { new JavaDocAutoIndentStrategy(partitioning) };
else if (IJavaPartitions.JAVA_STRING.equals(contentType))
return new IAutoEditStrategy[] { new SmartSemicolonAutoEditStrategy(partitioning), new JavaStringAutoIndentStrategy(partitioning, EditorUtility.getJavaProject(fTextEditor)) };
else if (IJavaPartitions.JAVA_CHARACTER.equals(contentType) || IDocument.DEFAULT_CONTENT_TYPE.equals(contentType))
return new IAutoEditStrategy[] { new SmartSemicolonAutoEditStrategy(partitioning), new JavaAutoIndentStrategy(partitioning, EditorUtility.getJavaProject(fTextEditor), sourceViewer) };
else if (IJavaPartitions.JAVA_MULTI_LINE_STRING.equals(contentType))
return new IAutoEditStrategy[] { new JavaMultiLineStringAutoIndentStrategy(partitioning, EditorUtility.getJavaProject(fTextEditor)) };
else
return new IAutoEditStrategy[] { new JavaAutoIndentStrategy(partitioning, EditorUtility.getJavaProject(fTextEditor), sourceViewer) };
}
/*
* @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String)
*/
@Override
public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
if (IJavaPartitions.JAVA_DOC.equals(contentType))
return new JavadocDoubleClickStrategy(getConfiguredDocumentPartitioning(sourceViewer));
if (IJavaPartitions.JAVA_SINGLE_LINE_COMMENT.equals(contentType))
return new PartitionDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), 0, 0);
if (IJavaPartitions.JAVA_MULTI_LINE_COMMENT.equals(contentType))
return new PartitionDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), 0, 0);
else if (IJavaPartitions.JAVA_STRING.equals(contentType) || IJavaPartitions.JAVA_CHARACTER.equals(contentType))
return new PartitionDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), 1, 1);
else if (IJavaPartitions.JAVA_MULTI_LINE_STRING.equals(contentType))
return new PartitionDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), 3, 3, 3);
if (fJavaDoubleClickSelector == null) {
fJavaDoubleClickSelector= new JavaDoubleClickSelector();
fJavaDoubleClickSelector.setSourceVersion(fPreferenceStore.getString(JavaCore.COMPILER_SOURCE));
}
return fJavaDoubleClickSelector;
}
/*
* @see SourceViewerConfiguration#getDefaultPrefixes(ISourceViewer, String)
* @since 2.0
*/
@Override
public String[] getDefaultPrefixes(ISourceViewer sourceViewer, String contentType) {
return new String[] { "//", "" }; //$NON-NLS-1$ //$NON-NLS-2$
}
/*
* @see SourceViewerConfiguration#getIndentPrefixes(ISourceViewer, String)
*/
@Override
public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) {
IJavaProject project= EditorUtility.getJavaProject(fTextEditor);
final int tabWidth= CodeFormatterUtil.getTabWidth(project);
final int indentWidth= CodeFormatterUtil.getIndentWidth(project);
boolean allowTabs= tabWidth <= indentWidth;
String indentMode;
if (project == null)
indentMode= JavaCore.getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR);
else
indentMode= project.getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, true);
boolean useSpaces= JavaCore.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);
}
/**
* 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)
* @since 3.3
*/
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]= spaces;
}
indentPrefixes[tabWidth + 1]= ""; //$NON-NLS-1$
return indentPrefixes;
}
/**
* Creates and returns a String with <code>count</code> spaces.
*
* @param count the space count
* @return the string with the spaces
* @since 3.3
*/
private String getStringWithSpaces(int count) {
char[] spaceChars= new char[count];
Arrays.fill(spaceChars, ' ');
return new String(spaceChars);
}
/*
* @see SourceViewerConfiguration#getTabWidth(ISourceViewer)
*/
@Override
public int getTabWidth(ISourceViewer sourceViewer) {
return CodeFormatterUtil.getTabWidth(EditorUtility.getJavaProject(fTextEditor));
}
/*
* @see SourceViewerConfiguration#getAnnotationHover(ISourceViewer)
*/
@Override
public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
return new HTMLAnnotationHover(false) {
@Override
protected boolean isIncluded(Annotation annotation) {
return isShowInVerticalRuler(annotation);
}
};
}
/*
* @see SourceViewerConfiguration#getOverviewRulerAnnotationHover(ISourceViewer)
* @since 3.0
*/
@Override
public IAnnotationHover getOverviewRulerAnnotationHover(ISourceViewer sourceViewer) {
return new HTMLAnnotationHover(true) {
@Override
protected boolean isIncluded(Annotation annotation) {
return isShowInOverviewRuler(annotation);
}
};
}
/*
* @see SourceViewerConfiguration#getConfiguredTextHoverStateMasks(ISourceViewer, String)
* @since 2.1
*/
@Override
public int[] getConfiguredTextHoverStateMasks(ISourceViewer sourceViewer, String contentType) {
JavaEditorTextHoverDescriptor[] hoverDescs= JavaPlugin.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;
}
/*
* @see SourceViewerConfiguration#getTextHover(ISourceViewer, String, int)
* @since 2.1
*/
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType, int stateMask) {
JavaEditorTextHoverDescriptor[] hoverDescs= JavaPlugin.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;
}
/*
* @see SourceViewerConfiguration#getTextHover(ISourceViewer, String)
*/
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
return getTextHover(sourceViewer, contentType, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
}
/*
* @see SourceViewerConfiguration#getConfiguredContentTypes(ISourceViewer)
*/
@Override
public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
return new String[] {
IDocument.DEFAULT_CONTENT_TYPE,
IJavaPartitions.JAVA_DOC,
IJavaPartitions.JAVA_MULTI_LINE_COMMENT,
IJavaPartitions.JAVA_SINGLE_LINE_COMMENT,
IJavaPartitions.JAVA_STRING,
IJavaPartitions.JAVA_CHARACTER,
IJavaPartitions.JAVA_MULTI_LINE_STRING
};
}
/*
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredDocumentPartitioning(org.eclipse.jface.text.source.ISourceViewer)
* @since 3.0
*/
@Override
public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
if (fDocumentPartitioning != null)
return fDocumentPartitioning;
return super.getConfiguredDocumentPartitioning(sourceViewer);
}
/*
* @see SourceViewerConfiguration#getContentFormatter(ISourceViewer)
*/
@Override
public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
final MultiPassContentFormatter formatter= new MultiPassContentFormatter(getConfiguredDocumentPartitioning(sourceViewer), IDocument.DEFAULT_CONTENT_TYPE);
formatter.setMasterStrategy(new JavaFormattingStrategy());
return formatter;
}
/*
* @see SourceViewerConfiguration#getInformationControlCreator(ISourceViewer)
* @since 2.0
*/
@Override
public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, false);
}
};
}
/**
* 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
* @since 2.1
*/
private IInformationControlCreator getInformationPresenterControlCreator(ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, true);
}
};
}
/**
* 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>JavaOutlineInformationControl</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
* @since 2.1
*/
private IInformationControlCreator getOutlinePresenterControlCreator(ISourceViewer sourceViewer, final String commandId) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
int shellStyle= SWT.RESIZE;
int treeStyle= SWT.V_SCROLL | SWT.H_SCROLL;
return new JavaOutlineInformationControl(parent, shellStyle, treeStyle, commandId);
}
};
}
private IInformationControlCreator getHierarchyPresenterControlCreator() {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent) {
int shellStyle= SWT.RESIZE;
int treeStyle= SWT.V_SCROLL | SWT.H_SCROLL;
return new HierarchyInformationControl(parent, shellStyle, treeStyle);
}
};
}
/*
* @see SourceViewerConfiguration#getInformationPresenter(ISourceViewer)
* @since 2.0
*/
@Override
public IInformationPresenter getInformationPresenter(ISourceViewer 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]);
// sizes: see org.eclipse.jface.text.TextViewer.TEXT_HOVER_*_CHARS
presenter.setSizeConstraints(100, 12, false, 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 Java element
* @return an information presenter
* @since 2.1
*/
public IInformationPresenter getOutlinePresenter(ISourceViewer sourceViewer, boolean doCodeResolve) {
InformationPresenter presenter;
if (doCodeResolve)
presenter= new InformationPresenter(getOutlinePresenterControlCreator(sourceViewer, IJavaEditorActionDefinitionIds.OPEN_STRUCTURE));
else
presenter= new InformationPresenter(getOutlinePresenterControlCreator(sourceViewer, IJavaEditorActionDefinitionIds.SHOW_OUTLINE));
presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
IInformationProvider provider= new JavaElementProvider(getEditor(), doCodeResolve);
presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_DOC);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_STRING);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_CHARACTER);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_MULTI_LINE_STRING);
presenter.setSizeConstraints(50, 20, true, false);
return presenter;
}
/**
* Returns the settings for the given section.
*
* @param sectionName the section name
* @return the settings
* @since 3.0
*/
private IDialogSettings getSettings(String sectionName) {
IDialogSettings settings= JavaPlugin.getDefault().getDialogSettings().getSection(sectionName);
if (settings == null)
settings= JavaPlugin.getDefault().getDialogSettings().addNewSection(sectionName);
return settings;
}
/**
* 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 Java element
* @return an information presenter
* @since 3.0
*/
public IInformationPresenter getHierarchyPresenter(ISourceViewer sourceViewer, boolean doCodeResolve) {
// Do not create hierarchy presenter if there's no CU.
if (getEditor() != null && getEditor().getEditorInput() != null && JavaUI.getEditorInputJavaElement(getEditor().getEditorInput()) == null)
return null;
InformationPresenter presenter= new InformationPresenter(getHierarchyPresenterControlCreator());
presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
IInformationProvider provider= new JavaElementProvider(getEditor(), doCodeResolve);
presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_DOC);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_STRING);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_CHARACTER);
presenter.setInformationProvider(provider, IJavaPartitions.JAVA_MULTI_LINE_STRING);
presenter.setSizeConstraints(50, 20, true, false);
return presenter;
}
/**
* 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
* @since 3.0
*/
public boolean affectsTextPresentation(PropertyChangeEvent event) {
return fCodeScanner.affectsBehavior(event)
|| fMultilineCommentScanner.affectsBehavior(event)
|| fSinglelineCommentScanner.affectsBehavior(event)
|| fStringScanner.affectsBehavior(event)
|| fJavaDocScanner.affectsBehavior(event);
}
/**
* 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 JavaSourceViewerConfiguration#JavaSourceViewerConfiguration(IColorManager, IPreferenceStore, ITextEditor, String)
* @since 3.0
*/
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 (fJavaDocScanner.affectsBehavior(event))
fJavaDocScanner.adaptToPreferenceChange(event);
if (fJavaDoubleClickSelector != null && JavaCore.COMPILER_SOURCE.equals(event.getProperty()))
if (event.getNewValue() instanceof String)
fJavaDoubleClickSelector.setSourceVersion((String) event.getNewValue());
}
/*
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getHyperlinkDetectorTargets(org.eclipse.jface.text.source.ISourceViewer)
* @since 3.3
*/
@Override
protected Map<String, IAdaptable> getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
Map<String, IAdaptable> targets= super.getHyperlinkDetectorTargets(sourceViewer);
targets.put("org.eclipse.jdt.ui.javaCode", fTextEditor); //$NON-NLS-1$
return targets;
}
}