blob: b2c10ec3b2f0ab129177297c5aaf8f74b38b42db [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.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/org/documents/epl-v10.php
*
* 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.android.ide.eclipse.adt.internal.editors;
import com.android.ide.eclipse.adt.internal.editors.formatting.AndroidXmlFormatter;
import com.android.ide.eclipse.adt.internal.editors.formatting.AndroidXmlFormattingStrategy;
import org.eclipse.jface.text.DefaultAutoIndentStrategy;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.wst.sse.core.text.IStructuredPartitions;
import org.eclipse.wst.xml.core.text.IXMLPartitions;
import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Base Source Viewer Configuration for Android resources.
*/
@SuppressWarnings({"restriction", "deprecation"}) // XMLContentAssistProcessor etc
public abstract class AndroidSourceViewerConfig extends StructuredTextViewerConfigurationXML {
public AndroidSourceViewerConfig() {
super();
}
@Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
return super.getContentAssistant(sourceViewer);
}
/**
* Returns the IContentAssistProcessor that
* {@link #getContentAssistProcessors(ISourceViewer, String)} should use
* for XML and default/unknown partitions.
*
* @return An {@link IContentAssistProcessor} or null.
*/
public abstract IContentAssistProcessor getAndroidContentAssistProcessor(
ISourceViewer sourceViewer,
String partitionType);
/**
* Returns the content assist processors that will be used for content
* assist in the given source viewer and for the given partition type.
*
* @param sourceViewer the source viewer to be configured by this
* configuration
* @param partitionType the partition type for which the content assist
* processors are applicable
* @return IContentAssistProcessors or null if should not be supported
*/
@Override
protected IContentAssistProcessor[] getContentAssistProcessors(
ISourceViewer sourceViewer, String partitionType) {
ArrayList<IContentAssistProcessor> processors = new ArrayList<IContentAssistProcessor>();
if (partitionType == IStructuredPartitions.UNKNOWN_PARTITION ||
partitionType == IStructuredPartitions.DEFAULT_PARTITION ||
partitionType == IXMLPartitions.XML_DEFAULT) {
IContentAssistProcessor processor =
getAndroidContentAssistProcessor(sourceViewer, partitionType);
if (processor != null) {
processors.add(processor);
}
}
IContentAssistProcessor[] others = super.getContentAssistProcessors(sourceViewer,
partitionType);
if (others != null && others.length > 0) {
for (IContentAssistProcessor p : others) {
// Builtin Eclipse WTP code completion assistant? If so,
// wrap it with our own filter which hides some unwanted completions.
if (p instanceof XMLContentAssistProcessor
// On Eclipse 3.7, XMLContentAssistProcessor is no longer used,
// and instead org.eclipse.wst.xml.ui.internal.contentassist.
// XMLStructuredContentAssistProcessor is used - which isn't available
// at compile time in 3.5.
|| p.getClass().getSimpleName().equals(
"XMLStructuredContentAssistProcessor")) { //$NON-NLS-1$
processors.add(new FilteringContentAssistProcessor(p));
} else {
processors.add(p);
}
}
}
if (processors.size() > 0) {
return processors.toArray(new IContentAssistProcessor[processors.size()]);
} else {
return null;
}
}
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
// TODO text hover for android xml
return super.getTextHover(sourceViewer, contentType);
}
@Override
public IAutoEditStrategy[] getAutoEditStrategies(
ISourceViewer sourceViewer, String contentType) {
IAutoEditStrategy[] strategies = super.getAutoEditStrategies(sourceViewer, contentType);
List<IAutoEditStrategy> s = new ArrayList<IAutoEditStrategy>(strategies.length + 1);
s.add(new AndroidXmlAutoEditStrategy());
// Add other registered strategies, except the builtin indentation strategy which is
// now handled by the above AndroidXmlAutoEditStrategy
for (IAutoEditStrategy strategy : strategies) {
if (strategy instanceof DefaultAutoIndentStrategy) {
continue;
}
s.add(strategy);
}
return s.toArray(new IAutoEditStrategy[s.size()]);
}
@Override
public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
IContentFormatter formatter = super.getContentFormatter(sourceViewer);
if (formatter instanceof MultiPassContentFormatter) {
((MultiPassContentFormatter) formatter).setMasterStrategy(
new AndroidXmlFormattingStrategy());
return formatter;
} else {
return new AndroidXmlFormatter();
}
}
@Override
protected Map<String, ?> getHyperlinkDetectorTargets(final ISourceViewer sourceViewer) {
@SuppressWarnings("unchecked")
Map<String, ?> targets = super.getHyperlinkDetectorTargets(sourceViewer);
// If we want to look up more context in our HyperlinkDetector via the
// getAdapter method, we should place an IAdaptable object into the map here.
targets.put("com.android.ide.eclipse.xmlCode", null); //$NON-NLS-1$
return targets;
}
/**
* A delegating {@link IContentAssistProcessor} whose purpose is to filter out some
* default Eclipse XML completions which are distracting in Android XML files
*/
private static class FilteringContentAssistProcessor implements IContentAssistProcessor {
private IContentAssistProcessor mDelegate;
public FilteringContentAssistProcessor(IContentAssistProcessor delegate) {
super();
mDelegate = delegate;
}
@Override
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
ICompletionProposal[] result = mDelegate.computeCompletionProposals(viewer, offset);
if (result == null) {
return null;
}
List<ICompletionProposal> proposals =
new ArrayList<ICompletionProposal>(result.length);
for (ICompletionProposal proposal : result) {
String replacement = proposal.getDisplayString();
if (replacement.charAt(0) == '"' &&
replacement.charAt(replacement.length() - 1) == '"') {
// Filter out attribute values. In Android XML files (where there is no DTD
// etc) the default Eclipse XML code completion simply provides the
// existing value as a completion. This is often misleading, since if you
// for example have a typo, completion will show your current (wrong)
// value as a valid completion.
} else if (replacement.contains("Namespace") //$NON-NLS-1$
|| replacement.startsWith("XSL ") //$NON-NLS-1$
|| replacement.contains("Schema")) { //$NON-NLS-1$
// Eclipse adds in a number of namespace and schema related completions which
// are not usually applicable in our files.
} else {
proposals.add(proposal);
}
}
if (proposals.size() == result.length) {
return result;
} else {
return proposals.toArray(new ICompletionProposal[proposals.size()]);
}
}
@Override
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
return mDelegate.computeContextInformation(viewer, offset);
}
@Override
public char[] getCompletionProposalAutoActivationCharacters() {
return mDelegate.getCompletionProposalAutoActivationCharacters();
}
@Override
public char[] getContextInformationAutoActivationCharacters() {
return mDelegate.getContextInformationAutoActivationCharacters();
}
@Override
public IContextInformationValidator getContextInformationValidator() {
return mDelegate.getContextInformationValidator();
}
@Override
public String getErrorMessage() {
return mDelegate.getErrorMessage();
}
}
}