├── CContentAssistProcessor.java ├── ContentAssistProcessor.java ├── README.md └── org.eclipse.cdt.ui_6.6.0.201909091956.jar /CContentAssistProcessor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2000, 2015 IBM Corporation and others. 3 | * 4 | * This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * https://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | * 11 | * Contributors: 12 | * IBM Corporation - initial API and implementation 13 | * Anton Leherbauer (Wind River Systems) 14 | * Bryan Wilkinson (QNX) 15 | * Markus Schorn (Wind River Systems) 16 | * Kirk Beitz (Nokia) 17 | *******************************************************************************/ 18 | package org.eclipse.cdt.internal.ui.text.contentassist; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | import org.eclipse.cdt.core.dom.ast.IASTCompletionNode; 25 | import org.eclipse.cdt.core.dom.ast.IASTExpression; 26 | import org.eclipse.cdt.core.dom.ast.IASTFieldReference; 27 | import org.eclipse.cdt.core.dom.ast.IASTName; 28 | import org.eclipse.cdt.core.dom.ast.IPointerType; 29 | import org.eclipse.cdt.core.dom.ast.IType; 30 | import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; 31 | import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; 32 | import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.HeuristicResolver; 33 | import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; 34 | import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil; 35 | import org.eclipse.cdt.internal.ui.text.CHeuristicScanner; 36 | import org.eclipse.cdt.internal.ui.text.CParameterListValidator; 37 | import org.eclipse.cdt.internal.ui.text.Symbols; 38 | import org.eclipse.cdt.ui.CUIPlugin; 39 | import org.eclipse.cdt.ui.text.ICCompletionProposal; 40 | import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext; 41 | import org.eclipse.cdt.ui.text.contentassist.IProposalFilter; 42 | import org.eclipse.core.runtime.CoreException; 43 | import org.eclipse.core.runtime.IConfigurationElement; 44 | import org.eclipse.core.runtime.IProgressMonitor; 45 | import org.eclipse.core.runtime.InvalidRegistryObjectException; 46 | import org.eclipse.jface.text.BadLocationException; 47 | import org.eclipse.jface.text.IDocument; 48 | import org.eclipse.jface.text.ITextViewer; 49 | import org.eclipse.jface.text.contentassist.ContentAssistant; 50 | import org.eclipse.jface.text.contentassist.ICompletionProposal; 51 | import org.eclipse.jface.text.contentassist.IContextInformation; 52 | import org.eclipse.jface.text.contentassist.IContextInformationValidator; 53 | import org.eclipse.swt.graphics.Image; 54 | import org.eclipse.swt.graphics.Point; 55 | import org.eclipse.ui.IEditorPart; 56 | 57 | /** 58 | * C/C++ content assist processor. 59 | */ 60 | public class CContentAssistProcessor extends ContentAssistProcessor { 61 | 62 | private static class ActivationSet { 63 | private final String set; 64 | 65 | ActivationSet(String s) { 66 | set = s; 67 | } 68 | 69 | boolean contains(char c) { 70 | return -1 != set.indexOf(c); 71 | } 72 | } 73 | 74 | /** 75 | * A wrapper for {@link ICompetionProposal}s. 76 | */ 77 | private static class CCompletionProposalWrapper implements ICCompletionProposal { 78 | private ICompletionProposal fWrappedProposal; 79 | 80 | public CCompletionProposalWrapper(ICompletionProposal proposal) { 81 | fWrappedProposal = proposal; 82 | } 83 | 84 | @Override 85 | public String getIdString() { 86 | return fWrappedProposal.getDisplayString(); 87 | } 88 | 89 | @Override 90 | public int getRelevance() { 91 | return RelevanceConstants.CASE_MATCH_RELEVANCE + RelevanceConstants.KEYWORD_TYPE_RELEVANCE; 92 | } 93 | 94 | @Override 95 | public void apply(IDocument document) { 96 | throw new UnsupportedOperationException(); 97 | } 98 | 99 | @Override 100 | public String getAdditionalProposalInfo() { 101 | return fWrappedProposal.getAdditionalProposalInfo(); 102 | } 103 | 104 | @Override 105 | public IContextInformation getContextInformation() { 106 | return fWrappedProposal.getContextInformation(); 107 | } 108 | 109 | @Override 110 | public String getDisplayString() { 111 | return fWrappedProposal.getDisplayString(); 112 | } 113 | 114 | @Override 115 | public Image getImage() { 116 | return fWrappedProposal.getImage(); 117 | } 118 | 119 | @Override 120 | public Point getSelection(IDocument document) { 121 | return fWrappedProposal.getSelection(document); 122 | } 123 | 124 | /** 125 | * @return the original proposal 126 | */ 127 | public ICompletionProposal unwrap() { 128 | return fWrappedProposal; 129 | } 130 | } 131 | 132 | private ActivationSet fReplacementAutoActivationCharacters; 133 | private ActivationSet fCContentAutoActivationCharacters; 134 | private IContextInformationValidator fValidator; 135 | private final IEditorPart fEditor; 136 | 137 | public CContentAssistProcessor(IEditorPart editor, ContentAssistant assistant, String partition) { 138 | super(assistant, partition); 139 | fEditor = editor; 140 | } 141 | 142 | @Override 143 | public IContextInformationValidator getContextInformationValidator() { 144 | if (fValidator == null) { 145 | fValidator = new CParameterListValidator(); 146 | } 147 | return fValidator; 148 | } 149 | 150 | @Override 151 | protected List filterAndSortProposals(List proposals, 152 | IProgressMonitor monitor, ContentAssistInvocationContext context) { 153 | IProposalFilter filter = getCompletionFilter(); 154 | ICCompletionProposal[] proposalsInput = new ICCompletionProposal[proposals.size()]; 155 | // Wrap proposals which are no ICCompletionProposals. 156 | boolean wrapped = false; 157 | int i = 0; 158 | for (ICompletionProposal proposal : proposals) { 159 | if (proposal instanceof ICCompletionProposal) { 160 | proposalsInput[i++] = (ICCompletionProposal) proposal; 161 | } else { 162 | wrapped = true; 163 | proposalsInput[i++] = new CCompletionProposalWrapper(proposal); 164 | } 165 | } 166 | // Filter. 167 | ICCompletionProposal[] proposalsFiltered = filter.filterProposals(proposalsInput); 168 | 169 | // Sort. 170 | boolean sortByAlphabet = CUIPlugin.getDefault().getPreferenceStore() 171 | .getBoolean(ContentAssistPreference.ORDER_PROPOSALS); 172 | if (sortByAlphabet) { 173 | // Already sorted alphabetically by DefaultProposalFilter 174 | // in case of custom proposal filter, keep ordering applied by filter. 175 | } else { 176 | // Sort by relevance. 177 | CCompletionProposalComparator propsComp = new CCompletionProposalComparator(); 178 | propsComp.setOrderAlphabetically(sortByAlphabet); 179 | Arrays.sort(proposalsFiltered, propsComp); 180 | } 181 | List filteredList; 182 | if (wrapped) { 183 | // Unwrap again. 184 | filteredList = new ArrayList<>(proposalsFiltered.length); 185 | for (ICCompletionProposal proposal : proposalsFiltered) { 186 | if (proposal instanceof CCompletionProposalWrapper) { 187 | filteredList.add(((CCompletionProposalWrapper) proposal).unwrap()); 188 | } else { 189 | filteredList.add(proposal); 190 | } 191 | } 192 | } else { 193 | final ICompletionProposal[] tmp = proposalsFiltered; 194 | filteredList = Arrays.asList(tmp); 195 | } 196 | return filteredList; 197 | } 198 | 199 | private IProposalFilter getCompletionFilter() { 200 | IProposalFilter filter = null; 201 | try { 202 | IConfigurationElement filterElement = ProposalFilterPreferencesUtil.getPreferredFilterElement(); 203 | if (null != filterElement) { 204 | Object contribObject = filterElement.createExecutableExtension("class"); //$NON-NLS-1$ 205 | if ((contribObject instanceof IProposalFilter)) { 206 | filter = (IProposalFilter) contribObject; 207 | } 208 | } 209 | } catch (InvalidRegistryObjectException e) { 210 | // No action required since we will be using the fail-safe default filter. 211 | CUIPlugin.log(e); 212 | } catch (CoreException e) { 213 | // No action required since we will be using the fail-safe default filter. 214 | CUIPlugin.log(e); 215 | } 216 | 217 | if (filter == null) { 218 | // Fail-safe default implementation. 219 | filter = new DefaultProposalFilter(); 220 | } 221 | return filter; 222 | } 223 | 224 | @Override 225 | protected List filterAndSortContextInformation(List contexts, 226 | IProgressMonitor monitor) { 227 | return contexts; 228 | } 229 | 230 | /** 231 | * Establishes this processor's set of characters checked after 232 | * auto-activation to determine if auto-replacement correction 233 | * is to occur. 234 | *

