OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014, the Dart project authors. | 2 * Copyright (c) 2014, the Dart project authors. |
3 * | 3 * |
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except | 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
5 * in compliance with the License. You may obtain a copy of the License at | 5 * in compliance with the License. You may obtain a copy of the License at |
6 * | 6 * |
7 * http://www.eclipse.org/legal/epl-v10.html | 7 * http://www.eclipse.org/legal/epl-v10.html |
8 * | 8 * |
9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License | 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express | 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 doc.replace(offset, 0, Character.toString(trigger)); | 246 doc.replace(offset, 0, Character.toString(trigger)); |
247 return; | 247 return; |
248 } | 248 } |
249 /* | 249 /* |
250 * Simplistic argument list completion... strip parens and continue | 250 * Simplistic argument list completion... strip parens and continue |
251 */ | 251 */ |
252 // TODO (danrubel) improve argument list completion | 252 // TODO (danrubel) improve argument list completion |
253 if (completion.startsWith("(")) { | 253 if (completion.startsWith("(")) { |
254 completion = completion.substring(1, completion.length() - 1); | 254 completion = completion.substring(1, completion.length() - 1); |
255 } | 255 } |
| 256 boolean hasArgumentList = completion.endsWith(")"); |
| 257 boolean hasArguments = !completion.endsWith("()"); |
256 /* | 258 /* |
257 * Insert the suggestion | 259 * Insert the suggestion |
258 */ | 260 */ |
259 doc.replace(replacementOffset, replacementLength, completion); | 261 doc.replace(replacementOffset, replacementLength, completion); |
260 /* | 262 /* |
261 * If the suggestion has parameters, initiate entering parameters | 263 * Check if linked mode for arguments is needed |
262 */ | 264 */ |
263 if (argumentLengths != null) { | 265 boolean isTriggerEnter = trigger == '\0' || trigger == '\n'; |
264 // Set up linked position groups for the arguments. | 266 if (hasArgumentList && (isTriggerEnter || trigger == '(')) { |
| 267 // If Enter or '(' (when blind typing), then use linked mode. |
| 268 } else { |
| 269 // Insert the trigger and stop completion. |
| 270 selectionOffset = completion.length(); |
| 271 selectionLength = 0; |
| 272 if (!isTriggerEnter) { |
| 273 doc.replace( |
| 274 replacementOffset + selectionOffset, |
| 275 selectionLength, |
| 276 Character.toString(trigger)); |
| 277 ++selectionOffset; |
| 278 } |
| 279 return; |
| 280 } |
| 281 /* |
| 282 * Done if zero arguments and Enter is the trigger |
| 283 */ |
| 284 if (!hasArguments && isTriggerEnter) { |
| 285 return; |
| 286 } |
| 287 /* |
| 288 * If the suggestion has an argument list, initiate entering arguments |
| 289 */ |
| 290 if (hasArgumentList) { |
| 291 // Prepare linked mode model |
265 LinkedModeModel model = new LinkedModeModel(); | 292 LinkedModeModel model = new LinkedModeModel(); |
266 buildLinkedModeModel(model, doc, replacementOffset); | 293 if (hasArguments) { |
| 294 buildLinkedModeModel_hasArgumentList(model, doc, replacementOffset); |
| 295 } else { |
| 296 // If there are no arguments, we still want to use linked mode to igno
re ')'. |
| 297 buildLinkedModeModel_emptyArguments(model, doc, replacementOffset, com
pletion); |
| 298 } |
267 model.forceInstall(); | 299 model.forceInstall(); |
268 | 300 // Start linked mode UI |
269 LinkedModeUI ui = new EditorLinkedModeUI(model, viewer); | 301 LinkedModeUI ui = new EditorLinkedModeUI(model, viewer); |
270 ui.setExitPolicy(new ExitPolicy(')', doc, viewer)); | 302 if (hasArguments) { |
| 303 ui.setExitPolicy(new ExitPolicy(')', doc, viewer)); |
| 304 } else { |
| 305 ui.setExitPolicy(new AnyExitPolicy()); |
| 306 } |
271 ui.setExitPosition(viewer, replacementOffset + completion.length(), 0, I
nteger.MAX_VALUE); | 307 ui.setExitPosition(viewer, replacementOffset + completion.length(), 0, I
nteger.MAX_VALUE); |
272 ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT); | 308 ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT); |
273 ui.enter(); | 309 ui.enter(); |
274 return; | |
275 } | |
276 /* | |
277 * If completion already includes '()' then don't insert extra '(' or ')' | |
278 */ | |
279 if (completion.endsWith(")") && (trigger == '(' || trigger == ')')) { | |
280 return; | |
281 } | |
282 /* | |
283 * Insert the trigger character typed if it is not enter or null | |
284 */ | |
285 if (trigger != '\0' && trigger != '\n') { | |
286 doc.replace( | |
287 replacementOffset + selectionOffset, | |
288 selectionLength, | |
289 Character.toString(trigger)); | |
290 ++selectionOffset; | |
291 selectionLength = 0; | |
292 return; | |
293 } | 310 } |
294 } catch (BadLocationException e) { | 311 } catch (BadLocationException e) { |
295 DartCore.logInformation("Failed to replace offset:" + replacementOffset +
" length:" | 312 DartCore.logInformation("Failed to replace offset:" + replacementOffset +
" length:" |
296 + replacementLength + " with:" + completion, e); | 313 + replacementLength + " with:" + completion, e); |
297 instrumentation.metric("Problem", "BadLocationException"); | 314 instrumentation.metric("Problem", "BadLocationException"); |
298 } finally { | 315 } finally { |
299 instrumentation.log(); | 316 instrumentation.log(); |
300 } | 317 } |
301 } | 318 } |
302 | 319 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 try { | 490 try { |
474 textEntered = document.get(replacementOffset, offset - replacementOffset); | 491 textEntered = document.get(replacementOffset, offset - replacementOffset); |
475 } catch (BadLocationException x) { | 492 } catch (BadLocationException x) { |
476 return false; | 493 return false; |
477 } | 494 } |
478 String completion = TextProcessor.deprocess(getDisplayString()); | 495 String completion = TextProcessor.deprocess(getDisplayString()); |
479 if (completion.length() == 0 || completion.length() < textEntered.length())
{ | 496 if (completion.length() == 0 || completion.length() < textEntered.length())
{ |
480 return false; | 497 return false; |
481 } | 498 } |
482 // If the user has entered an upper case char as the first char | 499 // If the user has entered an upper case char as the first char |
483 // then filter all lower case first character suggestions. | 500 // then filter using only camelCaseMatching |
484 if (Character.isUpperCase(textEntered.charAt(0)) && Character.isLowerCase(co
mpletion.charAt(0))) { | 501 if (!Character.isUpperCase(textEntered.charAt(0))) { |
485 return false; | 502 String partialCompletion = completion.substring(0, textEntered.length()); |
486 } | 503 if (partialCompletion.equalsIgnoreCase(textEntered)) { |
487 String partialCompletion = completion.substring(0, textEntered.length()); | 504 return true; |
488 if (partialCompletion.equalsIgnoreCase(textEntered)) { | 505 } |
489 return true; | |
490 } | 506 } |
491 char[] pattern = textEntered.toCharArray(); | 507 char[] pattern = textEntered.toCharArray(); |
492 char[] name = completion.toCharArray(); | 508 char[] name = completion.toCharArray(); |
493 return CharOperation.camelCaseMatch(pattern, 0, pattern.length, name, 0, nam
e.length, false); | 509 return CharOperation.camelCaseMatch(pattern, 0, pattern.length, name, 0, nam
e.length, false); |
494 } | 510 } |
495 | 511 |
496 protected void buildLinkedModeModel(LinkedModeModel model, IDocument document,
int baseOffset) | 512 protected void buildLinkedModeModel_emptyArguments(LinkedModeModel model, IDoc
ument document, |
497 throws BadLocationException { | 513 int baseOffset, String completion) throws BadLocationException { |
| 514 LinkedPositionGroup group = new LinkedPositionGroup(); |
| 515 LinkedPosition pos = new LinkedPosition( |
| 516 document, |
| 517 baseOffset + completion.length(), |
| 518 0, |
| 519 LinkedPositionGroup.NO_STOP); |
| 520 group.addPosition(pos); |
| 521 model.addGroup(group); |
| 522 } |
| 523 |
| 524 protected void buildLinkedModeModel_hasArgumentList(LinkedModeModel model, IDo
cument document, |
| 525 int baseOffset) throws BadLocationException { |
498 // TODO(paulberry): consider extending to support optional arguments, as | 526 // TODO(paulberry): consider extending to support optional arguments, as |
499 // FilledArgumentNamesMethodProposal does. | 527 // FilledArgumentNamesMethodProposal does. |
500 for (int i = 0; i != argumentOffsets.length; i++) { | 528 for (int i = 0; i != argumentOffsets.length; i++) { |
501 LinkedPositionGroup group = new LinkedPositionGroup(); | 529 LinkedPositionGroup group = new LinkedPositionGroup(); |
502 LinkedPosition pos = new LinkedPosition( | 530 LinkedPosition pos = new LinkedPosition( |
503 document, | 531 document, |
504 baseOffset + argumentOffsets[i], | 532 baseOffset + argumentOffsets[i], |
505 argumentLengths[i], | 533 argumentLengths[i], |
506 LinkedPositionGroup.NO_STOP); | 534 LinkedPositionGroup.NO_STOP); |
507 group.addPosition(pos); | 535 group.addPosition(pos); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 if (element != null) { | 697 if (element != null) { |
670 return element.getParameters(); | 698 return element.getParameters(); |
671 } | 699 } |
672 } | 700 } |
673 } | 701 } |
674 return null; | 702 return null; |
675 } | 703 } |
676 } | 704 } |
677 | 705 |
678 /** | 706 /** |
| 707 * {@link IExitPolicy} that exists on any character. |
| 708 */ |
| 709 class AnyExitPolicy implements IExitPolicy { |
| 710 @Override |
| 711 public ExitFlags doExit(LinkedModeModel environment, VerifyEvent event, int of
fset, int length) { |
| 712 if (event.character == 0) { |
| 713 return null; |
| 714 } |
| 715 boolean doit = event.character != ')'; |
| 716 return new ExitFlags(ILinkedModeListener.UPDATE_CARET, doit); |
| 717 } |
| 718 } |
| 719 |
| 720 /** |
679 * Allow the linked mode editor to continue running even when the exit character
is typed as part of | 721 * Allow the linked mode editor to continue running even when the exit character
is typed as part of |
680 * a function argument. Using shift operators in a context that expects balanced
angle brackets is | 722 * a function argument. Using shift operators in a context that expects balanced
angle brackets is |
681 * not legal syntax and will confuse the linked mode editor. | 723 * not legal syntax and will confuse the linked mode editor. |
682 */ | 724 */ |
683 class ExitPolicy implements IExitPolicy { | 725 class ExitPolicy implements IExitPolicy { |
684 | 726 |
685 private int parenCount = 0; | 727 private int parenCount = 0; |
686 private int braceCount = 0; | 728 private int braceCount = 0; |
687 private int bracketCount = 0; | 729 private int bracketCount = 0; |
688 private int angleBracketCount = 0; | 730 private int angleBracketCount = 0; |
689 private char lastChar = (char) 0; | 731 private char lastChar = (char) 0; |
690 | 732 |
691 final char exitChar; | 733 private final char exitChar; |
692 private final IDocument document; | 734 private final IDocument document; |
693 private final ITextViewer viewer; | 735 private final ITextViewer viewer; |
694 | 736 |
695 public ExitPolicy(char exitChar, IDocument document, ITextViewer viewer) { | 737 public ExitPolicy(char exitChar, IDocument document, ITextViewer viewer) { |
696 this.exitChar = exitChar; | 738 this.exitChar = exitChar; |
697 this.document = document; | 739 this.document = document; |
698 this.viewer = viewer; | 740 this.viewer = viewer; |
699 } | 741 } |
700 | 742 |
701 @Override | 743 @Override |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 return braceCount == -1; | 865 return braceCount == -1; |
824 case ']': | 866 case ']': |
825 return bracketCount == -1; | 867 return bracketCount == -1; |
826 case '>': | 868 case '>': |
827 return angleBracketCount == -1; | 869 return angleBracketCount == -1; |
828 default: | 870 default: |
829 return true; // never unbalanced | 871 return true; // never unbalanced |
830 } | 872 } |
831 } | 873 } |
832 } | 874 } |
OLD | NEW |