169 @Override |
169 @Override |
170 public CompletionInfo analyzeCompletion(String srcInput) { |
170 public CompletionInfo analyzeCompletion(String srcInput) { |
171 MaskCommentsAndModifiers mcm = new MaskCommentsAndModifiers(srcInput, false); |
171 MaskCommentsAndModifiers mcm = new MaskCommentsAndModifiers(srcInput, false); |
172 if (mcm.endsWithOpenComment()) { |
172 if (mcm.endsWithOpenComment()) { |
173 proc.debug(DBG_COMPA, "Incomplete (open comment): %s\n", srcInput); |
173 proc.debug(DBG_COMPA, "Incomplete (open comment): %s\n", srcInput); |
174 return new CompletionInfo(DEFINITELY_INCOMPLETE, srcInput.length(), null, srcInput + '\n'); |
174 return new CompletionInfoImpl(DEFINITELY_INCOMPLETE, null, srcInput + '\n'); |
175 } |
175 } |
176 String cleared = mcm.cleared(); |
176 String cleared = mcm.cleared(); |
177 String trimmedInput = Util.trimEnd(cleared); |
177 String trimmedInput = Util.trimEnd(cleared); |
178 if (trimmedInput.isEmpty()) { |
178 if (trimmedInput.isEmpty()) { |
179 // Just comment or empty |
179 // Just comment or empty |
180 return new CompletionInfo(Completeness.EMPTY, srcInput.length(), srcInput, ""); |
180 return new CompletionInfoImpl(Completeness.EMPTY, srcInput, ""); |
181 } |
181 } |
182 CaInfo info = ca.scan(trimmedInput); |
182 CaInfo info = ca.scan(trimmedInput); |
183 Completeness status = info.status; |
183 Completeness status = info.status; |
184 int unitEndPos = info.unitEndPos; |
184 int unitEndPos = info.unitEndPos; |
185 if (unitEndPos > srcInput.length()) { |
185 if (unitEndPos > srcInput.length()) { |
193 // The unit is the whole non-coment/white input plus semicolon |
193 // The unit is the whole non-coment/white input plus semicolon |
194 String compileSource = src |
194 String compileSource = src |
195 + mcm.mask().substring(nonCommentNonWhiteLength); |
195 + mcm.mask().substring(nonCommentNonWhiteLength); |
196 proc.debug(DBG_COMPA, "Complete: %s\n", compileSource); |
196 proc.debug(DBG_COMPA, "Complete: %s\n", compileSource); |
197 proc.debug(DBG_COMPA, " nothing remains.\n"); |
197 proc.debug(DBG_COMPA, " nothing remains.\n"); |
198 return new CompletionInfo(status, unitEndPos, compileSource, ""); |
198 return new CompletionInfoImpl(status, compileSource, ""); |
199 } else { |
199 } else { |
200 String remain = srcInput.substring(unitEndPos); |
200 String remain = srcInput.substring(unitEndPos); |
201 proc.debug(DBG_COMPA, "Complete: %s\n", src); |
201 proc.debug(DBG_COMPA, "Complete: %s\n", src); |
202 proc.debug(DBG_COMPA, " remaining: %s\n", remain); |
202 proc.debug(DBG_COMPA, " remaining: %s\n", remain); |
203 return new CompletionInfo(status, unitEndPos, src, remain); |
203 return new CompletionInfoImpl(status, src, remain); |
204 } |
204 } |
205 case COMPLETE_WITH_SEMI: |
205 case COMPLETE_WITH_SEMI: |
206 // The unit is the whole non-coment/white input plus semicolon |
206 // The unit is the whole non-coment/white input plus semicolon |
207 String compileSource = src |
207 String compileSource = src |
208 + ";" |
208 + ";" |
209 + mcm.mask().substring(nonCommentNonWhiteLength); |
209 + mcm.mask().substring(nonCommentNonWhiteLength); |
210 proc.debug(DBG_COMPA, "Complete with semi: %s\n", compileSource); |
210 proc.debug(DBG_COMPA, "Complete with semi: %s\n", compileSource); |
211 proc.debug(DBG_COMPA, " nothing remains.\n"); |
211 proc.debug(DBG_COMPA, " nothing remains.\n"); |
212 return new CompletionInfo(status, unitEndPos, compileSource, ""); |
212 return new CompletionInfoImpl(status, compileSource, ""); |
213 case DEFINITELY_INCOMPLETE: |
213 case DEFINITELY_INCOMPLETE: |
214 proc.debug(DBG_COMPA, "Incomplete: %s\n", srcInput); |
214 proc.debug(DBG_COMPA, "Incomplete: %s\n", srcInput); |
215 return new CompletionInfo(status, unitEndPos, null, srcInput + '\n'); |
215 return new CompletionInfoImpl(status, null, srcInput + '\n'); |
216 case CONSIDERED_INCOMPLETE: |
216 case CONSIDERED_INCOMPLETE: |
217 proc.debug(DBG_COMPA, "Considered incomplete: %s\n", srcInput); |
217 proc.debug(DBG_COMPA, "Considered incomplete: %s\n", srcInput); |
218 return new CompletionInfo(status, unitEndPos, null, srcInput + '\n'); |
218 return new CompletionInfoImpl(status, null, srcInput + '\n'); |
219 case EMPTY: |
219 case EMPTY: |
220 proc.debug(DBG_COMPA, "Detected empty: %s\n", srcInput); |
220 proc.debug(DBG_COMPA, "Detected empty: %s\n", srcInput); |
221 return new CompletionInfo(status, unitEndPos, srcInput, ""); |
221 return new CompletionInfoImpl(status, srcInput, ""); |
222 case UNKNOWN: |
222 case UNKNOWN: |
223 proc.debug(DBG_COMPA, "Detected error: %s\n", srcInput); |
223 proc.debug(DBG_COMPA, "Detected error: %s\n", srcInput); |
224 return new CompletionInfo(status, unitEndPos, srcInput, ""); |
224 return new CompletionInfoImpl(status, srcInput, ""); |
225 } |
225 } |
226 throw new InternalError(); |
226 throw new InternalError(); |
227 } |
227 } |
228 |
228 |
229 private Tree.Kind guessKind(String code) { |
229 private Tree.Kind guessKind(String code) { |
1698 synchronized (currentIndexes) { |
1698 synchronized (currentIndexes) { |
1699 upToDate = classpathVersion == indexVersion; |
1699 upToDate = classpathVersion == indexVersion; |
1700 } |
1700 } |
1701 } |
1701 } |
1702 } |
1702 } |
|
1703 |
|
1704 /** |
|
1705 * A candidate for continuation of the given user's input. |
|
1706 */ |
|
1707 private static class SuggestionImpl implements Suggestion { |
|
1708 |
|
1709 private final String continuation; |
|
1710 private final boolean matchesType; |
|
1711 |
|
1712 /** |
|
1713 * Create a {@code Suggestion} instance. |
|
1714 * |
|
1715 * @param continuation a candidate continuation of the user's input |
|
1716 * @param matchesType does the candidate match the target type |
|
1717 */ |
|
1718 public SuggestionImpl(String continuation, boolean matchesType) { |
|
1719 this.continuation = continuation; |
|
1720 this.matchesType = matchesType; |
|
1721 } |
|
1722 |
|
1723 /** |
|
1724 * The candidate continuation of the given user's input. |
|
1725 * |
|
1726 * @return the continuation string |
|
1727 */ |
|
1728 @Override |
|
1729 public String continuation() { |
|
1730 return continuation; |
|
1731 } |
|
1732 |
|
1733 /** |
|
1734 * Indicates whether input continuation matches the target type and is thus |
|
1735 * more likely to be the desired continuation. A matching continuation is |
|
1736 * preferred. |
|
1737 * |
|
1738 * @return {@code true} if this suggested continuation matches the |
|
1739 * target type; otherwise {@code false} |
|
1740 */ |
|
1741 @Override |
|
1742 public boolean matchesType() { |
|
1743 return matchesType; |
|
1744 } |
|
1745 } |
|
1746 |
|
1747 /** |
|
1748 * The result of {@code analyzeCompletion(String input)}. |
|
1749 * Describes the completeness and position of the first snippet in the given input. |
|
1750 */ |
|
1751 private static class CompletionInfoImpl implements CompletionInfo { |
|
1752 |
|
1753 private final Completeness completeness; |
|
1754 private final String source; |
|
1755 private final String remaining; |
|
1756 |
|
1757 CompletionInfoImpl(Completeness completeness, String source, String remaining) { |
|
1758 this.completeness = completeness; |
|
1759 this.source = source; |
|
1760 this.remaining = remaining; |
|
1761 } |
|
1762 |
|
1763 /** |
|
1764 * The analyzed completeness of the input. |
|
1765 * |
|
1766 * @return an enum describing the completeness of the input string. |
|
1767 */ |
|
1768 @Override |
|
1769 public Completeness completeness() { |
|
1770 return completeness; |
|
1771 } |
|
1772 |
|
1773 /** |
|
1774 * Input remaining after the complete part of the source. |
|
1775 * |
|
1776 * @return the portion of the input string that remains after the |
|
1777 * complete Snippet |
|
1778 */ |
|
1779 @Override |
|
1780 public String remaining() { |
|
1781 return remaining; |
|
1782 } |
|
1783 |
|
1784 /** |
|
1785 * Source code for the first Snippet of code input. For example, first |
|
1786 * statement, or first method declaration. Trailing semicolons will be |
|
1787 * added, as needed. |
|
1788 * |
|
1789 * @return the source of the first encountered Snippet |
|
1790 */ |
|
1791 @Override |
|
1792 public String source() { |
|
1793 return source; |
|
1794 } |
|
1795 } |
|
1796 |
1703 } |
1797 } |