235 | * This set is a (possibly complete) subset of the set established by 236 | * {@link ContentAssistProcessor#setCompletionProposalAutoActivationCharacters}, 237 | * which is the set of characters used to initially trigger auto-activation 238 | * for any content-assist operations, including this. (And while the 239 | * name setCompletionProposalAutoActivationCharacters may now be a bit 240 | * misleading, it is part of an API implementation called by jface.) 241 | * 242 | * @param activationSet the activation set 243 | */ 244 | public void setReplacementAutoActivationCharacters(String activationSet) { 245 | fReplacementAutoActivationCharacters = new ActivationSet(activationSet); 246 | } 247 | 248 | /** 249 | * Establishes this processor's set of characters checked after 250 | * auto-activation and any auto-correction to determine if completion 251 | * proposal computation is to proceed. 252 | *

253 | * This set is a (possibly complete) subset of the set established by 254 | * {@link ContentAssistProcessor#setCompletionProposalAutoActivationCharacters}, 255 | * which is the set of characters used to initially trigger auto-activation 256 | * for any content-assist operations, including this. (And while the 257 | * name setCompletionProposalAutoActivationCharacters may now be a bit 258 | * misleading, it is part of an API implementation called by jface.) 259 | * 260 | * @param activationSet the activation set 261 | */ 262 | public void setCContentAutoActivationCharacters(String activationSet) { 263 | fCContentAutoActivationCharacters = new ActivationSet(activationSet); 264 | } 265 | 266 | @Override 267 | protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) { 268 | char activationChar = getActivationChar(viewer, offset); 269 | CContentAssistInvocationContext context = new CContentAssistInvocationContext(viewer, offset, fEditor, 270 | isCompletion, isAutoActivated()); 271 | try { 272 | if (isCompletion && activationChar == '.' && fReplacementAutoActivationCharacters != null 273 | && fReplacementAutoActivationCharacters.contains('.')) { 274 | IASTCompletionNode node = context.getCompletionNode(); 275 | if (node != null) { 276 | IASTName[] names = node.getNames(); 277 | if (names.length > 0 && names[0].getParent() instanceof IASTFieldReference) { 278 | IASTFieldReference ref = (IASTFieldReference) names[0].getParent(); 279 | IASTExpression ownerExpr = ref.getFieldOwner(); 280 | IType ownerExprType = SemanticUtil.getNestedType(ownerExpr.getExpressionType(), 281 | SemanticUtil.TDEF); 282 | if (ownerExprType instanceof ICPPUnknownType) { 283 | try { 284 | CPPSemantics.pushLookupPoint(names[0]); 285 | ownerExprType = HeuristicResolver.resolveUnknownType((ICPPUnknownType) ownerExprType); 286 | } finally { 287 | CPPSemantics.popLookupPoint(); 288 | } 289 | } 290 | if (ownerExprType instanceof IPointerType) { 291 | context = replaceDotWithArrow(viewer, offset, isCompletion, context, activationChar); 292 | } 293 | } 294 | } 295 | if (context != null && isAutoActivated() 296 | && !fCContentAutoActivationCharacters.contains(activationChar)) { 297 | // Auto-replace, but not auto-content-assist - bug 344387. 298 | context.dispose(); 299 | context = null; 300 | } 301 | } 302 | } catch (RuntimeException | Error e) { 303 | if (context != null) 304 | context.dispose(); 305 | throw e; 306 | } 307 | 308 | return context; 309 | } 310 | 311 | private CContentAssistInvocationContext replaceDotWithArrow(ITextViewer viewer, int offset, boolean isCompletion, 312 | CContentAssistInvocationContext context, char activationChar) { 313 | IDocument doc = viewer.getDocument(); 314 | try { 315 | doc.replace(offset - 1, 1, "->"); //$NON-NLS-1$ 316 | context.dispose(); 317 | context = null; 318 | // If user turned on activation only for replacement characters, 319 | // setting the context to null will skip the proposals popup later. 320 | if (!isAutoActivated() || fCContentAutoActivationCharacters.contains(activationChar)) { 321 | context = new CContentAssistInvocationContext(viewer, offset + 1, fEditor, isCompletion, 322 | isAutoActivated()); 323 | } 324 | } catch (BadLocationException e) { 325 | // Ignore 326 | } 327 | return context; 328 | } 329 | 330 | /** 331 | * Returns the character preceding the content assist activation offset. 332 | * 333 | * @param viewer 334 | * @param offset 335 | * @return the activation character 336 | */ 337 | private char getActivationChar(ITextViewer viewer, int offset) { 338 | IDocument doc = viewer.getDocument(); 339 | if (doc == null) { 340 | return 0; 341 | } 342 | if (offset <= 0) { 343 | return 0; 344 | } 345 | try { 346 | return doc.getChar(offset - 1); 347 | } catch (BadLocationException e) { 348 | } 349 | return 0; 350 | } 351 | 352 | @Override 353 | protected boolean verifyAutoActivation(ITextViewer viewer, int offset) { 354 | IDocument doc = viewer.getDocument(); 355 | if (doc == null) { 356 | return false; 357 | } 358 | if (offset <= 0) { 359 | return false; 360 | } 361 | try { 362 | char activationChar = doc.getChar(--offset); 363 | switch (activationChar) { 364 | case ':': 365 | return offset > 0 && doc.getChar(--offset) == ':'; 366 | case '>': 367 | return offset > 0 && doc.getChar(--offset) == '-'; 368 | case '.': 369 | // Avoid completion of float literals 370 | CHeuristicScanner scanner = new CHeuristicScanner(doc); 371 | int token = scanner.previousToken(--offset, Math.max(0, offset - 200)); 372 | // The scanner reports numbers as identifiers 373 | if (token == Symbols.TokenIDENT 374 | && !Character.isJavaIdentifierStart(doc.getChar(scanner.getPosition() + 1))) { 375 | // Not a valid identifier 376 | return false; 377 | } 378 | return true; 379 | //add by nopear 0521 380 | default: 381 | return activationChar >= 97 && activationChar <= 122?true:activationChar >= 65 && activationChar <= 90; 382 | } 383 | } catch (BadLocationException e) { 384 | } 385 | return false; 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /ContentAssistProcessor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2005, 2016 IBM Corporation and others. 3 | * 4 | * This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * https://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | * 11 | * Contributors: 12 | * IBM Corporation - initial API and implementation 13 | * Anton Leherbauer (Wind River Systems) 14 | * Bryan Wilkinson (QNX) 15 | * Markus Schorn (Wind River Systems) 16 | * Kirk Beitz (Nokia) 17 | *******************************************************************************/ 18 | package org.eclipse.cdt.internal.ui.text.contentassist; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.Comparator; 23 | import java.util.List; 24 | 25 | import org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog; 26 | import org.eclipse.cdt.internal.ui.util.Messages; 27 | import org.eclipse.cdt.ui.CUIPlugin; 28 | import org.eclipse.cdt.ui.PreferenceConstants; 29 | import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext; 30 | import org.eclipse.core.runtime.Assert; 31 | import org.eclipse.core.runtime.IProgressMonitor; 32 | import org.eclipse.core.runtime.NullProgressMonitor; 33 | import org.eclipse.core.runtime.Platform; 34 | import org.eclipse.core.runtime.SubMonitor; 35 | import org.eclipse.jface.action.LegacyActionTools; 36 | import org.eclipse.jface.bindings.TriggerSequence; 37 | import org.eclipse.jface.bindings.keys.KeySequence; 38 | import org.eclipse.jface.dialogs.IDialogConstants; 39 | import org.eclipse.jface.dialogs.MessageDialog; 40 | import org.eclipse.jface.preference.IPreferenceStore; 41 | import org.eclipse.jface.resource.JFaceResources; 42 | import org.eclipse.jface.text.IDocument; 43 | import org.eclipse.jface.text.ITextViewer; 44 | import org.eclipse.jface.text.contentassist.ContentAssistEvent; 45 | import org.eclipse.jface.text.contentassist.ContentAssistant; 46 | import org.eclipse.jface.text.contentassist.ICompletionListener; 47 | import org.eclipse.jface.text.contentassist.ICompletionProposal; 48 | import org.eclipse.jface.text.contentassist.IContentAssistProcessor; 49 | import org.eclipse.jface.text.contentassist.IContentAssistantExtension2; 50 | import org.eclipse.jface.text.contentassist.IContentAssistantExtension3; 51 | import org.eclipse.jface.text.contentassist.IContextInformation; 52 | import org.eclipse.jface.text.contentassist.IContextInformationValidator; 53 | import org.eclipse.swt.SWT; 54 | import org.eclipse.swt.events.SelectionAdapter; 55 | import org.eclipse.swt.events.SelectionEvent; 56 | import org.eclipse.swt.layout.GridData; 57 | import org.eclipse.swt.layout.GridLayout; 58 | import org.eclipse.swt.widgets.Button; 59 | import org.eclipse.swt.widgets.Composite; 60 | import org.eclipse.swt.widgets.Control; 61 | import org.eclipse.swt.widgets.Link; 62 | import org.eclipse.swt.widgets.Shell; 63 | import org.eclipse.ui.PlatformUI; 64 | import org.eclipse.ui.dialogs.PreferencesUtil; 65 | import org.eclipse.ui.keys.IBindingService; 66 | import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; 67 | 68 | /** 69 | * A content assist processor that aggregates the proposals of the 70 | * {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}s contributed via 71 | * the {@code org.eclipse.cdt.ui.completionProposalComputer} extension point. 72 | *

73 | * Subclasses may extend: 74 | *

    75 | *
  • {@code createContext} to provide the context object passed to the computers
  • 76 | *
  • {@code createProgressMonitor} to change the way progress is reported
  • 77 | *
  • {@code filterAndSort} to add sorting and filtering
  • 78 | *
  • {@code getContextInformationValidator} to add context validation (needed if any 79 | * contexts are provided)
  • 80 | *
  • {@code getErrorMessage} to change error reporting
  • 81 | *
82 | * 83 | * @since 4.0 84 | */ 85 | public class ContentAssistProcessor implements IContentAssistProcessor { 86 | private static final boolean DEBUG = Boolean 87 | .parseBoolean(Platform.getDebugOption("org.eclipse.cdt.ui/debug/contentassist")); //$NON-NLS-1$ 88 | 89 | /** 90 | * Dialog settings key for the "all categories are disabled" warning dialog. 91 | * See {@link OptionalMessageDialog}. 92 | */ 93 | private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY = "EmptyDefaultAssistCategory"; //$NON-NLS-1$ 94 | 95 | private static final Comparator ORDER_COMPARATOR = new Comparator() { 96 | @Override 97 | public int compare(CompletionProposalCategory d1, CompletionProposalCategory d2) { 98 | return d1.getSortOrder() - d2.getSortOrder(); 99 | } 100 | }; 101 | 102 | private static final ICompletionProposal[] NO_PROPOSALS = {}; 103 | 104 | private final List fCategories; 105 | private final String fPartition; 106 | private final ContentAssistant fAssistant; 107 | 108 | private char[] fCompletionAutoActivationCharacters; 109 | 110 | /* cycling stuff */ 111 | private int fRepetition = -1; 112 | private List> fCategoryIteration; 113 | private String fIterationGesture; 114 | private int fNumberOfComputedResults; 115 | private String fErrorMessage; 116 | private boolean fIsAutoActivated; 117 | 118 | public ContentAssistProcessor(ContentAssistant assistant, String partition) { 119 | Assert.isNotNull(partition); 120 | Assert.isNotNull(assistant); 121 | fPartition = partition; 122 | fCategories = CompletionProposalComputerRegistry.getDefault().getProposalCategories(); 123 | fAssistant = assistant; 124 | fAssistant.addCompletionListener(new ICompletionListener() { 125 | @Override 126 | public void assistSessionStarted(ContentAssistEvent event) { 127 | if (event.processor != ContentAssistProcessor.this) 128 | return; 129 | 130 | fIsAutoActivated = event.isAutoActivated; 131 | fIterationGesture = getIterationGesture(); 132 | KeySequence binding = getIterationBinding(); 133 | 134 | // This may show the warning dialog if all categories are disabled. 135 | fCategoryIteration = getCategoryIteration(); 136 | for (Object element : fCategories) { 137 | CompletionProposalCategory cat = (CompletionProposalCategory) element; 138 | cat.sessionStarted(); 139 | } 140 | 141 | fRepetition = 0; 142 | if (event.assistant instanceof IContentAssistantExtension2) { 143 | IContentAssistantExtension2 extension = (IContentAssistantExtension2) event.assistant; 144 | 145 | if (fCategoryIteration.size() == 1) { 146 | extension.setRepeatedInvocationMode(false); 147 | extension.setShowEmptyList(false); 148 | } else { 149 | extension.setRepeatedInvocationMode(true); 150 | extension.setStatusLineVisible(true); 151 | extension.setStatusMessage(createIterationMessage()); 152 | extension.setShowEmptyList(true); 153 | if (extension instanceof IContentAssistantExtension3) { 154 | IContentAssistantExtension3 ext3 = (IContentAssistantExtension3) extension; 155 | ((ContentAssistant) ext3).setRepeatedInvocationTrigger(binding); 156 | } 157 | } 158 | 159 | } 160 | } 161 | 162 | @Override 163 | public void assistSessionEnded(ContentAssistEvent event) { 164 | if (event.processor != ContentAssistProcessor.this) 165 | return; 166 | 167 | for (Object element : fCategories) { 168 | CompletionProposalCategory cat = (CompletionProposalCategory) element; 169 | cat.sessionEnded(); 170 | } 171 | 172 | fCategoryIteration = null; 173 | fRepetition = -1; 174 | fIterationGesture = null; 175 | if (event.assistant instanceof IContentAssistantExtension2) { 176 | IContentAssistantExtension2 extension = (IContentAssistantExtension2) event.assistant; 177 | extension.setShowEmptyList(false); 178 | extension.setRepeatedInvocationMode(false); 179 | extension.setStatusLineVisible(false); 180 | if (extension instanceof IContentAssistantExtension3) { 181 | IContentAssistantExtension3 ext3 = (IContentAssistantExtension3) extension; 182 | ((ContentAssistant) ext3).setRepeatedInvocationTrigger(null); 183 | } 184 | } 185 | } 186 | 187 | @Override 188 | public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { 189 | } 190 | 191 | }); 192 | } 193 | 194 | @Override 195 | public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { 196 | long start = DEBUG ? System.currentTimeMillis() : 0; 197 | 198 | if (isAutoActivated() && !verifyAutoActivation(viewer, offset)) { 199 | return NO_PROPOSALS; 200 | } 201 | 202 | clearState(); 203 | 204 | IProgressMonitor monitor = createProgressMonitor(); 205 | monitor.beginTask(ContentAssistMessages.ContentAssistProcessor_computing_proposals, fCategories.size() + 1); 206 | 207 | ContentAssistInvocationContext context = createContext(viewer, offset, true); 208 | if (context == null) 209 | return null; 210 | 211 | try { 212 | long setup = DEBUG ? System.currentTimeMillis() : 0; 213 | 214 | monitor.subTask(ContentAssistMessages.ContentAssistProcessor_collecting_proposals); 215 | List proposals = collectProposals(viewer, offset, monitor, context); 216 | long collect = DEBUG ? System.currentTimeMillis() : 0; 217 | 218 | monitor.subTask(ContentAssistMessages.ContentAssistProcessor_sorting_proposals); 219 | List filtered = filterAndSortProposals(proposals, monitor, context); 220 | fNumberOfComputedResults = filtered.size(); 221 | long filter = DEBUG ? System.currentTimeMillis() : 0; 222 | 223 | ICompletionProposal[] result = filtered.toArray(new ICompletionProposal[filtered.size()]); 224 | monitor.done(); 225 | 226 | if (DEBUG) { 227 | System.out.println("Code Assist Stats (" + result.length + " proposals)"); //$NON-NLS-1$ //$NON-NLS-2$ 228 | System.out.println("Code Assist (setup):\t" + (setup - start)); //$NON-NLS-1$ 229 | System.out.println("Code Assist (collect):\t" + (collect - setup)); //$NON-NLS-1$ 230 | System.out.println("Code Assist (sort):\t" + (filter - collect)); //$NON-NLS-1$ 231 | } 232 | 233 | return result; 234 | } finally { 235 | context.dispose(); 236 | } 237 | } 238 | 239 | /** 240 | * Verifies that auto activation is allowed. 241 | *

242 | * The default implementation always returns {@code true}. 243 | * 244 | * @param viewer the text viewer 245 | * @param offset the offset where content assist was invoked on 246 | * @return {@code true} if auto activation is allowed 247 | */ 248 | protected boolean verifyAutoActivation(ITextViewer viewer, int offset) { 249 | return true; 250 | } 251 | 252 | private void clearState() { 253 | fErrorMessage = null; 254 | fNumberOfComputedResults = 0; 255 | } 256 | 257 | private List collectProposals(ITextViewer viewer, int offset, IProgressMonitor monitor, 258 | ContentAssistInvocationContext context) { 259 | List proposals = new ArrayList<>(); 260 | List providers = getCategories(); 261 | SubMonitor progress = SubMonitor.convert(monitor, providers.size()); 262 | for (CompletionProposalCategory cat : providers) { 263 | List computed = cat.computeCompletionProposals(context, fPartition, progress.split(1)); 264 | proposals.addAll(computed); 265 | if (fErrorMessage == null) 266 | fErrorMessage = cat.getErrorMessage(); 267 | } 268 | 269 | return proposals; 270 | } 271 | 272 | /** 273 | * Filters and sorts the proposals. The passed list may be modified 274 | * and returned, or a new list may be created and returned. 275 | * 276 | * @param proposals the list of collected proposals (element type: {@link ICompletionProposal}) 277 | * @param monitor a progress monitor 278 | * @param context TODO 279 | * @return the list of filtered and sorted proposals, ready for 280 | * display (element type: {@link ICompletionProposal}) 281 | */ 282 | protected List filterAndSortProposals(List proposals, 283 | IProgressMonitor monitor, ContentAssistInvocationContext context) { 284 | return proposals; 285 | } 286 | 287 | @Override 288 | public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { 289 | clearState(); 290 | 291 | IProgressMonitor monitor = createProgressMonitor(); 292 | monitor.beginTask(ContentAssistMessages.ContentAssistProcessor_computing_contexts, fCategories.size() + 1); 293 | 294 | monitor.subTask(ContentAssistMessages.ContentAssistProcessor_collecting_contexts); 295 | List proposals = collectContextInformation(viewer, offset, monitor); 296 | 297 | monitor.subTask(ContentAssistMessages.ContentAssistProcessor_sorting_contexts); 298 | List filtered = filterAndSortContextInformation(proposals, monitor); 299 | fNumberOfComputedResults = filtered.size(); 300 | 301 | IContextInformation[] result = filtered.toArray(new IContextInformation[filtered.size()]); 302 | monitor.done(); 303 | return result; 304 | } 305 | 306 | private List collectContextInformation(ITextViewer viewer, int offset, 307 | IProgressMonitor monitor) { 308 | List proposals = new ArrayList<>(); 309 | ContentAssistInvocationContext context = createContext(viewer, offset, false); 310 | 311 | try { 312 | List providers = getCategories(); 313 | SubMonitor progress = SubMonitor.convert(monitor, providers.size()); 314 | for (CompletionProposalCategory cat : providers) { 315 | List computed = cat.computeContextInformation(context, fPartition, 316 | progress.split(1)); 317 | proposals.addAll(computed); 318 | if (fErrorMessage == null) 319 | fErrorMessage = cat.getErrorMessage(); 320 | } 321 | 322 | return proposals; 323 | } finally { 324 | context.dispose(); 325 | } 326 | } 327 | 328 | /** 329 | * Filters and sorts the context information objects. The passed list may be modified 330 | * and returned, or a new list may be created and returned. 331 | * 332 | * @param contexts the list of collected proposals (element type: {@link IContextInformation}) 333 | * @param monitor a progress monitor 334 | * @return the list of filtered and sorted proposals, ready for 335 | * display (element type: {@link IContextInformation}) 336 | */ 337 | protected List filterAndSortContextInformation(List contexts, 338 | IProgressMonitor monitor) { 339 | return contexts; 340 | } 341 | 342 | /** 343 | * Sets this processor's set of characters triggering the activation of the 344 | * completion proposal computation (including auto-correction auto-activation) 345 | * 346 | * @param activationSet the activation set 347 | */ 348 | public void setCompletionProposalAutoActivationCharacters(char[] activationSet) { 349 | // fCompletionAutoActivationCharacters = activationSet; 350 | String test = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 351 | char[] triggers = test.toCharArray(); 352 | fCompletionAutoActivationCharacters = triggers; 353 | } 354 | 355 | @Override 356 | public char[] getCompletionProposalAutoActivationCharacters() { 357 | return fCompletionAutoActivationCharacters; 358 | } 359 | 360 | @Override 361 | public char[] getContextInformationAutoActivationCharacters() { 362 | return null; 363 | } 364 | 365 | @Override 366 | public String getErrorMessage() { 367 | if (fNumberOfComputedResults > 0) 368 | return null; 369 | if (fErrorMessage != null) 370 | return fErrorMessage; 371 | return ContentAssistMessages.ContentAssistProcessor_no_completions; 372 | } 373 | 374 | @Override 375 | public IContextInformationValidator getContextInformationValidator() { 376 | return null; 377 | } 378 | 379 | /** 380 | * Creates a progress monitor. 381 | *

382 | * The default implementation creates a {@code NullProgressMonitor}. 383 | * 384 | * @return a progress monitor 385 | */ 386 | protected IProgressMonitor createProgressMonitor() { 387 | return new NullProgressMonitor(); 388 | } 389 | 390 | /** 391 | * Creates the context that is passed to the completion proposal computers. 392 | * 393 | * @param viewer the viewer that content assist is invoked on 394 | * @param offset the content assist offset 395 | * @return the context to be passed to the computers, 396 | * or {@code null} if no completion is possible 397 | */ 398 | protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) { 399 | return new ContentAssistInvocationContext(viewer, offset); 400 | } 401 | 402 | /** 403 | * Test whether the current session was auto-activated. 404 | * 405 | * @return {@code true} if the current session was auto-activated. 406 | */ 407 | protected boolean isAutoActivated() { 408 | return fIsAutoActivated; 409 | } 410 | 411 | private List getCategories() { 412 | if (fCategoryIteration == null) 413 | return fCategories; 414 | 415 | int iteration = fRepetition % fCategoryIteration.size(); 416 | fAssistant.setStatusMessage(createIterationMessage()); 417 | fAssistant.setEmptyMessage(createEmptyMessage()); 418 | fRepetition++; 419 | 420 | // fAssistant.setShowMessage(fRepetition % 2 != 0); 421 | // 422 | return fCategoryIteration.get(iteration); 423 | } 424 | 425 | private List> getCategoryIteration() { 426 | List> sequence = new ArrayList<>(); 427 | sequence.add(getDefaultCategories()); 428 | for (CompletionProposalCategory cat : getSeparateCategories()) { 429 | sequence.add(Collections.singletonList(cat)); 430 | } 431 | return sequence; 432 | } 433 | 434 | private List getDefaultCategories() { 435 | // default mix - enable all included computers 436 | List included = getDefaultCategoriesUnchecked(); 437 | 438 | if (IDocument.DEFAULT_CONTENT_TYPE.equals(fPartition) && included.isEmpty() && !fCategories.isEmpty()) 439 | if (informUserAboutEmptyDefaultCategory()) 440 | // preferences were restored - recompute the default categories 441 | included = getDefaultCategoriesUnchecked(); 442 | 443 | return included; 444 | } 445 | 446 | private List getDefaultCategoriesUnchecked() { 447 | List included = new ArrayList<>(); 448 | for (Object element : fCategories) { 449 | CompletionProposalCategory category = (CompletionProposalCategory) element; 450 | if (category.isIncluded() && category.hasComputers(fPartition)) 451 | included.add(category); 452 | } 453 | return included; 454 | } 455 | 456 | /** 457 | * Informs the user about the fact that there are no enabled categories in the default content 458 | * assist set and shows a link to the preferences. 459 | */ 460 | private boolean informUserAboutEmptyDefaultCategory() { 461 | if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) { 462 | final Shell shell = CUIPlugin.getActiveWorkbenchShell(); 463 | String title = ContentAssistMessages.ContentAssistProcessor_all_disabled_title; 464 | String message = ContentAssistMessages.ContentAssistProcessor_all_disabled_message; 465 | // see PreferencePage#createControl for the 'defaults' label 466 | final String restoreButtonLabel = JFaceResources.getString("defaults"); //$NON-NLS-1$ 467 | final String linkMessage = Messages.format( 468 | ContentAssistMessages.ContentAssistProcessor_all_disabled_preference_link, 469 | LegacyActionTools.removeMnemonics(restoreButtonLabel)); 470 | final int restoreId = IDialogConstants.CLIENT_ID + 10; 471 | final int settingsId = IDialogConstants.CLIENT_ID + 11; 472 | final OptionalMessageDialog dialog = new OptionalMessageDialog(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY, shell, 473 | title, null /* default image */, message, MessageDialog.WARNING, 474 | new String[] { restoreButtonLabel, IDialogConstants.CLOSE_LABEL }, 1) { 475 | @Override 476 | protected Control createCustomArea(Composite composite) { 477 | // wrap link and checkbox in one composite without space 478 | Composite parent = new Composite(composite, SWT.NONE); 479 | GridLayout layout = new GridLayout(); 480 | layout.marginHeight = 0; 481 | layout.marginWidth = 0; 482 | layout.verticalSpacing = 0; 483 | parent.setLayout(layout); 484 | 485 | Composite linkComposite = new Composite(parent, SWT.NONE); 486 | layout = new GridLayout(); 487 | layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); 488 | layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); 489 | layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); 490 | linkComposite.setLayout(layout); 491 | 492 | Link link = new Link(linkComposite, SWT.NONE); 493 | link.setText(linkMessage); 494 | link.addSelectionListener(new SelectionAdapter() { 495 | @Override 496 | public void widgetSelected(SelectionEvent e) { 497 | setReturnCode(settingsId); 498 | close(); 499 | } 500 | }); 501 | GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false); 502 | gridData.widthHint = this.getMinimumMessageWidth(); 503 | link.setLayoutData(gridData); 504 | 505 | // create checkbox and "don't show this message" prompt 506 | super.createCustomArea(parent); 507 | 508 | return parent; 509 | } 510 | 511 | @Override 512 | protected void createButtonsForButtonBar(Composite parent) { 513 | Button[] buttons = new Button[2]; 514 | buttons[0] = createButton(parent, restoreId, restoreButtonLabel, false); 515 | buttons[1] = createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, true); 516 | setButtons(buttons); 517 | } 518 | }; 519 | int returnValue = dialog.open(); 520 | if (restoreId == returnValue || settingsId == returnValue) { 521 | if (restoreId == returnValue) { 522 | IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore(); 523 | store.setToDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER); 524 | store.setToDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES); 525 | } 526 | if (settingsId == returnValue) 527 | PreferencesUtil.createPreferenceDialogOn(shell, 528 | "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$ 529 | CompletionProposalComputerRegistry registry = CompletionProposalComputerRegistry.getDefault(); 530 | registry.reload(); 531 | return true; 532 | } 533 | } 534 | return false; 535 | } 536 | 537 | private List getSeparateCategories() { 538 | ArrayList sorted = new ArrayList<>(); 539 | for (Object element : fCategories) { 540 | CompletionProposalCategory category = (CompletionProposalCategory) element; 541 | if (category.isSeparateCommand() && category.hasComputers(fPartition)) 542 | sorted.add(category); 543 | } 544 | Collections.sort(sorted, ORDER_COMPARATOR); 545 | return sorted; 546 | } 547 | 548 | private String createEmptyMessage() { 549 | return Messages.format(ContentAssistMessages.ContentAssistProcessor_empty_message, 550 | getCategoryLabel(fRepetition)); 551 | } 552 | 553 | private String createIterationMessage() { 554 | return Messages.format(ContentAssistMessages.ContentAssistProcessor_toggle_affordance_update_message, 555 | getCategoryLabel(fRepetition), fIterationGesture, getCategoryLabel(fRepetition + 1)); 556 | } 557 | 558 | private String getCategoryLabel(int repetition) { 559 | int iteration = repetition % fCategoryIteration.size(); 560 | if (iteration == 0) 561 | return ContentAssistMessages.ContentAssistProcessor_defaultProposalCategory; 562 | return toString(fCategoryIteration.get(iteration).get(0)); 563 | } 564 | 565 | private String toString(CompletionProposalCategory category) { 566 | return category.getDisplayName(); 567 | } 568 | 569 | private String getIterationGesture() { 570 | TriggerSequence binding = getIterationBinding(); 571 | return binding != null 572 | ? Messages.format(ContentAssistMessages.ContentAssistProcessor_toggle_affordance_press_gesture, 573 | new Object[] { binding.format() }) 574 | : ContentAssistMessages.ContentAssistProcessor_toggle_affordance_click_gesture; 575 | } 576 | 577 | private KeySequence getIterationBinding() { 578 | final IBindingService bindingSvc = PlatformUI.getWorkbench().getAdapter(IBindingService.class); 579 | TriggerSequence binding = bindingSvc 580 | .getBestActiveBindingFor(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); 581 | if (binding instanceof KeySequence) 582 | return (KeySequence) binding; 583 | return null; 584 | } 585 | } 586 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cubeIDE_Autocomplete 2 | cubeIDE_Autocomplete eclipse cdt modify 3 | 4 | 2 source file can repalce the origin source file. 5 | 6 | use the 7 | org.eclipse.cdt.ui_6.6.0.201909091956.jar 8 | file repalce the D:\ST\STM32CubeIDE_1.3.0\STM32CubeIDE\plugins 9 | 10 | 11 | -------------------------------------------------------------------------------- /org.eclipse.cdt.ui_6.6.0.201909091956.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopear1/cubeIDE_Autocomplete/06f11f15234f1f5b854524c47ac4f42cbe3c868e/org.eclipse.cdt.ui_6.6.0.201909091956.jar --------------------------------------------------------------------------------