Home | History | Annotate | Download | only in editors
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.editors;
     18 
     19 
     20 import com.android.ide.eclipse.adt.internal.editors.formatting.AndroidXmlFormatter;
     21 import com.android.ide.eclipse.adt.internal.editors.formatting.AndroidXmlFormattingStrategy;
     22 
     23 import org.eclipse.jface.text.DefaultAutoIndentStrategy;
     24 import org.eclipse.jface.text.IAutoEditStrategy;
     25 import org.eclipse.jface.text.ITextHover;
     26 import org.eclipse.jface.text.ITextViewer;
     27 import org.eclipse.jface.text.contentassist.ICompletionProposal;
     28 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
     29 import org.eclipse.jface.text.contentassist.IContentAssistant;
     30 import org.eclipse.jface.text.contentassist.IContextInformation;
     31 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
     32 import org.eclipse.jface.text.formatter.IContentFormatter;
     33 import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
     34 import org.eclipse.jface.text.source.ISourceViewer;
     35 import org.eclipse.wst.sse.core.text.IStructuredPartitions;
     36 import org.eclipse.wst.xml.core.text.IXMLPartitions;
     37 import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
     38 import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor;
     39 
     40 import java.util.ArrayList;
     41 import java.util.List;
     42 import java.util.Map;
     43 
     44 /**
     45  * Base Source Viewer Configuration for Android resources.
     46  */
     47 @SuppressWarnings({"restriction", "deprecation"}) // XMLContentAssistProcessor etc
     48 public abstract class AndroidSourceViewerConfig extends StructuredTextViewerConfigurationXML {
     49 
     50     public AndroidSourceViewerConfig() {
     51         super();
     52     }
     53 
     54     @Override
     55     public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
     56         return super.getContentAssistant(sourceViewer);
     57     }
     58 
     59     /**
     60      * Returns the IContentAssistProcessor that
     61      * {@link #getContentAssistProcessors(ISourceViewer, String)} should use
     62      * for XML and default/unknown partitions.
     63      *
     64      * @return An {@link IContentAssistProcessor} or null.
     65      */
     66     public abstract IContentAssistProcessor getAndroidContentAssistProcessor(
     67             ISourceViewer sourceViewer,
     68             String partitionType);
     69 
     70     /**
     71      * Returns the content assist processors that will be used for content
     72      * assist in the given source viewer and for the given partition type.
     73      *
     74      * @param sourceViewer the source viewer to be configured by this
     75      *        configuration
     76      * @param partitionType the partition type for which the content assist
     77      *        processors are applicable
     78      * @return IContentAssistProcessors or null if should not be supported
     79      */
     80     @Override
     81     protected IContentAssistProcessor[] getContentAssistProcessors(
     82             ISourceViewer sourceViewer, String partitionType) {
     83         ArrayList<IContentAssistProcessor> processors = new ArrayList<IContentAssistProcessor>();
     84         if (partitionType == IStructuredPartitions.UNKNOWN_PARTITION ||
     85             partitionType == IStructuredPartitions.DEFAULT_PARTITION ||
     86             partitionType == IXMLPartitions.XML_DEFAULT) {
     87 
     88             IContentAssistProcessor processor =
     89                 getAndroidContentAssistProcessor(sourceViewer, partitionType);
     90 
     91             if (processor != null) {
     92                 processors.add(processor);
     93             }
     94         }
     95 
     96         IContentAssistProcessor[] others = super.getContentAssistProcessors(sourceViewer,
     97                 partitionType);
     98         if (others != null && others.length > 0) {
     99             for (IContentAssistProcessor p : others) {
    100                 // Builtin Eclipse WTP code completion assistant? If so,
    101                 // wrap it with our own filter which hides some unwanted completions.
    102                 if (p instanceof XMLContentAssistProcessor
    103                         // On Eclipse 3.7, XMLContentAssistProcessor is no longer used,
    104                         // and instead org.eclipse.wst.xml.ui.internal.contentassist.
    105                         // XMLStructuredContentAssistProcessor is used - which isn't available
    106                         // at compile time in 3.5.
    107                         || p.getClass().getSimpleName().equals(
    108                             "XMLStructuredContentAssistProcessor")) { //$NON-NLS-1$
    109                     processors.add(new FilteringContentAssistProcessor(p));
    110                 } else {
    111                     processors.add(p);
    112                 }
    113             }
    114         }
    115 
    116         if (processors.size() > 0) {
    117             return processors.toArray(new IContentAssistProcessor[processors.size()]);
    118         } else {
    119             return null;
    120         }
    121     }
    122 
    123     @Override
    124     public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
    125         // TODO text hover for android xml
    126         return super.getTextHover(sourceViewer, contentType);
    127     }
    128 
    129     @Override
    130     public IAutoEditStrategy[] getAutoEditStrategies(
    131             ISourceViewer sourceViewer, String contentType) {
    132         IAutoEditStrategy[] strategies = super.getAutoEditStrategies(sourceViewer, contentType);
    133         List<IAutoEditStrategy> s = new ArrayList<IAutoEditStrategy>(strategies.length + 1);
    134         s.add(new AndroidXmlAutoEditStrategy());
    135 
    136         // Add other registered strategies, except the builtin indentation strategy which is
    137         // now handled by the above AndroidXmlAutoEditStrategy
    138         for (IAutoEditStrategy strategy : strategies) {
    139             if (strategy instanceof DefaultAutoIndentStrategy) {
    140                 continue;
    141             }
    142             s.add(strategy);
    143         }
    144 
    145         return s.toArray(new IAutoEditStrategy[s.size()]);
    146     }
    147 
    148     @Override
    149     public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
    150         IContentFormatter formatter = super.getContentFormatter(sourceViewer);
    151 
    152         if (formatter instanceof MultiPassContentFormatter) {
    153             ((MultiPassContentFormatter) formatter).setMasterStrategy(
    154                     new AndroidXmlFormattingStrategy());
    155             return formatter;
    156         } else {
    157             return new AndroidXmlFormatter();
    158         }
    159     }
    160 
    161     @Override
    162     protected Map<String, ?> getHyperlinkDetectorTargets(final ISourceViewer sourceViewer) {
    163         @SuppressWarnings("unchecked")
    164         Map<String, ?> targets = super.getHyperlinkDetectorTargets(sourceViewer);
    165         // If we want to look up more context in our HyperlinkDetector via the
    166         // getAdapter method, we should place an IAdaptable object into the map here.
    167         targets.put("com.android.ide.eclipse.xmlCode", null); //$NON-NLS-1$
    168         return targets;
    169     }
    170 
    171     /**
    172      * A delegating {@link IContentAssistProcessor} whose purpose is to filter out some
    173      * default Eclipse XML completions which are distracting in Android XML files
    174      */
    175     private static class FilteringContentAssistProcessor implements IContentAssistProcessor {
    176         private IContentAssistProcessor mDelegate;
    177 
    178         public FilteringContentAssistProcessor(IContentAssistProcessor delegate) {
    179             super();
    180             mDelegate = delegate;
    181         }
    182 
    183         @Override
    184         public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
    185             ICompletionProposal[] result = mDelegate.computeCompletionProposals(viewer, offset);
    186             if (result == null) {
    187                 return null;
    188             }
    189 
    190             List<ICompletionProposal> proposals =
    191                 new ArrayList<ICompletionProposal>(result.length);
    192             for (ICompletionProposal proposal : result) {
    193                 String replacement = proposal.getDisplayString();
    194                 if (replacement.charAt(0) == '"' &&
    195                         replacement.charAt(replacement.length() - 1) == '"') {
    196                     // Filter out attribute values. In Android XML files (where there is no DTD
    197                     // etc) the default Eclipse XML code completion simply provides the
    198                     // existing value as a completion. This is often misleading, since if you
    199                     // for example have a typo, completion will show your current (wrong)
    200                     // value as a valid completion.
    201                 } else if (replacement.contains("Namespace")  //$NON-NLS-1$
    202                         || replacement.startsWith("XSL ")  //$NON-NLS-1$
    203                         || replacement.contains("Schema")) {  //$NON-NLS-1$
    204                     // Eclipse adds in a number of namespace and schema related completions which
    205                     // are not usually applicable in our files.
    206                 } else {
    207                     proposals.add(proposal);
    208                 }
    209             }
    210 
    211             if (proposals.size() == result.length) {
    212                 return result;
    213             } else {
    214                 return proposals.toArray(new ICompletionProposal[proposals.size()]);
    215             }
    216         }
    217 
    218         @Override
    219         public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
    220             return mDelegate.computeContextInformation(viewer, offset);
    221         }
    222 
    223         @Override
    224         public char[] getCompletionProposalAutoActivationCharacters() {
    225             return mDelegate.getCompletionProposalAutoActivationCharacters();
    226         }
    227 
    228         @Override
    229         public char[] getContextInformationAutoActivationCharacters() {
    230             return mDelegate.getContextInformationAutoActivationCharacters();
    231         }
    232 
    233         @Override
    234         public IContextInformationValidator getContextInformationValidator() {
    235             return mDelegate.getContextInformationValidator();
    236         }
    237 
    238         @Override
    239         public String getErrorMessage() {
    240             return mDelegate.getErrorMessage();
    241         }
    242     }
    243 }
    244