Codebase list eclipse-platform-text / e4d18f1
New upstream version 4.14 Emmanuel Bourg 4 years ago
220 changed file(s) with 5252 addition(s) and 1764 deletion(s). Raw diff Collapse all Expand all
0 <?xml version="1.0" encoding="UTF-8"?>
1 <extensions>
2 <extension>
3 <groupId>org.eclipse.tycho.extras</groupId>
4 <artifactId>tycho-pomless</artifactId>
5 <version>1.5.1</version>
6 </extension>
7 </extensions>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <projectDescription>
2 <name>eclipse.platform.text</name>
3 <comment></comment>
4 <projects>
5 </projects>
6 <buildSpec>
7 </buildSpec>
8 <natures>
9 </natures>
10 </projectDescription>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <projectDescription>
2 <name>eclipse.platform.text</name>
3 <comment></comment>
4 <projects>
5 </projects>
6 <buildSpec>
7 </buildSpec>
8 <natures>
9 </natures>
10 </projectDescription>
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.core.filebuffers; singleton:=true
4 Bundle-Version: 3.6.700.qualifier
4 Bundle-Version: 3.6.800.qualifier
55 Bundle-Activator: org.eclipse.core.internal.filebuffers.FileBuffersPlugin
66 Bundle-ActivationPolicy: lazy
77 Bundle-Vendor: %providerName
+0
-23
org.eclipse.core.filebuffers/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2014 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.core</groupId>
19 <artifactId>org.eclipse.core.filebuffers</artifactId>
20 <version>3.6.700-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
125125
126126 try {
127127 commitFileBufferContent(monitor, overwrite);
128 } catch (CoreException x) {
129 fManager.fireStateChangeFailed(this);
130 throw x;
131 } catch (RuntimeException x) {
128 } catch (CoreException | RuntimeException x) {
132129 fManager.fireStateChangeFailed(this);
133130 throw x;
134131 }
352352 if (fEncoding == null)
353353 fEncoding= description.getCharset();
354354 }
355 } catch (CoreException e) {
356 // do nothing
357 } catch (IOException e) {
355 } catch (CoreException | IOException e) {
358356 // do nothing
359357 }
360358
3131
3232 /**
3333 * This is a special {@link ExtensionsRegistry} that is
34 * optimized for <code>IFile<code>s..
34 * optimized for <code>IFile</code>s..
3535 *
3636 * @since 3.3
3737 */
314314
315315 try {
316316 commitFileBufferContent(monitor, overwrite);
317 } catch (CoreException x) {
318 fManager.fireStateChangeFailed(this);
319 throw x;
320 } catch (RuntimeException x) {
317 } catch (CoreException | RuntimeException x) {
321318 fManager.fireStateChangeFailed(this);
322319 throw x;
323320 }
275275 if (type != null)
276276 return type.isKindOf(TEXT_CONTENT_TYPE);
277277 }
278 } catch (CoreException ex) {
279 // ignore: API specification tells return true if content type can't be determined
280 } catch (IOException ex) {
278 } catch (CoreException | IOException ex) {
281279 // ignore: API specification tells return true if content type can't be determined
282280 }
283281
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %Plugin.name
33 Bundle-SymbolicName: org.eclipse.core.filebuffers.tests;singleton:=true
4 Bundle-Version: 3.11.400.qualifier
4 Bundle-Version: 3.11.500.qualifier
55 Bundle-Activator: org.eclipse.core.filebuffers.tests.FileBuffersTestPlugin
66 Bundle-ActivationPolicy: lazy
77 Bundle-Vendor: %Plugin.providerName
88 Bundle-Localization: plugin
9 Export-Package: org.eclipse.core.filebuffers.tests
9 Export-Package: org.eclipse.core.filebuffers.tests;x-internal:=true
1010 Require-Bundle:
1111 org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
1212 org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)",
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.core</groupId>
2020 <artifactId>org.eclipse.core.filebuffers.tests</artifactId>
21 <version>3.11.400-SNAPSHOT</version>
21 <version>3.11.500-SNAPSHOT</version>
2222 <packaging>eclipse-test-plugin</packaging>
2323 <properties>
2424 <testSuite>${project.artifactId}</testSuite>
9393
9494 @Override
9595 protected boolean modifyUnderlyingFile() throws Exception {
96 FileTool.write(fExternalFile.getAbsolutePath(), new StringBuffer("Changed content of linked file"));
96 FileTool.write(fExternalFile.getAbsolutePath(), "Changed content of linked file");
9797 fExternalFile.setLastModified(1000);
9898 IFile iFile= FileBuffers.getWorkspaceFileAtLocation(getPath());
9999 iFile.refreshLocal(IResource.DEPTH_INFINITE, null);
1616 import java.io.File;
1717 import java.io.FileInputStream;
1818 import java.io.FileOutputStream;
19 import java.io.FileReader;
2019 import java.io.FileWriter;
2120 import java.io.IOException;
2221 import java.io.InputStream;
2322 import java.io.OutputStream;
24 import java.io.Reader;
2523 import java.io.Writer;
2624 import java.net.URL;
2725 import java.util.Enumeration;
167165 return stateLocation.toFile();
168166 }
169167
170 public static StringBuffer read(String fileName) throws IOException {
171 return read(new FileReader(fileName));
172 }
173
174 public static StringBuffer read(Reader reader) throws IOException {
175 StringBuffer s= new StringBuffer();
176 try {
177 char[] charBuffer= new char[8196];
178 int chars= reader.read(charBuffer);
179 while (chars != -1) {
180 s.append(charBuffer, 0, chars);
181 chars= reader.read(charBuffer);
182 }
183 } finally {
184 try {
185 reader.close();
186 } catch (IOException e) {
187 }
188 }
189 return s;
190 }
191
192 public static void write(String fileName, StringBuffer content) throws IOException {
168 public static void write(String fileName, String content) throws IOException {
193169 try (Writer writer= new FileWriter(fileName)) {
194 writer.write(content.toString());
170 writer.write(content);
195171 }
196172 }
197173
00 /*******************************************************************************
1 * Copyright (c) 2000, 2008 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
1212 *******************************************************************************/
1313 package org.eclipse.core.filebuffers.tests;
1414
15 import java.io.ByteArrayInputStream;
1516 import java.io.File;
1617 import java.io.InputStream;
1718
106107 private static IFile createFile(IFile file, String contents) throws CoreException {
107108 if (contents == null)
108109 contents= "";
109 InputStream inputStream= new java.io.StringBufferInputStream(contents);
110 InputStream inputStream= new ByteArrayInputStream(contents.getBytes());
110111 file.create(inputStream, true, NULL_MONITOR);
111112 return file;
112113 }
00 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
11 <component id="org.eclipse.jface.text" version="2">
2 <resource path="META-INF/MANIFEST.MF">
3 <filter comment="Version wrongly bumped again in Bug 483846 - [typing] Spaces only mode: backspace key to remove many spaces " id="931135546">
4 <message_arguments>
5 <message_argument value="3.16.100"/>
6 <message_argument value="3.15.300"/>
7 </message_arguments>
8 </filter>
9 </resource>
10 <resource path="src/org/eclipse/jface/text/ITextViewer.java" type="org.eclipse.jface.text.ITextViewer">
11 <filter comment="Method introduction unlikely to collide with existing implementations." id="404000815">
12 <message_arguments>
13 <message_argument value="org.eclipse.jface.text.ITextViewer"/>
14 <message_argument value="getLastKnownSelection()"/>
15 </message_arguments>
16 </filter>
17 </resource>
218 <resource path="src/org/eclipse/jface/text/TextViewer.java" type="org.eclipse.jface.text.TextViewer">
319 <filter id="572522506">
420 <message_arguments>
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.jface.text
4 Bundle-Version: 3.15.300.qualifier
4 Bundle-Version: 3.16.100.qualifier
55 Bundle-Vendor: %providerName
66 Bundle-Localization: plugin
77 Export-Package:
3434 Require-Bundle:
3535 org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
3636 org.eclipse.text;bundle-version="[3.8.0,4.0.0)";visibility:=reexport,
37 org.eclipse.swt;bundle-version="[3.107.0,4.0.0)",
37 org.eclipse.swt;bundle-version="[3.110.100,4.0.0)",
3838 org.eclipse.jface;bundle-version="[3.15.0,4.0.0)"
3939 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
4040 Import-Package: com.ibm.icu.text
+0
-23
org.eclipse.jface.text/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2017 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.jface</groupId>
19 <artifactId>org.eclipse.jface.text</artifactId>
20 <version>3.15.300-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
158158 if (position.getOffset() > -1 && position.getLength() > -1) {
159159 try {
160160 int startLine= document.getLineOfOffset(position.getOffset());
161 int endLine= document.getLineOfOffset(position.getOffset() + position.getLength());
162 if (startLine <= line && line < endLine) {
163 if (annotation.isCollapsed()) {
164 int captionOffset;
165 if (position instanceof IProjectionPosition)
166 captionOffset= ((IProjectionPosition) position).computeCaptionOffset(document);
167 else
168 captionOffset= 0;
169
170 int captionLine= document.getLineOfOffset(position.getOffset() + captionOffset);
171 if (startLine <= captionLine && captionLine < endLine)
172 return Math.abs(line - captionLine);
173 }
174 return line - startLine;
161 if (startLine <= line) {
162 int end= position.getOffset() + position.getLength();
163 // Bug 347628: this method expects that the offset after the position range is the
164 // offset of the first line after this projected line range. In other words position
165 // comprise the whole projected range including the last lines delimiter. If position
166 // ends at document end the next offset is not the next line because there is no more content.
167 int endLine= end != document.getLength() ? document.getLineOfOffset(end) : document.getNumberOfLines();
168 if (line < endLine) {
169 if (annotation.isCollapsed()) {
170 int captionOffset;
171 if (position instanceof IProjectionPosition)
172 captionOffset= ((IProjectionPosition) position).computeCaptionOffset(document);
173 else
174 captionOffset= 0;
175
176 int captionLine= document.getLineOfOffset(position.getOffset() + captionOffset);
177 if (startLine <= captionLine && captionLine < endLine)
178 return Math.abs(line - captionLine);
179 }
180 return line - startLine;
181 }
175182 }
176183 } catch (BadLocationException x) {
177184 }
3838 import org.eclipse.jface.text.ITextSelection;
3939 import org.eclipse.jface.text.ITextViewer;
4040 import org.eclipse.jface.text.ITextViewerExtension;
41 import org.eclipse.jface.text.MultiStringMatcher;
42 import org.eclipse.jface.text.MultiStringMatcher.Match;
4143 import org.eclipse.jface.text.Region;
4244 import org.eclipse.jface.text.TextSelection;
4345 import org.eclipse.jface.text.TextUtilities;
243245 int visualEndColumn= computeVisualColumn(endLine, endColumn);
244246 root= new MultiTextEdit();
245247 String[] delimiters= fDocument.getLegalLineDelimiters();
248 MultiStringMatcher delimiterMatcher= MultiStringMatcher.create(delimiters);
246249
247250 int lastDelim= 0;
248251 for (int line= startLine; line <= endLine; line++) {
250253 if (lastDelim == -1) {
251254 string= ""; //$NON-NLS-1$
252255 } else {
253 int[] index= TextUtilities.indexOf(delimiters, replacement, lastDelim);
254 if (index[0] == -1) {
256 Match m= delimiterMatcher.indexOf(replacement, lastDelim);
257 if (m == null) {
255258 string= replacement.substring(lastDelim);
256259 lastDelim= -1;
257260 } else {
258 string= replacement.substring(lastDelim, index[0]);
259 lastDelim= index[0] + delimiters[index[1]].length();
261 string= replacement.substring(lastDelim, m.getOffset());
262 lastDelim= m.getOffset() + m.getText().length();
260263 }
261264 }
262265 TextEdit replace= createReplaceEdit(line, visualStartColumn, visualEndColumn, string, delete);
265268 while (lastDelim != -1) {
266269 // more stuff to insert
267270 String string;
268 int[] index= TextUtilities.indexOf(delimiters, replacement, lastDelim);
269 if (index[0] == -1) {
271 Match m= delimiterMatcher.indexOf(replacement, lastDelim);
272 if (m == null) {
270273 string= replacement.substring(lastDelim);
271274 lastDelim= -1;
272275 } else {
273 string= replacement.substring(lastDelim, index[0]);
274 lastDelim= index[0] + delimiters[index[1]].length();
276 string= replacement.substring(lastDelim, m.getOffset());
277 lastDelim= m.getOffset() + m.getText().length();
275278 }
276279 endLine++;
277280 TextEdit edit;
378381 @Override
379382 ISelection makeReplaceSelection(ISelection selection, String replacement) throws BadLocationException {
380383 IBlockTextSelection bts= (IBlockTextSelection)selection;
381 String[] delimiters= fDocument.getLegalLineDelimiters();
382 int[] index= TextUtilities.indexOf(delimiters, replacement, 0);
383 int length;
384 if (index[0] == -1)
385 length= replacement.length();
386 else
387 length= index[0];
384 Match m= MultiStringMatcher.indexOf(replacement, 0, fDocument.getLegalLineDelimiters());
385 int length= m != null ? m.getOffset() : replacement.length();
388386
389387 int startLine= bts.getStartLine();
390388 int column= bts.getStartColumn() + length;
6363 * </p>
6464 * <p>
6565 * Current problems:
66 * </p>
6667 * <ul>
6768 * <li>the size computation is too small</li>
6869 * <li>focusLost event is not sent - see https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532</li>
6970 * </ul>
70 * </p>
7171 *
7272 * @since 3.2
7373 */
10851085 * <li>CONTEXT_SELECTOR
10861086 * <li>PROPOSAL_SELECTOR
10871087 * <li>CONTEXT_INFO_POPUP
1088 * <ul>
1088 * </ul>
10891089 * @param type the listener type for which to acquire
10901090 * @return <code>true</code> if the widget token could be acquired
10911091 * @since 2.0
11131113 * <li>CONTEXT_SELECTOR
11141114 * <li>PROPOSAL_SELECTOR
11151115 * <li>CONTEXT_INFO_POPUP
1116 * <ul>
1116 * </ul>
11171117 * Returns whether the listener could be added successfully. A listener
11181118 * can not be added if the widget token could not be acquired.
11191119 *
11681168 * <li>CONTEXT_SELECTOR
11691169 * <li>PROPOSAL_SELECTOR
11701170 * <li>CONTEXT_INFO_POPUP
1171 * <ul>
1171 * </ul>
11721172 *
11731173 * @param type the listener type
11741174 * @since 2.0
231231 *
232232 * @param remaining the number of lines to remain in the receiver, must be in [1, {@link #length() length})
233233 * @return the split off range
234 * @throws LineIndexOutOfBoundsException if <code>remaining</code>&gt;= {@link #length()} or <code>remaining</code>&ltt;= 0
234 * @throws LineIndexOutOfBoundsException if <code>remaining</code>&gt;= {@link #length()} or <code>remaining</code>&lt;= 0
235235 */
236236 public Range split(int remaining) throws LineIndexOutOfBoundsException {
237237 if (!(remaining < length())) // assert before modification
588588 * @since 3.3
589589 */
590590 private int fLastWidth= -1;
591 /**
592 * The zoom level for the current painting operation. Workaround for bug 516293.
593 * @since 3.12
594 */
595 private int fZoom= 100;
596591
597592 /**
598593 * Creates a new revision painter for a vertical ruler column.
660655 */
661656 public void setParentRuler(CompositeRuler parentRuler) {
662657 fParentRuler= parentRuler;
663 }
664
665 /**
666 * Sets the zoom level for the current painting operation. Workaround for bug 516293.
667 *
668 * @param zoom the zoom to set
669 * @since 3.12
670 */
671 public void setZoom(int zoom) {
672 fZoom= zoom;
673 }
674
675 private int autoScaleUp(int value) {
676 return value * fZoom / 100;
677658 }
678659
679660 /**
10721053 int y1= fWidget.getLinePixel(range.getStartLine());
10731054 int y2= fWidget.getLinePixel(range.getStartLine() + range.getNumberOfLines());
10741055
1075 return new Rectangle(0, autoScaleUp(y1), autoScaleUp(getWidth()), autoScaleUp(y2 - y1 - 1));
1056 return new Rectangle(0, y1, getWidth(), y2 - y1 - 1);
10761057 }
10771058
10781059 /**
8282 private final AnnotationListener fAnnotationListener= new AnnotationListener();
8383 /** The shared color provider, possibly <code>null</code>. */
8484 private final ISharedTextColors fSharedColors;
85 /**
86 * The zoom level for the current painting operation. Workaround for bug 516293.
87 * @since 3.12
88 */
89 private int fZoom= 100;
9085
9186 /**
9287 * Creates a new diff painter for a vertical ruler column.
137132 */
138133 public void setBackground(Color background) {
139134 fBackground= background;
140 }
141
142 /**
143 * Sets the zoom level for the current painting operation. Workaround for bug 516293.
144 *
145 * @param zoom the zoom to set
146 * @since 3.12
147 */
148 public void setZoom(int zoom) {
149 fZoom= zoom;
150 }
151
152 private int autoScaleUp(int value) {
153 return value * fZoom / 100;
154135 }
155136
156137 /**
240221 // draw background color if special
241222 if (hasSpecialColor(info)) {
242223 gc.setBackground(getColor(info));
243 gc.fillRectangle(0, autoScaleUp(y), autoScaleUp(width), autoScaleUp(lineHeight));
224 gc.fillRectangle(0, y, width, lineHeight);
244225 }
245226
246227 /* Deletion Indicator: Simply a horizontal line */
248229 int delBelow= info.getRemovedLinesBelow();
249230 if (delBefore > 0 || delBelow > 0) {
250231 gc.setForeground(deletionColor);
251 gc.setLineWidth(autoScaleUp(1));
232 gc.setLineWidth(1);
252233 if (delBefore > 0)
253 gc.drawLine(0, autoScaleUp(y), autoScaleUp(width), autoScaleUp(y));
234 gc.drawLine(0, y, width, y);
254235 if (delBelow > 0)
255 gc.drawLine(0, autoScaleUp(y + lineHeight - 1), autoScaleUp(width), autoScaleUp(y + lineHeight - 1));
236 gc.drawLine(0, y + lineHeight - 1, width, y + lineHeight - 1);
256237 }
257238 }
258239 }
313313 private Anchor fAnchor= ANCHOR_BOTTOM;
314314
315315 /**
316 * The anchor sequence used to layout the information control if the original anchor
317 * can not be used because the information control would not fit in the display client area.
316 * The anchor sequence used to layout the information control if the original anchor can not be
317 * used because the information control would not fit in the display client area.
318318 * <p>
319 * The fallback anchor for a given anchor is the one that comes directly after the given anchor or
320 * is the first one in the sequence if the given anchor is the last one in the sequence.
319 * The fallback anchor for a given anchor is the one that comes directly after the given anchor
320 * or is the first one in the sequence if the given anchor is the last one in the sequence.
321 * </p>
321322 * <p>
322 * </p>
323323 * Note: This sequence is ignored if the original anchor is not contained in this sequence.
324324 * </p>
325325 *
158158 }
159159 return new IRegion[] {new Region(getOffset(), getLength())};
160160 }
161
162 /**
163 * @since 3.16
164 */
165 @Override
166 public String toString() {
167 StringBuilder sb= new StringBuilder();
168 sb.append("BlockTextSelection [offset: ").append(getOffset()); //$NON-NLS-1$
169 sb.append(", startLine: ").append(fStartLine); //$NON-NLS-1$
170 if (fEndLine != fStartLine) {
171 sb.append(", endLine: ").append(fEndLine); //$NON-NLS-1$
172 }
173 sb.append(", startColumn: ").append(fStartColumn); //$NON-NLS-1$
174 if (fEndColumn != fStartColumn) {
175 sb.append(", endColumn").append(fEndColumn); //$NON-NLS-1$
176 }
177 if (getLength() != 0) {
178 sb.append(", text: ").append(getText()); //$NON-NLS-1$
179 }
180 if (getDocument() != null) {
181 sb.append(", document: ").append(getDocument()); //$NON-NLS-1$
182 }
183 sb.append("]"); //$NON-NLS-1$
184 return sb.toString();
185 }
161186 }
00 /*******************************************************************************
1 * Copyright (c) 2000, 2015 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
250250 */
251251 public boolean shiftsCaret;
252252
253 ITextSelection fSelection;
253254
254255 /**
255256 * Creates a new document command.
3737 * <pre>
3838 * return fShell.getDisplay().getActiveShell() == fShell
3939 * </pre>
40 *
40 *
4141 * Likewise, {@link IInformationControl#addFocusListener(org.eclipse.swt.events.FocusListener)}
4242 * should install listeners for {@link SWT#Activate} and {@link SWT#Deactivate} on the shell and
4343 * forward events to the focus listeners. Clients are encouraged to subclass
0 /*******************************************************************************
1 * Copyright (c) 2019 Red Hat Inc. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10 package org.eclipse.jface.text;
11
12 import org.eclipse.jface.viewers.ISelectionProvider;
13
14 /**
15 * Extension interface for {@link org.eclipse.jface.text.ITextViewer}. Adds the ability to retrieve
16 * the last known selection from outside of the UI Thread.
17 *
18 * @since 3.16
19 */
20 public interface ITextViewerExtension9 {
21
22
23 /**
24 * Returns the last known selection from a cache, without polling widget.
25 * <p>
26 * This may <strong>not</strong> be the current selection. Indeed, operations that change the
27 * selection without sending related events may not refresh the returned value.
28 * </p>
29 * <p>
30 * As opposed to {@link ISelectionProvider#getSelection()} that usually requires UI Thread, this
31 * method can run from any thread.
32 * </p>
33 *
34 * @return the last known selection.
35 */
36 public ITextSelection getLastKnownSelection();
37 }
00 /*******************************************************************************
1 * Copyright (c) 2007, 2008 IBM Corporation and others.
1 * Copyright (c) 2007, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
1212 *******************************************************************************/
1313 package org.eclipse.jface.text;
1414
15
1615 /**
1716 * Auto edit strategy that converts tabs into spaces.
1817 * <p>
2524 public class TabsToSpacesConverter implements IAutoEditStrategy {
2625
2726 private int fTabRatio;
27
28 private boolean fDeleteSpacesAsTab;
29
2830 private ILineTracker fLineTracker;
2931
3032
3133 public void setNumberOfSpacesPerTab(int ratio) {
3234 fTabRatio= ratio;
35 }
36
37 /**
38 * @param enabled if true, spaces deletion will be modified to match tabs behavior
39 * @since 3.16
40 */
41 public void setDeleteSpacesAsTab(boolean enabled) {
42 fDeleteSpacesAsTab= enabled;
3343 }
3444
3545 public void setLineTracker(ILineTracker lineTracker) {
5464 if (text == null)
5565 return;
5666
57 int index= text.indexOf('\t');
58 if (index > -1) {
67 if (text.isEmpty()) {
68
69 replaceDeleteSpaceByDeleteTab(document, command);
70
71 } else if (text.indexOf('\t') > -1) {
5972
6073 StringBuilder buffer= new StringBuilder();
6174
92105 command.text= buffer.toString();
93106
94107 } catch (BadLocationException x) {
108 throw new IllegalArgumentException("should never happen", x); //$NON-NLS-1$
95109 }
96110 }
97111 }
112
113 private void replaceDeleteSpaceByDeleteTab(IDocument document, DocumentCommand command) {
114 if (!fDeleteSpacesAsTab || fTabRatio == 0 || command.length != 1)
115 return;
116 ITextSelection selection= command.fSelection;
117 if (selection == null || selection.getLength() != 0)
118 return;
119 try {
120 if (document.getChar(command.offset) != ' ')
121 return;
122
123 IRegion line= document.getLineInformationOfOffset(command.offset);
124 int offsetInLine= command.offset - line.getOffset();
125 boolean isDeleteKey= selection.getOffset() == command.offset;
126 if (isDeleteKey) {
127 int spacesToRemove= fTabRatio - (offsetInLine % fTabRatio) - 1;
128 while (spacesToRemove-- > 0 && document.getChar(command.offset + command.length) == ' ') {
129 command.length++;
130 }
131 } else { //backspace
132 int spacesToRemove= offsetInLine % fTabRatio;
133 while (spacesToRemove-- > 0 && document.getChar(command.offset - 1) == ' ') {
134 command.offset--;
135 command.length++;
136 }
137 }
138 } catch (BadLocationException e) {
139 throw new IllegalArgumentException("should never happen", e); //$NON-NLS-1$
140 }
141 }
98142 }
3535
3636 /**
3737 * Text attribute for underline style. (value <code>1 &lt;&lt; 30</code>)
38 *
38 *
3939 * @since 3.1
4040 */
4141 public static final int UNDERLINE= 1 << 30;
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
8080 import org.eclipse.jface.viewers.SelectionChangedEvent;
8181 import org.eclipse.jface.viewers.Viewer;
8282
83 import org.eclipse.jface.text.MultiStringMatcher.Match;
8384 import org.eclipse.jface.text.hyperlink.HyperlinkManager;
8485 import org.eclipse.jface.text.hyperlink.HyperlinkManager.DETECTION_STRATEGY;
8586 import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
111112 * @noextend This class is not intended to be subclassed by clients.
112113 */
113114 public class TextViewer extends Viewer implements
114 ITextViewer, ITextViewerExtension, ITextViewerExtension2, ITextViewerExtension4, ITextViewerExtension6, ITextViewerExtension7, ITextViewerExtension8,
115 ITextViewer, ITextViewerExtension, ITextViewerExtension2, ITextViewerExtension4, ITextViewerExtension6, ITextViewerExtension7, ITextViewerExtension8, ITextViewerExtension9,
115116 IEditingSupportRegistry, ITextOperationTarget, ITextOperationTargetExtension,
116117 IWidgetTokenOwner, IWidgetTokenOwnerExtension, IPostSelectionProvider {
117118
22322233
22332234 //---- Selection
22342235
2236 /**
2237 * Caches the selection value. Is only modified from inside UI Thread. Can be accessed from any
2238 * thread.
2239 */
2240 private volatile ITextSelection cachedSelection= TextSelection.emptySelection();
2241
2242 private void updateSelectionCache() {
2243 cachedSelection= computeSelection();
2244 }
2245
2246 @Override
2247 public ITextSelection getLastKnownSelection() {
2248 return cachedSelection;
2249 }
2250
22352251 @Override
22362252 public Point getSelectedRange() {
22372253
24082424
24092425 @Override
24102426 public ISelection getSelection() {
2427 final ITextSelection res= computeSelection();
2428 cachedSelection= res;
2429 return res;
2430 }
2431
2432 private ITextSelection computeSelection() {
24112433 if (fTextWidget != null && fTextWidget.getBlockSelection()) {
24122434 int[] ranges= fTextWidget.getSelectionRanges();
24132435 int startOffset= ranges[0];
25722594 * @param length the length of the newly selected range in the visible document
25732595 */
25742596 protected void selectionChanged(int offset, int length) {
2597 updateSelectionCache();
25752598 queuePostSelectionChanged(true);
25762599 fireSelectionChanged(offset, length);
25772600 }
36323655
36333656 IRegion modelRange= event2ModelRange(e);
36343657 fDocumentCommand.setEvent(e, modelRange);
3658 fDocumentCommand.fSelection= (ITextSelection) getSelection();
36353659 customizeDocumentCommand(fDocumentCommand);
36363660 if (!fDocumentCommand.fillEvent(e, modelRange)) {
36373661
39263950 TextTransfer plainTextTransfer= TextTransfer.getInstance();
39273951 String contents= (String) clipboard.getContents(plainTextTransfer, DND.CLIPBOARD);
39283952 String toInsert;
3929 if (TextUtilities.indexOf(fDocument.getLegalLineDelimiters(), contents, 0)[0] != -1) {
3953 if (MultiStringMatcher.indexOf(contents, 0, fDocument.getLegalLineDelimiters()) != null) {
39303954 // multi-line insertion
39313955 toInsert= contents;
39323956 } else {
43024326
43034327 IRegion[] occurrences= new IRegion[endLine - startLine + 1];
43044328
4329 boolean allowEmptyPrefix= Arrays.stream(prefixes).anyMatch(String::isEmpty);
4330 MultiStringMatcher prefixMatcher= MultiStringMatcher.create(prefixes);
4331
43054332 // find all the first occurrences of prefix in the given lines
43064333 for (int i= 0; i < occurrences.length; i++) {
43074334
43094336 String text= d.get(line.getOffset(), line.getLength());
43104337
43114338 int index= -1;
4312 int[] found= TextUtilities.indexOf(prefixes, text, 0);
4313 if (found[0] != -1) {
4339 int matchOffset= -1;
4340 String matchText= ""; //$NON-NLS-1$
4341 Match m= prefixMatcher.indexOf(text, 0);
4342 if (m != null) {
4343 matchOffset= m.getOffset();
4344 matchText= m.getText();
4345 } else if (allowEmptyPrefix) {
4346 matchOffset= 0;
4347 }
4348 if (matchOffset > -1) {
43144349 if (ignoreWhitespace) {
4315 String s= d.get(line.getOffset(), found[0]);
4350 String s= d.get(line.getOffset(), matchOffset);
43164351 s= s.trim();
43174352 if (s.isEmpty())
4318 index= line.getOffset() + found[0];
4319 } else if (found[0] == 0)
4353 index= line.getOffset() + matchOffset;
4354 } else if (matchOffset == 0)
43204355 index= line.getOffset();
43214356 }
43224357
43234358 if (index > -1) {
43244359 // remember where prefix is in line, so that it can be removed
4325 int length= prefixes[found[1]].length();
4360 int length= matchText.length();
43264361 if (length == 0 && !ignoreWhitespace && line.getLength() > 0) {
43274362 // found a non-empty line which cannot be shifted
43284363 return;
5757 *
5858 * <p>
5959 * The returned label can have several values:
60 * </p>
6061 * <ul>
6162 * <li><code>null</code> when mining is not resolved</li>
6263 * <li><code>null</code> when mining is resolved means that mining was resolved with an error and it will not
6465 * <li>empty when mining is resolved means that mining will not be displayed</li>
6566 * <li>non empty when mining must be displayed</li>
6667 * </ul>
67 * </p>
6868 *
6969 * @return the label may be set early in the class lifecycle, or upon completion of the future
7070 * provided by {@link #resolve(ITextViewer, IProgressMonitor)} operation.
2020
2121 /**
2222 * Abstract class for line content code mining.
23 *
23 *
2424 * @since 3.13
2525 *
2626 */
2222
2323 /**
2424 * Abstract class for line header code mining.
25 *
25 *
2626 * @since 3.13
2727 *
2828 */
3131 import org.eclipse.swt.graphics.Image;
3232 import org.eclipse.swt.graphics.Point;
3333 import org.eclipse.swt.widgets.Control;
34 import org.eclipse.swt.widgets.Display;
3534
3635 import org.eclipse.core.runtime.ISafeRunnable;
3736 import org.eclipse.core.runtime.SafeRunner;
230229 }
231230 List<ICompletionProposal> newProposals= new ArrayList<>(computedProposals);
232231 fComputedProposals= newProposals;
233 Display.getDefault().asyncExec(() -> {
234 if (autoInsert && !autoActivated && remaining.isEmpty() && newProposals.size() == 1 && canAutoInsert(newProposals.get(0))) {
235 if (Helper.okToUse(fProposalShell)) {
236 insertProposal(newProposals.get(0), (char) 0, 0, offset);
237 hide();
232 Control control= fContentAssistSubjectControlAdapter.getControl();
233 if (!control.isDisposed()) {
234 control.getDisplay().asyncExec(() -> {
235 // Don't run anything if offset has changed while runnable was scheduled (i.e. filtering might have occurred for fast CA)
236 if (offset == fInvocationOffset) {
237 if (autoInsert && !autoActivated && remaining.isEmpty() && newProposals.size() == 1 && canAutoInsert(newProposals.get(0))) {
238 if (Helper.okToUse(fProposalShell)) {
239 insertProposal(newProposals.get(0), (char) 0, 0, offset);
240 hide();
241 }
242 return;
243 }
244 if (remaining.isEmpty() && callback != null) {
245 callback.accept(newProposals);
246 } else {
247 setProposals(newProposals, false);
248 displayProposals();
249 }
238250 }
239 return;
240 }
241 if (remaining.isEmpty() && callback != null) {
242 callback.accept(newProposals);
243 } else {
244 setProposals(newProposals, false);
245 displayProposals();
246 }
247 });
251 });
252 }
248253 });
249254 }
250255 displayProposals();
00 /*******************************************************************************
1 * Copyright (c) 2015, 2016 IBM Corporation and others.
1 * Copyright (c) 2015, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
2424 * Provides {@link Styler} that applies bold style on the given font.
2525 *
2626 * @since 3.11
27 *
28 * @deprecated use {@link org.eclipse.jface.viewers.BoldStylerProvider} directly
2729 */
30 @Deprecated
2831 public final class BoldStylerProvider {
2932
3033 private Font fFont;
140140
141141 @Override
142142 public Object execute(ExecutionEvent event) throws ExecutionException {
143 if (fProposalTable.isDisposed()) {
144 return null;
145 }
143146 int itemCount= fProposalTable.getItemCount();
144147 int selectionIndex= fProposalTable.getSelectionIndex();
145148 switch (fOperationCode) {
0 /*******************************************************************************
1 * Copyright (c) 2019 Red Hat Inc. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10 package org.eclipse.jface.text.contentassist;
11
12 import java.util.Arrays;
13
14 import org.eclipse.jface.text.ITextViewer;
15 import org.eclipse.jface.text.TextPresentation;
16
17 class CompositeContextInformationValidator implements IContextInformationValidator, IContextInformationPresenter {
18
19 private final IContextInformationValidator[] children;
20
21 public CompositeContextInformationValidator(IContextInformationValidator[] validators) {
22 this.children= validators;
23 }
24
25 @Override
26 public void install(IContextInformation info, ITextViewer viewer, int offset) {
27 Arrays.stream(children).forEach(child -> child.install(info, viewer, offset));
28 }
29
30 @Override
31 public boolean isContextInformationValid(int offset) {
32 return Arrays.stream(children).anyMatch(child -> child.isContextInformationValid(offset));
33 }
34
35 @Override
36 public boolean updatePresentation(int offset, TextPresentation presentation) {
37 if (children.length == 1 && children[0] instanceof IContextInformationPresenter) {
38 return ((IContextInformationPresenter) children[0]).updatePresentation(offset, presentation);
39 }
40 return false;
41 }
42
43 }
276276 *
277277 * @param contentAssistant the content assistant
278278 * @param controller the additional info controller, or <code>null</code>
279 * @param asynchronous <true> if this content assistant should present the proposals
279 * @param asynchronous <code>true</code> if this content assistant should present the proposals
280280 * asynchronously, <code>false</code> otherwise
281281 * @return the completion proposal popup
282282 */
21132113 if (processors == null || processors.isEmpty()) {
21142114 return null;
21152115 }
2116 // pick first one, arbitrary
2117 IContentAssistProcessor p = processors.iterator().next();
2118 return p != null ? p.getContextInformationValidator() : null;
2116 IContextInformationValidator[] validators= processors.stream()
2117 .map(IContentAssistProcessor::getContextInformationValidator)
2118 .filter(Objects::nonNull)
2119 .toArray(IContextInformationValidator[]::new);
2120 if (validators.length == 0) {
2121 return null;
2122 } else if (validators.length == 1) {
2123 return validators[0];
2124 }
2125 return new CompositeContextInformationValidator(validators);
21192126 }
21202127
21212128 /**
21342141 if (processors == null || processors.isEmpty()) {
21352142 return null;
21362143 }
2137 // pick first one, arbitrary
2138 IContentAssistProcessor p = processors.iterator().next();
2139 return p != null ? p.getContextInformationValidator() : null;
2144 IContextInformationValidator[] validators= processors.stream()
2145 .map(IContentAssistProcessor::getContextInformationValidator)
2146 .filter(Objects::nonNull)
2147 .toArray(IContextInformationValidator[]::new);
2148 if (validators.length == 0) {
2149 return null;
2150 } else if (validators.length == 1) {
2151 return validators[0];
2152 }
2153 return new CompositeContextInformationValidator(validators);
21402154 }
21412155
21422156 /**
9494
9595 @Override
9696 public int hashCode() {
97 return super.hashCode() | (fProposals == null ? 0 : fProposals.hashCode());
97 return super.hashCode() | (fProposals == null ? 0 : Arrays.hashCode(fProposals));
9898 }
9999 }
104104 fQuickAssistAssistantImpl= new QuickAssistAssistantImpl();
105105 fQuickAssistAssistantImpl.enableAutoActivation(false);
106106 fQuickAssistAssistantImpl.enableAutoInsert(false);
107 fQuickAssistAssistantImpl.setRepeatedInvocationMode(true);
107108 }
108109
109110 @Override
5252 * <p>
5353 * This interface must be implemented by clients.
5454 * </p>
55 *
55 *
5656 * @since 3.0
5757 */
5858 public interface IReconcileStep {
8080 private static class ReusableRegion extends Position implements IRegion {}
8181
8282 /**
83 * Pair of an annotation and their associated position. Used inside the paint method
84 * for sorting annotations based on the offset of their position.
83 * Holder for an annotation, their associated position and paint layer. Used inside the paint
84 * method for sorting annotations based on the offset of their position and layer.
85 *
8586 * @since 3.0
8687 */
8788 private static class Tuple {
8889 Annotation annotation;
8990 Position position;
90
91 Tuple(Annotation annotation, Position position) {
91 int layer;
92
93 Tuple(Annotation annotation, Position position, int layer) {
9294 this.annotation= annotation;
9395 this.position= position;
94 }
95 }
96
97 /**
98 * Comparator for <code>Tuple</code>s.
96 this.layer= layer;
97 }
98 }
99
100 /**
101 * Comparator for <code>Tuple</code>s to order them by layer and offset.
102 *
99103 * @since 3.0
100104 */
101105 private static class TupleComparator implements Comparator<Tuple> {
102106 @Override
103107 public int compare(Tuple o1, Tuple o2) {
108 int cmp= Integer.compare(o1.layer, o2.layer);
109 if (cmp != 0) {
110 return cmp;
111 }
104112 Position p1= o1.position;
105113 Position p2= o2.position;
106 return p1.getOffset() - p2.getOffset();
114 return Integer.compare(p1.getOffset(), p2.getOffset());
107115 }
108116 }
109117
724732 Rectangle r= new Rectangle(0, 0, 0, 0);
725733 ReusableRegion range= new ReusableRegion();
726734 boolean isWrapActive= fCachedTextWidget.getWordWrap();
727 int minLayer= Integer.MAX_VALUE, maxLayer= Integer.MIN_VALUE;
728735 fCachedAnnotations.clear();
729736 Iterator<Annotation> iter;
730737 if (fModel instanceof IAnnotationModelExtension2)
751758 if (fAnnotationAccessExtension != null)
752759 lay= fAnnotationAccessExtension.getLayer(annotation);
753760
754 minLayer= Math.min(minLayer, lay);
755 maxLayer= Math.max(maxLayer, lay);
756 fCachedAnnotations.add(new Tuple(annotation, position));
761 fCachedAnnotations.add(new Tuple(annotation, position, lay));
757762 }
758763 Collections.sort(fCachedAnnotations, fTupleComparator);
759764
760 for (int layer= minLayer; layer <= maxLayer; layer++) {
761 for (int i= 0, n= fCachedAnnotations.size(); i < n; i++) {
762 Tuple tuple= fCachedAnnotations.get(i);
763 Annotation annotation= tuple.annotation;
764 Position position= tuple.position;
765
766 int lay= IAnnotationAccessExtension.DEFAULT_LAYER;
767 if (fAnnotationAccessExtension != null)
768 lay= fAnnotationAccessExtension.getLayer(annotation);
769 if (lay != layer) // wrong layer: skip annotation
770 continue;
771
772 range.setOffset(position.getOffset());
773 range.setLength(position.getLength());
774 IRegion widgetRegion= extension.modelRange2WidgetRange(range);
775 if (widgetRegion == null)
776 continue;
777
778 int offset= widgetRegion.getOffset();
779 int startLine= extension.widgetLineOfWidgetOffset(offset);
780 if (startLine == -1)
781 continue;
782
783 int length= Math.max(widgetRegion.getLength() -1, 0);
784 int endLine= extension.widgetLineOfWidgetOffset(offset + length);
785 if (endLine == -1)
786 continue;
787
788 r.x= 0;
789
790 r.width= dimension.x;
791 int lines= endLine - startLine;
792
793 if(startLine != endLine || !isWrapActive || length <= 0){
794 // line height for different lines includes wrapped line info already,
795 // end we show annotations without offset info at very first line anyway
796 r.height= JFaceTextUtil.computeLineHeight(fCachedTextWidget, startLine, endLine + 1, lines + 1);
797 r.y= JFaceTextUtil.computeLineHeight(fCachedTextWidget, 0, startLine, startLine) - fScrollPos;
798 } else {
799 // annotate only the part of the line related to the given offset
800 Rectangle textBounds= fCachedTextWidget.getTextBounds(offset, offset + length);
801 r.height= textBounds.height;
802 r.y = textBounds.y;
803 }
804 // adjust the annotation position at the bottom of the line if line height has custom vertical line indent
805 int verticalIndent= fCachedTextViewer.getTextWidget().getLineVerticalIndent(startLine);
806 if (verticalIndent > 0) {
807 r.y+= verticalIndent;
808 r.height-= verticalIndent;
809 }
810 if (r.y < dimension.y && fAnnotationAccessExtension != null) // annotation within visible area
811 fAnnotationAccessExtension.paint(annotation, gc, fCanvas, r);
812 }
765 for (Tuple tuple : fCachedAnnotations) {
766 Annotation annotation= tuple.annotation;
767 Position position= tuple.position;
768
769 range.setOffset(position.getOffset());
770 range.setLength(position.getLength());
771 IRegion widgetRegion= extension.modelRange2WidgetRange(range);
772 if (widgetRegion == null)
773 continue;
774
775 int offset= widgetRegion.getOffset();
776 int startLine= extension.widgetLineOfWidgetOffset(offset);
777 if (startLine == -1)
778 continue;
779
780 int length= Math.max(widgetRegion.getLength() - 1, 0);
781 int endLine= extension.widgetLineOfWidgetOffset(offset + length);
782 if (endLine == -1)
783 continue;
784
785 r.x= 0;
786
787 r.width= dimension.x;
788 int lines= endLine - startLine;
789
790 if (startLine != endLine || !isWrapActive || length <= 0) {
791 // line height for different lines includes wrapped line info already,
792 // end we show annotations without offset info at very first line anyway
793 r.height= JFaceTextUtil.computeLineHeight(fCachedTextWidget, startLine, endLine + 1, lines + 1);
794 r.y= JFaceTextUtil.computeLineHeight(fCachedTextWidget, 0, startLine, startLine) - fScrollPos;
795 } else {
796 // annotate only the part of the line related to the given offset
797 Rectangle textBounds= fCachedTextWidget.getTextBounds(offset, offset + length);
798 r.height= textBounds.height;
799 r.y= textBounds.y;
800 }
801 // adjust the annotation position at the bottom of the line if line height has custom vertical line indent
802 int verticalIndent= fCachedTextViewer.getTextWidget().getLineVerticalIndent(startLine);
803 if (verticalIndent > 0) {
804 r.y+= verticalIndent;
805 r.height-= verticalIndent;
806 }
807 if (r.y < dimension.y && fAnnotationAccessExtension != null) // annotation within visible area
808 fAnnotationAccessExtension.paint(annotation, gc, fCanvas, r);
813809 }
814810
815811 fCachedAnnotations.clear();
169169 Color foreground= gc.getForeground();
170170 if (visibleLines != null) {
171171 if (fRevisionPainter.hasInformation()) {
172 fRevisionPainter.setZoom(fZoom);
173172 fRevisionPainter.paint(gc, visibleLines);
174173 } else if (fDiffPainter.hasInformation()) { // don't paint quick diff colors if revisions are painted
175 fDiffPainter.setZoom(fZoom);
176174 fDiffPainter.paint(gc, visibleLines);
177175 }
178176 }
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
1717 *******************************************************************************/
1818 package org.eclipse.jface.text.source;
1919
20 import java.lang.ref.WeakReference;
2120 import java.util.Arrays;
2221 import java.util.function.Consumer;
2322
3130 import org.eclipse.swt.events.MouseWheelListener;
3231 import org.eclipse.swt.graphics.Color;
3332 import org.eclipse.swt.graphics.Font;
34 import org.eclipse.swt.graphics.FontData;
3533 import org.eclipse.swt.graphics.FontMetrics;
3634 import org.eclipse.swt.graphics.GC;
3735 import org.eclipse.swt.graphics.Image;
38 import org.eclipse.swt.graphics.ImageData;
39 import org.eclipse.swt.graphics.ImageDataProvider;
4036 import org.eclipse.swt.graphics.Point;
4137 import org.eclipse.swt.graphics.Rectangle;
4238 import org.eclipse.swt.widgets.Canvas;
4440 import org.eclipse.swt.widgets.Control;
4541 import org.eclipse.swt.widgets.Display;
4642 import org.eclipse.swt.widgets.TypedListener;
47
48 import org.eclipse.jface.util.Util;
4943
5044 import org.eclipse.jface.text.BadLocationException;
5145 import org.eclipse.jface.text.IDocument;
6559 * @since 2.0
6660 */
6761 public class LineNumberRulerColumn implements IVerticalRulerColumn {
68
69 /**
70 * <code>true</code> if we're on a Mac, where drawing on an Image currently only draws at 100% zoom level,
71 * which results in blurry line numbers on a Retina display.
72 *
73 * @see <a href="https://bugs.eclipse.org/516293">bug 516293</a>
74 * @since 3.6
75 */
76 private final boolean IS_MAC_BUG_516293= Util.isMac()
77 && !"false".equals(System.getProperty("LineNumberRulerColumn.retina.workaround")) //$NON-NLS-1$ //$NON-NLS-2$
78 && internalSupportsZoomedPaint();
7962
8063 /**
8164 * Internal listener class.
397380 private int fCachedNumberOfDigits= -1;
398381 /** Flag indicating whether a relayout is required */
399382 private boolean fRelayoutRequired= false;
383 /** Last top pixel. */
384 private int fLastTopPixel = -1;
385 /** Last top model line. */
386 private int fLastTopModelLine;
387 /** Last number of lines visible. */
388 private int fLastNumberOfLines;
389 /** Last bottom model line. */
390 private int fLastBottomModelLine;
391 /** Last canvas height used. */
392 private int fLastHeight= -1;
400393 /**
401394 * Redraw runnable lock
402395 * @since 3.0
419412 };
420413 /* @since 3.2 */
421414 private MouseHandler fMouseHandler;
422 /*
423 * Zoom level and cached font for the current painting operation. Workaround for bug 516293.
424 * @since 3.12
425 */
426 int fZoom= 100;
427 private WeakReference<Font> fLastFont;
428 private Font fLastZoomedFont;
429415
430416 /**
431417 * Redraw the ruler handler called when a line height change.
671657 fBuffer.dispose();
672658 fBuffer= null;
673659 }
674
675 if (fLastZoomedFont != null) {
676 fLastZoomedFont.dispose();
677 fLastZoomedFont= null;
678 fLastFont= null;
679 }
680660 }
681661
682662 /**
688668
689669 Point size= fCanvas.getSize();
690670
691 if (size.x <= 0 || size.y <= 0)
671 if (size.x <= 0 || size.y <= 0) {
692672 return;
673 }
693674
694675 if (fBuffer != null) {
695676 Rectangle r= fBuffer.getBounds();
696 if (IS_MAC_BUG_516293 || r.width != size.x || r.height != size.y) {
677 if (r.width != size.x || r.height != size.y) {
697678 fBuffer.dispose();
698679 fBuffer= null;
699680 }
700681 }
701682
702683 ILineRange visibleLines= JFaceTextUtil.getVisibleModelLines(fCachedTextViewer);
703 if (visibleLines == null)
684 if (visibleLines == null) {
704685 return;
705
706 if (IS_MAC_BUG_516293) {
707 /* FIXME: Workaround (bug 516293):
708 * Relies on SWT implementation detail that GC drawing on macOS only draws at 100% zoom level.
709 * For higher zoom levels (200%), we manually scale the font and drawing coordinates,
710 * and then use getImageData(100) to extract the high-resolution image data. */
711 fBuffer= new Image(fCanvas.getDisplay(), (ImageDataProvider) zoom -> {
712 fZoom = zoom;
713 internalSetZoom(zoom);
714 int width= size.x * zoom / 100;
715 int height= size.y * zoom / 100;
716 Image gcImage= new Image(fCanvas.getDisplay(), width, height);
717
718 GC gc= new GC(gcImage);
719 Font font= fCanvas.getFont();
720 if (zoom != 100) {
721 if (fLastFont != null && font == fLastFont.get()) {
722 font= fLastZoomedFont;
686 }
687
688 boolean bufferStillValid = fBuffer != null;
689 if (fBuffer == null) {
690 fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
691 }
692 GC bufferGC= new GC(fBuffer);
693 Image newBuffer= null;
694 try {
695 int topPixel= fCachedTextWidget.getTopPixel();
696 int bufferY= 0;
697 int bufferH= size.y;
698 int numberOfLines= visibleLines.getNumberOfLines();
699 int dy= topPixel - fLastTopPixel;
700 int topModelLine= visibleLines.getStartLine();
701 int bottomModelLine= topModelLine + numberOfLines - 1;
702 int bottomWidgetLine= JFaceTextUtil.modelLineToWidgetLine(fCachedTextViewer, bottomModelLine);
703 boolean atEnd= bottomWidgetLine + 1 >= fCachedTextWidget.getLineCount();
704 int height= size.y;
705 if (dy != 0 && !atEnd && bufferStillValid && fLastTopPixel >= 0 && numberOfLines > 1 && numberOfLines == fLastNumberOfLines) {
706 int bottomPixel= fCachedTextWidget.getLinePixel(bottomWidgetLine + 1);
707 if (dy > 0 && bottomPixel < size.y) {
708 // Can occur on GTK with static scrollbars; see bug 551320.
709 height= bottomPixel;
710 }
711 if (dy > 0 && dy < height) {
712 int goodPixels= height;
713 if (goodPixels > fLastHeight) {
714 // Dont copy empty pixels from last time.
715 goodPixels= fLastHeight;
716 }
717 if (dy < goodPixels) {
718 bufferGC.copyArea(0, dy, size.x, goodPixels - dy, 0, 0);
719 bufferY= goodPixels - dy;
720 bufferH= height - bufferY;
723721 } else {
724 fLastFont= new WeakReference<>(font);
725 FontData fontData= font.getFontData()[0];
726 fontData.setHeight(fontData.getHeight() * zoom / 100);
727 font= new Font(font.getDevice(), fontData);
728 fLastZoomedFont= font;
722 // Redraw everything.
723 height= size.y;
724 dy= 0;
729725 }
726 } else if (dy < 0 && -dy < height) {
727 bufferGC.copyArea(0, 0, size.x, height + dy, 0, -dy);
728 bufferY= 0;
729 bufferH= -dy;
730 } else {
731 height= size.y;
732 dy= 0;
730733 }
731 gc.setFont(font);
732 if (fForeground != null)
733 gc.setForeground(fForeground);
734
734 } else {
735 dy= 0;
736 }
737 // dy == 0 means now "draw everything", either because there was no overlap, or we indeed didn't move
738 // (refresh or other cases), or there was a resize, or it's the first time, or we are showing the very
739 // last line.
740 if (dy != 0) {
741 // Reduce the line range.
742 if (dy > 0) {
743 visibleLines= new LineRange(fLastBottomModelLine, bottomModelLine - fLastBottomModelLine + 1);
744 } else {
745 visibleLines= new LineRange(topModelLine, fLastTopModelLine - topModelLine + 1);
746 }
747 }
748 fLastTopPixel= topPixel;
749 fLastTopModelLine= topModelLine;
750 fLastNumberOfLines= numberOfLines;
751 fLastBottomModelLine= bottomModelLine;
752 fLastHeight= height;
753 if (dy != 0) {
754 // Some rulers may paint outside the line region. Let them paint in a new image,
755 // the copy the wanted bits.
756 newBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
757 GC localGC= new GC(newBuffer);
735758 try {
736 gc.setBackground(getBackground(fCanvas.getDisplay()));
737 gc.fillRectangle(0, 0, width, height);
738
739 doPaint(gc, visibleLines);
759 initializeGC(localGC, 0, bufferY, size.x, bufferH);
760 doPaint(localGC, visibleLines);
740761 } finally {
741 gc.dispose();
742 fZoom= 100;
762 localGC.dispose();
743763 }
744
745 ImageData imageData= gcImage.getImageData(100);
746 gcImage.dispose();
747 return imageData;
748 });
749
750 } else {
751 if (fBuffer == null)
752 fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
753
754 GC gc= new GC(fBuffer);
755 gc.setFont(fCanvas.getFont());
756 if (fForeground != null)
757 gc.setForeground(fForeground);
758
759 try {
760 gc.setBackground(getBackground(fCanvas.getDisplay()));
761 gc.fillRectangle(0, 0, size.x, size.y);
762
763 doPaint(gc, visibleLines);
764 } finally {
765 gc.dispose();
766 }
767 }
768
764 bufferGC.drawImage(newBuffer, 0, bufferY, size.x, bufferH, 0, bufferY, size.x, bufferH);
765 if (dy > 0 && bufferY + bufferH < size.y) {
766 // Scrolled down in the text, but didn't use the full height of the Canvas: clear
767 // the rest. Occurs on GTK with static scrollbars; the area cleared here is the
768 // bit next to the horizontal scrollbar. See bug 551320.
769 bufferGC.setBackground(getBackground(fCanvas.getDisplay()));
770 bufferGC.fillRectangle(0, bufferY + bufferH, size.x, size.y - bufferY - bufferH + 1);
771 }
772 } else {
773 // We redraw everything; paint directly into the buffer
774 initializeGC(bufferGC, 0, 0, size.x, size.y);
775 doPaint(bufferGC, visibleLines);
776 }
777 } finally {
778 bufferGC.dispose();
779 if (newBuffer != null) {
780 newBuffer.dispose();
781 }
782 }
769783 dest.drawImage(fBuffer, 0, 0);
770784 }
771785
772 /**
773 * This method is not API and it is expected to disappear in Eclipse 4.8.
774 * Subclasses that want to take advantage of the unsupported workaround for bug 516258
775 * can re-implement this method and return true.
776 *
777 * @return true iff this class supports the workaround for bug 516258
778 *
779 * @nooverride This method is not intended to be re-implemented or extended by clients.
780 * @noreference This method is not intended to be referenced by clients.
781 * @since 3.12
782 */
783 protected boolean internalSupportsZoomedPaint() {
784 return getClass().getPackage().equals(LineNumberChangeRulerColumn.class.getPackage());
785 }
786
787 /**
788 * This method is not API and it is expected to disappear in Eclipse 4.8.
789 * Subclasses that want to take advantage of the unsupported workaround for bug 516258
790 * can override this method and store the given zoom level for later use.
791 *
792 * @param zoom the zoom level to use for drawing operations
793 *
794 * @nooverride This method is not intended to be re-implemented or extended by clients.
795 * @noreference This method is not intended to be referenced by clients.
796 * @since 3.12
797 */
798 protected void internalSetZoom(int zoom) {
799 // callback for subclasses
786 private void initializeGC(GC gc, int x, int y, int width, int height) {
787 gc.setFont(fCanvas.getFont());
788 if (fForeground != null) {
789 gc.setForeground(fForeground);
790 }
791 gc.setBackground(getBackground(fCanvas.getDisplay()));
792 gc.fillRectangle(x, y, width, height);
800793 }
801794
802795 /**
833826 void doPaint(GC gc, ILineRange visibleLines) {
834827 Display display= fCachedTextWidget.getDisplay();
835828
836 // draw diff info
837 int y= -JFaceTextUtil.getHiddenTopLinePixels(fCachedTextWidget);
829 int firstWidgetLineToDraw= JFaceTextUtil.modelLineToWidgetLine(fCachedTextViewer, visibleLines.getStartLine());
830 int y= fCachedTextWidget.getLinePixel(firstWidgetLineToDraw);
838831
839832 // add empty lines if line is wrapped
840833 boolean isWrapActive= fCachedTextWidget.getWordWrap();
937930 int indentation= fIndentation[index];
938931 int baselineBias= getBaselineBias(gc, widgetLine);
939932 int verticalIndent= fCachedTextViewer.getTextWidget().getLineVerticalIndent(widgetLine);
940 gc.drawString(s, indentation * fZoom / 100, (y + baselineBias + verticalIndent) * fZoom / 100, true);
933 gc.drawString(s, indentation, y + baselineBias + verticalIndent, true);
941934 }
942935
943936 /**
278278 *
279279 * @param sourceViewer the source viewer
280280 * @return a region denoting the current signed selection, for a resulting RtoL selections
281 * length is < 0
281 * length is &lt; 0
282282 * @since 3.8
283283 */
284284 private static final IRegion getSignedSelection(ISourceViewer sourceViewer) {
307307 *
308308 * @since 3.7
309309 */
310 static class WidgetInfos {
310 private static class WidgetInfos {
311311 /**
312312 * the text widget line count
313313 */
328328 * the bounds of {@link OverviewRuler#fCanvas}
329329 */
330330 Rectangle bounds;
331
331332 /**
332 * the writable area in the text widget (height of all lines in pixels)
333 * the writable area in the text widget (height of all lines in pixels), if smaller than
334 * bounds.height; otherwise an unspecified value &gt;= bounds.height
333335 */
334336 int writable;
335337
342344 public WidgetInfos(StyledText textWidget, Canvas canvas) {
343345 maxLines= textWidget.getLineCount();
344346 bounds= canvas.getBounds();
345 writable= JFaceTextUtil.computeLineHeight(textWidget, 0, maxLines, maxLines);
347 // writeable is of interest only if it is smaller than bounds.height.
348 int w= 0;
349 for (int i= 0; i < maxLines && w < bounds.height; i++) {
350 w+= JFaceTextUtil.computeLineHeight(textWidget, i);
351 }
352 writable= w;
346353
347354 ScrollBar verticalBar= textWidget.getVerticalBar();
348355 if (verticalBar != null && !verticalBar.getVisible()) {
1818
1919 import org.eclipse.swt.SWT;
2020 import org.eclipse.swt.graphics.RGB;
21 import org.eclipse.swt.widgets.Shell;
2221
2322 import org.eclipse.jface.text.DefaultInformationControl;
2423 import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
2524 import org.eclipse.jface.text.IAutoEditStrategy;
2625 import org.eclipse.jface.text.IDocument;
2726 import org.eclipse.jface.text.IDocumentExtension3;
28 import org.eclipse.jface.text.IInformationControl;
2927 import org.eclipse.jface.text.IInformationControlCreator;
3028 import org.eclipse.jface.text.ITextDoubleClickStrategy;
3129 import org.eclipse.jface.text.ITextHover;
332330 * @since 2.0
333331 */
334332 public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) {
335 return new IInformationControlCreator() {
336 @Override
337 public IInformationControl createInformationControl(Shell parent) {
338 return new DefaultInformationControl(parent);
339 }
340 };
333 return DefaultInformationControl::new;
341334 }
342335
343336 /**
0 /**
1 * Copyright (c) 2018 Angelo ZERR.
0 /*******************************************************************************
1 * Copyright (c) 2018, 2019 Angelo ZERR and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
88 * SPDX-License-Identifier: EPL-2.0
99 *
1010 * Contributors:
11 * Angelo Zerr <angelo.zerr@gmail.com> - Bug 527720 - [CodeMining] Line number in vertical ruler can be not synchronized with line header annotation
12 */
11 * Angelo Zerr <angelo.zerr@gmail.com> - Bug 527720 - [CodeMining] Line number in vertical ruler can be not synchronized with line header annotation
12 * Thomas Wolf <thomas.wolf@paranor.ch> - Bug 553133
13 *******************************************************************************/
1314 package org.eclipse.jface.text.source;
1415
1516 import java.util.LinkedHashSet;
2324 import org.eclipse.jface.text.JFaceTextUtil;
2425
2526 /**
26 * Class to track line height change of visible lines of a given {@link StyledText}.
27 *
27 * Tracks line height changes of visible lines of a given {@link StyledText}.
2828 */
2929 class VisibleLinesTracker implements PaintListener {
3030
3636 private final ITextViewer viewer;
3737
3838 /**
39 * The previous bottom line index.
39 * The previous bottom model line index.
4040 */
41 private int oldBottom= -1;
41 private int oldModelBottom= -1;
42
43 /**
44 * The previous bottom widget line index.
45 */
46 private int oldWidgetBottom= -1;
4247
4348 /**
4449 * The previous bottom line pixel.
6469 public void paintControl(PaintEvent e) {
6570 StyledText textWidget= viewer.getTextWidget();
6671 // track if bottom line index or bottom line pixel changed.
67 if (oldBottom == -1) {
68 oldBottom= JFaceTextUtil.getPartialBottomIndex(viewer);
69 oldBottomPixel= JFaceTextUtil.getLinePixel(textWidget, oldBottom);
72 if (oldModelBottom == -1) {
73 oldWidgetBottom= JFaceTextUtil.getPartialBottomIndex(textWidget);
74 oldModelBottom= JFaceTextUtil.widgetLine2ModelLine(viewer, oldWidgetBottom);
75 oldBottomPixel= JFaceTextUtil.getLinePixel(textWidget, oldWidgetBottom);
7076 return;
7177 }
72 int newBottom= JFaceTextUtil.getPartialBottomIndex(viewer);
73 if (newBottom != oldBottom) {
74 oldBottom= newBottom;
75 oldBottomPixel= JFaceTextUtil.getLinePixel(textWidget, oldBottom);
76 handlers.forEach(handler -> handler.accept(textWidget));
77 return;
78 }
79 int newBottomPixel= JFaceTextUtil.getLinePixel(textWidget, newBottom);
80 if (newBottomPixel != oldBottomPixel) {
78 int newWidgetBottom= JFaceTextUtil.getPartialBottomIndex(textWidget);
79 int newModelBottom= JFaceTextUtil.widgetLine2ModelLine(viewer, newWidgetBottom);
80 int newBottomPixel= JFaceTextUtil.getLinePixel(textWidget, newWidgetBottom);
81 if (newWidgetBottom != oldWidgetBottom || newModelBottom != oldModelBottom || newBottomPixel != oldBottomPixel) {
82 oldWidgetBottom= newWidgetBottom;
83 oldModelBottom= newModelBottom;
8184 oldBottomPixel= newBottomPixel;
8285 handlers.forEach(handler -> handler.accept(textWidget));
83 return;
8486 }
8587 }
8688
0 <?xml version="1.0" encoding="UTF-8"?>
1 <classpath>
2 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
3 <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
4 <classpathentry kind="src" path="src"/>
5 <classpathentry kind="output" path="bin"/>
6 </classpath>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <classpath>
2 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
3 <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
4 <classpathentry kind="src" path="src"/>
5 <classpathentry kind="output" path="bin"/>
6 </classpath>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <projectDescription>
2 <name>org.eclipse.jface.text.examples</name>
3 <comment></comment>
4 <projects>
5 </projects>
6 <buildSpec>
7 <buildCommand>
8 <name>org.eclipse.jdt.core.javabuilder</name>
9 <arguments>
10 </arguments>
11 </buildCommand>
12 <buildCommand>
13 <name>org.eclipse.pde.ManifestBuilder</name>
14 <arguments>
15 </arguments>
16 </buildCommand>
17 <buildCommand>
18 <name>org.eclipse.pde.SchemaBuilder</name>
19 <arguments>
20 </arguments>
21 </buildCommand>
22 </buildSpec>
23 <natures>
24 <nature>org.eclipse.pde.PluginNature</nature>
25 <nature>org.eclipse.jdt.core.javanature</nature>
26 </natures>
27 </projectDescription>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <projectDescription>
2 <name>org.eclipse.jface.text.examples</name>
3 <comment></comment>
4 <projects>
5 </projects>
6 <buildSpec>
7 <buildCommand>
8 <name>org.eclipse.jdt.core.javabuilder</name>
9 <arguments>
10 </arguments>
11 </buildCommand>
12 <buildCommand>
13 <name>org.eclipse.pde.ManifestBuilder</name>
14 <arguments>
15 </arguments>
16 </buildCommand>
17 <buildCommand>
18 <name>org.eclipse.pde.SchemaBuilder</name>
19 <arguments>
20 </arguments>
21 </buildCommand>
22 </buildSpec>
23 <natures>
24 <nature>org.eclipse.pde.PluginNature</nature>
25 <nature>org.eclipse.jdt.core.javanature</nature>
26 </natures>
27 </projectDescription>
0 eclipse.preferences.version=1
1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
2 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
3 org.eclipse.jdt.core.compiler.compliance=1.8
4 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
5 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
6 org.eclipse.jdt.core.compiler.source=1.8
0 eclipse.preferences.version=1
1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
2 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
3 org.eclipse.jdt.core.compiler.compliance=1.8
4 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
5 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
6 org.eclipse.jdt.core.compiler.source=1.8
0 eclipse.preferences.version=1
1 pluginProject.extensions=false
2 resolve.requirebundle=false
0 eclipse.preferences.version=1
1 pluginProject.extensions=false
2 resolve.requirebundle=false
0 source.. = src/
1 output.. = bin/
2 bin.includes = META-INF/,\
3 .
0 source.. = src/
1 output.. = bin/
2 bin.includes = META-INF/,\
3 .
1313 <parent>
1414 <artifactId>eclipse.platform.text</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 </parent>
1818 <groupId>org.eclipse.core</groupId>
1919 <artifactId>org.eclipse.jface.text.examples</artifactId>
0 /**s
1 * Copyright (c) 2017 Angelo ZERR.
0 /** Copyright (c) 2017, 2019 Angelo ZERR and others.
21 *
32 * This program and the accompanying materials
43 * are made available under the terms of the Eclipse Public License 2.0
3736 public class ColorAnnotation extends LineContentAnnotation {
3837
3938 private Color color;
40
39
4140 private Consumer<MouseEvent> action = e -> {
4241 StyledText styledText = super.getTextWidget();
4342 Shell shell = new Shell(styledText.getDisplay());
6160 }
6261 }
6362 };
64
63
6564 /**
6665 * Format the given rgb to hexa color.
67 *
66 *
6867 * @param rgb
6968 * @return the hexa color from the given rgb.
7069 */
118117 */
119118 private static int getSquareWidth(FontMetrics fontMetrics) {
120119 // width = 2 spaces + size width of square
121 int width = 2 * fontMetrics.getAverageCharWidth() + getSquareSize(fontMetrics);
120 int width = (int) (2 * fontMetrics.getAverageCharacterWidth() + getSquareSize(fontMetrics));
122121 return width;
123122 }
124
123
125124 @Override
126125 public Consumer<MouseEvent> getAction(MouseEvent e) {
127126 return action;
209209
210210 /**
211211 * Add RGB parameter name annotation
212 *
212 *
213213 * @param paramName
214214 * @param rgbContent
215215 * @param startIndex
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %Plugin.name
33 Bundle-SymbolicName: org.eclipse.jface.text.tests
4 Bundle-Version: 3.11.800.qualifier
4 Bundle-Version: 3.11.900.qualifier
55 Bundle-Vendor: %Plugin.providerName
66 Bundle-Localization: plugin
77 Export-Package:
1515 org.eclipse.jface.text.tests.templates.persistence,
1616 org.eclipse.jface.text.tests.util
1717 Require-Bundle:
18 org.eclipse.jface.text;bundle-version="[3.5.0,4.0.0)",
18 org.eclipse.jface.text;bundle-version="[3.16.0,4.0.0)",
1919 org.eclipse.jface;bundle-version="[3.5.0,4.0.0)",
2020 org.junit;bundle-version="4.12.0",
2121 org.eclipse.text.tests;bundle-version="[3.5.0,4.0.0)",
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.jface</groupId>
2020 <artifactId>org.eclipse.jface.text.tests</artifactId>
21 <version>3.11.800-SNAPSHOT</version>
21 <version>3.11.900-SNAPSHOT</version>
2222 <packaging>eclipse-test-plugin</packaging>
2323 <properties>
2424 <testSuite>${project.artifactId}</testSuite>
5454
5555 /**
5656 * Constructs a new character pair matcher.
57 *
57 *
5858 * @param chars the characters to match
5959 * @return the character pair matcher
6060 */
6464
6565 /**
6666 * Returns the partitioning treated by the matcher.
67 *
67 *
6868 * @return the partition
6969 */
7070 protected String getDocumentPartitioning() {
8282
8383 /**
8484 * Very simple checks.
85 *
85 *
8686 * @throws BadLocationException test failure
8787 */
8888 @Test
115115
116116 /**
117117 * Very simple checks.
118 *
118 *
119119 * @throws BadLocationException test failure
120120 */
121121 @Test
134134
135135 /**
136136 * Close matches.
137 *
137 *
138138 * @throws BadLocationException test failure
139139 */
140140 @Test
162162
163163 /**
164164 * Checks of simple situations where no matches should be found.
165 *
165 *
166166 * @throws BadLocationException test failure
167167 */
168168 @Test
176176
177177 /**
178178 * Test that it doesn't match across different partitions.
179 *
179 *
180180 * @throws BadLocationException test failure
181181 */
182182 @Test
214214
215215 /**
216216 * Test that it works properly next to partition boundaries.
217 *
217 *
218218 * @throws BadLocationException test failure
219219 */
220220 @Test
270270
271271 /**
272272 * Test a few boundary conditions.
273 *
273 *
274274 * * @throws BadLocationException test failure
275275 */
276276 @Test
306306
307307 /**
308308 * Checks that the test case reader reads the test case as specified.
309 *
309 *
310310 * @param testString the string to test
311311 * @param expectedPos the expected position
312312 * @param expectedMatch the expected match
321321
322322 /**
323323 * Checks that the given matcher matches the input as specified.
324 *
324 *
325325 * @param matcher the matcher
326326 * @param testCase the test string
327327 */
371371 /**
372372 * Creates a text case from a string. In the given string a '%' represents the position of the
373373 * cursor and a '#' represents the position of the expected matching character.
374 *
374 *
375375 * @param str the string for which to create the test case
376376 * @return the created test case
377377 */
2525 * @since 3.3
2626 */
2727 public class DefaultPairMatcherTest extends AbstractPairMatcherTest {
28
28
2929 public DefaultPairMatcherTest() {
3030 super(false);
3131 }
3939
4040 /**
4141 * Close matches.
42 *
42 *
4343 * @throws BadLocationException test failure
4444 */
4545 @Test
5353
5454 /**
5555 * Checks of simple situations where no matches should be found.
56 *
56 *
5757 * @throws BadLocationException test failure
5858 */
5959 @Test
1919
2020 /**
2121 * Tests for the default pair matcher.
22 *
22 *
2323 * @since 3.8
2424 */
2525 public class DefaultPairMatcherTest2 extends AbstractPairMatcherTest {
3737
3838 /**
3939 * Very simple checks.
40 *
40 *
4141 * @throws BadLocationException test failure
4242 */
4343 @Test
9191 if (DEBUG)
9292 System.out.println("<" + result + "/>");
9393 assertEquals(expectedOutput, result);
94
94
9595 Iterator<StyleRange> styleRangeIterator= textPresentation.getAllStyleRangeIterator();
9696 List<StyleRange> ranges= new ArrayList<>();
9797 while (styleRangeIterator.hasNext()) {
9898 ranges.add(styleRangeIterator.next());
9999 }
100
100
101101 Collections.sort(ranges, (r1, r2) -> r1.start - r2.start);
102
102
103103 assertEquals(Arrays.asList(styleRanges), ranges);
104
104
105105 for (int i= 0; i < ranges.size() - 1; i++) {
106106 StyleRange range1= ranges.get(i);
107107 StyleRange range2= ranges.get(i + 1);
108
108
109109 if (range1.start + range1.length > range2.start) {
110110 assertTrue("StyleRanges overlap", false);
111111 }
112112 }
113
113
114114 }
115115
116116 @Test
119119 String expected= "3<5";
120120 verify(string, expected, 0);
121121 }
122
122
123123 @Test
124124 public void test1() throws IOException{
125125 String string= "<dl><dt>@author</dt><dd>Foo Bar</dd></dl>";
126126 String expected= LD+ "@author"+LD+"\tFoo Bar"+LD;
127127 verify(string, expected, 1);
128128 }
129
129
130130 @Test
131131 public void test2() throws IOException{
132132 String string= "<code>3>5<code>";
147147 String expected= "void p.Bb.fes()"+ LD + LD + LD+ "Parameters:"+ LD + "\ti fred or null"+LD;
148148 verify(string, expected, 3);
149149 }
150
150
151151 @Test
152152 public void test5() throws IOException{
153153 String string= "<code>1<2<3<4</code>";
162162 String expected= LD + "Something." + LD + "Something more.";
163163 verify(string, expected, 0);
164164 }
165
165
166166 @Test
167167 public void testEntity1() throws IOException {
168168 String string= "&amp;";
176176 String expected= "&unknown;";
177177 verify(string, expected, 0);
178178 }
179
179
180180 @Test
181181 public void testBug367378() throws IOException {
182182 verify("<head>", "", 0);
196196 String expected= "no comment";
197197 verify(string, expected, 0);
198198 }
199
199
200200 @Test
201201 public void testStyles1() throws IOException {
202202 String string= "<b>Hello World</b>";
266266 String expected= "This is yet another test";
267267 verify(string, expected, 3);
268268 }
269
269
270270 @Test
271271 public void testStylesWithPre() throws IOException {
272272 String string= "I am <b>bold</b>." + LD + "<p>" + LD + "<pre>One" + LD + LD + "<b>T</b>hree.</pre>" + LD + "<p>" + LD + "<b>Author:</b> me.";
278278 };
279279 verify(string, expected, ranges);
280280 }
281
281
282282 @Test
283283 public void testCombineBoldItalicStriker() throws IOException {
284284 String string= "<strong>strong</strong>,<em>italic</em>,<s>strike</s>," +
00 /*******************************************************************************
1 * Copyright (c) 2000, 2016 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
1919 import org.eclipse.jface.text.tests.codemining.CodeMiningProjectionViewerTest;
2020 import org.eclipse.jface.text.tests.codemining.CodeMiningTest;
2121 import org.eclipse.jface.text.tests.contentassist.AsyncContentAssistTest;
22 import org.eclipse.jface.text.tests.contentassist.ContextInformationPresenterTest;
23 import org.eclipse.jface.text.tests.contentassist.ContextInformationTest;
24 import org.eclipse.jface.text.tests.contentassist.FilteringAsyncContentAssistTests;
2225 import org.eclipse.jface.text.tests.reconciler.AbstractReconcilerTest;
2326 import org.eclipse.jface.text.tests.rules.DefaultPartitionerTest;
2427 import org.eclipse.jface.text.tests.rules.DefaultPartitionerZeroLengthTest;
4851 DefaultPairMatcherTest.class,
4952 DefaultPairMatcherTest2.class,
5053 AsyncContentAssistTest.class,
54 FilteringAsyncContentAssistTests.class,
55 ContextInformationTest.class,
56 ContextInformationPresenterTest.class,
5157
5258 AbstractReconcilerTest.class,
5359
6167 LineContentBoundsDrawingTest.class,
6268 AnnotationOnTabTest.class,
6369 CodeMiningTest.class,
64 CodeMiningProjectionViewerTest.class
70 CodeMiningProjectionViewerTest.class,
71
72 TabsToSpacesConverterTest.class,
6573 })
6674 public class JFaceTextTestSuite {
6775 // see @SuiteClasses
0 /*******************************************************************************
1 * Copyright (c) 2019 Mateusz Matela and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Mateusz Matela - initial API and implementation
12 *******************************************************************************/
13 package org.eclipse.jface.text.tests;
14
15 import static org.junit.Assert.assertEquals;
16
17 import org.junit.Test;
18
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.widgets.Shell;
21
22 import org.eclipse.jface.text.BadLocationException;
23 import org.eclipse.jface.text.DefaultLineTracker;
24 import org.eclipse.jface.text.Document;
25 import org.eclipse.jface.text.Position;
26 import org.eclipse.jface.text.TabsToSpacesConverter;
27 import org.eclipse.jface.text.TextViewer;
28 import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
29 import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
30 import org.eclipse.jface.text.source.projection.ProjectionViewer;
31
32 public class TabsToSpacesConverterTest {
33
34 private void doTest(String input, String output, int keyCode, int tabWidth) {
35 Shell shell= new Shell();
36 TextViewer textViewer= new TextViewer(shell, SWT.NONE);
37
38 TabsToSpacesConverter tabToSpacesConverter= new TabsToSpacesConverter();
39 tabToSpacesConverter.setLineTracker(new DefaultLineTracker());
40 tabToSpacesConverter.setNumberOfSpacesPerTab(tabWidth);
41 tabToSpacesConverter.setDeleteSpacesAsTab(true);
42 textViewer.setTabsToSpacesConverter(tabToSpacesConverter);
43
44 int selectionFrom= input.indexOf('|');
45 int selectionTo= input.indexOf('|', selectionFrom + 1) - 1;
46 Document document= new Document(input.replace("|", ""));
47 textViewer.setDocument(document);
48 textViewer.setSelectedRange(selectionFrom, selectionTo - selectionFrom);
49
50 TextViewerTest.postKeyEvent(textViewer.getTextWidget(), keyCode, SWT.NONE, SWT.KeyDown);
51
52 assertEquals(output, document.get());
53 }
54
55 @Test
56 public void testDelete1() {
57 doTest("|| ABC", " ABC", SWT.DEL, 4);
58 }
59
60 @Test
61 public void testDelete2() {
62 doTest(" || ABC", " ABC", SWT.DEL, 4);
63 }
64
65 @Test
66 public void testDelete3() {
67 doTest(" || ABC", " ABC", SWT.DEL, 4);
68 }
69
70 @Test
71 public void testDelete4() {
72 doTest(" || ABC", " ABC", SWT.DEL, 4);
73 }
74
75 @Test
76 public void testDeleteRange1() {
77 doTest(" | | ABC", " ABC", SWT.DEL, 4);
78 }
79
80 @Test
81 public void testDeleteRange2() {
82 doTest(" | | ABC", " ABC", SWT.DEL, 4);
83 }
84
85 @Test
86 public void testDeleteInside1() {
87 doTest(" ABCD|| EFG", " ABCDEFG", SWT.DEL, 4);
88 }
89
90 @Test
91 public void testDeleteInside2() {
92 doTest(" ABCD || EFG", " ABCD EFG", SWT.DEL, 4);
93 }
94
95 @Test
96 public void testDeleteInside3() {
97 doTest(" ABCD|| EFG", " ABCDEFG", SWT.DEL, 4);
98 }
99
100 @Test
101 public void testDeleteLargeWidth1() {
102 doTest(" || ABC", " ABC", SWT.DEL, 10);
103 }
104
105 @Test
106 public void testDeleteLargeWidth2() {
107 doTest(" || ABC", " ABC", SWT.DEL, 10);
108 }
109
110 @Test
111 public void testDeleteSmallWidth() {
112 doTest(" || ABC", " ABC", SWT.DEL, 2);
113 }
114
115 @Test
116 public void testBackspace1() {
117 doTest(" || ABC", " ABC", SWT.BS, 4);
118 }
119
120 @Test
121 public void testBackspace2() {
122 doTest(" ||ABC", " ABC", SWT.BS, 4);
123 }
124
125 @Test
126 public void testBackspace3() {
127 doTest(" || ABC", " ABC", SWT.BS, 4);
128 }
129
130 @Test
131 public void testBackspace4() {
132 doTest(" || ABC", " ABC", SWT.BS, 4);
133 }
134
135 @Test
136 public void testBackspaceRange1() {
137 doTest(" | | ABC", " ABC", SWT.BS, 4);
138 }
139
140 @Test
141 public void testBackspaceRange2() {
142 doTest(" | | ABC", " ABC", SWT.BS, 4);
143 }
144
145 @Test
146 public void testBackspaceInside1() {
147 doTest(" ABCD ||EFG", " ABCDEFG", SWT.BS, 4);
148 }
149
150 @Test
151 public void testBackspaceInside2() {
152 doTest(" ABCD ||EFG", " ABCD EFG", SWT.BS, 4);
153 }
154
155 @Test
156 public void testBackspaceInside3() {
157 doTest(" ABCDEF ||G", " ABCDEFG", SWT.BS, 4);
158 }
159
160 @Test
161 public void testBackspaceLargeWidth1() {
162 doTest(" || ABC", " ABC", SWT.BS, 10);
163 }
164
165 @Test
166 public void testBackspaceLargeWidth2() {
167 doTest(" || ABC", " ABC", SWT.BS, 10);
168 }
169
170 @Test
171 public void testBackspaceSmallWidth() {
172 doTest(" || ABC", " ABC", SWT.BS, 2);
173 }
174
175 @Test
176 public void testDeleteAfterCollapsedRegion() throws BadLocationException {
177 Shell shell= new Shell();
178 ProjectionViewer textViewer= new ProjectionViewer(shell, null, null, false, SWT.NONE);
179
180 TabsToSpacesConverter tabToSpacesConverter= new TabsToSpacesConverter();
181 tabToSpacesConverter.setLineTracker(new DefaultLineTracker());
182 tabToSpacesConverter.setNumberOfSpacesPerTab(4);
183 tabToSpacesConverter.setDeleteSpacesAsTab(true);
184 textViewer.setTabsToSpacesConverter(tabToSpacesConverter);
185
186 Document document= new Document(" COLLAPSED!!!\n REGION!!!\n VISIBLE\n REGION");
187 int caretPosition= document.get().indexOf("VISIBLE") - 4;
188 textViewer.setDocument(document, new ProjectionAnnotationModel());
189 textViewer.enableProjection();
190 textViewer.setSelectedRange(caretPosition, 0);
191
192 ProjectionAnnotation annotation= new ProjectionAnnotation(true);
193 textViewer.getProjectionAnnotationModel().addAnnotation(annotation, new Position(0, document.getLineOffset(2)));
194 textViewer.doOperation(ProjectionViewer.COLLAPSE_ALL);
195
196 TextViewerTest.postKeyEvent(textViewer.getTextWidget(), SWT.DEL, SWT.NONE, SWT.KeyDown);
197
198 assertEquals(" COLLAPSED!!!\n REGION!!!\nVISIBLE\n REGION", document.get());
199 }
200 }
8686
8787 /**
8888 * Creates a new color.
89 *
89 *
9090 * @param red the amount of red in the color
9191 * @param green the amount of green in the color
9292 * @param blue the amount of blue in the color
118118 public void testUnclippedRegions() {
119119 checkRegions(fAllRanges, fNonDefaultRanges);
120120 }
121
121
122122 @Test
123123 public void testClippedRegions1() {
124124 fTextPresentation.setResultWindow(new Region(0, 140));
1010 * Contributors:
1111 * Sergey Prigogin (Google) - initial API and implementation
1212 * Mickael Istria (Red Hat Inc.) - [Bug 544708] Ctrl+Home
13 * Paul Pazderski - [Bug 545530] Test for TextViewer's default IDocumentAdapter implementation.
13 * Paul Pazderski - [Bug 545530] Test for TextViewer's default IDocumentAdapter implementation.
1414 *******************************************************************************/
1515 package org.eclipse.jface.text.tests;
1616
2626 import org.junit.Test;
2727
2828 import org.eclipse.swt.SWT;
29 import org.eclipse.swt.custom.StyledText;
2930 import org.eclipse.swt.custom.StyledTextContent;
3031 import org.eclipse.swt.layout.FillLayout;
3132 import org.eclipse.swt.widgets.Control;
3435 import org.eclipse.swt.widgets.Listener;
3536 import org.eclipse.swt.widgets.Shell;
3637
38 import org.eclipse.core.runtime.IStatus;
39 import org.eclipse.core.runtime.Status;
40 import org.eclipse.core.runtime.jobs.Job;
41
3742 import org.eclipse.jface.util.Util;
3843
44 import org.eclipse.jface.text.BlockTextSelection;
3945 import org.eclipse.jface.text.Document;
46 import org.eclipse.jface.text.IDocument;
4047 import org.eclipse.jface.text.IDocumentAdapter;
48 import org.eclipse.jface.text.IDocumentExtension3;
49 import org.eclipse.jface.text.ITextOperationTarget;
50 import org.eclipse.jface.text.ITextSelection;
4151 import org.eclipse.jface.text.ITextViewer;
4252 import org.eclipse.jface.text.TextViewer;
4353 import org.eclipse.jface.text.source.SourceViewer;
7181 assertEquals(0, textViewer.getTextWidget().getCaretOffset());
7282 } finally {
7383 shell.dispose();
84 }
85 }
86
87 @Test
88 public void testCaretMoveChangesSelection() throws Exception {
89 Shell shell= new Shell();
90 try {
91 TextViewer textViewer= new TextViewer(shell, SWT.NONE);
92 Document document= new Document("abc");
93 textViewer.setDocument(document);
94 int len= document.getLength();
95 // Select the whole document with the caret at the beginning.
96 textViewer.setSelectedRange(0, len);
97 ITextSelection selection = (ITextSelection)textViewer.getSelectionProvider().getSelection();
98 assertEquals(0, selection.getOffset());
99 assertEquals(len, selection.getLength());
100 textViewer.getTextWidget().setCaretOffset(1);
101 selection = (ITextSelection)textViewer.getSelectionProvider().getSelection();
102 assertEquals(1, selection.getOffset());
103 assertEquals(0, selection.getLength());
104 } finally {
105 shell.dispose();
106 }
107 }
108
109 @Test
110 public void testGetCachedSelection() throws Exception {
111 Shell shell= new Shell();
112 try {
113 TextViewer textViewer= new TextViewer(shell, SWT.NONE);
114 Document document= new Document("abc");
115 textViewer.setDocument(document);
116 int len= document.getLength();
117 // Select the whole document with the caret at the beginning.
118 textViewer.setSelectedRange(0, len);
119 checkInAndOutUIThread(() -> {
120 ITextSelection selection = textViewer.getLastKnownSelection();
121 assertEquals(0, selection.getOffset());
122 assertEquals(len, selection.getLength());
123 });
124 } finally {
125 shell.dispose();
126 }
127 }
128
129 @Test
130 public void testBlockSelectionAccessors() throws Exception {
131 Shell shell= new Shell();
132 try {
133 ITextViewer textViewer= new TextViewer(shell, SWT.NONE);
134 Document document= new Document("0123\n4567\n89ab\ncdef");
135 textViewer.setDocument(document);
136 // Select the whole document with the caret at the beginning.
137 StyledText textWidget= textViewer.getTextWidget();
138 textWidget.setBlockSelection(true);
139 shell.setLayout(new FillLayout());
140 shell.open();
141 textViewer.getSelectionProvider().setSelection(new BlockTextSelection(textViewer.getDocument(), 1, 1, 2, 2, textWidget.getTabs()));
142 BlockTextSelection sel = (BlockTextSelection)textViewer.getSelectionProvider().getSelection();
143 assertEquals(1, sel.getStartLine());
144 assertEquals(2, sel.getEndLine());
145 assertEquals(1, sel.getStartColumn());
146 assertEquals(2, sel.getEndColumn());
147 } finally {
148 shell.dispose();
149 }
150 }
151
152
153 private void checkInAndOutUIThread(Runnable r) throws InterruptedException {
154 // first run in UI Thread, forward exceptions
155 r.run();
156 // then run in non-UI Thread
157 Job job = Job.create("Check in non-UI Thread", monitor -> {
158 try {
159 r.run();
160 return Status.OK_STATUS;
161 } catch (Throwable t) {
162 return new Status(IStatus.ERROR, "org.eclipse.jface.text.tests", t.getMessage(), t);
163 }
164 });
165 job.schedule();
166 job.join();
167 if (!job.getResult().isOK()) {
168 Throwable ex = job.getResult().getException();
169 if (ex != null) {
170 throw new AssertionError("Assertion fail in non-UI Thread", ex);
171 } else {
172 fail(job.getResult().toString());
173 }
74174 }
75175 }
76176
194294 postKeyEvent(viewer.getTextWidget(), SWT.HOME, SWT.CTRL, SWT.KeyDown);
195295 }
196296
197 private static void postKeyEvent(Control widget, int keyCode, int stateMask, int type) {
297 static void postKeyEvent(Control widget, int keyCode, int stateMask, int type) {
198298 Display display= widget.getDisplay();
199299 widget.setFocus();
200300 DisplayHelper.driveEventQueue(display);
220320 b.append("end");
221321 return b.toString();
222322 }
323
324 @Test
325 public void testShiftLeft() {
326 Shell shell= new Shell();
327 try {
328 TextViewer textViewer= new TextViewer(shell, SWT.NONE);
329 {
330 // Normal case, both lines match prefix
331 Document document= new Document("//line1\n//line2");
332 textViewer.setDocumentPartitioning(IDocumentExtension3.DEFAULT_PARTITIONING);
333 textViewer.setDocument(document);
334 textViewer.setDefaultPrefixes(new String[] { "//" }, IDocument.DEFAULT_CONTENT_TYPE);
335
336 textViewer.doOperation(ITextOperationTarget.SELECT_ALL);
337 textViewer.doOperation(ITextOperationTarget.STRIP_PREFIX);
338
339 assertEquals("line1\nline2", textViewer.getDocument().get());
340 }
341 {
342 // Don't shift anything, as 2nd line does not match any prefix
343 Document document= new Document("//line1\nline2");
344 textViewer.setDocumentPartitioning(IDocumentExtension3.DEFAULT_PARTITIONING);
345 textViewer.setDocument(document);
346 textViewer.setDefaultPrefixes(new String[] { "//" }, IDocument.DEFAULT_CONTENT_TYPE);
347
348 textViewer.doOperation(ITextOperationTarget.SELECT_ALL);
349 textViewer.doOperation(ITextOperationTarget.STRIP_PREFIX);
350
351 assertEquals("//line1\nline2", textViewer.getDocument().get());
352 }
353 {
354 // Shift line1, since line2 matches the allowed empty prefix
355 Document document= new Document("//line1\nline2");
356 textViewer.setDocumentPartitioning(IDocumentExtension3.DEFAULT_PARTITIONING);
357 textViewer.setDocument(document);
358 textViewer.setDefaultPrefixes(new String[] { "//", "" }, IDocument.DEFAULT_CONTENT_TYPE);
359
360 textViewer.doOperation(ITextOperationTarget.SELECT_ALL);
361 textViewer.doOperation(ITextOperationTarget.STRIP_PREFIX);
362
363 assertEquals("line1\nline2", textViewer.getDocument().get());
364 }
365 } finally {
366 shell.dispose();
367 }
368 }
223369 }
9494
9595 undoManager.disconnect(newContext);
9696 }
97
97
9898 @Test
9999 public void testTransferNonUndoableNonTextOp() throws Exception {
100100 internalTestTransferNonTextOp(false);
101101 }
102
102
103103 @Test
104104 public void testTransferUndoableNonTextOp() throws Exception {
105105 internalTestTransferNonTextOp(true);
106106 }
107
107
108108 @Test
109109 public void testCanUndo() throws Exception {
110110 IDocument doc= new Document();
194194 }
195195
196196 @Test
197 public void testCodeMiningMultiLine() throws BadLocationException {
197 public void testCodeMiningMultiLine() {
198198 fViewer.getDocument().set("a\nbc");
199199 fViewer.setCodeMiningProviders(new ICodeMiningProvider[] { new ICodeMiningProvider() {
200200 @Override
0 /*******************************************************************************
1 * Copyright (c) 2019 Stephan Wahlbrink and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Stephan Wahlbrink <sw@wahlbrink.eu>
12 *******************************************************************************/
13
14 package org.eclipse.jface.text.tests.contentassist;
15
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.assertTrue;
18
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.List;
22 import java.util.stream.Collectors;
23
24 import org.junit.After;
25 import org.junit.Assert;
26
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.custom.StyledText;
29 import org.eclipse.swt.layout.FillLayout;
30 import org.eclipse.swt.widgets.Event;
31 import org.eclipse.swt.widgets.Shell;
32
33 import org.eclipse.jface.text.Document;
34 import org.eclipse.jface.text.ITextOperationTarget;
35 import org.eclipse.jface.text.contentassist.ContentAssistant;
36 import org.eclipse.jface.text.contentassist.IContentAssistant;
37 import org.eclipse.jface.text.source.ISourceViewer;
38 import org.eclipse.jface.text.source.SourceViewer;
39 import org.eclipse.jface.text.source.SourceViewerConfiguration;
40 import org.eclipse.jface.text.tests.util.DisplayHelper;
41
42
43 public class AbstractContentAssistTest {
44
45
46 private Shell shell;
47 private SourceViewer viewer;
48 private ContentAssistant assistant;
49 private Document document;
50
51
52 public AbstractContentAssistTest() {
53 }
54
55
56 @After
57 public void close() {
58 if (shell != null && !shell.isDisposed()) {
59 shell.close();
60 }
61 }
62
63
64 protected void setupSourceViewer(ContentAssistant contentAssistant, String initialText) {
65 shell= new Shell();
66 shell.setSize(500, 240);
67 shell.setLayout(new FillLayout());
68
69 viewer= new SourceViewer(shell, null, SWT.NONE);
70 assistant= contentAssistant;
71 viewer.configure(createSourceViewerConfiguration());
72
73 document= new Document();
74 if (initialText != null) {
75 document.set(initialText);
76 }
77 viewer.setDocument(document);
78
79 shell.open();
80 Assert.assertTrue(new DisplayHelper() {
81 @Override
82 protected boolean condition() {
83 return viewer.getTextWidget().isVisible();
84 }
85 }.waitForCondition(shell.getDisplay(), 3000));
86 }
87
88 protected SourceViewerConfiguration createSourceViewerConfiguration() {
89 return new SourceViewerConfiguration() {
90 @Override
91 public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
92 return AbstractContentAssistTest.this.getContentAssistant();
93 }
94 };
95 }
96
97 protected SourceViewer getSourceViewer() {
98 return viewer;
99 }
100
101 protected Document getDocument() {
102 return document;
103 }
104
105 protected ContentAssistant getContentAssistant() {
106 return assistant;
107 }
108
109 protected void selectAndReveal(int selectionStart, int selectionLength) {
110 StyledText widget= viewer.getTextWidget();
111 widget.setRedraw(false);
112
113 viewer.revealRange(selectionStart, selectionLength);
114 viewer.setSelectedRange(selectionStart, selectionLength);
115
116 widget.setRedraw(true);
117 }
118
119 protected void postSourceViewerKeyEvent(int keyCode, int stateMask, int type) {
120 processEvents();
121 Event event= new Event();
122 event.type= type;
123 event.widget= viewer.getTextWidget();
124 event.display= viewer.getTextWidget().getDisplay();
125 event.keyCode= keyCode;
126 event.stateMask= stateMask;
127 event.doit= true;
128 viewer.getTextWidget().notifyListeners(type, event);
129 processEvents();
130 }
131
132 protected void runTextOperation(int operation) {
133 ITextOperationTarget textOperationTarget= viewer.getTextOperationTarget();
134
135 assertTrue(textOperationTarget.canDoOperation(operation));
136 textOperationTarget.doOperation(operation);
137 }
138
139 protected void triggerContextInformation() {
140 runTextOperation(ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION);
141 }
142
143
144 protected void processEvents() {
145 DisplayHelper.driveEventQueue(shell.getDisplay());
146 }
147
148 protected List<Shell> getCurrentShells() {
149 return Arrays.stream(shell.getDisplay().getShells())
150 .filter(Shell::isVisible)
151 .collect(Collectors.toList());
152 }
153
154 protected List<Shell> findNewShells(Collection<Shell> beforeShells) {
155 return Arrays.stream(shell.getDisplay().getShells())
156 .filter(Shell::isVisible)
157 .filter(shell -> !beforeShells.contains(shell))
158 .collect(Collectors.toList());
159 }
160
161 protected Shell findNewShell(Collection<Shell> beforeShells) {
162 DisplayHelper.sleep(shell.getDisplay(), 100);
163 List<Shell> afterShells= findNewShells(beforeShells);
164 if (afterShells.isEmpty()) {
165 DisplayHelper.sleep(shell.getDisplay(), 1000);
166 }
167 afterShells= findNewShells(beforeShells);
168 assertEquals("No new shell found", 1, afterShells.size());
169 return afterShells.get(0);
170 }
171
172 }
0 /*******************************************************************************
1 * Copyright (c) 2016, 2019 Red Hat Inc. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Mickael Istria (Red Hat Inc.)
12 * Stephan Wahlbrink <sw@wahlbrink.eu> - Bug 512251 - Fix IllegalArgumentException in ContextInformationPopup
13 *******************************************************************************/
14
15 package org.eclipse.jface.text.tests.contentassist;
16
17 import java.util.Arrays;
18
19 import org.eclipse.swt.graphics.Image;
20
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.IDocument;
23 import org.eclipse.jface.text.IRegion;
24 import org.eclipse.jface.text.ITextViewer;
25 import org.eclipse.jface.text.contentassist.CompletionProposal;
26 import org.eclipse.jface.text.contentassist.ICompletionProposal;
27 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
28 import org.eclipse.jface.text.contentassist.IContextInformation;
29 import org.eclipse.jface.text.contentassist.IContextInformationExtension;
30 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
31
32
33 public class BarContentAssistProcessor implements IContentAssistProcessor {
34
35 public static final String PROPOSAL= "bars are good for a beer.";
36
37 protected static class BarContextInformation implements IContextInformation, IContextInformationExtension {
38
39 private String contextDisplayString;
40
41 private String informationDisplayString;
42
43 private int offset;
44
45 public BarContextInformation(String contextDisplayString, String informationDisplayString, int offset) {
46 this.contextDisplayString= contextDisplayString;
47 this.informationDisplayString= informationDisplayString;
48 this.offset= offset;
49 }
50
51 @Override
52 public String getContextDisplayString() {
53 return contextDisplayString;
54 }
55
56 @Override
57 public Image getImage() {
58 return null;
59 }
60
61 @Override
62 public String getInformationDisplayString() {
63 return informationDisplayString;
64 }
65
66 @Override
67 public int getContextInformationPosition() {
68 return offset;
69 }
70
71 }
72
73 protected static class ContextInformationValidator implements IContextInformationValidator {
74
75 protected BarContextInformation info;
76
77 protected ITextViewer viewer;
78
79 protected int offset;
80
81 @Override
82 public void install(IContextInformation info, ITextViewer viewer, int offset) {
83 if (info instanceof BarContextInformation) {
84 this.info= (BarContextInformation) info;
85 }
86 this.viewer= viewer;
87 this.offset= offset;
88 }
89
90 @Override
91 public boolean isContextInformationValid(int offset) {
92 if (this.info == null) {
93 return false;
94 }
95 try {
96 IDocument document= viewer.getDocument();
97 IRegion line= document.getLineInformationOfOffset(this.offset);
98 int end= line.getOffset() + line.getLength();
99 return (offset >= this.offset && offset < end);
100 } catch (BadLocationException e) {
101 return false;
102 }
103 }
104 }
105
106
107 private final String completeString;
108
109 public BarContentAssistProcessor() {
110 this(PROPOSAL);
111 }
112
113 public BarContentAssistProcessor(String completeString) {
114 this.completeString= completeString;
115 }
116
117 @Override
118 public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
119 for (int offsetInProposal= Math.min(this.completeString.length(), viewer.getDocument().getLength()); offsetInProposal > 0; offsetInProposal--) {
120 String maybeMatchingString= this.completeString.substring(0, offsetInProposal);
121 try {
122 int lastIndex= offset - offsetInProposal + this.completeString.length();
123 if (offset >= offsetInProposal && viewer.getDocument().get(offset - offsetInProposal, maybeMatchingString.length()).equals(maybeMatchingString)) {
124 CompletionProposal proposal= new CompletionProposal(this.completeString.substring(offsetInProposal), offset, 0, lastIndex);
125 return new ICompletionProposal[] { proposal };
126 }
127 } catch (BadLocationException e) {
128 e.printStackTrace();
129 }
130 }
131 return new ICompletionProposal[0];
132 }
133
134 @Override
135 public char[] getCompletionProposalAutoActivationCharacters() {
136 return null;
137 }
138
139 @Override
140 public char[] getContextInformationAutoActivationCharacters() {
141 return null;
142 }
143
144 /**
145 * Creates context info "idx= <word index in #PROPOSAL>" at the end of a word.
146 **/
147 @Override
148 public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
149 try {
150 IDocument document= viewer.getDocument();
151 int wordBegin= offset;
152 while (wordBegin > 0 && Character.isLetterOrDigit(document.getChar(wordBegin - 1))) {
153 wordBegin--;
154 }
155 if (wordBegin < offset) {
156 String word= document.get(wordBegin, offset - wordBegin);
157 int wordIdx= Arrays.asList(completeString.split("\\W")).indexOf(word);
158 if (wordIdx >= 0) {
159 return new IContextInformation[] {
160 new BarContextInformation(word, "idx= " + wordIdx, wordBegin)
161 };
162 }
163 }
164 } catch (BadLocationException e) {
165 e.printStackTrace();
166 }
167 return null;
168 }
169
170 @Override
171 public IContextInformationValidator getContextInformationValidator() {
172 return new ContextInformationValidator();
173 }
174
175 @Override
176 public String getErrorMessage() {
177 return null;
178 }
179
180 }
0 /*******************************************************************************
1 * Copyright (c) 2017, 2019 Stephan Wahlbrink and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Stephan Wahlbrink <sw@wahlbrink.eu>
12 *******************************************************************************/
13 package org.eclipse.jface.text.tests.contentassist;
14
15 import static org.eclipse.jface.text.tests.contentassist.ContextInformationTest.getInfoText;
16 import static org.junit.Assert.assertArrayEquals;
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertTrue;
19
20 import java.util.List;
21
22 import org.junit.Test;
23
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.custom.StyleRange;
26 import org.eclipse.swt.custom.StyledText;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Shell;
29 import org.eclipse.swt.widgets.Text;
30
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.TextPresentation;
33 import org.eclipse.jface.text.contentassist.ContentAssistant;
34 import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
35 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
36
37
38 public class ContextInformationPresenterTest extends AbstractContentAssistTest {
39
40 private static class ValidatorWithPresenter extends BarContentAssistProcessor.ContextInformationValidator
41 implements IContextInformationPresenter {
42
43 private boolean isStyled;
44
45 /**
46 * Hightlight (bold) "idx" if caret is inside the word (including end)
47 */
48 @Override
49 public boolean updatePresentation(int offset, TextPresentation presentation) {
50 if (info == null) { // Ignore unknown information
51 return false;
52 }
53
54 int begin= info.getContextInformationPosition();
55 int end= begin + info.getContextDisplayString().length();
56 boolean style= (offset >= begin && offset <= end);
57 if (style == isStyled) {
58 return false;
59 }
60 if (style) {
61 presentation.clear();
62 presentation.addStyleRange(new StyleRange(0, 3, null, null, SWT.BOLD));
63 } else {
64 presentation.clear();
65 }
66 isStyled= style;
67 return true;
68 }
69
70 }
71
72
73 private Shell infoShell;
74
75
76 private ContentAssistant createBarContentAssist() {
77 ContentAssistant contentAssistant= new ContentAssistant();
78 contentAssistant.setContentAssistProcessor(new BarContentAssistProcessor() {
79 @Override
80 public IContextInformationValidator getContextInformationValidator() {
81 return new ValidatorWithPresenter();
82 }
83 }, IDocument.DEFAULT_CONTENT_TYPE);
84 return contentAssistant;
85 }
86
87 @Test
88 public void testContextInfo_withStyledTextPresentation() throws Exception {
89 setupSourceViewer(createBarContentAssist(), BarContentAssistProcessor.PROPOSAL);
90
91 final List<Shell> beforeShells= getCurrentShells();
92
93 postSourceViewerKeyEvent(SWT.ARROW_RIGHT, 0, SWT.KeyDown);
94 selectAndReveal(4, 0);
95 processEvents();
96
97 triggerContextInformation();
98 this.infoShell= findNewShell(beforeShells);
99 assertEquals("idx= 0", getInfoText(this.infoShell));
100 assertArrayEquals(new StyleRange[] {
101 new StyleRange(0, 3, null, null, SWT.BOLD)
102 }, getInfoStyleRanges(this.infoShell));
103
104 postSourceViewerKeyEvent(SWT.ARROW_RIGHT, 0, SWT.KeyDown);
105
106 assertEquals("idx= 0", getInfoText(this.infoShell));
107 assertArrayEquals(new StyleRange[] {
108 }, getInfoStyleRanges(this.infoShell));
109 }
110
111
112 static StyleRange[] getInfoStyleRanges(final Shell shell) {
113 assertTrue(shell.isVisible());
114 Control[] children= shell.getChildren();
115 for (Control child : children) {
116 if (child instanceof Text) {
117 return null;
118 }
119 if (child instanceof StyledText) {
120 return ((StyledText) child).getStyleRanges();
121 }
122 }
123 return null;
124 }
125
126 }
0 /*******************************************************************************
1 * Copyright (c) 2017, 2019 Stephan Wahlbrink and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Stephan Wahlbrink <sw@wahlbrink.eu>
12 *******************************************************************************/
13 package org.eclipse.jface.text.tests.contentassist;
14
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertTrue;
17
18 import java.util.List;
19
20 import org.junit.Test;
21
22 import org.eclipse.swt.custom.StyledText;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.swt.widgets.Text;
26
27 import org.eclipse.text.tests.Accessor;
28
29 import org.eclipse.jface.text.IDocument;
30 import org.eclipse.jface.text.contentassist.ContentAssistant;
31
32
33 public class ContextInformationTest extends AbstractContentAssistTest {
34
35
36 private Shell infoShell;
37
38
39 private ContentAssistant createBarContentAssist() {
40 ContentAssistant contentAssistant= new ContentAssistant();
41 contentAssistant.setContentAssistProcessor(new BarContentAssistProcessor(), IDocument.DEFAULT_CONTENT_TYPE);
42 return contentAssistant;
43 }
44
45 @Test
46 public void testContextInfo() throws Exception {
47 setupSourceViewer(createBarContentAssist(), BarContentAssistProcessor.PROPOSAL);
48
49 final List<Shell> beforeShells= getCurrentShells();
50
51 selectAndReveal(4, 0);
52 processEvents();
53
54 triggerContextInformation();
55 this.infoShell= findNewShell(beforeShells);
56 assertEquals("idx= 0", getInfoText(this.infoShell));
57
58 selectAndReveal(8, 0);
59 processEvents();
60
61 triggerContextInformation();
62 this.infoShell= findNewShell(beforeShells);
63 assertEquals("idx= 1", getInfoText(this.infoShell));
64 }
65
66 @Test
67 public void testContextInfo_hide_Bug512251() throws Exception {
68 setupSourceViewer(createBarContentAssist(), BarContentAssistProcessor.PROPOSAL);
69
70 final List<Shell> beforeShells= getCurrentShells();
71
72 selectAndReveal(4, 0);
73 processEvents();
74
75 triggerContextInformation();
76 this.infoShell= findNewShell(beforeShells);
77
78 selectAndReveal(8, 0);
79 processEvents();
80
81 triggerContextInformation();
82 this.infoShell= findNewShell(beforeShells);
83
84 // ITextEditorActionConstants.DELETE_LINE
85 getDocument().set("");
86
87 new Accessor(getContentAssistant(), ContentAssistant.class).invoke("hide", new Object[0]);
88 }
89
90
91 static String getInfoText(final Shell shell) {
92 assertTrue(shell.isVisible());
93 Control[] children= shell.getChildren();
94 for (Control child : children) {
95 if (child instanceof Text) {
96 return ((Text) child).getText();
97 }
98 if (child instanceof StyledText) {
99 return ((StyledText) child).getText();
100 }
101 }
102 return null;
103 }
104
105 }
0 /*******************************************************************************
1 * Copyright (c) 2019 Pivotal, Inc.
2 * All rights reserved. This program and the accompanying materials
3 * are made available under the terms of the Eclipse Public License v1.0
4 * which accompanies this distribution, and is available at
5 * https://www.eclipse.org/legal/epl-v10.html
6 *
7 * Contributors:
8 * Pivotal, Inc. - initial API and implementation
9 *******************************************************************************/
10 package org.eclipse.jface.text.tests.contentassist;
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertTrue;
14
15 import java.lang.reflect.Field;
16 import java.util.List;
17 import java.util.function.Predicate;
18 import java.util.stream.Collectors;
19
20 import org.junit.After;
21 import org.junit.Before;
22 import org.junit.Ignore;
23 import org.junit.Test;
24
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.graphics.Image;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.widgets.Shell;
29
30 import org.eclipse.text.edits.InsertEdit;
31
32 import org.eclipse.jface.text.BadLocationException;
33 import org.eclipse.jface.text.Document;
34 import org.eclipse.jface.text.DocumentEvent;
35 import org.eclipse.jface.text.IDocument;
36 import org.eclipse.jface.text.ITextViewer;
37 import org.eclipse.jface.text.contentassist.ContentAssistant;
38 import org.eclipse.jface.text.contentassist.ContextInformationValidator;
39 import org.eclipse.jface.text.contentassist.ICompletionProposal;
40 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
41 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
42 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
43 import org.eclipse.jface.text.contentassist.IContextInformation;
44 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
45 import org.eclipse.jface.text.source.SourceViewer;
46 import org.eclipse.jface.text.tests.util.DisplayHelper;
47
48 /**
49 * Tests for Async completion proposal popup proposals filtering mechanics
50 *
51 * @author Alex Boyko
52 *
53 */
54 public class FilteringAsyncContentAssistTests {
55
56 private Shell shell;
57 private SourceViewer viewer;
58 private ContentAssistant ca;
59
60 @Before
61 public void setup() {
62 tearDown();
63
64 shell = new Shell();
65 shell.setSize(300, 300);
66 shell.open();
67
68 viewer = new SourceViewer(shell, null, SWT.NONE);
69 Document document = new Document();
70 viewer.setDocument(document);
71 ca = new ContentAssistant(true);
72 }
73
74 @After
75 public void tearDown() {
76 if (shell != null) {
77 ca.uninstall();
78 if (!shell.isDisposed()) {
79 shell.dispose();
80 }
81 shell = null;
82 }
83 }
84
85 /**
86 * Simple CA with 1 immediate CA processor. Empty text, invoke CA, verify 1
87 * proposal, apply it, verify the resultant text
88 *
89 * @throws Exception exception
90 */
91 @Test
92 public void testSimpleCa() throws Exception {
93
94 ca.addContentAssistProcessor(new ImmediateContentAssistProcessor("xx"), IDocument.DEFAULT_CONTENT_TYPE);
95
96 ca.install(viewer);
97
98 viewer.setSelectedRange(0, 0);
99
100 ca.showPossibleCompletions();
101
102 DisplayHelper.sleep(shell.getDisplay(), 300);
103
104 List<ICompletionProposal> computedProposals = getComputedProposals(ca);
105
106 assertEquals(1, computedProposals.size());
107
108 ICompletionProposal proposal = computedProposals.get(0);
109
110 IDocument document = viewer.getDocument();
111
112 proposal.apply(document);
113
114 assertEquals("xx", document.get());
115 }
116
117 /**
118 * Simple CA with filtering with 2 immediate CA processors. Empty text
119 * initially. Invoke CA, verify 2 proposals, type 'x', verify only 1 proposal 1
120 *
121 * @throws Exception exception
122 */
123 @Test
124 public void testFilteredCa() throws Exception {
125 IDocument document = viewer.getDocument();
126
127 ca.addContentAssistProcessor(new ImmediateContentAssistProcessor("xx"), IDocument.DEFAULT_CONTENT_TYPE);
128 ca.addContentAssistProcessor(new ImmediateContentAssistProcessor("yy"), IDocument.DEFAULT_CONTENT_TYPE);
129
130 ca.install(viewer);
131
132 viewer.setSelectedRange(1, 0);
133
134 ca.showPossibleCompletions();
135
136 DisplayHelper.sleep(shell.getDisplay(), 300);
137
138 List<ICompletionProposal> computedProposals = getComputedProposals(ca);
139 assertEquals(2, computedProposals.size());
140 List<ICompletionProposal> filteredProposals = getFilteredProposals(ca);
141 assertEquals(2, filteredProposals.size());
142
143 new InsertEdit(0, "x").apply(document);
144 viewer.setSelectedRange(1, 0);
145
146 DisplayHelper.sleep(shell.getDisplay(), 300);
147
148 computedProposals = getComputedProposals(ca);
149 assertEquals(2, computedProposals.size());
150 filteredProposals = getFilteredProposals(ca);
151 assertEquals(1, filteredProposals.size());
152
153 ((ICompletionProposalExtension) filteredProposals.get(0)).apply(document, (char) 0,
154 viewer.getSelectedRange().x);
155 assertEquals("xxx", document.get());
156 }
157
158 /**
159 * Simple CA with filtering with 1 immediate CA processors. Empty text
160 * initially. Invoke CA, verify 1 proposal, type 'a', verify no proposals
161 *
162 * @throws Exception exception
163 */
164 @Test
165 public void testFilteredCa_AllFilteredOut() throws Exception {
166 IDocument document = viewer.getDocument();
167
168 ca.addContentAssistProcessor(new ImmediateContentAssistProcessor("xx"), IDocument.DEFAULT_CONTENT_TYPE);
169
170 ca.install(viewer);
171
172 viewer.setSelectedRange(1, 0);
173
174 ca.showPossibleCompletions();
175
176 DisplayHelper.sleep(shell.getDisplay(), 300);
177
178 List<ICompletionProposal> computedProposals = getComputedProposals(ca);
179 assertEquals(1, computedProposals.size());
180 List<ICompletionProposal> filteredProposals = getFilteredProposals(ca);
181 assertEquals(1, filteredProposals.size());
182
183 new InsertEdit(0, "a").apply(document);
184 viewer.setSelectedRange(1, 0);
185
186 DisplayHelper.sleep(shell.getDisplay(), 600);
187
188 filteredProposals = getFilteredProposals(ca);
189 assertTrue(filteredProposals == null || filteredProposals.isEmpty());
190 }
191
192 /**
193 * CA with 1 immediate and 1 delayed CA processors. Empty text initially. Invoke
194 * CA, verify 1 proposal shows right away, and then another added later after
195 * delay
196 *
197 * @throws Exception exception
198 */
199 @Test
200 public void testMultipleCaProcessors() throws Exception {
201 IDocument document = viewer.getDocument();
202
203 ca.addContentAssistProcessor(new ImmediateContentAssistProcessor("xx"), IDocument.DEFAULT_CONTENT_TYPE);
204 ca.addContentAssistProcessor(new DelayedContentAssistProcessor("yy", 3000, false),
205 IDocument.DEFAULT_CONTENT_TYPE);
206
207 ca.install(viewer);
208
209 viewer.setSelectedRange(0, 0);
210
211 ca.showPossibleCompletions();
212
213 DisplayHelper.sleep(shell.getDisplay(), 300);
214
215 List<ICompletionProposal> computedProposals = getComputedProposals(ca,
216 p -> p instanceof IncompleteCompletionProposal);
217 assertEquals(1, computedProposals.size());
218 List<ICompletionProposal> filteredProposals = getFilteredProposals(ca,
219 p -> p instanceof IncompleteCompletionProposal);
220 assertEquals(1, filteredProposals.size());
221
222 DisplayHelper.sleep(shell.getDisplay(), 3000);
223
224 computedProposals = getComputedProposals(ca, p -> p instanceof IncompleteCompletionProposal);
225 assertEquals(2, computedProposals.size());
226 filteredProposals = getFilteredProposals(ca, p -> p instanceof IncompleteCompletionProposal);
227 assertEquals(2, filteredProposals.size());
228
229 ((ICompletionProposalExtension) filteredProposals.get(1)).apply(document, (char) 0,
230 viewer.getSelectedRange().x);
231 assertEquals("yy", document.get());
232 }
233
234 /**
235 * CA with 1 CA processor for which the first request takes long time and consequent request are
236 * instant. Invoke CA. and type 'a' such that completions are not ready yet, but while recompute
237 * was cancelling futures the futures from previous invocation completed and scheduled an async
238 * UI runnable to show completions. Recompute is immediate. Hence proposals shown right away.
239 * However the async UI runnable to show old proposals runs after and overwrites the correct
240 * immediate proposals. Test that this behaviour is fixed
241 *
242 * @throws Exception exception
243 */
244 @Test
245 public void testCA_WithFirstDelayedThenImmediateProposals() throws Exception {
246 IDocument document = viewer.getDocument();
247
248 ca.addContentAssistProcessor(new LongInitialContentAssistProcessor("abc", 500, true),
249 IDocument.DEFAULT_CONTENT_TYPE);
250
251 ca.install(viewer);
252
253 viewer.setSelectedRange(0, 0);
254
255 ca.showPossibleCompletions();
256
257 DisplayHelper.sleep(shell.getDisplay(), 200);
258 new InsertEdit(0, "a").apply(document);
259 viewer.setSelectedRange(1, 0);
260
261 DisplayHelper.sleep(shell.getDisplay(), 3000);
262
263 List<ICompletionProposal> filteredProposals= getFilteredProposals(ca,
264 p -> p instanceof IncompleteCompletionProposal);
265 assertTrue(filteredProposals != null);
266 assertEquals(1, filteredProposals.size());
267
268 filteredProposals.get(0).apply(document);
269
270 assertEquals("aabc", document.get());
271
272 }
273
274 /**
275 * CA with filtering with 1 immediate and 1 delayed CA processors. Empty text
276 * initially. Invoke CA, verify 1 proposal shows right away, type `a` before
277 * delayed proposal calculated, verify immediate proposal filtered out
278 *
279 * Bug: filtering only applied after all CA processors have completed
280 *
281 * @throws Exception exception
282 */
283 @Test @Ignore
284 public void testFastCompletionsNotFilteredUntilLongComplitionsCalculated() throws Exception {
285 IDocument document = viewer.getDocument();
286
287 ca.addContentAssistProcessor(new ImmediateContentAssistProcessor("xxxx"), IDocument.DEFAULT_CONTENT_TYPE);
288 ca.addContentAssistProcessor(new DelayedContentAssistProcessor("yyyy", 5000, false),
289 IDocument.DEFAULT_CONTENT_TYPE);
290
291 ca.install(viewer);
292
293 viewer.setSelectedRange(1, 0);
294
295 ca.showPossibleCompletions();
296
297 DisplayHelper.sleep(shell.getDisplay(), 300);
298
299 List<ICompletionProposal> computedProposals = getComputedProposals(ca,
300 p -> p instanceof IncompleteCompletionProposal);
301 assertEquals(1, computedProposals.size());
302 List<ICompletionProposal> filteredProposals = getFilteredProposals(ca,
303 p -> p instanceof IncompleteCompletionProposal);
304 assertEquals(1, filteredProposals.size());
305
306 new InsertEdit(0, "a").apply(document);
307 viewer.setSelectedRange(1, 0);
308
309 DisplayHelper.sleep(shell.getDisplay(), 1000);
310
311 filteredProposals = getFilteredProposals(ca, p -> p instanceof IncompleteCompletionProposal);
312 assertTrue(filteredProposals == null || filteredProposals.isEmpty());
313 }
314
315 private class ImmediateContentAssistProcessor implements IContentAssistProcessor {
316
317 final private String template;
318 final private boolean incomplete;
319
320 ImmediateContentAssistProcessor(String template) {
321 this(template, false);
322 }
323
324 ImmediateContentAssistProcessor(String template, boolean incomplete) {
325 this.template = template;
326 this.incomplete = incomplete;
327 }
328
329 @Override
330 public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int offset) {
331 try {
332 IDocument document= textViewer.getDocument();
333 if (document != null && (document.getLength() == 0 || isSubstringFoundOrderedInString(document.get(0, offset), template))) {
334 if (incomplete) {
335 return new ICompletionProposal[] {
336 new IncompleteCompletionProposal(template, offset, 0, offset, template) };
337 } else {
338 CompletionProposal proposal = new CompletionProposal(template, offset, 0, offset, template);
339 return new ICompletionProposal[] { proposal };
340 }
341 }
342 } catch (BadLocationException e) {
343 throw new IllegalStateException("Error computing proposals");
344 }
345 return new ICompletionProposal[0];
346 }
347
348 @Override
349 public IContextInformation[] computeContextInformation(ITextViewer textViewer, int offset) {
350 return new IContextInformation[0];
351 }
352
353 @Override
354 public char[] getCompletionProposalAutoActivationCharacters() {
355 return new char[0];
356 }
357
358 @Override
359 public char[] getContextInformationAutoActivationCharacters() {
360 return new char[0];
361 }
362
363 @Override
364 public String getErrorMessage() {
365 return "No proposals!";
366 }
367
368 @Override
369 public IContextInformationValidator getContextInformationValidator() {
370 return new ContextInformationValidator(this);
371 }
372
373 }
374
375 private class DelayedContentAssistProcessor extends ImmediateContentAssistProcessor {
376
377 protected long delay;
378
379 DelayedContentAssistProcessor(String template, long delay, boolean incomplete) {
380 super(template, incomplete);
381 this.delay = delay;
382 }
383
384 @Override
385 public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int offset) {
386 if (delay > 0) {
387 try {
388 Thread.sleep(delay);
389 } catch (InterruptedException e) {
390 throw new IllegalStateException("Cannot generate delayed content assist proposals!");
391 }
392 }
393 return super.computeCompletionProposals(viewer, offset);
394 }
395 }
396
397 private class LongInitialContentAssistProcessor extends DelayedContentAssistProcessor {
398
399 LongInitialContentAssistProcessor(String template, long delay, boolean incomplete) {
400 super(template, delay, incomplete);
401 }
402
403 @Override
404 public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int offset) {
405 ICompletionProposal[] completionProposals= super.computeCompletionProposals(viewer, offset);
406 delay = 0;
407 return completionProposals;
408 }
409 }
410
411 @SuppressWarnings("unchecked")
412 private static List<ICompletionProposal> getComputedProposals(ContentAssistant ca) throws Exception {
413 Field f = ContentAssistant.class.getDeclaredField("fProposalPopup");
414 f.setAccessible(true);
415 Object caPopup = f.get(ca);
416 assertEquals("org.eclipse.jface.text.contentassist.AsyncCompletionProposalPopup", caPopup.getClass().getName());
417 Class<?> caPopupSuperClass = caPopup.getClass().getSuperclass();
418 assertEquals("org.eclipse.jface.text.contentassist.CompletionProposalPopup", caPopupSuperClass.getName());
419 Field computedProposals = caPopupSuperClass.getDeclaredField("fComputedProposals");
420 computedProposals.setAccessible(true);
421 return (List<ICompletionProposal>) computedProposals.get(caPopup);
422 }
423
424 @SuppressWarnings("unchecked")
425 private static List<ICompletionProposal> getFilteredProposals(ContentAssistant ca) throws Exception {
426 Field f = ContentAssistant.class.getDeclaredField("fProposalPopup");
427 f.setAccessible(true);
428 Object caPopup = f.get(ca);
429 assertEquals("org.eclipse.jface.text.contentassist.AsyncCompletionProposalPopup", caPopup.getClass().getName());
430 Class<?> caPopupSuperClass = caPopup.getClass().getSuperclass();
431 assertEquals("org.eclipse.jface.text.contentassist.CompletionProposalPopup", caPopupSuperClass.getName());
432 Field computedProposals = caPopupSuperClass.getDeclaredField("fFilteredProposals");
433 computedProposals.setAccessible(true);
434 return (List<ICompletionProposal>) computedProposals.get(caPopup);
435 }
436
437 private static List<ICompletionProposal> getComputedProposals(ContentAssistant ca, Predicate<ICompletionProposal> p)
438 throws Exception {
439 List<ICompletionProposal> computedProposals = getComputedProposals(ca);
440 return computedProposals == null ? null : computedProposals.stream().filter(p).collect(Collectors.toList());
441 }
442
443 private static List<ICompletionProposal> getFilteredProposals(ContentAssistant ca, Predicate<ICompletionProposal> p)
444 throws Exception {
445 List<ICompletionProposal> filteredProposals = getFilteredProposals(ca);
446 return filteredProposals == null ? null : filteredProposals.stream().filter(p).collect(Collectors.toList());
447 }
448
449 private static class IncompleteCompletionProposal implements ICompletionProposal {
450
451 /** The string to be displayed in the completion proposal popup. */
452 private String fDisplayString;
453 /** The replacement string. */
454 protected String fReplacementString;
455 /** The replacement offset. */
456 protected int fReplacementOffset;
457 /** The replacement length. */
458 private int fReplacementLength;
459 /** The cursor position after this proposal has been applied. */
460 private int fCursorPosition;
461
462 public IncompleteCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, String displayString) {
463 fReplacementString= replacementString;
464 fReplacementOffset= replacementOffset;
465 fReplacementLength= replacementLength;
466 fCursorPosition= cursorPosition;
467 fDisplayString= displayString;
468 }
469
470 @Override
471 public void apply(IDocument document) {
472 try {
473 document.replace(fReplacementOffset, fReplacementLength, fReplacementString);
474 } catch (BadLocationException x) {
475 // ignore
476 }
477 }
478
479 @Override
480 public Point getSelection(IDocument document) {
481 return new Point(fReplacementOffset + fCursorPosition, 0);
482 }
483
484 @Override
485 public IContextInformation getContextInformation() {
486 return null;
487 }
488
489 @Override
490 public Image getImage() {
491 return null;
492 }
493
494 @Override
495 public String getDisplayString() {
496 if (fDisplayString != null)
497 return fDisplayString;
498 return fReplacementString;
499 }
500
501 @Override
502 public String getAdditionalProposalInfo() {
503 return null;
504 }
505 }
506
507 private static class CompletionProposal extends IncompleteCompletionProposal
508 implements ICompletionProposalExtension, ICompletionProposalExtension2 {
509
510 public CompletionProposal(String replacementString, int replacementOffset, int replacementLength,
511 int cursorPosition, String displayString) {
512 super(replacementString, replacementOffset, replacementLength, cursorPosition, displayString);
513 }
514
515 @Override
516 public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
517 apply(viewer.getDocument());
518 }
519
520 @Override
521 public void selected(ITextViewer viewer, boolean smartToggle) {
522 // nothing
523 }
524
525 @Override
526 public void unselected(ITextViewer viewer) {
527 // nothing
528 }
529
530 @Override
531 public boolean validate(IDocument document, int offset, DocumentEvent event) {
532 if (offset > fReplacementOffset) {
533 try {
534 return isSubstringFoundOrderedInString(document.get(fReplacementOffset, offset - fReplacementOffset), fReplacementString);
535 } catch (BadLocationException e) {
536 throw new IllegalStateException("Completion validation failed");
537 }
538 }
539 return false;
540 }
541
542 @Override
543 public void apply(IDocument document, char trigger, int offset) {
544 apply(document);
545 }
546
547 @Override
548 public boolean isValidFor(IDocument document, int offset) {
549 return validate(document, offset, null);
550 }
551
552 @Override
553 public char[] getTriggerCharacters() {
554 return new char[0];
555 }
556
557 @Override
558 public int getContextInformationPosition() {
559 return 0;
560 }
561
562 }
563
564 @SuppressWarnings("boxing")
565 private static boolean isSubstringFoundOrderedInString(String subString, String string) {
566 int lastIndex = 0;
567 subString = subString.toLowerCase();
568 string = string.toLowerCase();
569 for (Character c : subString.toCharArray()) {
570 int index = string.indexOf(c, lastIndex);
571 if (index < 0) {
572 return false;
573 } else {
574 lastIndex = index + 1;
575 }
576 }
577 return true;
578 }
579
580 }
4444 * Reconciler tests. Uses barrier synchronization and a call log to assert
4545 * correct order of reconciling events.
4646 *
47 * TODO test reconciler arguments (delay > 0 etc.)
48 * TODO incremental reconciler tests
49 *
5047 * @since 3.1
5148 */
49 // TODO test reconciler arguments (delay > 0 etc.)
50 // TODO incremental reconciler tests
5251 public class AbstractReconcilerTest {
5352
5453 /**
147146 @Before
148147 public void setUp() {
149148 fBarrier= new Barrier();
150 fCallLog= Collections.synchronizedList(new ArrayList<String>());
149 fCallLog= Collections.synchronizedList(new ArrayList<>());
151150 fReconciler= new AbstractReconciler() {
152151 @Override
153152 protected void initialProcess() {
178177 };
179178 fReconciler.setIsIncrementalReconciler(false);
180179 fReconciler.setDelay(50); // make tests run faster
181
180
182181 fProgressMonitor= new NullProgressMonitor();
183182 fReconciler.setProgressMonitor(fProgressMonitor);
184183
221220 assertFalse(isActive());
222221 assertFalse(isDirty());
223222 }
224
223
225224 @Test
226225 public void testDirtyingWhenClean() throws BadLocationException, InterruptedException {
227226 installDocument();
7878 int[] offsets= new int[] { 13, 26, 26, 39 };
7979 assertGetPartition_InterleavingPartitions(offsets);
8080 }
81
81
8282 @Test
8383 public void testGetPartitionEmptyStart() {
8484 fDoc.set("/* comment */docu ment");
107107 /**
108108 * The condition which has to be met in order for {@link #waitForCondition(Display, long)} to
109109 * return before the timeout elapses.
110 *
110 *
111111 * @return <code>true</code> if the condition is met, <code>false</code> if the event loop
112112 * should be driven some more
113113 */
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.search; singleton:=true
4 Bundle-Version: 3.11.700.qualifier
4 Bundle-Version: 3.11.800.qualifier
55 Bundle-Activator: org.eclipse.search.internal.ui.SearchPlugin
66 Bundle-ActivationPolicy: lazy
77 Bundle-Vendor: %providerName
+0
-23
org.eclipse.search/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2015 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.search</groupId>
19 <artifactId>org.eclipse.search</artifactId>
20 <version>3.11.700-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
269269 * Copied from {@link FindReplaceDocumentAdapter}}
270270 *
271271 * FindReplaceDocumentAdapter with contributions from:
272 * Cagatay Calli <ccalli@gmail.com> - [find/replace] retain caps when replacing - https://bugs.eclipse.org/bugs/show_bug.cgi?id=28949
273 * Cagatay Calli <ccalli@gmail.com> - [find/replace] define & fix behavior of retain caps with other escapes and text before \C - https://bugs.eclipse.org/bugs/show_bug.cgi?id=217061
272 * <ul>
273 * <li>Cagatay Calli &lt;ccalli@gmail.com&gt; - [find/replace] retain caps when replacing - https://bugs.eclipse.org/bugs/show_bug.cgi?id=28949
274 * <li>Cagatay Calli &lt;ccalli@gmail.com&gt; - [find/replace] define &amp; fix behavior of retain caps with other escapes and text before \C - https://bugs.eclipse.org/bugs/show_bug.cgi?id=217061
275 * </ul>
274276 */
275277 private static class ReplaceStringConstructor {
276278
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
127127 private SortAction fSortByPathAction;
128128
129129
130 private static final String[] SHOW_IN_TARGETS= new String[] { IPageLayout.ID_RES_NAV };
130 private static final String[] SHOW_IN_TARGETS = new String[] { IPageLayout.ID_PROJECT_EXPLORER };
131131 private static final IShowInTargetList SHOW_IN_TARGET_LIST= () -> SHOW_IN_TARGETS;
132132
133133 public FileSearchPage() {
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.search.tests
4 Bundle-Version: 3.9.400.qualifier
4 Bundle-Version: 3.9.500.qualifier
55 Bundle-Activator: org.eclipse.search.tests.SearchTestPlugin
66 Bundle-Vendor: %providerName
77 Bundle-Localization: plugin
8 Export-Package: org.eclipse.search.core.tests,
9 org.eclipse.search.tests,
10 org.eclipse.search.tests.filesearch
8 Export-Package: org.eclipse.search.core.tests;x-internal:=true,
9 org.eclipse.search.tests;x-internal:=true,
10 org.eclipse.search.tests.filesearch;x-internal:=true
1111 Require-Bundle:
1212 org.eclipse.ui;bundle-version="[3.5.0,4.0.0)",
1313 org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)",
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.search</groupId>
2020 <artifactId>org.eclipse.search.tests</artifactId>
21 <version>3.9.400-SNAPSHOT</version>
21 <version>3.9.500-SNAPSHOT</version>
2222 <packaging>eclipse-test-plugin</packaging>
2323 <properties>
2424 <testSuite>${project.artifactId}</testSuite>
1616 import java.io.File;
1717 import java.io.FileInputStream;
1818 import java.io.FileOutputStream;
19 import java.io.FileReader;
20 import java.io.FileWriter;
2119 import java.io.IOException;
2220 import java.io.InputStream;
2321 import java.io.OutputStream;
24 import java.io.Reader;
25 import java.io.Writer;
2622 import java.net.URL;
2723 import java.util.Enumeration;
2824 import java.util.zip.ZipEntry;
171167 return stateLocation.toFile();
172168 }
173169
174 public static StringBuffer read(String fileName) throws IOException {
175 return read(new FileReader(fileName));
176 }
177
178 public static StringBuffer read(Reader reader) throws IOException {
179 StringBuffer s= new StringBuffer();
180 try {
181 char[] charBuffer= new char[8196];
182 int chars= reader.read(charBuffer);
183 while (chars != -1) {
184 s.append(charBuffer, 0, chars);
185 chars= reader.read(charBuffer);
186 }
187 } finally {
188 try {
189 reader.close();
190 } catch (IOException e) {
191 }
192 }
193 return s;
194 }
195
196 public static void write(String fileName, StringBuffer content) throws IOException {
197 try (Writer writer= new FileWriter(fileName)) {
198 writer.write(content.toString());
199 }
200 }
201
202170 public static void delete(File file) {
203171 if (file.exists()) {
204172 for (int i= 0; i < MAX_RETRY; i++) {
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.text
4 Bundle-Version: 3.9.0.qualifier
4 Bundle-Version: 3.10.0.qualifier
55 Bundle-Vendor: %providerName
66 Bundle-Localization: plugin
77 Export-Package:
+0
-23
org.eclipse.text/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2015 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.text</groupId>
19 <artifactId>org.eclipse.text</artifactId>
20 <version>3.9.0-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
4545 * Combines the information of the occurrence of a line delimiter. <code>delimiterIndex</code>
4646 * is the index where a line delimiter starts, whereas <code>delimiterLength</code>,
4747 * indicates the length of the delimiter.
48 */
49 protected static class DelimiterInfo {
48 * @since 3.10
49 */
50 public static class DelimiterInfo {
5051 public int delimiterIndex;
5152 public int delimiterLength;
5253 public String delimiter;
262262 }
263263
264264 /**
265 * Substitutes \R in a regex find pattern with (?>\r\n?|\n)
265 * Substitutes \R in a regex find pattern with {@code (?>\r\n?|\n)}
266266 *
267267 * @param findString the original find pattern
268268 * @return the transformed find pattern
2222 * line delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract
2323 * implementation defines the following line scheme:
2424 * <ul>
25 * <li> "" -> [0,0]
26 * <li> "a" -> [0,1]
27 * <li> "\n" -> [0,1], [1,0]
28 * <li> "a\n" -> [0,2], [2,0]
29 * <li> "a\nb" -> [0,2], [2,1]
30 * <li> "a\nbc\n" -> [0,2], [2,3], [5,0]
25 * <li> "" -&gt; [0,0]
26 * <li> "a" -&gt; [0,1]
27 * <li> "\n" -&gt; [0,1], [1,0]
28 * <li> "a\n" -&gt; [0,2], [2,0]
29 * <li> "a\nb" -&gt; [0,2], [2,1]
30 * <li> "a\nbc\n" -&gt; [0,2], [2,3], [5,0]
3131 * </ul>
3232 * This class must be subclassed.
3333 *
1717 import java.util.List;
1818 import java.util.Map;
1919 import java.util.Objects;
20 import java.util.function.Consumer;
2021 import java.util.stream.Collectors;
2122
2223 /**
115116 // no search strings were added; return a specialized "matches nothing" matcher
116117 return new MultiStringMatcher() {
117118 @Override
118 public List<Match> find(CharSequence text, int offset) {
119 return new LinkedList<>();
119 public void find(CharSequence text, int offset, Consumer<Match> matches) {
120 return;
120121 }
121122
122123 @Override
193194
194195 Node output;
195196
197 final int depth;
198
199 Node(int depth) {
200 this.depth= depth;
201 }
202
196203 Node next(Character c) {
197204 return children == null ? null : children.get(c);
198205 }
201208 if (children == null) {
202209 children= new HashMap<>();
203210 }
204 return children.computeIfAbsent(Character.valueOf(c), key -> new Node());
211 return children.computeIfAbsent(Character.valueOf(c), key -> new Node(depth + 1));
205212 }
206213
207214 boolean hasChildren() {
210217
211218 @Override
212219 public String toString() {
213 return "Match: " + (match == null ? "null" : '>' + match + '<') //$NON-NLS-1$ //$NON-NLS-2$
214 + " Children: " + (children == null ? "<none>" : children.keySet().stream().map(c -> c.toString()).collect(Collectors.joining(", "))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
220 return "[depth=" + depth + ", match=" + match //$NON-NLS-1$ //$NON-NLS-2$
221 + ", children=" + (children == null ? "<none>" : children.keySet().stream().map(c -> c.toString()).collect(Collectors.joining(", "))) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
222 + ']';
215223 }
216224 }
217225
218226 /** Root node of the trie. */
219 private final Node root= new Node() {
227 private final Node root= new Node(0) {
220228 @Override
221229 Node next(Character c) {
222230 // Implements the sentinel loop on the root node for all non-matching characters.
250258 // s, r, and state are kept as in the paper.
251259 List<Node> queue= new LinkedList<>();
252260 for (Node s : root.children.values()) {
253 if (s.children != null) {
261 if (s.hasChildren()) {
254262 // No need to queue nodes without children since we don't do anything
255263 // with them anyway.
256264 queue.add(s);
262270 for (Map.Entry<Character, Node> entry : r.children.entrySet()) {
263271 Character c= entry.getKey();
264272 Node s= entry.getValue();
265 if (s.children != null) {
273 if (s.hasChildren()) {
266274 queue.add(s);
267275 }
268276 Node state= r.fail;
278286 }
279287 }
280288 }
289 }
290
291 /**
292 * Finds all occurrences of any of the search strings of the {@link MultiStringMatcher} in the
293 * given {@code text} starting at the given {@code offset}, including overlapping occurrences.
294 *
295 * @param text to search (not {@code null})
296 * @param offset to start searching at
297 * @param matches {@link Consumer} all matches are fed to
298 *
299 * @since 3.10
300 */
301 public void find(CharSequence text, int offset, Consumer<Match> matches) {
302 // Main search loop of the standard Aho-Corasick algorithm.
303 int textEnd= text.length();
304 Node node= root;
305 for (int i= offset; i < textEnd; i++) {
306 Character c= Character.valueOf(text.charAt(i));
307 Node next;
308 while ((next= node.next(c)) == null) {
309 node= node.fail;
310 }
311 node= next;
312 if (node.match != null) {
313 matches.accept(new MatchResult(node.match, i - node.depth + 1));
314 }
315 Node out= node.output;
316 while (out != null) {
317 matches.accept(new MatchResult(out.match, i - out.depth + 1));
318 out= out.output;
319 }
320 }
321 }
322
323 /**
324 * Finds all occurrences of any of the search strings of the {@link MultiStringMatcher} in the
325 * given {@code text} starting at the given {@code offset}, including overlapping occurrences.
326 *
327 * @param text to search (not {@code null})
328 * @param offset to start searching at
329 * @return a possibly empty list of matches
330 */
331 public List<Match> find(CharSequence text, int offset) {
332 List<Match> matches= new LinkedList<>();
333 find(text, offset, matches::add);
334 return matches;
281335 }
282336
283337 /**
320374 int textEnd= text.length();
321375 Match primaryMatch= null;
322376 Match subMatch= null;
323 boolean failover= false;
324377 Node node= root;
325378 for (int i= offset; i < textEnd; i++) {
326379 Character c= Character.valueOf(text.charAt(i));
327380 Node next= node.next(c);
328381 if (next == null) {
329 // Fell off the trie.
382 // Can't continue on this path.
330383 if (primaryMatch != null) {
331384 // Return primary match because any other match must have a higher offset.
332385 return primaryMatch;
333386 }
334 // Search for other trie to change to.
387 // Search for another path to continue matching.
335388 do {
336389 node= node.fail;
337390 } while ((next= node.next(c)) == null);
338 failover= (node != root);
339 if (!failover && subMatch != null) {
340 // We fell of the trie and could not switch to another. Return best sub-match
341 // if possible.
342 return subMatch;
391 if (subMatch != null) {
392 if (next == root) {
393 // We fell off the trie and could not switch to another. Return the best
394 // sub-match.
395 return subMatch;
396 } else if (subMatch.getOffset() < i - node.depth) {
397 // The new path starts at i - node.depth == i - next.depth + 1, so if a
398 // sub-match is earlier, we may return it. Any primary match on this path
399 // or on any other path we might switch to later on will have a higher
400 // offset, and so will any sub-matches we might discover on these paths.
401 return subMatch;
402 }
343403 }
344404 }
345405 node= next;
346406 if (node.match != null) {
347 int newOffset= i - node.match.length() + 1;
348 // On a failover trie the sub match can be better.
349 // And if it is return it because nothing better will follow.
350 if (failover && subMatch != null && subMatch.getOffset() < newOffset) {
351 return subMatch;
352 }
353407 // Any new primary match is better because all have the same offset but any new one
354 // must be longer.
355 primaryMatch= new MatchResult(node.match, newOffset);
408 // must be longer. An existing sub-match from a previous path is checked above.
409 primaryMatch= new MatchResult(node.match, i - node.depth + 1);
356410 if (!node.hasChildren()) {
357 // We will fall off the trie on the next character, so we can return right here
411 // We will fall off the trie on the next character, so we can return right here.
358412 return primaryMatch;
359413 }
360414 }
363417 if (primaryMatch == null) {
364418 Node out= node.output;
365419 if (out != null) {
366 int newOffset= i - out.match.length() + 1;
420 int newOffset= i - out.depth + 1;
367421 if (subMatch == null
368422 || newOffset < subMatch.getOffset()
369 || (newOffset == subMatch.getOffset() && out.match.length() > subMatch.getText().length())) {
423 || (newOffset == subMatch.getOffset() && out.depth > subMatch.getText().length())) {
370424 subMatch= new MatchResult(out.match, newOffset);
371425 }
372426 }
373427 }
374428 }
375429 return primaryMatch != null ? primaryMatch : subMatch;
376 }
377
378 /**
379 * Finds all occurrences of any of the search strings of the {@link MultiStringMatcher} in the
380 * given {@code text} starting at the given {@code offset}, including overlapping occurrences.
381 *
382 * @param text to search (not {@code null})
383 * @param offset to start searching at
384 * @return a possibly empty list of matches
385 */
386 public List<Match> find(CharSequence text, int offset) {
387 // Main search loop of the standard Aho-Corasick algorithm.
388 int textEnd= text.length();
389 List<Match> matches= new LinkedList<>();
390 Node node= root;
391 for (int i= offset; i < textEnd; i++) {
392 Character c= Character.valueOf(text.charAt(i));
393 Node next;
394 while ((next= node.next(c)) == null) {
395 node= node.fail;
396 }
397 node= next;
398 if (node.match != null) {
399 matches.add(new MatchResult(node.match, i - node.match.length() + 1));
400 }
401 Node out= node.output;
402 while (out != null) {
403 matches.add(new MatchResult(out.match, i - out.match.length() + 1));
404 out= out.output;
405 }
406 }
407 return matches;
408430 }
409431
410432 /**
00 /*******************************************************************************
1 * Copyright (c) 2000, 2016 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
2020 import java.util.ListIterator;
2121 import java.util.Map;
2222 import java.util.Map.Entry;
23 import java.util.Objects;
2324 import java.util.Set;
2425
2526 import org.eclipse.core.runtime.Assert;
2627
28 import org.eclipse.jface.text.AbstractLineTracker.DelimiterInfo;
2729
2830 /**
2931 * A collection of text functions.
3840 /**
3941 * Default line delimiters used by the text functions of this class.
4042 */
43 // Note: nextDelimiter implementation is sensitive to element order
4144 public final static String[] DELIMITERS= new String[] { "\n", "\r", "\r\n" }; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
4245
4346 /**
5962 * @return the line delimiter
6063 */
6164 public static String determineLineDelimiter(String text, String hint) {
62 try {
63 int[] info= indexOf(DELIMITERS, text, 0);
64 return DELIMITERS[info[1]];
65 } catch (ArrayIndexOutOfBoundsException x) {
66 }
67 return hint;
68 }
69
70 /**
71 * Returns the starting position and the index of the first matching search string
72 * in the given text that is greater than the given offset. If more than one search
73 * string matches with the same starting position then the longest one is returned.
65 String delimiter = nextDelimiter(text, 0).delimiter;
66 return delimiter != null ? delimiter : hint;
67 }
68
69 /**
70 * Returns the starting position and the index of the first matching search string in the given
71 * text that is greater than the given offset. If more than one search string matches with the
72 * same starting position then the longest one is returned.
7473 *
7574 * @param searchStrings the strings to search for
7675 * @param text the text to be searched
7776 * @param offset the offset at which to start the search
78 * @return an <code>int[]</code> with two elements where the first is the starting offset, the second the index of the found
79 * search string in the given <code>searchStrings</code> array, returns <code>[-1, -1]</code> if no match exists
80 */
77 * @return an <code>int[]</code> with two elements where the first is the starting offset, the
78 * second the index of the found search string in the given <code>searchStrings</code>
79 * array, returns <code>[-1, -1]</code> if no match exists
80 * @deprecated use {@link MultiStringMatcher#indexOf(CharSequence, int, String...)} instead.
81 * Notable differences:
82 * <ul>
83 * <li>new matcher indexOf does not allow negative offsets (old matcher treated them
84 * as <code>0</code>)</li>
85 * <li>new matcher indexOf will tolerate <code>null</code> and empty search strings
86 * (old accepted empty but throw on <code>null</code>)</li>
87 * <li>new matcher indexOf will <b>not</b> match empty string (old matched empty if
88 * nothing else matched)</li>
89 * </ul>
90 * For the common case of searching the next default {@link #DELIMITERS delimiter}
91 * use the optimized {@link #nextDelimiter(CharSequence, int)} method instead.
92 */
93 @Deprecated
8194 public static int[] indexOf(String[] searchStrings, String text, int offset) {
82
83 int[] result= { -1, -1 };
84 int zeroIndex= -1;
85
86 for (int i= 0; i < searchStrings.length; i++) {
87
88 int length= searchStrings[i].length();
89
90 if (length == 0) {
91 zeroIndex= i;
92 continue;
93 }
94
95 int index= text.indexOf(searchStrings[i], offset);
96 if (index >= 0) {
97
98 if (result[0] == -1) {
99 result[0]= index;
100 result[1]= i;
101 } else if (index < result[0]) {
102 result[0]= index;
103 result[1]= i;
104 } else if (index == result[0] && length > searchStrings[result[1]].length()) {
105 result[0]= index;
106 result[1]= i;
95 // For compatibility this will throw a NullPointerException like the old implementation
96 // (instead of an IllegalArgumentException what would be the result from MultiStringMatcher.indexOf)
97 // and mimic the strange result for empty search string match from the old method.
98 Objects.requireNonNull(searchStrings);
99 for (String searchString : searchStrings) {
100 Objects.requireNonNull(searchString);
101 }
102 if (offset < 0) {
103 offset = 0; // for compatibility with old implementation
104 }
105 final MultiStringMatcher.Match match= MultiStringMatcher.indexOf(text, offset, searchStrings);
106 if (match != null) {
107 for (int i= 0; i < searchStrings.length; i++) {
108 if (match.getText().equals(searchStrings[i])) {
109 return new int[] { match.getOffset(), i };
107110 }
108111 }
109 }
110
111 if (zeroIndex > -1 && result[0] == -1) {
112 result[0]= 0;
113 result[1]= zeroIndex;
114 }
115
116 return result;
112 } else {
113 // no match must check for empty search strings and mimic old return value
114 // search reversed because we want the last empty search string
115 for (int i= searchStrings.length - 1; i >= 0; i--) {
116 if (searchStrings[i].length() == 0) {
117 return new int[] { 0, i };
118 }
119 }
120 }
121 return new int[] { -1, -1 };
117122 }
118123
119124 /**
494499 try {
495500 lineDelimiter= document.getLineDelimiter(0);
496501 } catch (BadLocationException x) {
502 // usually impossible for the first line
497503 }
498504
499505 if (lineDelimiter != null)
575581 }
576582 return null;
577583 }
584
585 /**
586 * Search for the first standard line delimiter in text starting at given offset. Standard line
587 * delimiters are those defined in {@link #DELIMITERS}. This is a faster variant of the equal
588 *
589 * <pre>
590 * MultiStringMatcher.indexOf(TextUtilities.DELIMITERS, text, offset)
591 * </pre>
592 *
593 * @param text the text to be searched. Not <code>null</code>.
594 * @param offset the offset in text at which to start the search
595 * @return a {@link DelimiterInfo}. If no delimiter was found
596 * {@link DelimiterInfo#delimiterIndex} is <code>-1</code> and
597 * {@link DelimiterInfo#delimiter} is <code>null</code>.
598 * @since 3.10
599 */
600 public static DelimiterInfo nextDelimiter(CharSequence text, int offset) {
601 final DelimiterInfo info= new DelimiterInfo();
602 char ch;
603 final int length= text.length();
604 for (int i= offset; i < length; i++) {
605 ch= text.charAt(i);
606 if (ch == '\r') {
607 info.delimiterIndex= i;
608 if (i + 1 < length && text.charAt(i + 1) == '\n') {
609 info.delimiter= DELIMITERS[2];
610 break;
611 }
612 info.delimiter= DELIMITERS[1];
613 break;
614 } else if (ch == '\n') {
615 info.delimiterIndex= i;
616 info.delimiter= DELIMITERS[0];
617 break;
618 }
619 }
620 if (info.delimiter == null) {
621 info.delimiterIndex= -1;
622 } else {
623 info.delimiterLength= info.delimiter.length();
624 }
625 return info;
626 }
578627 }
2626 * delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract
2727 * implementation defines the following line scheme:
2828 * <ul>
29 * <li> "" -> [0,0]
30 * <li> "a" -> [0,1]
31 * <li> "\n" -> [0,1], [1,0]
32 * <li> "a\n" -> [0,2], [2,0]
33 * <li> "a\nb" -> [0,2], [2,1]
34 * <li> "a\nbc\n" -> [0,2], [2,3], [5,0]
29 * <li> "" -&gt; [0,0]
30 * <li> "a" -&gt; [0,1]
31 * <li> "\n" -&gt; [0,1], [1,0]
32 * <li> "a\n" -&gt; [0,2], [2,0]
33 * <li> "a\nb" -&gt; [0,2], [2,1]
34 * <li> "a\nbc\n" -&gt; [0,2], [2,3], [5,0]
3535 * </ul>
3636 * <p>
3737 * This class must be subclassed.
207207 * This means that for offsets smaller than the length, the following holds:
208208 * </p>
209209 * <p>
210 * <code>line.offset <= offset < line.offset + offset.length</code>.
210 * <code>line.offset &lt;= offset &lt; line.offset + offset.length</code>.
211211 * </p>
212212 * <p>
213213 * If <code>offset</code> is the document length, then this is true:
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.text.quicksearch;singleton:=true
4 Bundle-Version: 1.0.0.qualifier
4 Bundle-Version: 1.0.100.qualifier
55 Bundle-Activator: org.eclipse.text.quicksearch.internal.ui.QuickSearchActivator
66 Require-Bundle: org.eclipse.ui;bundle-version="[3.113.0,4.0.0)",
77 org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)",
1919 Export-Package: org.eclipse.text.quicksearch.internal.core;x-internal:=true,
2020 org.eclipse.text.quicksearch.internal.core.pathmatch;x-internal:=true,
2121 org.eclipse.text.quicksearch.internal.core.preferences;x-internal:=true,
22 org.eclipse.text.quicksearch.internal.core.priority;x-internal:=true,
23 org.eclipse.text.quicksearch.internal.ui;x-internal:=true,
22 org.eclipse.text.quicksearch.internal.core.priority;x-friends:="org.eclipse.text.quicksearch.tests",
23 org.eclipse.text.quicksearch.internal.ui;x-friends:="org.eclipse.text.quicksearch.tests",
2424 org.eclipse.text.quicksearch.internal.util;x-internal:=true
2525 Import-Package: org.eclipse.core.runtime;version="3.5.0",
2626 org.eclipse.core.runtime.jobs,
1414 providerName= Eclipse.org
1515 searchMenu.label= Se&arch
1616 quickSearch.label= Quick Search
17 quickSearch.ellipsis= Quick Search...
17 quickSearch.ellipsis= &Quick Search...
1818 quickSearch.tooltip=Search for a text pattern in the workspace
19 quickAccess.category.label=File content
106106 name="%quickSearch.label">
107107 </page>
108108 </extension>
109 <extension
110 point="org.eclipse.ui.quickAccess">
111 <computer
112 class="org.eclipse.text.quicksearch.internal.ui.QuickSearchQuickAccessComputer"
113 name="%quickAccess.category.label"
114 requiresUIAccess="false">
115 </computer>
116 </extension>
109117
110118 </plugin>
+0
-29
org.eclipse.text.quicksearch/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!-- Copyright (c) 2012, 2014. 2019 Eclipse Foundation and others. All rights
2 reserved. This program and the accompanying materials are made available
3 under the terms of the Eclipse Distribution License v2.0 which accompanies
4 this distribution, and is available at http://www.eclipse.org/org/documents/edl-v20.php
5
6 SPDX-License-Identifier: EPL-2.0
7
8 Contributors: Igor Fedorenko - initial implementation
9 Pivotal Inc - copy adapted for quicksearch bundle
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0"
12 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
13 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
14 <modelVersion>4.0.0</modelVersion>
15 <parent>
16 <artifactId>eclipse.platform.text</artifactId>
17 <groupId>eclipse.platform.text</groupId>
18 <version>4.13.0-SNAPSHOT</version>
19 </parent>
20 <groupId>org.eclipse.core</groupId>
21 <artifactId>org.eclipse.text.quicksearch</artifactId>
22 <version>1.0.0-SNAPSHOT</version>
23 <packaging>eclipse-plugin</packaging>
24
25 <properties>
26 <skipAPIAnalysis>true</skipAPIAnalysis> <!-- https://bugs.eclipse.org/bugs/show_bug.cgi?id=548518#c41 -->
27 </properties>
28 </project>
194194 if (isTrivial()) {
195195 return Arrays.asList();
196196 } else {
197 List<TextRange> ranges = new ArrayList<QuickTextQuery.TextRange>();
197 List<TextRange> ranges = new ArrayList<>();
198198 Matcher matcher = pattern.matcher(text);
199199 while (matcher.find()) {
200200 int start = matcher.start();
3838 * Keeps track of currently found matches. Items are added as they are found and may also
3939 * be removed when the query changed and they become invalid.
4040 */
41 private Set<LineItem> matches = new HashSet<LineItem>(2000);
41 private Set<LineItem> matches = new HashSet<>(2000);
4242
4343 /**
4444 * Scheduling rule used by Jobs that work on the matches collection.
242242 if (!query.isTrivial()) {
243243 walker.init(); //Reinitialize the walker work queue to its starting state
244244 walker.resume(); //Allow walker to resume when we release the scheduling rule.
245 } else {
246 walker.stop();
245247 }
246248 }
247249 }
305307 //Walker can be null if job was canceled because dialog closed. But stuff like
306308 //the job that shows 'Searching ...' doesn't instantly stop and may still
307309 //be asking the incremental update job whether its done.
308 return walker!=null && walker.isDone();
310 return /*(incrementalUpdate != null && incrementalUpdate.getState() != Job.NONE) ||*/ (walker!=null && walker.isDone());
309311 }
310312
311313 public void requestMoreResults() {
5858 }
5959
6060 protected void init() {
61 queue = new PriorityQueue<ResourceWalker.QItem>();
61 queue = new PriorityQueue<>();
6262 queue.add(new QItem(0, ResourcesPlugin.getWorkspace().getRoot()));
6363 }
6464
8989 }
9090
9191 /**
92 * Request that the walker stops walking at the next reasonable opportunity and drop
93 * all pending workitems. The walker cannot be resumed and must be reinitialized.
94 */
95 public void stop() {
96 this.queue = null;
97 this.suspend = false;
98 }
99
100 /**
92101 * Request the walker to be restarted... i.e. begin walking the resource tree from
93102 * the initial state.
94103 */
95104
96105 /**
97 * Request that the walker be resumed. This clears the 'supsend' state if it is set
106 * Request that the walker be resumed. This clears the 'suspend' state if it is set
98107 * and ensures that the Job is scheduled.
99108 */
100109 public void resume() {
7373 */
7474 private String[] parseStringList(String raw) {
7575 String[] elements = raw.split("[,\n]"); //$NON-NLS-1$
76 List<String> list = new ArrayList<String>(elements.length);
76 List<String> list = new ArrayList<>(elements.length);
7777 for (String e : elements) {
7878 e = e.trim();
7979 if (!e.isEmpty()) {
1111 *******************************************************************************/
1212 package org.eclipse.text.quicksearch.internal.core.priority;
1313
14 import java.net.URI;
15 import java.util.HashSet;
16 import java.util.Set;
17
1814 import org.eclipse.core.resources.IContainer;
19 import org.eclipse.core.resources.IProject;
2015 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.resources.ResourcesPlugin;
16 import org.eclipse.core.resources.IWorkspaceRoot;
17 import org.eclipse.core.runtime.IPath;
2218 import org.eclipse.text.quicksearch.internal.core.preferences.QuickSearchPreferences;
2319
2420 /**
6561 "bin", "build", "target" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
6662 };
6763
68 public Set<IResource> ignoredResources = null;
69
7064 @Override
7165 public double priority(IResource r) {
7266 if (r!=null && r.isAccessible()) {
7367 if (ignoreDerived && r.isDerived()) {
7468 return PRIORITY_IGNORE;
7569 }
76 if (ignoredResources!=null && ignoredResources.contains(r)) {
70 if (isIgnoredLinkedContainer(r)) {
7771 return PRIORITY_IGNORE;
7872 }
7973 String name = r.getName();
9892 }
9993
10094 /**
95 * We want to avoid searching the same files / folders twice in cases where users have 'overlapping projects'.
96 * I.e a project contains folders that are actually correspond to other projects also imported in the workspace.
97 * <p>
98 * See https://issuetracker.springsource.com/browse/STS-3783
99 */
100 private boolean isIgnoredLinkedContainer(IResource resource) {
101 if (!(resource instanceof IContainer) || !resource.isLinked(IResource.NONE)) {
102 return false;
103 }
104
105 IPath location = resource.getLocation();
106 if (location == null) {
107 return true;
108 }
109 IWorkspaceRoot root = resource.getWorkspace().getRoot();
110 IContainer linkTarget = root.getContainerForLocation(location);
111 return linkTarget != null;
112 }
113
114 /**
101115 * Initialize some configurable settings from an instance of QuickSearchPreferences
102116 */
103117 public void configure(QuickSearchPreferences preferences) {
113127 if (pref!=null) {
114128 this.ignoredPrefixes = pref;
115129 }
116 computeIgnoredFolders();
117130 }
118131
119 /**
120 * We want to avoid searchin the same files / folders twice in cases where users have 'overlapping projects'.
121 * I.e a project contains folders that are actually correspond to other projects also imported in the workspace.
122 * <p>
123 * See https://issuetracker.springsource.com/browse/STS-3783
124 * <p>
125 * This method computes a set of folders to ignore.
126 */
127 private void computeIgnoredFolders() {
128 //TODO: Hopefully this won't take too long to compute. Otherwise we may need to look at ways of caching it.
129 // it probably doesn't change that often.
130 IProject[] allprojects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
131 for (IProject p : allprojects) {
132 if (p.isAccessible()) {
133 URI location = p.getLocationURI();
134 if (location!=null) {
135 IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(location);
136 if (containers!=null) {
137 for (IContainer folder : containers) {
138 if (!folder.equals(p)) {
139 ignore(folder);
140 }
141 }
142 }
143 }
144 }
145 }
146 }
147
148 private void ignore(IContainer folder) {
149 if (ignoredResources==null) {
150 ignoredResources = new HashSet<IResource>();
151 }
152 ignoredResources.add(folder);
153 }
154132 }
144144 */
145145 private PrioriTree ensureChild(String segment) {
146146 if (children==null) {
147 children = new HashMap<String, PrioriTree>();
147 children = new HashMap<>();
148148 }
149149 PrioriTree child = children.get(segment);
150150 if (child==null) {
177177
178178 /**
179179 * Locate tree node corresponding to a given path.
180 * @param fullPath
180 * @param path
181181 * @return The node or null if no corresponding node exists in the tree.
182182 */
183183 private PrioriTree lookup(IPath path) {
3939 public static String QuickSearchDialog_caseInsensitive_label;
4040 public static String QuickSearchDialog_patternHint;
4141 public static String QuickTextSearch_updateMatchesJob;
42 public static String quickAccessMatch;
4243
4344 static {
4445 // initialize resource bundle
2828 import org.eclipse.ui.IEditorInput;
2929 import org.eclipse.ui.IEditorPart;
3030 import org.eclipse.ui.IEditorReference;
31 import org.eclipse.ui.ISelectionService;
3132 import org.eclipse.ui.IWorkbenchPage;
3233 import org.eclipse.ui.IWorkbenchWindow;
3334 import org.eclipse.ui.PartInitException;
9495 }
9596
9697 private Collection<IFile> getOpenFiles() {
98 if (window == null) {
99 return Collections.emptyList();
100 }
97101 try {
98102 IWorkbenchPage page = window.getActivePage();
99103 if (page!=null) {
100 Collection<IFile> files = new ArrayList<IFile>();
104 Collection<IFile> files = new ArrayList<>();
101105 IEditorReference[] editors = page.getEditorReferences();
102106 if (editors!=null) {
103107 for (IEditorReference editor : editors) {
104108 try {
105109 IEditorInput input = editor.getEditorInput();
106110 if (input!=null) {
107 IFile file = (IFile) input.getAdapter(IFile.class);
111 IFile file = input.getAdapter(IFile.class);
108112 if (file != null) {
109113 files.add(file);
110114 }
132136 * @return IFile or null if there is no current editor or the editor isn't associated to a file.
133137 */
134138 private IFile getActiveFile() {
139 if (window == null) {
140 return null;
141 }
135142 IWorkbenchPage page = window.getActivePage();
136143 if (page!=null) {
137144 IEditorPart editor = page.getActiveEditor();
138145 if (editor!=null) {
139146 IEditorInput input = editor.getEditorInput();
140147 if (input!=null) {
141 return (IFile) input.getAdapter(IFile.class);
148 return input.getAdapter(IFile.class);
142149 }
143150 }
144151 }
150157 * a Structured selection (e.g. in navigator or project/package explorer)
151158 */
152159 private Collection<IResource> getSelectedResources() {
153 ISelection _s = window.getSelectionService().getSelection();
154 if (_s!=null && _s instanceof IStructuredSelection) {
155 IStructuredSelection s = (IStructuredSelection) _s;
156 if (s!=null && !s.isEmpty()) {
157 Object[] elements = s.toArray();
158 List<IResource> resources = new ArrayList<IResource>(elements.length);
160 if (window == null) {
161 return Collections.emptyList();
162 }
163 ISelectionService selectionService = window.getSelectionService();
164 ISelection selection = selectionService.getSelection();
165 if (selection instanceof IStructuredSelection) {
166 IStructuredSelection structuredSelection = (IStructuredSelection) selection;
167 if (!structuredSelection.isEmpty()) {
168 Object[] elements = structuredSelection.toArray();
169 List<IResource> resources = new ArrayList<>(elements.length);
159170 for (Object e : elements) {
160171 if (e instanceof IResource) {
161172 resources.add((IResource) e);
162173 } else if (e instanceof IAdaptable) {
163174 IAdaptable ae = (IAdaptable) e;
164 IResource r = (IResource) ae.getAdapter(IResource.class);
175 IResource r = ae.getAdapter(IResource.class);
165176 if (r!=null) {
166177 resources.add(r);
167178 }
8585 import org.eclipse.swt.events.TraverseEvent;
8686 import org.eclipse.swt.events.TraverseListener;
8787 import org.eclipse.swt.graphics.Color;
88 import org.eclipse.swt.graphics.FontMetrics;
89 import org.eclipse.swt.graphics.GC;
9088 import org.eclipse.swt.graphics.Image;
9189 import org.eclipse.swt.graphics.Point;
9290 import org.eclipse.swt.graphics.Rectangle;
196194 public IStatus runInUIThread(IProgressMonitor mon) {
197195 if (!mon.isCanceled() && progressLabel!=null && !progressLabel.isDisposed()) {
198196 if (searcher==null || !searcher.isActive()) {
199 progressLabel.setText(""); //$NON-NLS-1$
197 progressLabel.setText(EMPTY_STRING);
200198 } else {
201199 progressLabel.setText(NLS.bind(Messages.QuickSearchDialog_searching, currentFileInfo(searcher.getCurrentFile(), animate)));
202200 animate = (animate+1)%4;
232230 cell.setText(text.getString());
233231 cell.setStyleRanges(text.getStyleRanges());
234232 } else {
235 cell.setText(""); //$NON-NLS-1$
233 cell.setText(EMPTY_STRING);
236234 cell.setStyleRanges(null);
237235 }
238236 cell.setImage(getBlankImage());
270268 };
271269 cell.setStyleRanges(styleRanges);
272270 } else {
273 cell.setText(""); //$NON-NLS-1$
271 cell.setText(EMPTY_STRING);
274272 cell.setStyleRanges(null);
275273 }
276274 cell.setImage(getBlankImage());
419417 if (initialPatternText==null) {
420418 String lastSearch = settings.get(DIALOG_LAST_QUERY);
421419 if (lastSearch==null) {
422 lastSearch = ""; //$NON-NLS-1$
420 lastSearch = EMPTY_STRING;
423421 }
424422 pattern.setText(lastSearch);
425 pattern.setSelection(0, lastSearch.length());
423 pattern.selectAll();
426424 }
427425 if (settings.get(DIALOG_PATH_FILTER)!=null) {
428426 String filter = settings.get(DIALOG_PATH_FILTER);
904902 pattern.setSelection(0, 0);
905903 break;
906904 case FULL_SELECTION:
907 pattern.setSelection(0, initialPatternText.length());
905 pattern.selectAll();
908906 break;
909907 }
910908
937935 }
938936
939937 private void createDetailsArea(Composite parent) {
940 details = new StyledText(parent, SWT.MULTI+SWT.READ_ONLY+SWT.BORDER+SWT.H_SCROLL);
938 details = new StyledText(parent, SWT.MULTI+SWT.READ_ONLY+SWT.BORDER+SWT.H_SCROLL+SWT.V_SCROLL);
941939 details.setFont(JFaceResources.getFont(TEXT_FONT));
942940
943941 list.addSelectionChangedListener(new ISelectionChangedListener() {
962960 }
963961 IStructuredSelection sel = (IStructuredSelection) list.getSelection();
964962 if (sel==null || sel.isEmpty()) {
965 details.setText(""); //$NON-NLS-1$
963 details.setText(EMPTY_STRING);
966964 } else {
967965 //Not empty selection
966 final int context = 100; // number of lines before and after match to include in preview
968967 int numLines = computeLines();
969968 if (numLines > 0) {
970969 LineItem item = (LineItem) sel.getFirstElement();
972971 if (document!=null) {
973972 try {
974973 int line = item.getLineNumber()-1; //in document lines are 0 based. In search 1 based.
975 int start = document.getLineOffset(Math.max(line-(numLines-1)/2, 0));
974 int contextStartLine = Math.max(line-(numLines-1)/2 - context, 0);
975 int start = document.getLineOffset(contextStartLine);
976976 int end = document.getLength();
977977 try {
978 IRegion lineInfo = document.getLineInformation(line + numLines/2);
978 IRegion lineInfo = document.getLineInformation(line + numLines/2 + context);
979979 end = lineInfo.getOffset() + lineInfo.getLength();
980980 } catch (BadLocationException e) {
981981 //Presumably line number is past the end of document.
985985 StyledString styledString = highlightMatches(document.get(start, end-start));
986986 details.setText(styledString.getString());
987987 details.setStyleRanges(styledString.getStyleRanges());
988
988 details.setTopIndex(Math.max(line - contextStartLine - numLines/2, 0));
989989 return;
990990 } catch (BadLocationException e) {
991991 }
993993 }
994994 }
995995 //empty selection or some error:
996 details.setText(""); //$NON-NLS-1$
997 }
998 }
999
1000 /**
1001 * Computes how much lines of text can be displayed in the details section based on
1002 * its current height and font metrics.
996 details.setText(EMPTY_STRING);
997 }
998 }
999
1000 /**
1001 * Computes how many lines of text can be displayed in the details section.
10031002 */
10041003 private int computeLines() {
10051004 if (details!=null && !details.isDisposed()) {
1006 GC gc = new GC(details);
1007 try {
1008 FontMetrics fm = gc.getFontMetrics();
1009 int itemH = fm.getHeight();
1010 int areaH = details.getClientArea().height;
1011 return (areaH+itemH-1) / itemH;
1012 } finally {
1013 gc.dispose();
1014 }
1005 int lineHeight = details.getLineHeight();
1006 int areaHeight = details.getClientArea().height;
1007 return (areaHeight + lineHeight - 1) / lineHeight;
10151008 }
10161009 return 0;
10171010 }
0 /*******************************************************************************
1 * Copyright (c) 2019 Red Hat Inc.
2 * All rights reserved. This program and the accompanying materials
3 * are made available under the terms of the Eclipse Public License v2.0
4 * which accompanies this distribution, and is available at
5 * https://www.eclipse.org/legal/epl-2.0/
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9 package org.eclipse.text.quicksearch.internal.ui;
10
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.jface.resource.ImageDescriptor;
17 import org.eclipse.jface.text.TextSelection;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.text.quicksearch.internal.core.LineItem;
20 import org.eclipse.text.quicksearch.internal.core.QuickTextQuery;
21 import org.eclipse.text.quicksearch.internal.core.QuickTextSearchRequestor;
22 import org.eclipse.text.quicksearch.internal.core.QuickTextSearcher;
23 import org.eclipse.text.quicksearch.internal.core.priority.PriorityFunction;
24 import org.eclipse.ui.IEditorPart;
25 import org.eclipse.ui.PartInitException;
26 import org.eclipse.ui.PlatformUI;
27 import org.eclipse.ui.ide.IDE;
28 import org.eclipse.ui.quickaccess.IQuickAccessComputer;
29 import org.eclipse.ui.quickaccess.IQuickAccessComputerExtension;
30 import org.eclipse.ui.quickaccess.QuickAccessElement;
31 import org.eclipse.ui.texteditor.ITextEditor;
32
33 public class QuickSearchQuickAccessComputer extends QuickTextSearchRequestor implements IQuickAccessComputer, IQuickAccessComputerExtension {
34
35 private static final int MAX_ENTRIES = 20;
36 private static final long TIMEOUT = 200;
37 private PriorityFunction priorities;
38
39 public QuickSearchQuickAccessComputer() {
40 priorities = new QuickSearchContext(PlatformUI.getWorkbench().getActiveWorkbenchWindow()).createPriorityFun();
41 }
42
43 @Override public QuickAccessElement[] computeElements(String query, IProgressMonitor monitor) {
44 List<LineItem> matches = Collections.synchronizedList(new ArrayList<>());
45 QuickTextSearcher searcher = new QuickTextSearcher(new QuickTextQuery("", false), priorities, 100, new QuickTextSearchRequestor() { //$NON-NLS-1$
46 @Override public void add(LineItem match) {
47 matches.add(match);
48 }
49
50 @Override public void clear() {
51 matches.clear();
52 }
53
54 @Override public void revoke(LineItem line) {
55 matches.remove(line);
56 }
57 });
58 searcher.setMaxResults(MAX_ENTRIES);
59 searcher.setQuery(new QuickTextQuery(query, false), true);
60 long start = System.currentTimeMillis();
61 while (matches.size() < 20 && !searcher.isDone() && System.currentTimeMillis() - start < TIMEOUT) {
62 try {
63 Thread.sleep(100);
64 } catch (InterruptedException e) {
65 QuickSearchActivator.log(e);
66 }
67 }
68 searcher.cancel();
69 return matches.stream().map(LineItemQuickAccessElement::new).toArray(QuickAccessElement[]::new);
70 }
71
72 @Override public QuickAccessElement[] computeElements() {
73 return new QuickAccessElement[0];
74 }
75
76 @Override public void resetState() {
77 // stateless
78
79 }
80
81 @Override public boolean needsRefresh() {
82 return false;
83 }
84
85 private class LineItemQuickAccessElement extends QuickAccessElement {
86
87 private final LineItem item;
88
89 public LineItemQuickAccessElement(LineItem item) {
90 this.item = item;
91 }
92
93 @Override public String getLabel() {
94 return NLS.bind(Messages.quickAccessMatch, item.getText(), item.getFile().getName());
95 }
96
97 @Override public ImageDescriptor getImageDescriptor() {
98 return null;
99 }
100
101 @Override public String getId() {
102 return item.getFile().getFullPath().toString() + '[' + item.getOffset() + ':' + (item.getOffset() + item.getText().length() - 1) + ']';
103 }
104
105 @Override public void execute() {
106 IEditorPart part;
107 try {
108 part = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), item.getFile());
109 if (part instanceof ITextEditor) {
110 ((ITextEditor) part).getSelectionProvider().setSelection(new TextSelection(item.getOffset(), item.getText().length()));
111 }
112 } catch (PartInitException e) {
113 QuickSearchActivator.log(e);
114 }
115 }
116
117 }
118
119 }
77 QuickSearchPreferencesPage_Ignored_Names=Ignored Names
88 QuickSearchDialog_Open=&Open
99 QuickSearchDialog_Refresh=&Refresh
10 QuickSearchDialog_In=in:
10 QuickSearchDialog_In=&in:
1111 QuickSearchDialog_InTooltip=Search in (comma-separated list of '.gitignore' style inclusion patterns)
1212 QuickSearchDialog_line=Line
1313 QuickSearchDialog_text=Text
1919 QuickSearchDialog_title=Quick Search
2020 QuickSearchDialog_caseSensitive_label=Case SENSITIVE
2121 QuickSearchDialog_caseInsensitive_label=Case INSENSITIVE
22 QuickSearchDialog_patternHint=Pattern (? = any character, * = any string)
23 QuickTextSearch_updateMatchesJob=Update matches
22 QuickSearchDialog_patternHint=&Pattern (? = any character, * = any string)
23 QuickTextSearch_updateMatchesJob=Update matches
24 quickAccessMatch=`{0}` in {1}
00 /*******************************************************************************
1 * Copyright (c) 2000, 2008, 2013-2019 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 * All rights reserved. This program and the accompanying materials
33 * are made available under the terms of the Eclipse Public License v2.0
44 * which accompanies this distribution, and is available at
2525 import org.eclipse.core.runtime.IPath;
2626 import org.eclipse.core.runtime.NullProgressMonitor;
2727 import org.eclipse.jface.text.IDocument;
28 import org.eclipse.search.internal.ui.SearchPlugin;
2928 import org.eclipse.text.quicksearch.internal.ui.QuickSearchActivator;
3029 import org.eclipse.ui.IEditorInput;
3130 import org.eclipse.ui.IEditorPart;
4847 *
4948 * @author Kris De Volder
5049 */
51 @SuppressWarnings("restriction")
5250 public class DocumentFetcher {
5351
5452 private Map<IFile, IDocument> dirtyEditors;
133131 * @return returns a map from IFile to IDocument for all open, dirty editors.
134132 */
135133 private Map<IFile, IDocument> evalNonFileBufferDocuments() {
136 Map<IFile, IDocument> result= new HashMap<IFile, IDocument>();
137 IWorkbench workbench= SearchPlugin.getDefault().getWorkbench();
134 Map<IFile, IDocument> result= new HashMap<>();
135 IWorkbench workbench= PlatformUI.getWorkbench();
138136 IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
139137 for (int i= 0; i < windows.length; i++) {
140138 IWorkbenchPage[] pages= windows[i].getPages();
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.text.quicksearch.tests
4 Bundle-Version: 1.0.0.qualifier
4 Bundle-Version: 1.0.100.qualifier
55 Require-Bundle: org.eclipse.core.runtime,
66 org.eclipse.text.quicksearch,
77 org.eclipse.core.resources,
1818 <parent>
1919 <artifactId>tests-pom</artifactId>
2020 <groupId>eclipse.platform.text</groupId>
21 <version>4.13.0-SNAPSHOT</version>
21 <version>4.14.0-SNAPSHOT</version>
2222 <relativePath>../tests-pom/</relativePath>
2323 </parent>
2424 <groupId>org.eclipse.text</groupId>
2525 <artifactId>org.eclipse.text.quicksearch.tests</artifactId>
26 <version>1.0.0-SNAPSHOT</version>
26 <version>1.0.100-SNAPSHOT</version>
2727 <packaging>eclipse-test-plugin</packaging>
2828 <properties>
2929 <testSuite>${project.artifactId}</testSuite>
0 /*******************************************************************************
1 * Copyright (c) 2019 Julian Honnen
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Julian Honnen <julian.honnen@vector.com> - initial API and implementation
12 *******************************************************************************/
13 package org.eclipse.text.quicksearch.tests;
14
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertNotEquals;
17
18 import org.eclipse.core.resources.IFolder;
19 import org.eclipse.core.resources.IProject;
20 import org.eclipse.core.resources.IWorkspaceRoot;
21 import org.eclipse.core.resources.ResourcesPlugin;
22 import org.eclipse.text.quicksearch.internal.core.priority.DefaultPriorityFunction;
23 import org.eclipse.text.quicksearch.internal.core.priority.PriorityFunction;
24 import org.eclipse.text.quicksearch.internal.ui.QuickSearchActivator;
25 import org.junit.Before;
26 import org.junit.Test;
27
28 public class DefaultPriorityFunctionTest {
29
30 private DefaultPriorityFunction fPriorityFunction;
31
32 @Before
33 public void setup() {
34 fPriorityFunction = new DefaultPriorityFunction();
35 fPriorityFunction.configure(QuickSearchActivator.getDefault().getPreferences());
36 }
37
38 @Test
39 public void testIgnoreLinkedContainers() throws Exception {
40 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
41 IProject p1 = root.getProject("p1");
42 p1.create(null);
43 p1.open(null);
44 IProject p2 = root.getProject("p2");
45 p2.create(null);
46 p2.open(null);
47
48 IFolder f1 = p1.getFolder("f1");
49 f1.create(true, true, null);
50
51 IFolder linkedp1 = p2.getFolder("p1");
52 linkedp1.createLink(p1.getLocationURI(), 0, null);
53
54 IFolder linkedF1 = p2.getFolder("f1");
55 linkedF1.createLink(f1.getLocationURI(), 0, null);
56
57 assertEquals(PriorityFunction.PRIORITY_IGNORE, fPriorityFunction.priority(linkedp1), 1.0);
58 assertNotEquals(PriorityFunction.PRIORITY_IGNORE, fPriorityFunction.priority(p1), 1.0);
59 assertEquals(PriorityFunction.PRIORITY_IGNORE, fPriorityFunction.priority(linkedF1), 1.0);
60 assertNotEquals(PriorityFunction.PRIORITY_IGNORE, fPriorityFunction.priority(f1), 1.0);
61 }
62
63 }
0 Manifest-Version: 1.0
1 Bundle-ManifestVersion: 2
2 Bundle-Name: %Plugin.name
3 Bundle-SymbolicName: org.eclipse.text.tests
4 Bundle-Version: 3.12.300.qualifier
5 Bundle-Vendor: %Plugin.providerName
6 Bundle-Localization: plugin
7 Export-Package:
8 org.eclipse.text.tests,
9 org.eclipse.text.tests.link,
10 org.eclipse.text.tests.templates
11 Require-Bundle:
12 org.eclipse.core.commands;bundle-version="[3.5.0,4.0.0)",
13 org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
14 org.eclipse.text;bundle-version="[3.6.3,4.0.0)",
15 org.junit;bundle-version="4.12.0"
16 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
17 Eclipse-BundleShape: dir
18 Import-Package: com.ibm.icu.text,
19 com.ibm.icu.util
20 Automatic-Module-Name: org.eclipse.text.tests
0 Manifest-Version: 1.0
1 Bundle-ManifestVersion: 2
2 Bundle-Name: %Plugin.name
3 Bundle-SymbolicName: org.eclipse.text.tests
4 Bundle-Version: 3.12.400.qualifier
5 Bundle-Vendor: %Plugin.providerName
6 Bundle-Localization: plugin
7 Export-Package:
8 org.eclipse.text.tests,
9 org.eclipse.text.tests.link,
10 org.eclipse.text.tests.templates
11 Require-Bundle:
12 org.eclipse.core.commands;bundle-version="[3.5.0,4.0.0)",
13 org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
14 org.eclipse.text;bundle-version="[3.6.3,4.0.0)",
15 org.junit;bundle-version="4.12.0"
16 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
17 Eclipse-BundleShape: dir
18 Import-Package: com.ibm.icu.text,
19 com.ibm.icu.util
20 Automatic-Module-Name: org.eclipse.text.tests
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.text</groupId>
2020 <artifactId>org.eclipse.text.tests</artifactId>
21 <version>3.12.300-SNAPSHOT</version>
21 <version>3.12.400-SNAPSHOT</version>
2222 <packaging>eclipse-test-plugin</packaging>
2323 <properties>
2424 <testSuite>${project.artifactId}</testSuite>
2929 public ExpectedException thrown = ExpectedException.none();
3030
3131 private static Match run(String text, String... needles) {
32 return MultiStringMatcher.indexOf(text, 0, needles);
32 return run(text, 0, needles);
3333 }
3434
3535 private static Match run(String text, int offset, String... needles) {
36 return MultiStringMatcher.indexOf(text, offset, needles);
36 return run(new TestCharSequence(text), offset, needles);
37 }
38
39 private static Match run(TestCharSequence text, int offset, String... needles) {
40 Match result = MultiStringMatcher.indexOf(text, offset, needles);
41 assertEquals("Algorithm backtracked", 0, text.getBackTrack());
42 return result;
3743 }
3844
3945 private static void test(Match m, String expected, int index) {
448454 thrown.expect(IllegalStateException.class);
449455 b.build();
450456 }
457
458 @Test
459 public void scan001() throws Exception {
460 TestCharSequence text = new TestCharSequence("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
461 Match m = run(text, 0, "x", "xx", "xxx", "xxxx");
462 test(m, "xxxx", 0);
463 assertEquals("Scanned too far", 3, text.getLastIndex());
464 }
465
466 @Test
467 public void scan002() throws Exception {
468 TestCharSequence text = new TestCharSequence("ddcababababababcabxdd");
469 Match m = run(text, 0, "ca", "cabx", "ababc");
470 test(m, "ca", 2);
471 assertEquals("Scanned too far", 5, text.getLastIndex());
472 }
473
474 @Test
475 public void scan003() throws Exception {
476 TestCharSequence text = new TestCharSequence("ddcabarbarazz");
477 Match m = run(text, 0, "a", "cabby", "barbara");
478 test(m, "a", 3);
479 assertEquals("Scanned too far", 5, text.getLastIndex());
480 }
481
482 private static class TestCharSequence implements CharSequence {
483
484 private final String value;
485
486 private int lastIndex = -1;
487
488 private int backtrack = 0;
489
490 public TestCharSequence(String value) {
491 this.value = value;
492 }
493
494 @Override
495 public int length() {
496 return value.length();
497 }
498
499 @Override
500 public char charAt(int index) {
501 if (index < lastIndex) {
502 backtrack = Math.min(backtrack, index - lastIndex);
503 }
504 lastIndex = index;
505 return value.charAt(index);
506 }
507
508 @Override
509 public CharSequence subSequence(int start, int end) {
510 throw new UnsupportedOperationException();
511 }
512
513 public int getLastIndex() {
514 return lastIndex;
515 }
516
517 public int getBackTrack() {
518 return backtrack;
519 }
520 }
451521 }
00 /*******************************************************************************
1 * Copyright (c) 2000, 2013 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
1414
1515 import static org.junit.Assert.assertEquals;
1616 import static org.junit.Assert.assertFalse;
17 import static org.junit.Assert.fail;
1718
1819 import java.util.ArrayList;
1920 import java.util.Iterator;
2223 import org.junit.Assert;
2324 import org.junit.Test;
2425
26 import org.eclipse.jface.text.AbstractLineTracker.DelimiterInfo;
2527 import org.eclipse.jface.text.BadLocationException;
2628 import org.eclipse.jface.text.Document;
2729 import org.eclipse.jface.text.DocumentEvent;
4345
4446 private final class DocumentListener implements IDocumentListener {
4547 @Override
46 public void documentAboutToBeChanged(DocumentEvent event) {}
48 public void documentAboutToBeChanged(DocumentEvent event) { /* not used */ }
4749 @Override
4850 public void documentChanged(DocumentEvent event) {
4951 fEvents.add(event);
9395
9496 private final class DocumentListener implements IDocumentListener {
9597 @Override
96 public void documentAboutToBeChanged(DocumentEvent event) {}
98 public void documentAboutToBeChanged(DocumentEvent event) { /* not used */ }
9799 @Override
98100 public void documentChanged(DocumentEvent event) {
99101 event= new DocumentEvent(event.getDocument(), event.getOffset(), event.getLength(), event.getText());
137139 }
138140
139141
140 /**
141 * Constructor for UtilitiesTest.
142 *
143 * @param name the name
144 */
145142 private static DocumentEvent createRandomEvent(IDocument document, int maxLength, char character) {
146143
147144 int index0= (int) (Math.random() * (maxLength + 1));
280277 }
281278
282279 @Test
280 @SuppressWarnings("deprecation")
283281 public void testIndexOf() {
284282 int[] result;
285 result= TextUtilities.indexOf(new String[] {"a", "ab", "abc"}, "xxxxxxxxxx", 0);
283 result = TextUtilities.indexOf(new String[0], "xxxxxxxxxx", 0);
286284 assertEquals(-1, result[0]);
287285 assertEquals(-1, result[1]);
288286
289 result= TextUtilities.indexOf(new String[] {"a", "ab", "abc"}, "foobarabcd", 0);
287 result = TextUtilities.indexOf(new String[] { "a", "ab", "abc" }, "xxxxxxxxxx", 0);
288 assertEquals(-1, result[0]);
289 assertEquals(-1, result[1]);
290
291 result = TextUtilities.indexOf(new String[] { "a", "ab", "abc" }, "foobarabcd", 0);
290292 assertEquals(4, result[0]);
291293 assertEquals(0, result[1]);
292 }
293
294
295 result = TextUtilities.indexOf(new String[] { "ab", "ab" }, "foobarabcd", 0);
296 assertEquals(6, result[0]);
297 assertEquals(0, result[1]);
298
299 result = TextUtilities.indexOf(new String[] { "", "ab", "abc" }, "foobarabcd", 0);
300 assertEquals(6, result[0]);
301 assertEquals(2, result[1]);
302
303 result = TextUtilities.indexOf(new String[] { "arac", "", "fuu" }, "foobarabcd", 0);
304 assertEquals(0, result[0]);
305 assertEquals(1, result[1]);
306
307 result = TextUtilities.indexOf(new String[] { "", "" }, "foobarabcd", 0);
308 assertEquals(0, result[0]);
309 assertEquals(1, result[1]);
310
311 result = TextUtilities.indexOf(new String[] { "" }, "foobarabcd", 5);
312 // looks strange that searching from offset 5 returns match offset 0 but that is
313 // how it was implemented
314 assertEquals(0, result[0]);
315 assertEquals(0, result[1]);
316
317 result = TextUtilities.indexOf(new String[] { "abc" }, "foobarabcd", -5);
318 assertEquals(6, result[0]);
319 assertEquals(0, result[1]);
320
321 result = TextUtilities.indexOf(new String[] { "abc" }, "foobarabcd", 20);
322 assertEquals(-1, result[0]);
323 assertEquals(-1, result[1]);
324
325 try {
326 TextUtilities.indexOf(null, "foobarabcd", 0);
327 fail("Exception not thrown");
328 } catch (NullPointerException ex) {
329 // expected
330 }
331
332 try {
333 TextUtilities.indexOf(new String[] { "abc", null }, "foobarabcd", 0);
334 fail("Exception not thrown");
335 } catch (NullPointerException ex) {
336 // expected
337 }
338
339 try {
340 TextUtilities.indexOf(new String[] { "abc" }, null, 0);
341 fail("Exception not thrown");
342 } catch (NullPointerException ex) {
343 // expected
344 }
345 }
346
347 @Test
348 public void testNextDelimiter() {
349 DelimiterInfo result;
350 result = TextUtilities.nextDelimiter("abc\ndef", 0);
351 assertEquals(3, result.delimiterIndex);
352 assertEquals("\n", result.delimiter);
353
354 result = TextUtilities.nextDelimiter("abc\ndef", 5);
355 assertEquals(-1, result.delimiterIndex);
356 assertEquals(null, result.delimiter);
357
358 result = TextUtilities.nextDelimiter("abc\rdef\n123", 0);
359 assertEquals(3, result.delimiterIndex);
360 assertEquals("\r", result.delimiter);
361
362 result = TextUtilities.nextDelimiter("abc+\r\ndef\n123", 0);
363 assertEquals(4, result.delimiterIndex);
364 assertEquals("\r\n", result.delimiter);
365
366 result = TextUtilities.nextDelimiter("abc~>\r\r\ndef\n123", 0);
367 assertEquals(5, result.delimiterIndex);
368 assertEquals("\r", result.delimiter);
369
370 result = TextUtilities.nextDelimiter("\nabc~>\r\r\ndef\n123", 0);
371 assertEquals(0, result.delimiterIndex);
372 assertEquals("\n", result.delimiter);
373
374 result = TextUtilities.nextDelimiter("abc~>123\r\n", 0);
375 assertEquals(8, result.delimiterIndex);
376 assertEquals("\r\n", result.delimiter);
377
378 result = TextUtilities.nextDelimiter("abc~>\r\r\ndef\n123", 9);
379 assertEquals(11, result.delimiterIndex);
380 assertEquals("\n", result.delimiter);
381
382 result = TextUtilities.nextDelimiter("", 0);
383 assertEquals(-1, result.delimiterIndex);
384 assertEquals(null, result.delimiter);
385
386 result = TextUtilities.nextDelimiter("abc123", 0);
387 assertEquals(-1, result.delimiterIndex);
388 assertEquals(null, result.delimiter);
389 }
294390 }
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.ui.editors; singleton:=true
4 Bundle-Version: 3.12.0.qualifier
4 Bundle-Version: 3.13.0.qualifier
55 Bundle-Activator: org.eclipse.ui.internal.editors.text.EditorsPlugin
66 Bundle-ActivationPolicy: lazy
77 Bundle-Vendor: %providerName
1111 org.eclipse.ui.editors.text.templates,
1212 org.eclipse.ui.internal.editors.quickdiff;x-internal:=true,
1313 org.eclipse.ui.internal.editors.text;x-internal:=true,
14 org.eclipse.ui.internal.editors.text.codemining.annotation;x-internal:=true,
1415 org.eclipse.ui.internal.texteditor;x-internal:=true,
1516 org.eclipse.ui.texteditor
1617 Require-Bundle:
2021 org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)",
2122 org.eclipse.ui;bundle-version="[3.5.0,4.0.0)",
2223 org.eclipse.jface.text;bundle-version="[3.8.0,4.0.0)",
23 org.eclipse.ui.workbench.texteditor;bundle-version="[3.13.0,4.0.0)",
24 org.eclipse.ui.workbench;bundle-version="[3.117.0,4.0.0)",
25 org.eclipse.ui.workbench.texteditor;bundle-version="[3.14.0,4.0.0)",
2426 org.eclipse.core.filebuffers;visibility:=reexport;bundle-version="[3.5.0,4.0.0)",
2527 org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
26 org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)"
28 org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)",
29 org.eclipse.jdt.annotation;bundle-version="2.2";resolution:=optional
2730 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
2831 Import-Package: com.ibm.icu.text
2932 Automatic-Module-Name: org.eclipse.ui.editors
119119 preferenceKeywords.tabWidth= tab width
120120 preferenceKeywords.lineNumber= line numbers
121121 preferenceKeywords.printMargin= print margin
122 preferenceKeywords.annotationCodeMining= annotation code mining marker error warning info
122123 preferenceKeywords.annotations= annotations vertical ruler overview colors text editor
123124 preferenceKeywords.quickdiff= quick diff compare reference colors text editor changes
124125 preferenceKeywords.accessibility= accessibility caret cursor quick diff text editor ruler
226226 <keywordReference id="org.eclipse.ui.editors.tabWidth"/>
227227 <keywordReference id="org.eclipse.ui.editors.lineNumber"/>
228228 <keywordReference id="org.eclipse.ui.editors.printMargin"/>
229 <keywordReference id="org.eclipse.ui.editors.annotationCodeMining"/>
229230 </page>
230231 <page
231232 name="%PreferencePages.Annotations"
285286 <keyword
286287 label="%preferenceKeywords.printMargin"
287288 id="org.eclipse.ui.editors.printMargin"/>
289 <keyword
290 label="%preferenceKeywords.annotationCodeMining"
291 id="org.eclipse.ui.editors.annotationCodeMining"/>
288292 <keyword
289293 label="%preferenceKeywords.annotations"
290294 id="org.eclipse.ui.editors.annotations"/>
10621066
10631067 </extension>
10641068
1069 <extension
1070 point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
1071 <codeMiningProvider
1072 class="org.eclipse.ui.internal.editors.text.codemining.annotation.AnnotationCodeMiningProvider"
1073 id="org.eclipse.ui.internal.editors.annotationCodeMiningProvider">
1074 <enabledWhen>
1075 <with
1076 variable="editorInput">
1077 <adapt
1078 type="org.eclipse.core.resources.IFile">
1079 <test
1080 property="org.eclipse.core.resources.contentTypeId"
1081 value="org.eclipse.core.runtime.text"
1082 args="kindOf">
1083 </test>
1084 </adapt>
1085 </with>
1086 </enabledWhen>
1087 </codeMiningProvider>
1088 </extension>
10651089 </plugin>
+0
-23
org.eclipse.ui.editors/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2015 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.ui</groupId>
19 <artifactId>org.eclipse.ui.editors</artifactId>
20 <version>3.12.0-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
9898 }
9999 }
100100 };
101
101
102102 prefs.addPreferenceChangeListener(fPreferenceChangeListener);
103103 }
104104
9292 * To access the general preference from another plug-in use a
9393 * {@link org.eclipse.ui.texteditor.ChainedPreferenceStore}:
9494 * </p>
95 *
95 *
9696 * <pre>
9797 * List stores= new ArrayList(3);
9898 * stores.add(YourPlugin.getDefault().getPreferenceStore());
117117 * To access the general preference from another plug-in use a
118118 * {@link org.eclipse.ui.texteditor.ChainedPreferenceStore}:
119119 * </p>
120 *
120 *
121121 * <pre>
122122 * List stores= new ArrayList(3);
123123 * stores.add(YourPlugin.getDefault().getPreferenceStore());
145145
146146 /**
147147 * Returns the preferences of this plug-in.
148 *
148 *
149149 * @return the plug-in preferences
150150 * @see org.eclipse.core.runtime.Plugin#getPluginPreferences()
151151 * @deprecated As of 3.5, replaced by {@link #getPreferenceStore()}
4747
4848 /**
4949 * Action group for encoding actions.
50 *
50 *
5151 * @since 2.0
5252 * @deprecated As of 3.1, encoding needs to be changed via properties dialog. This class is planned
5353 * for removal after March 2021 (see bug#544309 for details).
151151 /**
152152 * Collect the files to process. This method may show a dialog to ask the user.
153153 * Subclasses may extend or reimplement.
154 *
154 *
155155 * @param resources selected resources
156156 * @return the files to process, can be <code>null</code>
157157 */
5959 * @since 3.1
6060 */
6161 public class FileBufferOperationHandler extends AbstractHandler {
62
62
6363 private IFileBufferOperation fFileBufferOperation;
6464 private IWorkbenchWindow fWindow;
6565 private IResource[] fResources;
7474 * @since 3.6
7575 */
7676 String ACCESSIBILITY_PREFERENCE_PAGE= PREFIX + "accessibility_preference_page_context"; //$NON-NLS-1$
77
77
7878 }
5454
5555 /**
5656 * Creates a new text editor.
57 *
57 *
5858 * @see #initializeEditor()
5959 * @see #initializeKeyBindingScopes()
6060 */
6161 /**
6262 * Creates a new context type registry and registers all context types contributed for the given
6363 * registry ID.
64 *
64 *
6565 * @param registryId the registry ID
6666 * @since 3.5
6767 */
8080
8181 /**
8282 * Registers all context types contributed for the given registry ID.
83 *
83 *
8484 * @param registryId the registry ID
8585 * @since 3.5
8686 */
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
416416 * - byte order mark is not valid for UTF-8
417417 */
418418 private static boolean isUTF8BOM(String encoding, IStorage storage) throws CoreException {
419 if (storage instanceof IFile && StandardCharsets.UTF_8.name().equals(encoding)) { //$NON-NLS-1$
419 if (storage instanceof IFile && StandardCharsets.UTF_8.name().equals(encoding)) {
420420 IFile file= (IFile) storage;
421421 IContentDescription description= file.getContentDescription();
422422 if (description != null) {
100100 @Override
101101 protected Composite createSelectionButtonGroup(Composite parent) {
102102 Composite buttonGroup= super.createSelectionButtonGroup(parent);
103
103
104104 final Button button = new Button(buttonGroup, SWT.CHECK);
105105 ((GridLayout) buttonGroup.getLayout()).numColumns++;
106106 button.setText(TextEditorMessages.ConvertLineDelimitersAction_show_only_text_files);
113113 refresh();
114114 }
115115 });
116
116
117117 return buttonGroup;
118118 }
119119 };
125125 }
126126 return null;
127127 }
128
128
129129 private String getDialogTitle() {
130130 return NLSUtility.format(TextEditorMessages.ConvertLineDelimitersAction_dialog_title, fLabel);
131131 }
2121 import org.eclipse.jface.resource.ColorRegistry;
2222
2323 import org.eclipse.ui.PlatformUI;
24 import org.eclipse.ui.internal.editors.text.codemining.annotation.AnnotationCodeMiningPreferenceConstants;
2425 import org.eclipse.ui.internal.texteditor.ITextEditorThemeConstants;
2526
2627 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
4142 IPreferenceStore store= EditorsPlugin.getDefault().getPreferenceStore();
4243 TextEditorPreferenceConstants.initializeDefaultValues(store);
4344 migrateOverviewRulerPreference(store);
45 AnnotationCodeMiningPreferenceConstants.initializeDefaultValues(store);
4446 }
4547
4648 public static void setThemeBasedPreferences(IPreferenceStore store, boolean fireEvent) {
213213 messageLabel.setFont(font);
214214 return messageComposite;
215215 }
216
216
217217 /**
218218 * Creates page for hover preferences.
219219 *
349349 }
350350
351351 });
352
352
353353 fQuickDiffProviderNote= createNoteComposite(parent.getFont(), editorComposite, TextEditorMessages.QuickDiffConfigurationBlock_referenceProviderNoteTitle,
354354 TextEditorMessages.QuickDiffConfigurationBlock_referenceProviderNoteMessage);
355355 gd= new GridData(SWT.BEGINNING, SWT.FILL, false, true);
254254 gc.dispose();
255255 return width;
256256 }
257
257
258258 /**
259259 * Returns a boolean indicating whether the passed tree element should be at
260260 * LEAST gray-checked. Note that this method does not consider whether it
676676 listViewer.setAllChecked(selection);
677677 });
678678 }
679
679
680680 public void refresh() {
681681 //Potentially long operation - show a busy cursor
682682 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), () -> {
850850
851851 // Update the store before the hierarchy to prevent updating parents
852852 // before all of the children are done
853
853
854854 for (Entry<IContainer, List<Object>> entry : items.entrySet()) {
855855 Object key = entry.getKey();
856856 primeHierarchyForSelection(key, selectedNodes);
857857 checkedStateStore.put(key, entry.getValue());
858858 }
859
859
860860
861861 // Update the checked tree items. Since each tree item has a selected
862862 // item, all the tree items will be gray checked.
9090 fResourceGroup.refresh();
9191 setSelection(fInput, fAcceptableLocationsFilter);
9292 }
93
93
9494 public IResource[] getSelectedResources() {
9595 List<Object> items= fResourceGroup.getAllCheckedListItems();
9696 return items.toArray(new IResource[items.size()]);
220220 selectTypesButton.addSelectionListener(listener);
221221 selectTypesButton.setFont(font);
222222 setButtonLayoutData(selectTypesButton);
223
223
224224 return buttonComposite;
225225 }
226226
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
7373 import org.eclipse.ui.dialogs.PreferencesUtil;
7474 import org.eclipse.ui.internal.editors.text.OverlayPreferenceStore.OverlayKey;
7575 import org.eclipse.ui.internal.editors.text.TextEditorDefaultsPreferencePage.EnumeratedDomain.EnumValue;
76 import org.eclipse.ui.internal.editors.text.codemining.annotation.AnnotationCodeMiningPreferenceConstants;
7677
7778 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
7879 import org.eclipse.ui.texteditor.AbstractTextEditor;
576577
577578 /**
578579 * Sets or clears the error message. If not <code>null</code>, the OK button is disabled.
579 *
580 *
580581 * @param errorMessage the error message, or <code>null</code> to clear
581582 * @since 3.0
582583 */
731732 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH));
732733 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractTextEditor.PREFERENCE_WORD_WRAP_ENABLED));
733734 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS));
735 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DELETE_SPACES_AS_TABS));
734736
735737 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR));
736738 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN));
768770 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TEXT_DRAG_AND_DROP_ENABLED));
769771 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
770772 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_HOVER_ENRICH_MODE));
773
774 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL));
775 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_MAX));
771776
772777 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LEADING_SPACES));
773778 overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ENCLOSED_SPACES));
853858
854859 label= TextEditorMessages.TextEditorPreferencePage_convertTabsToSpaces;
855860 Preference spacesForTabs= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, label, null);
856 addCheckBox(appearanceComposite, spacesForTabs, new BooleanDomain(), 0);
857
861 final Button spacesForTabsButton= addCheckBox(appearanceComposite, spacesForTabs, new BooleanDomain(), 0);
862
863 label= TextEditorMessages.TextEditorDefaultsPreferencePage_deleteSpacesAsTabs;
864 Preference deleteSpacesAsTabs= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DELETE_SPACES_AS_TABS, label, null);
865 final Button deleteSpacesAsTabsButton= addCheckBox(appearanceComposite, deleteSpacesAsTabs, new BooleanDomain(), 0);
866 createDependency(spacesForTabsButton, spacesForTabs, new Control[] { deleteSpacesAsTabsButton });
858867
859868 label= TextEditorMessages.TextEditorPreferencePage_highlightCurrentLine;
860869 Preference highlightCurrentLine= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, label, null);
870879 final IntegerDomain printMarginDomain= new IntegerDomain(20, 200);
871880 final Control[] printMarginControls= addTextField(appearanceComposite, printMarginColumn, printMarginDomain, 15, 20);
872881 createDependency(showPrintMarginButton, showPrintMargin, printMarginControls);
873
882
874883 label= TextEditorMessages.TextEditorPreferencePage_printMarginAllowOverride;
875884 Preference printMarginAllowOverride= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_ALLOW_OVERRIDE, label, null);
876885 final Button showPrintMarginAllowOverride= addCheckBox(appearanceComposite, printMarginAllowOverride, new BooleanDomain(), 0);
934943 label= TextEditorMessages.TextEditorDefaultsPreferencePage_smartHomeEnd;
935944 Preference smartHomeEnd= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SMART_HOME_END, label, null);
936945 addCheckBox(appearanceComposite, smartHomeEnd, new BooleanDomain(), 0);
946
947 label= TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_show;
948 String description= TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_description;
949 Preference showCodeMinings= new Preference(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL, label, description);
950 EnumeratedDomain codeMiningsDomain= new EnumeratedDomain();
951 codeMiningsDomain.addValue(new EnumValue(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__NONE, TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_none));
952 codeMiningsDomain.addValue(new EnumValue(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR, TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_error));
953 codeMiningsDomain.addValue(new EnumValue(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR_WARNING,
954 TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_ErrorWarnings));
955 codeMiningsDomain.addValue(new EnumValue(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR_WARNING_INFO,
956 TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_ErrorWarningsInfo));
957 final Control[] showCodeMiningsControls= addCombo(appearanceComposite, showCodeMinings, codeMiningsDomain, 0);
958
959 label= TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_max;
960 description= TextEditorMessages.TextEditorDefaultsPreferencePage_codeMinings_max_description;
961 Preference maxCodeMinings= new Preference(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_MAX, label, description);
962 IntegerDomain maxCodeMiningsDomain= new IntegerDomain(0, 99999);
963 Control[] maxCodeMiningsControls= addTextField(appearanceComposite, maxCodeMinings, maxCodeMiningsDomain, 15, 20);
964
965 final SelectionListener codeMiningsListener= new SelectionAdapter() {
966 @Override
967 public void widgetSelected(SelectionEvent e) {
968 final int showCodeMiningsSetting= fOverlayStore.getInt(showCodeMinings.getKey());
969 boolean enabled= showCodeMiningsSetting != AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__NONE;
970 for (Control control : maxCodeMiningsControls) {
971 control.setEnabled(enabled);
972 }
973 }
974 };
975
976 ((Combo) showCodeMiningsControls[1]).addSelectionListener(codeMiningsListener);
977 fMasterSlaveListeners.add(codeMiningsListener);
978
937979
938980 addFiller(appearanceComposite, 2);
939981
10481090 int dimensions= 10;
10491091 Image image= new Image(tableComposite.getParent().getDisplay(), dimensions, dimensions);
10501092 GC gc= new GC(image);
1051 // Draw color preview
1093 // Draw color preview
10521094 gc.setBackground(color);
10531095 gc.fillRectangle(0, 0, dimensions, dimensions);
10541096 // Draw outline around color preview
14171459
14181460 /**
14191461 * Returns the currently selected item in the Appearance Color Options Table.
1420 *
1462 *
14211463 * @return {@link ColorEntry} the ColorEntry representing the currently selected item in the
14221464 * table
14231465 */
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
136136
137137 public static String TextEditorDefaultsPreferencePage_carriageReturn;
138138 public static String TextEditorDefaultsPreferencePage_transparencyLevel;
139 public static String TextEditorDefaultsPreferencePage_codeMinings_description;
140 public static String TextEditorDefaultsPreferencePage_codeMinings_error;
141 public static String TextEditorDefaultsPreferencePage_codeMinings_ErrorWarnings;
142 public static String TextEditorDefaultsPreferencePage_codeMinings_ErrorWarningsInfo;
143 public static String TextEditorDefaultsPreferencePage_codeMinings_max;
144 public static String TextEditorDefaultsPreferencePage_codeMinings_max_description;
145 public static String TextEditorDefaultsPreferencePage_codeMinings_none;
146 public static String TextEditorDefaultsPreferencePage_codeMinings_show;
139147 public static String TextEditorDefaultsPreferencePage_configureWhitespaceCharacterPainterProperties;
148 public static String TextEditorDefaultsPreferencePage_deleteSpacesAsTabs;
140149 public static String TextEditorDefaultsPreferencePage_enclosed;
141150 public static String TextEditorDefaultsPreferencePage_enrichHoverMode;
142151 public static String TextEditorDefaultsPreferencePage_enrichHover_immediately;
00 ###############################################################################
1 # Copyright (c) 2000, 2018 IBM Corporation and others.
1 # Copyright (c) 2000, 2019 IBM Corporation and others.
22 #
33 # This program and the accompanying materials
44 # are made available under the terms of the Eclipse Public License 2.0
3838 TextEditorPreferencePage_accessibility_useSaturatedColorsInOverviewRuler=U&se saturated colors in overview ruler
3939 TextEditorDefaultsPreferencePage_carriageReturn=Carriage Return ( \u00a4 )
4040 TextEditorDefaultsPreferencePage_transparencyLevel=&Transparency level (0 is transparent and 255 is opaque):
41 TextEditorDefaultsPreferencePage_codeMinings_description=How annotations should be shown in-line in text editors which support code minings
42 TextEditorDefaultsPreferencePage_codeMinings_error=Errors only
43 TextEditorDefaultsPreferencePage_codeMinings_ErrorWarnings=Errors and Warnings
44 TextEditorDefaultsPreferencePage_codeMinings_ErrorWarningsInfo=Errors, Warnings and Infos
45 TextEditorDefaultsPreferencePage_codeMinings_max=Maximum annotations shown:
46 TextEditorDefaultsPreferencePage_codeMinings_max_description=Limits the number of shown annotations to prevent performance issues
47 TextEditorDefaultsPreferencePage_codeMinings_none=None
48 TextEditorDefaultsPreferencePage_codeMinings_show=Show code minings &for problem annotations:
4149 TextEditorDefaultsPreferencePage_configureWhitespaceCharacterPainterProperties=Configure visibility of whitespace characters in different regions of a line of text:
50 TextEditorDefaultsPreferencePage_deleteSpacesAsTabs=Remove &multiple spaces on backspace/delete
4251 TextEditorDefaultsPreferencePage_enclosed=Enclosed
4352 TextEditorDefaultsPreferencePage_enrichHoverMode=When mouse mo&ved into hover:
4453 TextEditorDefaultsPreferencePage_enrichHover_afterDelay=Enrich after delay
0 /*******************************************************************************
1 # * Copyright (c) 2018 Altran Netherlands B.V. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Niko Stotz (Altran Netherlands B.V.) - initial implementation
12 *******************************************************************************/
13 package org.eclipse.ui.internal.editors.text.codemining.annotation;
14
15 import java.util.function.Consumer;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19
20 import org.eclipse.swt.custom.StyledText;
21 import org.eclipse.swt.events.MouseEvent;
22 import org.eclipse.swt.graphics.Color;
23 import org.eclipse.swt.graphics.GC;
24 import org.eclipse.swt.graphics.Point;
25 import org.eclipse.swt.graphics.Rectangle;
26
27 import org.eclipse.jface.text.BadLocationException;
28 import org.eclipse.jface.text.IDocument;
29 import org.eclipse.jface.text.codemining.ICodeMiningProvider;
30 import org.eclipse.jface.text.codemining.LineHeaderCodeMining;
31 import org.eclipse.jface.text.source.Annotation;
32 import org.eclipse.jface.text.source.IAnnotationAccessExtension;
33
34 /**
35 * Draws an Annotation's text and icon as Line header code mining.
36 *
37 * @since 3.13
38 */
39 @NonNullByDefault
40 public class AnnotationCodeMining extends LineHeaderCodeMining {
41 private final Annotation annotation;
42
43 private final IAnnotationAccessExtension annotationAccess;
44
45 public AnnotationCodeMining(IAnnotationAccessExtension annotationAccess, Annotation annotation, int lineNumber, IDocument document, ICodeMiningProvider provider,
46 @Nullable Consumer<MouseEvent> action) throws BadLocationException {
47 super(lineNumber, document, provider, action);
48 this.annotationAccess= annotationAccess;
49
50 setLabel(sanitizeLabel(annotation.getText()));
51
52 this.annotation= annotation;
53 }
54
55 private static String sanitizeLabel(String label) {
56 return label.replace('\r', ' ').replace('\n', ' ');
57 }
58
59 @Override
60 @SuppressWarnings("null")
61 public Point draw(GC gc, StyledText textWidget, Color color, int x, int y) {
62 final int width= 16;
63 annotationAccess.paint(this.annotation, gc, textWidget, new Rectangle(x, y, width, 16));
64 final Point result= super.draw(gc, textWidget, color, x + width, y);
65 result.x+= width;
66 return result;
67 }
68 }
0 /*******************************************************************************
1 * Copyright (c) 2019 Altran Netherlands B.V. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Niko Stotz (Altran Netherlands B.V.) - initial implementation
12 *******************************************************************************/
13 package org.eclipse.ui.internal.editors.text.codemining.annotation;
14
15 import java.util.Arrays;
16 import java.util.Iterator;
17 import java.util.LinkedHashMap;
18 import java.util.Map;
19 import java.util.Objects;
20 import java.util.Spliterator;
21 import java.util.Spliterators;
22 import java.util.function.Function;
23 import java.util.function.Predicate;
24 import java.util.stream.Stream;
25 import java.util.stream.StreamSupport;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29
30 import org.eclipse.core.resources.IMarker;
31
32 import org.eclipse.jface.text.quickassist.IQuickFixableAnnotation;
33 import org.eclipse.jface.text.source.Annotation;
34 import org.eclipse.jface.text.source.IAnnotationAccessExtension;
35 import org.eclipse.jface.text.source.IAnnotationPresentation;
36
37 import org.eclipse.ui.texteditor.MarkerAnnotation;
38
39 /**
40 * Filters and arranges Annotations that are suitable as code minings. Takes user preferences into
41 * account.
42 *
43 * @since 3.13
44 */
45 @NonNullByDefault
46 public class AnnotationCodeMiningFilter {
47 /**
48 * Callback to locate an Annotation inside the editor.
49 */
50 public interface Locator {
51 public @Nullable Integer getOffset(Annotation annotation);
52
53 public @Nullable Integer getLine(Annotation annotation);
54 }
55
56 final private IAnnotationAccessExtension annotationAccess;
57
58 final private AnnotationCodeMiningPreferences preferences= new AnnotationCodeMiningPreferences();
59
60 final private Stream<Annotation> annotations;
61
62 public AnnotationCodeMiningFilter(IAnnotationAccessExtension annotationAccess, Annotation[]... annotations) {
63 this.annotationAccess= annotationAccess;
64 this.annotations= Arrays.stream(annotations).flatMap(Arrays::stream);
65 }
66
67 public AnnotationCodeMiningFilter(IAnnotationAccessExtension annotationAccess, Iterator<Annotation> annotations) {
68 this.annotationAccess= annotationAccess;
69 this.annotations= StreamSupport.stream(Spliterators.spliteratorUnknownSize(annotations, Spliterator.ORDERED), false);
70 }
71
72 /**
73 * Checks if there are any suitable annotations.
74 */
75 public boolean isEmpty() {
76 return !filterReTrigger(annotations).findAny().isPresent();
77 }
78
79 /**
80 * Returns all suitable annotations.
81 */
82 public Stream<Annotation> sortDistinctLimit(Locator locator) {
83 return limit(distinct(locator, sort(locator, filterShown(filterReTrigger(annotations)))));
84 }
85
86 /**
87 * Filters suitable annotations to decide whether we need to re-trigger code minings.
88 */
89 private Stream<Annotation> filterReTrigger(Stream<Annotation> anns) {
90 return anns
91 .filter(this::isTypeProcessable)
92 .filter(this::isPaintable)
93 .filter(this::isInScope);
94 }
95
96 private boolean isTypeProcessable(Annotation a) {
97 return a instanceof MarkerAnnotation ||
98 a instanceof IQuickFixableAnnotation ||
99 a instanceof IAnnotationPresentation;
100 }
101
102 private boolean isPaintable(Annotation a) {
103 // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=552760
104 // (NPE on JavaAnnotationImageProvider.getQuickFixErrorImage(): No Display)
105 try {
106 return annotationAccess.isPaintable(a);
107 } catch (NullPointerException e) {
108 return false;
109 }
110 }
111
112 private boolean isInScope(Annotation a) {
113 return isError(a) || isWarning(a) || isInfo(a);
114 }
115
116 /**
117 * Filters suitable annotations to show.
118 */
119 private Stream<Annotation> filterShown(Stream<Annotation> anns) {
120 return anns
121 .filter(a -> !a.isMarkedDeleted())
122 .filter(this::isEnabled);
123 }
124
125 private boolean isEnabled(Annotation a) {
126 if (isError(a)) {
127 return preferences.isErrorEnabled();
128 } else if (isWarning(a)) {
129 return preferences.isWarningEnabled();
130 } else if (isInfo(a)) {
131 return preferences.isInfoEnabled();
132 } else {
133 return false;
134 }
135 }
136
137 /**
138 * Sorts annotations based on 1) position in text, 2) layer, 3) severity, 4) text.
139 */
140 private Stream<Annotation> sort(Locator locator, Stream<Annotation> anns) {
141 return anns.sorted((a, b) -> {
142 int resultPosition= comparePosition(locator, a, b);
143 if (resultPosition != 0) {
144 return resultPosition;
145 }
146
147 final int resultLayer= compareLayer(a, b);
148 if (resultLayer != 0) {
149 return resultLayer;
150 }
151
152 final int resultSeverity= compareSeverity(a, b);
153 if (resultSeverity != 0) {
154 return resultSeverity;
155 }
156
157 return a.getText().compareTo(b.getText());
158 });
159 }
160
161 private int comparePosition(Locator locator, Annotation a, Annotation b) {
162 final Integer aOffset= locator.getOffset(a);
163 final Integer bOffset= locator.getOffset(b);
164
165 if (aOffset == null || bOffset == null) {
166 return 0;
167 }
168
169 int resultPosition= Integer.compare(aOffset, bOffset);
170 return resultPosition;
171 }
172
173 private int compareLayer(Annotation a, Annotation b) {
174 final int resultPriority= Integer.compare(annotationAccess.getLayer(a), annotationAccess.getLayer(b));
175 return resultPriority;
176 }
177
178 private int compareSeverity(Annotation a, Annotation b) {
179 final int resultSeverity= Integer.compare(getSeverity(a), getSeverity(b));
180 return resultSeverity;
181 }
182
183 private int getSeverity(Annotation a) {
184 if (isError(a)) {
185 return IMarker.SEVERITY_ERROR;
186 } else if (isWarning(a)) {
187 return IMarker.SEVERITY_WARNING;
188 } else if (isInfo(a)) {
189 return IMarker.SEVERITY_INFO;
190 } else {
191 return -1;
192 }
193 }
194
195 /**
196 * Assures annotations are distinct by line and text. Required, as sometimes the same message is
197 * shown at the same place from different annotations.
198 */
199 @SuppressWarnings("null")
200 private Stream<Annotation> distinct(Locator locator, Stream<Annotation> anns) {
201 return anns
202 .filter(distinctByKey(a -> {
203 final Integer line= locator.getLine(a);
204 if (line == null) {
205 return null;
206 }
207 String key= line + a.getText();
208
209 return key;
210 }))
211 .filter(Objects::nonNull);
212 }
213
214 /**
215 * Limits annotations to user-defined amount.
216 */
217 private Stream<Annotation> limit(Stream<Annotation> anns) {
218 return anns.limit(preferences.getMaxMinings());
219 }
220
221 private boolean isInfo(Annotation a) {
222 return annotationAccess.isSubtype(a.getType(), "org.eclipse.ui.workbench.texteditor.info"); //$NON-NLS-1$
223 }
224
225 private boolean isWarning(Annotation a) {
226 return annotationAccess.isSubtype(a.getType(), "org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
227 }
228
229 private boolean isError(Annotation a) {
230 return annotationAccess.isSubtype(a.getType(), "org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
231 }
232
233 @SuppressWarnings("null")
234 public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
235 Map<Object, Boolean> seen= new LinkedHashMap<>();
236 return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
237 }
238 }
0 /*******************************************************************************
1 * Copyright (c) 2019 Altran Netherlands B.V. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Niko Stotz (Altran Netherlands B.V.) - initial implementation
12 *******************************************************************************/
13 package org.eclipse.ui.internal.editors.text.codemining.annotation;
14
15 import org.eclipse.jface.preference.IPreferenceStore;
16
17 import org.eclipse.ui.internal.editors.text.EditorsPlugin;
18
19 /**
20 * Preference constants used for the annotation code mining preference store.
21 *
22 * @since 3.13
23 * @noinstantiate This class is not intended to be instantiated by clients.
24 * @noextend This class is not intended to be subclassed by clients.
25 */
26 public class AnnotationCodeMiningPreferenceConstants {
27 private AnnotationCodeMiningPreferenceConstants() {
28
29 }
30
31 /**
32 * A named preference that controls which {@link org.eclipse.jface.text.source.Annotation
33 * Annotations} level should be shown as code minings.
34 * <p>
35 * Value is of type <code>Integer</code>.
36 * </p>
37 *
38 * @since 3.13
39 */
40 public final static String SHOW_ANNOTATION_CODE_MINING_LEVEL= "showAnnotationAsCodeMiningLevel"; //$NON-NLS-1$
41
42 /**
43 * Value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL} to show no annotation code minings.
44 *
45 * @since 3.13
46 */
47 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__NONE= 0b0;
48
49 /**
50 * Value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL} to show info annotation code minings.
51 *
52 * @since 3.13
53 */
54 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__INFO= 0b10;
55
56 /**
57 * Value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL} to show warning annotation code minings.
58 *
59 * @since 3.13
60 */
61 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__WARNING= 0b100;
62
63 /**
64 * Value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL} to show error annotation code minings.
65 *
66 * @since 3.13
67 */
68 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR= 0b1000;
69
70 /**
71 * Value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL} to show error and warning annotation
72 * code minings.
73 *
74 * @since 3.13
75 */
76 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR_WARNING= SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR
77 | SHOW_ANNOTATION_CODE_MINING_LEVEL__WARNING;
78
79 /**
80 * Value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL} to show error, warning, and info
81 * annotation code minings.
82 *
83 * @since 3.13
84 */
85 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR_WARNING_INFO= SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR
86 | SHOW_ANNOTATION_CODE_MINING_LEVEL__WARNING
87 | SHOW_ANNOTATION_CODE_MINING_LEVEL__INFO;
88
89 /**
90 * Default value for {@link #SHOW_ANNOTATION_CODE_MINING_LEVEL}.
91 *
92 * @since 3.13
93 */
94 public final static int SHOW_ANNOTATION_CODE_MINING_LEVEL__DEFAULT= SHOW_ANNOTATION_CODE_MINING_LEVEL__NONE;
95
96 /**
97 * A named preference that controls how many {@link org.eclipse.jface.text.source.Annotation
98 * Annotations}s should be shown at most as code minings.
99 * <p>
100 * Value is of type <code>Integer</code>.
101 * </p>
102 *
103 * @since 3.13
104 */
105 public final static String SHOW_ANNOTATION_CODE_MINING_MAX= "showAnnotationAsCodeMiningMax"; //$NON-NLS-1$
106
107 /**
108 * Default value for {@link #SHOW_ANNOTATION_CODE_MINING_MAX}.
109 *
110 * @since 3.13
111 */
112 public final static int SHOW_ANNOTATION_CODE_MINING_MAX__DEFAULT= 100;
113
114 /**
115 * Returns the Generic Editor preference store.
116 *
117 * @return the Generic Editor preference store
118 */
119 public static IPreferenceStore getPreferenceStore() {
120 return EditorsPlugin.getDefault().getPreferenceStore();
121 }
122
123 /**
124 * Initializes the given preference store with the default values.
125 *
126 * @param store the preference store to be initialized
127 *
128 * @since 3.13
129 */
130 public static void initializeDefaultValues(IPreferenceStore store) {
131 store.setDefault(SHOW_ANNOTATION_CODE_MINING_LEVEL, SHOW_ANNOTATION_CODE_MINING_LEVEL__DEFAULT);
132 store.setDefault(SHOW_ANNOTATION_CODE_MINING_MAX, SHOW_ANNOTATION_CODE_MINING_MAX__DEFAULT);
133 }
134
135 }
0 /*******************************************************************************
1 * Copyright (c) 2019 Altran Netherlands B.V. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Niko Stotz (Altran Netherlands B.V.) - initial implementation
12 *******************************************************************************/
13 package org.eclipse.ui.internal.editors.text.codemining.annotation;
14
15 import org.eclipse.jdt.annotation.Nullable;
16
17 import org.eclipse.jface.preference.IPreferenceStore;
18
19 /**
20 * Simplifies access to user preferences related to Annotation-based code minings.
21 *
22 * <p>
23 * All methods fall back to defaults if the preference store is unavailable.
24 * </p>
25 *
26 * <p>
27 * The following preferences are available:
28 * </p>
29 *
30 * <dl>
31 * <dt>show infos <i>(default: <code>false</code>)</i></dt>
32 * <dd>Whether INFO-level annotations should be shown as code minings.</dd>
33 *
34 * <dt>show warnings <i>(default: <code>false</code>)</i></dt>
35 * <dd>Whether WARNING-level annotations should be shown as code minings.</dd>
36 *
37 * <dt>show errors <i>(default: <code>false</code>)</i></dt>
38 * <dd>Whether ERROR-level annotations should be shown as code minings.</dd>
39 *
40 * <dt>Maximum annotations shown <i>(default: <code>100</code>)</i></dt>
41 * <dd>How many annotations should be shown at most as code minings. Mainly to prevent bad editor
42 * performance.</dd>
43 * </dl>
44 *
45 * @since 3.13
46 */
47 public class AnnotationCodeMiningPreferences {
48 private IPreferenceStore preferenceStore;
49
50 public boolean isInfoEnabled() {
51 return (getLevel() & AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__INFO) > 0;
52 }
53
54 public boolean isWarningEnabled() {
55 return (getLevel() & AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__WARNING) > 0;
56 }
57
58 public boolean isErrorEnabled() {
59 return (getLevel() & AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__ERROR) > 0;
60 }
61
62 public boolean isEnabled() {
63 final IPreferenceStore node= getPreferences();
64 if (node == null) {
65 return false;
66 }
67
68 final int max= getMaxMinings();
69
70 return max > 0 && getLevel() > 0;
71 }
72
73 int getLevel() {
74 IPreferenceStore node= getPreferences();
75
76 return node != null
77 ? node.getInt(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL)
78 : AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL__DEFAULT;
79 }
80
81 int getMaxMinings() {
82 final IPreferenceStore node= getPreferences();
83
84 return node != null
85 ? node.getInt(AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_MAX)
86 : AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_MAX__DEFAULT;
87 }
88
89 protected @Nullable IPreferenceStore getPreferences() {
90 if (preferenceStore == null) {
91 preferenceStore= AnnotationCodeMiningPreferenceConstants.getPreferenceStore();
92 }
93
94 return preferenceStore;
95 }
96 }
0 /*******************************************************************************
1 * Copyright (c) 2018 Altran Netherlands B.V. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Niko Stotz (Altran Netherlands B.V.) - initial implementation
12 *******************************************************************************/
13 package org.eclipse.ui.internal.editors.text.codemining.annotation;
14
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Objects;
18 import java.util.concurrent.CompletableFuture;
19 import java.util.function.Consumer;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25
26 import org.eclipse.swt.events.MouseEvent;
27
28 import org.eclipse.core.runtime.Assert;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.Status;
32
33 import org.eclipse.jface.preference.IPreferenceStore;
34 import org.eclipse.jface.util.IPropertyChangeListener;
35 import org.eclipse.jface.util.PropertyChangeEvent;
36
37 import org.eclipse.jface.text.BadLocationException;
38 import org.eclipse.jface.text.IDocument;
39 import org.eclipse.jface.text.ITextViewer;
40 import org.eclipse.jface.text.Position;
41 import org.eclipse.jface.text.codemining.AbstractCodeMining;
42 import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider;
43 import org.eclipse.jface.text.codemining.ICodeMining;
44 import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
45 import org.eclipse.jface.text.quickassist.IQuickFixableAnnotation;
46 import org.eclipse.jface.text.source.Annotation;
47 import org.eclipse.jface.text.source.AnnotationModelEvent;
48 import org.eclipse.jface.text.source.IAnnotationAccess;
49 import org.eclipse.jface.text.source.IAnnotationAccessExtension;
50 import org.eclipse.jface.text.source.IAnnotationModel;
51 import org.eclipse.jface.text.source.IAnnotationModelListener;
52 import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
53 import org.eclipse.jface.text.source.ISourceViewerExtension2;
54 import org.eclipse.jface.text.source.ISourceViewerExtension3;
55 import org.eclipse.jface.text.source.ISourceViewerExtension5;
56
57 import org.eclipse.ui.internal.editors.text.EditorsPlugin;
58
59 import org.eclipse.ui.editors.text.EditorsUI;
60
61 /**
62 * Shows <i>info</i>, <i>warning</i>, and <i>error</i> Annotations as line header code minings.
63 *
64 * <p>
65 * If the annotation is quickfixable, clicking on the code mining triggers the quickfix.
66 * </p>
67 * <p>
68 * The user can configure which and how many Annotations should be shown in preferences.
69 * </p>
70 * <p>
71 * Works out-of-the-box for all code mining-enabled text editors.
72 * </p>
73 *
74 * @since 3.13
75 * @see org.eclipse.ui.internal.editors.text.codemining.annotation.AnnotationCodeMiningPreferences
76 */
77 @NonNullByDefault
78 public class AnnotationCodeMiningProvider extends AbstractCodeMiningProvider
79 implements AnnotationCodeMiningFilter.Locator {
80
81 /**
82 * Updates code minings after changes to preferences.
83 */
84 private class PropertyChangeListener implements IPropertyChangeListener {
85
86 @Override
87 public void propertyChange(PropertyChangeEvent event) {
88 switch (event.getProperty()) {
89 case AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_LEVEL:
90 case AnnotationCodeMiningPreferenceConstants.SHOW_ANNOTATION_CODE_MINING_MAX:
91 getCodeMiningViewer().updateCodeMinings();
92 break;
93 default:
94 // ignore
95 }
96 }
97 }
98
99 /**
100 * Updates code minings after changes to annotations.
101 */
102 private class AnnotationModelListener implements IAnnotationModelListener, IAnnotationModelListenerExtension {
103 @Override
104 public void modelChanged(@Nullable IAnnotationModel model) {
105 // ignore
106 }
107
108 @Override
109 public void modelChanged(@SuppressWarnings("null") AnnotationModelEvent event) {
110 if (viewer == null) {
111 return;
112 }
113
114 if (!event.isValid() || event.isEmpty()) {
115 return;
116 }
117
118 AnnotationCodeMiningFilter filter= new AnnotationCodeMiningFilter(getAnnotationAccess(),
119 event.getAddedAnnotations(), event.getRemovedAnnotations(), event.getChangedAnnotations());
120
121 if (!filter.isEmpty()) {
122 getCodeMiningViewer().updateCodeMinings();
123 }
124 }
125 }
126
127 private @Nullable ITextViewer viewer= null;
128
129 private @Nullable AnnotationModelListener annotationModelListener= null;
130
131 private @Nullable PropertyChangeListener propertyChangeListener= null;
132
133 private @Nullable IAnnotationAccessExtension annotationAccess= null;
134
135 @Override
136 @SuppressWarnings("null")
137 public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, IProgressMonitor monitor) {
138 if (!(viewer instanceof ISourceViewerExtension5)) {
139 throw new IllegalArgumentException("Cannot attach to TextViewer without code mining support"); //$NON-NLS-1$
140 }
141
142 if (!new AnnotationCodeMiningPreferences().isEnabled()) {
143 return CompletableFuture.completedFuture(Collections.emptyList());
144 }
145
146 this.viewer= viewer;
147
148 final IAnnotationAccess annotationAccess= getAdapter(IAnnotationAccess.class);
149 if (!(annotationAccess instanceof IAnnotationAccessExtension)) {
150 throw new IllegalStateException("annotationAccess must implement IAnnotationAccessExtension"); //$NON-NLS-1$
151 }
152 this.annotationAccess= (IAnnotationAccessExtension) annotationAccess;
153
154 return provideCodeMiningsInternal(monitor);
155 }
156
157 @Override
158 public void dispose() {
159 unregisterPropertyChangeListener();
160 unregisterAnnotationModelListener();
161
162 this.viewer= null;
163
164 super.dispose();
165 }
166
167 @Override
168 @SuppressWarnings("boxing")
169 public @Nullable Integer getLine(Annotation annotation) {
170 Integer offset= getOffset(annotation);
171 if (offset == null) {
172 return null;
173 }
174
175 try {
176 return getDocument().getLineOfOffset(offset);
177 } catch (BadLocationException e) {
178 return null;
179 }
180 }
181
182 @Override
183 @SuppressWarnings("boxing")
184 public @Nullable Integer getOffset(Annotation annotation) {
185 final Position position= getAnnotationModel().getPosition(annotation);
186 if (position == null) {
187 return null;
188 }
189
190 return position.getOffset();
191 }
192
193 private CompletableFuture<List<? extends ICodeMining>> provideCodeMiningsInternal(IProgressMonitor monitor) {
194 return CompletableFuture.supplyAsync(() -> {
195 if (!checkAnnotationModelAvailable()) {
196 return Collections.emptyList();
197 }
198
199 registerAnnotationModelListener();
200 registerPropertyChangeListener();
201
202 final Stream<Annotation> annotations= getAnnotations();
203 final List<AbstractCodeMining> codeMinings= createCodeMinings(annotations, monitor);
204
205 return codeMinings;
206 });
207 }
208
209 private void registerAnnotationModelListener() {
210 if (annotationModelListener == null) {
211 annotationModelListener= new AnnotationModelListener();
212 getAnnotationModel().addAnnotationModelListener(annotationModelListener);
213 }
214 }
215
216 private void unregisterAnnotationModelListener() {
217 if (this.annotationModelListener != null) {
218 getAnnotationModel().removeAnnotationModelListener(annotationModelListener);
219 this.annotationModelListener= null;
220 }
221 }
222
223 private void registerPropertyChangeListener() {
224 if (propertyChangeListener == null) {
225 final @Nullable IPreferenceStore store= new AnnotationCodeMiningPreferences().getPreferences();
226 if (store != null) {
227 propertyChangeListener= new PropertyChangeListener();
228 store.addPropertyChangeListener(propertyChangeListener);
229 }
230 }
231 }
232
233 private void unregisterPropertyChangeListener() {
234 if (this.propertyChangeListener != null) {
235 final @Nullable IPreferenceStore store= new AnnotationCodeMiningPreferences().getPreferences();
236 if (store != null) {
237 store.removePropertyChangeListener(propertyChangeListener);
238 }
239 this.propertyChangeListener= null;
240 }
241 }
242
243 private Stream<Annotation> getAnnotations() {
244 return new AnnotationCodeMiningFilter(getAnnotationAccess(), getAnnotationModel().getAnnotationIterator())
245 .sortDistinctLimit(this);
246 }
247
248 private List<AbstractCodeMining> createCodeMinings(Stream<Annotation> annotations, IProgressMonitor monitor) {
249 @SuppressWarnings("null")
250 final Stream<AbstractCodeMining> result= annotations
251 .filter(m -> !monitor.isCanceled())
252 .map(this::createCodeMining)
253 .filter(Objects::nonNull);
254 return result.collect(Collectors.toList());
255 }
256
257 @SuppressWarnings("boxing")
258 private @Nullable AbstractCodeMining createCodeMining(Annotation annotation) {
259 final Integer lineNumber= getLine(annotation);
260
261 if (lineNumber == null) {
262 return null;
263 }
264
265 try {
266 final Consumer<MouseEvent> action= createAction(annotation);
267 return new AnnotationCodeMining(getAnnotationAccess(), annotation, lineNumber, getDocument(), this, action);
268 } catch (BadLocationException e) {
269 return null;
270 }
271 }
272
273 /**
274 * The action selects the text attached to the Annotation and activates quickfixes.
275 */
276 private @Nullable Consumer<MouseEvent> createAction(Annotation annotation) {
277 if (!(annotation instanceof IQuickFixableAnnotation) || !(getTextViewer() instanceof ISourceViewerExtension3)) {
278 return null;
279 }
280
281 final Position position= getAnnotationModel().getPosition(annotation);
282 if (position == null) {
283 return null;
284 }
285
286 return (e -> {
287 final IQuickFixableAnnotation quickFixableAnnotation= (IQuickFixableAnnotation) annotation;
288 if (!quickFixableAnnotation.isQuickFixableStateSet() || !quickFixableAnnotation.isQuickFixable()) {
289 return;
290 }
291
292 final IQuickAssistAssistant quickAssistAssistant= ((ISourceViewerExtension3) getTextViewer()).getQuickAssistAssistant();
293 if (quickAssistAssistant == null) {
294 return;
295 }
296
297 if (!quickAssistAssistant.canFix(annotation)) {
298 return;
299 }
300
301 getTextViewer().setSelectedRange(position.getOffset(), position.getLength());
302
303 final String message= quickAssistAssistant.showPossibleQuickAssists();
304
305 if (message != null) {
306 EditorsPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, message));
307 }
308
309 });
310 }
311
312 private boolean checkAnnotationModelAvailable() {
313 return viewer != null && getAnnotationViewer().getVisualAnnotationModel() != null;
314 }
315
316 private IAnnotationModel getAnnotationModel() {
317 return getAnnotationViewer().getVisualAnnotationModel();
318 }
319
320 private ITextViewer getTextViewer() {
321 Assert.isNotNull(viewer);
322 return viewer;
323 }
324
325 private ISourceViewerExtension5 getCodeMiningViewer() {
326 return (ISourceViewerExtension5) getTextViewer();
327 }
328
329 private ISourceViewerExtension2 getAnnotationViewer() {
330 return (ISourceViewerExtension2) getTextViewer();
331 }
332
333 private IDocument getDocument() {
334 return getTextViewer().getDocument();
335 }
336
337 private IAnnotationAccessExtension getAnnotationAccess() {
338 Assert.isNotNull(annotationAccess);
339 return annotationAccess;
340 }
341 }
8080 private Font fStatusTextFont;
8181 /**
8282 * The color of the optional status text label or <code>null</code> if none.
83 *
83 *
8484 * @since 3.6
8585 */
8686 private Color fStatusTextForegroundColor;
207207 Assert.isLegal(bg != null);
208208 Assert.isLegal(fg != null);
209209 Assert.isLegal(factor >= 0f && factor <= 1f);
210
210
211211 float complement= 1f - factor;
212212 return new RGB(
213213 (int) (complement * bg.red + factor * fg.red),
215215 (int) (complement * bg.blue + factor * fg.blue)
216216 );
217217 }
218
218
219219 /*
220220 * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
221221 */
255255 if (fStatusTextForegroundColor != null && !fStatusTextForegroundColor.isDisposed())
256256 fStatusTextForegroundColor.dispose();
257257 fStatusTextForegroundColor= null;
258
258
259259 fTextFont= null;
260260 fShell= null;
261261 fText= null;
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
120120 import org.eclipse.ui.IEditorInput;
121121 import org.eclipse.ui.IEditorPart;
122122 import org.eclipse.ui.IFileEditorInput;
123 import org.eclipse.ui.IPageLayout;
123124 import org.eclipse.ui.IURIEditorInput;
124125 import org.eclipse.ui.IWorkbenchActionConstants;
125126 import org.eclipse.ui.IWorkbenchCommandConstants;
150151 import org.eclipse.ui.operations.NonLocalUndoUserApprover;
151152 import org.eclipse.ui.part.FileEditorInput;
152153 import org.eclipse.ui.part.IShowInSource;
154 import org.eclipse.ui.part.IShowInTargetList;
153155 import org.eclipse.ui.part.ShowInContext;
154156 import org.eclipse.ui.views.markers.MarkerViewUtil;
155157
223225
224226 /**
225227 * Preference key that controls whether to use saturated colors in the overview ruler.
226 *
228 *
227229 * @since 3.8
228230 */
229231 private static final String USE_SATURATED_COLORS_IN_OVERVIEW_RULER= AbstractDecoratedTextEditorPreferenceConstants.USE_SATURATED_COLORS_IN_OVERVIEW_RULER;
311313 * @since 3.6
312314 */
313315 private boolean fIsComingFromGotoMarker= false;
314
316
315317 /**
316318 * Tells whether editing the current derived editor input is allowed.
317319 * @since 3.3
339341
340342 /**
341343 * Creates a new text editor.
342 *
344 *
343345 * @see #initializeEditor()
344346 * @see #initializeKeyBindingScopes()
345347 */
652654
653655 /**
654656 * Checks if the preference to use saturated colors is enabled for the overview ruler.
655 *
657 *
656658 * @return <code>true</code> if the saturated colors preference is enabled, <code>false</code>
657659 * otherwise
658660 * @since 3.8
853855 return;
854856 }
855857
856 if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS.equals(property)) {
858 if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS.equals(property)
859 || AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DELETE_SPACES_AS_TABS.equals(property)) {
857860 if (isTabsToSpacesConversionEnabled())
858861 installTabsToSpacesConverter();
859862 else
958961 if (fSourceViewerDecorationSupport == null) {
959962 fSourceViewerDecorationSupport= new SourceViewerDecorationSupport(viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors());
960963 configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
961
964
962965 // Fix for overridden print margin column, see https://bugs.eclipse.org/468307
963966 if (!getPreferenceStore().getBoolean(PRINT_MARGIN_ALLOW_OVERRIDE))
964967 fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
12641267 // Override print action to provide additional options
12651268 if (getAction(ITextEditorActionConstants.PRINT).isEnabled() && getSourceViewer() instanceof ITextViewerExtension8)
12661269 createPrintAction();
1267
1270
12681271 action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ShowChangeRulerInformation.", IAction.AS_PUSH_BUTTON) { //$NON-NLS-1$
12691272 @Override
12701273 public void run() {
12871290 /**
12881291 * Opens a sticky change ruler hover for the caret line. Does nothing if no change hover is
12891292 * available.
1290 *
1293 *
12911294 * @since 3.5
12921295 */
12931296 private void showChangeRulerInformation() {
12941297 IVerticalRuler ruler= getVerticalRuler();
12951298 if (!(ruler instanceof CompositeRuler) || fLineColumn == null)
12961299 return;
1297
1300
12981301 CompositeRuler compositeRuler= (CompositeRuler)ruler;
12991302
13001303 // fake a mouse move (some hovers rely on this to determine the hovered line):
13011304 int x= fLineColumn.getControl().getLocation().x;
1302
1305
13031306 ISourceViewer sourceViewer= getSourceViewer();
13041307 StyledText textWidget= sourceViewer.getTextWidget();
13051308 int caretOffset= textWidget.getCaretOffset();
13061309 int caretLine= textWidget.getLineAtOffset(caretOffset);
13071310 int y= textWidget.getLinePixel(caretLine);
1308
1311
13091312 compositeRuler.setLocationOfLastMouseButtonActivity(x, y);
1310
1313
13111314 IAnnotationHover hover= fLineColumn.getHover();
13121315 showFocusedRulerHover(hover, sourceViewer, caretOffset);
13131316 }
13151318 /**
13161319 * Opens a sticky annotation ruler hover for the caret line. Does nothing if no annotation hover
13171320 * is available.
1318 *
1321 *
13191322 * @since 3.6
13201323 */
13211324 private void showRulerAnnotationInformation() {
13221325 ISourceViewer sourceViewer= getSourceViewer();
13231326 IAnnotationHover hover= getSourceViewerConfiguration().getAnnotationHover(sourceViewer);
13241327 int caretOffset= sourceViewer.getTextWidget().getCaretOffset();
1325
1328
13261329 showFocusedRulerHover(hover, sourceViewer, caretOffset);
13271330 }
13281331
13291332 /**
13301333 * Shows a focused hover at the specified offset.
13311334 * Does nothing if <code>hover</code> is <code>null</code> or cannot be shown.
1332 *
1335 *
13331336 * @param hover the hover to be shown, can be <code>null</code>
13341337 * @param sourceViewer the source viewer
13351338 * @param caretOffset the caret offset
1336 *
1339 *
13371340 * @since 3.6
13381341 */
13391342 private void showFocusedRulerHover(IAnnotationHover hover, ISourceViewer sourceViewer, int caretOffset) {
13401343 if (hover == null)
13411344 return;
1342
1345
13431346 int modelCaretOffset= widgetOffset2ModelOffset(sourceViewer, caretOffset);
13441347 if (modelCaretOffset == -1)
13451348 return;
1346
1349
13471350 IDocument document= sourceViewer.getDocument();
13481351 if (document == null)
13491352 return;
1350
1353
13511354 try {
13521355 int line= document.getLineOfOffset(modelCaretOffset);
13531356 if (fInformationPresenter == null) {
14251428
14261429 if (MarkerAnnotationPreferences.class.equals(adapter))
14271430 return (T) EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
1431
1432 if (IShowInTargetList.class.equals(adapter))
1433 return (T) getShowInTargetList();
14281434
14291435 return super.getAdapter(adapter);
14301436
16321638 * Overrides the default behavior by showing a more advanced error dialog in case of encoding
16331639 * problems.
16341640 * </p>
1635 *
1641 *
16361642 * @param title the dialog title
16371643 * @param message the message to display
16381644 * @param exception the exception to handle
16501656 final int saveAsUTF8ButtonId= IDialogConstants.OK_ID + IDialogConstants.CANCEL_ID + 1;
16511657 final int selectUnmappableCharButtonId= saveAsUTF8ButtonId + 1;
16521658 final Charset charset= getCharset();
1653
1659
16541660 ErrorDialog errorDialog= new ErrorDialog(getSite().getShell(), title, message, status, IStatus.ERROR) {
16551661
16561662 @Override
17141720
17151721 /**
17161722 * Returns the charset of the current editor input.
1717 *
1723 *
17181724 * @return the charset of the current editor input or <code>null</code> if it fails
17191725 * @since 3.6
17201726 */
20162022
20172023 /**
20182024 * Selects and reveals the given offset and length in the given editor part.
2019 *
2025 *
20202026 * @param editor the editor part
20212027 * @param offset the offset
20222028 * @param length the length
20872093 }
20882094
20892095 /**
2096 * Creates and returns the list of target part IDs for the Show In menu
2097 *
2098 * @return the 'Show In' target part IDs
2099 * @since 3.13
2100 */
2101 protected String[] createShowInTargetList() {
2102 return new String[] { IPageLayout.ID_MINIMAP_VIEW };
2103 }
2104
2105 /**
2106 * Returns the Show In target list
2107 *
2108 * @return the IShowInTargetList adapter, or <code>null</code> if no targets are listed
2109 */
2110 private IShowInTargetList getShowInTargetList() {
2111 final String[] targetList= createShowInTargetList();
2112 if (targetList != null && targetList.length > 0) {
2113 return () -> targetList;
2114 }
2115 return null;
2116 }
2117
2118 /**
20902119 * Returns the preference page ids of the preference pages to be shown when executing the
20912120 * preferences action from the editor context menu. The first page will be selected.
20922121 * <p>
20932122 * Subclasses may extend or replace.
20942123 * </p>
2095 *
2124 *
20962125 * @return the preference page ids to show, may be empty
20972126 * @since 3.1
20982127 */
21162145 * <p>
21172146 * Subclasses may extend or replace.
21182147 * </p>
2119 *
2148 *
21202149 * @return the preference page ids to show, may be empty
21212150 * @since 3.1
21222151 */
21342163 * <p>
21352164 * Subclasses may extend or replace.
21362165 * </p>
2137 *
2166 *
21382167 * @return the preference page ids to show, may be empty
21392168 * @since 3.4
21402169 */
22312260 protected boolean isTabsToSpacesConversionEnabled() {
22322261 return getPreferenceStore() != null && getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS);
22332262 }
2263
2264 /**
2265 * @since 3.13
2266 */
2267 @Override
2268 protected boolean isSpacesAsTabsDeletionEnabled() {
2269 return getPreferenceStore() != null && getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DELETE_SPACES_AS_TABS);
2270 }
22342271 }
00 /*******************************************************************************
1 * Copyright (c) 2000, 2018 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
9090 public final static String EDITOR_SPACES_FOR_TABS= "spacesForTabs"; //$NON-NLS-1$
9191
9292 /**
93 * A named preference that specifies if the editor removes multiple spaces on delete/backspace
94 * key as if they were tabs. Only relevant when {@link #EDITOR_SPACES_FOR_TABS} preference is
95 * set to <code>true</code>.
96 * <p>
97 * Value is of type <code>Boolean</code>. If <code>true</code>, the editor removes multiple
98 * spaces.
99 * </p>
100 *
101 * @since 3.13
102 */
103 public final static String EDITOR_DELETE_SPACES_AS_TABS= "removeSpacesAsTabs"; //$NON-NLS-1$
104
105 /**
93106 * A named preference that holds the size of the editor's undo history.
94107 * <p>
95108 * Value is of type <code>int</code>: 0 or positive int value specifying the size of
135148 * <p>
136149 * The preference value is of type <code>boolean</code>.
137150 * </p>
138 *
151 *
139152 * @noreference This field is not intended to be referenced by clients.
140153 */
141154 public final static String EDITOR_PRINT_MARGIN_ALLOW_OVERRIDE= "printMarginAllowOverride"; //$NON-NLS-1$
201214 * <p>
202215 * The preference value is of type <code>Boolean</code>.
203216 * </p>
204 *
217 *
205218 * @since 3.12
206219 */
207220 public final static String EDITOR_SHOW_CARET_OFFSET= AbstractTextEditor.PREFERENCE_SHOW_CARET_OFFSET;
212225 * <p>
213226 * The preference value is of type <code>Boolean</code>.
214227 * </p>
215 *
228 *
216229 * @since 3.12
217230 */
218231 public final static String EDITOR_SHOW_SELECTION_SIZE= AbstractTextEditor.PREFERENCE_SHOW_SELECTION_SIZE;
224237 * The preference value is of type <code>String</code>. A RGB color value encoded as a string
225238 * using class <code>PreferenceConverter</code>.
226239 * </p>
227 *
240 *
228241 * @see org.eclipse.jface.resource.StringConverter
229242 * @see PreferenceConverter
230243 * @see #EDITOR_LINE_NUMBER_RULER
297310 * <p>
298311 * Value is of type <code>Boolean</code>. If <code>true</code>, saturated colors are used
299312 * </p>
300 *
313 *
301314 * @since 3.8
302315 * @see org.eclipse.jface.text.source.IOverviewRulerExtension#setUseSaturatedColors(boolean)
303316 */
398411 * <p>
399412 * The preference value is of type <code>Boolean</code>.
400413 * </p>
401 *
414 *
402415 * @since 3.5
403416 */
404417 public final static String EDITOR_HYPERLINK_COLOR_SYSTEM_DEFAULT= DefaultHyperlinkPresenter.HYPERLINK_COLOR_SYSTEM_DEFAULT;
444457 * <p>
445458 * Value is of type <code>Boolean</code>.
446459 * </p>
447 *
460 *
448461 * <p>
449462 * The following preferences can be used for fine-grained configuration when enabled.
450463 * </p>
462475 * <li>{@link #EDITOR_SHOW_LINE_FEED}</li>
463476 * <li>{@link #EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE}</li>
464477 * </ul>
465 *
478 *
466479 * @since 3.3
467480 */
468481 public static final String EDITOR_SHOW_WHITESPACE_CHARACTERS= AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS;
473486 * <p>
474487 * Value is of type <code>Boolean</code>.
475488 * </p>
476 *
489 *
477490 * @since 3.7
478491 */
479492 public static final String EDITOR_SHOW_LEADING_SPACES= AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES;
484497 * <p>
485498 * Value is of type <code>Boolean</code>.
486499 * </p>
487 *
500 *
488501 * @since 3.7
489502 */
490503 public static final String EDITOR_SHOW_ENCLOSED_SPACES= AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES;
495508 * <p>
496509 * Value is of type <code>Boolean</code>.
497510 * </p>
498 *
511 *
499512 * @since 3.7
500513 */
501514 public static final String EDITOR_SHOW_TRAILING_SPACES= AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES;
507520 * <p>
508521 * Value is of type <code>Boolean</code>.
509522 * </p>
510 *
523 *
511524 * @since 3.7
512525 */
513526 public static final String EDITOR_SHOW_LEADING_IDEOGRAPHIC_SPACES= AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES;
519532 * <p>
520533 * Value is of type <code>Boolean</code>.
521534 * </p>
522 *
535 *
523536 * @since 3.7
524537 */
525538 public static final String EDITOR_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES= AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES;
531544 * <p>
532545 * Value is of type <code>Boolean</code>.
533546 * </p>
534 *
547 *
535548 * @since 3.7
536549 */
537550 public static final String EDITOR_SHOW_TRAILING_IDEOGRAPHIC_SPACES= AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES;
542555 * <p>
543556 * Value is of type <code>Boolean</code>.
544557 * </p>
545 *
558 *
546559 * @since 3.7
547560 */
548561 public static final String EDITOR_SHOW_LEADING_TABS= AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS;
553566 * <p>
554567 * Value is of type <code>Boolean</code>.
555568 * </p>
556 *
569 *
557570 * @since 3.7
558571 */
559572 public static final String EDITOR_SHOW_ENCLOSED_TABS= AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS;
564577 * <p>
565578 * Value is of type <code>Boolean</code>.
566579 * </p>
567 *
580 *
568581 * @since 3.7
569582 */
570583 public static final String EDITOR_SHOW_TRAILING_TABS= AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS;
575588 * <p>
576589 * Value is of type <code>Boolean</code>.
577590 * </p>
578 *
591 *
579592 * @since 3.7
580593 */
581594 public static final String EDITOR_SHOW_CARRIAGE_RETURN= AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN;
586599 * <p>
587600 * Value is of type <code>Boolean</code>.
588601 * </p>
589 *
602 *
590603 * @since 3.7
591604 */
592605 public static final String EDITOR_SHOW_LINE_FEED= AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED;
597610 * <p>
598611 * Value is of type <code>Integer</code>.
599612 * </p>
600 *
613 *
601614 * @since 3.7
602615 */
603616 public static final String EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE= AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE;
705718
706719 store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, 4);
707720 store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, false);
721 store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DELETE_SPACES_AS_TABS, false);
708722
709723 store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_UNDO_HISTORY_SIZE, 200);
710724
6363
6464 /**
6565 * Creates a new action for the given text editor.
66 *
66 *
6767 * @param editor the text editor
6868 * @see TextEditorAction#TextEditorAction(ResourceBundle, String, ITextEditor)
6969 * @since 3.5
7575 /**
7676 * Creates a new action for the given text editor. The action configures its visual
7777 * representation from the given resource bundle.
78 *
78 *
7979 * @param bundle the resource bundle
8080 * @param prefix a prefix to be prepended to the various resource keys (described in
8181 * <code>ResourceAction</code> constructor), or <code>null</code> if none
5858 * <p>
5959 * This class may be instantiated but is not intended for sub-classing.
6060 * </p>
61 *
61 *
6262 * @since 2.0, allowed to be subclassed since 3.5
6363 */
6464 public class SelectMarkerRulerAction extends ResourceAction implements IUpdate {
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %Plugin.name
33 Bundle-SymbolicName: org.eclipse.ui.editors.tests;singleton:=true
4 Bundle-Version: 3.11.500.qualifier
4 Bundle-Version: 3.11.600.qualifier
55 Bundle-Vendor: %Plugin.providerName
66 Bundle-Localization: plugin
77 Export-Package: org.eclipse.ui.editors.tests
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.ui</groupId>
2020 <artifactId>org.eclipse.ui.editors.tests</artifactId>
21 <version>3.11.500-SNAPSHOT</version>
21 <version>3.11.600-SNAPSHOT</version>
2222 <packaging>eclipse-test-plugin</packaging>
2323 <properties>
2424 <testSuite>${project.artifactId}</testSuite>
00 /*******************************************************************************
1 * Copyright (c) 2000, 2016 IBM Corporation and others.
1 * Copyright (c) 2000, 2019 IBM Corporation and others.
22 *
33 * This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License 2.0
3333 ZoomTest.class,
3434 FileDocumentProviderTest.class,
3535 TextFileDocumentProviderTest.class,
36 StatusEditorTest.class
36 StatusEditorTest.class,
37 LargeFileTest.class
3738 })
3839 public class EditorsTestSuite {
3940 // see @SuiteClasses
0 /*******************************************************************************
1 * Copyright (c) 2019 Thomas Wolf and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10 package org.eclipse.ui.editors.tests;
11
12 import static org.junit.Assert.assertTrue;
13
14 import java.io.BufferedWriter;
15 import java.io.OutputStreamWriter;
16 import java.nio.charset.StandardCharsets;
17
18 import org.junit.After;
19 import org.junit.Before;
20 import org.junit.Test;
21
22 import org.eclipse.swt.widgets.Display;
23
24 import org.eclipse.core.filesystem.EFS;
25 import org.eclipse.core.filesystem.IFileStore;
26
27 import org.eclipse.core.resources.IFile;
28 import org.eclipse.core.resources.IFolder;
29 import org.eclipse.core.resources.IMarker;
30 import org.eclipse.core.resources.IResource;
31
32 import org.eclipse.core.filebuffers.tests.ResourceHelper;
33
34 import org.eclipse.jface.preference.IPreferenceStore;
35
36 import org.eclipse.ui.IEditorPart;
37 import org.eclipse.ui.IWorkbench;
38 import org.eclipse.ui.IWorkbenchPage;
39 import org.eclipse.ui.PlatformUI;
40 import org.eclipse.ui.ide.IDE;
41 import org.eclipse.ui.internal.editors.text.EditorsPlugin;
42 import org.eclipse.ui.intro.IIntroPart;
43
44 import org.eclipse.ui.texteditor.AbstractTextEditor;
45 import org.eclipse.ui.texteditor.ITextEditor;
46
47 /**
48 * Tests opening large files in a text editor.
49 */
50 public class LargeFileTest {
51
52 private IFile fLargeFile;
53
54 private IPreferenceStore preferenceStore;
55
56 boolean initialWordWrap;
57
58 @Before
59 public void setUp() throws Exception {
60 IIntroPart intro = PlatformUI.getWorkbench().getIntroManager().getIntro();
61 if (intro != null) {
62 PlatformUI.getWorkbench().getIntroManager().closeIntro(intro);
63 }
64 IFolder folder = ResourceHelper.createFolder("LargeFileTestProject/test/");
65 fLargeFile = ResourceHelper.createFile(folder, "large.txt", "");
66 IFileStore store = EFS.getLocalFileSystem().getStore(fLargeFile.getLocationURI());
67 try (BufferedWriter writer = new BufferedWriter(
68 new OutputStreamWriter(store.openOutputStream(EFS.NONE, null), StandardCharsets.UTF_8))) {
69 for (int i = 1; i <= 40000; i++) {
70 writer.write("This is line # " + i);
71 writer.newLine();
72 }
73 }
74 fLargeFile.refreshLocal(IResource.DEPTH_ZERO, null);
75 preferenceStore = EditorsPlugin.getDefault().getPreferenceStore();
76 initialWordWrap = preferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_WORD_WRAP_ENABLED);
77 }
78
79 @After
80 public void tearDown() throws Exception {
81 fLargeFile.deleteMarkers(IMarker.BOOKMARK, true, IResource.DEPTH_INFINITE);
82 ResourceHelper.deleteProject("LargeFileTestProject");
83 fLargeFile= null;
84 preferenceStore.setValue(AbstractTextEditor.PREFERENCE_WORD_WRAP_ENABLED, initialWordWrap);
85 TestUtil.cleanUp();
86 }
87
88 @Test
89 public void openLargeFileWithAnnotation() throws Exception {
90 IWorkbench workbench= PlatformUI.getWorkbench();
91 Display display = workbench.getDisplay();
92 IWorkbenchPage page= workbench.getActiveWorkbenchWindow().getActivePage();
93 // Set word-wrap (makes the StyledText have variable line height)
94 preferenceStore.setValue(AbstractTextEditor.PREFERENCE_WORD_WRAP_ENABLED, true);
95 // Let's get an idea how long it takes to open the file at all. Open the
96 // file twice; the first time takes longer.
97 long[] baseline = new long[1];
98 for (int i = 0; i < 2; i++) {
99 baseline[0] = System.nanoTime();
100 IEditorPart part = IDE.openEditor(page, fLargeFile);
101 display.asyncExec(() -> {
102 baseline[0] = System.nanoTime() - baseline[0];
103 });
104 TestUtil.runEventLoop();
105 assertTrue("Expected a text editor", part instanceof ITextEditor);
106 page.closeEditor(part, false);
107 TestUtil.runEventLoop();
108 }
109 // Create a marker on the file
110 IMarker marker = fLargeFile.createMarker(IMarker.BOOKMARK);
111 marker.setAttribute(IMarker.LOCATION, "line 1");
112 marker.setAttribute(IMarker.MESSAGE, "Just a test marker");
113 marker.setAttribute(IMarker.LINE_NUMBER, 1);
114 marker.setAttribute(IMarker.CHAR_START, 8);
115 marker.setAttribute(IMarker.CHAR_END, 12);
116 marker.setAttribute(IMarker.USER_EDITABLE, false);
117 TestUtil.runEventLoop();
118 // Open it again
119 long[] withMarker = { System.nanoTime() };
120 IEditorPart part = IDE.openEditor(page, fLargeFile);
121 display.asyncExec(() -> {
122 withMarker[0] = System.nanoTime() - withMarker[0];
123 });
124 TestUtil.runEventLoop();
125 assertTrue("Expected a text editor", part instanceof ITextEditor);
126 page.closeEditor(part, false);
127 TestUtil.runEventLoop();
128 // Be generous here; all this timing is approximate. Fail if the attempt
129 // with the marker takes more than twice as long. If the OverviewRuler
130 // is badly implemented, opening with the marker will take much longer.
131 assertTrue("Opening large file took too long: " + (withMarker[0] / 1000000.0f) + "ms with marker vs. "
132 + (baseline[0] / 1000000.0f) + "ms without",
133 withMarker[0] / 2 <= baseline[0]);
134 }
135 }
2525
2626 /**
2727 * The example java editor plug-in class.
28 *
28 *
2929 * @since 3.0
3030 */
3131 public class JavaEditorExamplePlugin extends AbstractUIPlugin {
5353
5454 /**
5555 * Returns the default plug-in instance.
56 *
56 *
5757 * @return the default plug-in instance
5858 */
5959 public static JavaEditorExamplePlugin getDefault() {
6262
6363 /**
6464 * Return a scanner for creating Java partitions.
65 *
65 *
6666 * @return a scanner for creating Java partitions
6767 */
6868 public JavaPartitionScanner getJavaPartitionScanner() {
7373
7474 /**
7575 * Returns the singleton Java code scanner.
76 *
76 *
7777 * @return the singleton Java code scanner
7878 */
7979 public RuleBasedScanner getJavaCodeScanner() {
8484
8585 /**
8686 * Returns the singleton Java color provider.
87 *
87 *
8888 * @return the singleton Java color provider
8989 */
9090 public JavaColorProvider getJavaColorProvider() {
9595
9696 /**
9797 * Returns the singleton Javadoc scanner.
98 *
98 *
9999 * @return the singleton Javadoc scanner
100100 */
101101 public RuleBasedScanner getJavaDocScanner() {
2929
3030 /**
3131 * {@inheritDoc}
32 *
32 *
3333 * @deprecated As of 3.4, replaced by
3434 * {@link ITextHoverExtension2#getHoverInfo2(ITextViewer, IRegion)}
3535 */
5959 */
6060 public JavaDocScanner(JavaColorProvider provider) {
6161 super();
62
62
6363 setDefaultReturnToken(new Token(new TextAttribute(provider.getColor(JavaColorProvider.JAVADOC_DEFAULT))));
6464
6565 IToken keyword= new Token(new TextAttribute(provider.getColor(JavaColorProvider.JAVADOC_KEYWORD)));
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.ui.examples.javaeditor; singleton:=true
4 Bundle-Version: 3.2.400.qualifier
4 Bundle-Version: 3.2.500.qualifier
55 Bundle-Activator: org.eclipse.ui.examples.javaeditor.JavaEditorExamplePlugin
66 Bundle-Vendor: %providerName
77 Bundle-Localization: plugin
+0
-23
org.eclipse.ui.examples.javaeditor/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2013 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.ui</groupId>
19 <artifactId>org.eclipse.ui.examples.javaeditor</artifactId>
20 <version>3.2.400-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %Bundle-Name
33 Bundle-SymbolicName: org.eclipse.ui.genericeditor;singleton:=true
4 Bundle-Version: 1.1.500.qualifier
4 Bundle-Version: 1.1.600.qualifier
55 Bundle-Vendor: %Bundle-Vendor
66 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
77 Require-Bundle: org.eclipse.ui.workbench.texteditor;bundle-version="3.10.0",
1818 plugin.properties,\
1919 about.html,\
2020 icons/,\
21 resources/
21 resources/,\
22 schema/
2223
2324 src.includes = about.html,\
2425 schema/
2424 <extension-point id="foldingReconcilers" name="%ExtPoint.foldingReconcilers" schema="schema/foldingReconcilers.exsd"/>
2525 <extension-point id="characterPairMatchers" name="%ExtPoint.characterPairMatchers" schema="schema/characterPairMatchers.exsd"/>
2626 <extension-point id="icons" name="%ExtPoint.iconProviders" schema="schema/icons.exsd"/>
27 <extension-point id="quickAssistProcessors" name="%ExtPoint.quickAssistProcessors" schema="schema/quickAssistProcessors.exsd"/>
2728 <extension
2829 point="org.eclipse.ui.editors">
2930 <editor
229230 class="org.eclipse.ui.internal.genericeditor.GenericEditorWithIconAssociationOverride"
230231 id="org.eclipse.ui.internal.genericeditor.GenericEditorAssociationOverride"/>
231232 </extension>
233 <extension
234 point="org.eclipse.ui.genericeditor.reconcilers">
235 <reconciler
236 class="org.eclipse.jface.text.codemining.CodeMiningReconciler"
237 contentType="org.eclipse.core.runtime.text">
238 </reconciler>
239 </extension>
232240 </plugin>
+0
-23
org.eclipse.ui.genericeditor/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2016 Red Hat Inc. and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Mickael Istria (Red Hat Inc.) - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.ui</groupId>
19 <artifactId>org.eclipse.ui.genericeditor</artifactId>
20 <version>1.1.500-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="characterPairMatchers" name="Character pair matchers"/>
6 </appinfo>
7 <documentation>
8 This extension point is used to contribute character pair matchers for controlling the matching brackets on a file with a given content type.
9 </documentation>
10 </annotation>
11
12 <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
13
14 <element name="extension">
15 <annotation>
16 <appinfo>
17 <meta.element />
18 </appinfo>
19 </annotation>
20 <complexType>
21 <sequence minOccurs="1" maxOccurs="unbounded">
22 <element ref="characterPairMatcher"/>
23 </sequence>
24 <attribute name="point" type="string" use="required">
25 <annotation>
26 <documentation>
27 a fully qualified identifier of the target extension point
28 </documentation>
29 </annotation>
30 </attribute>
31 <attribute name="id" type="string">
32 <annotation>
33 <documentation>
34 an optional identifier of the extension instance
35 </documentation>
36 </annotation>
37 </attribute>
38 <attribute name="name" type="string">
39 <annotation>
40 <documentation>
41 an optional name of the extension instance
42 </documentation>
43 <appinfo>
44 <meta.attribute translatable="true"/>
45 </appinfo>
46 </annotation>
47 </attribute>
48 </complexType>
49 </element>
50
51 <element name="characterPairMatcher">
52 <complexType>
53 <sequence>
54 <element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
55 </sequence>
56 <attribute name="class" type="string" use="required">
57 <annotation>
58 <documentation>
59 The fully qualified class name implementing the interface &lt;code&gt;org.eclipse.jface.text.source.ICharacterPairMatcher&lt;/code&gt;
60 </documentation>
61 <appinfo>
62 <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.source.ICharacterPairMatcher"/>
63 </appinfo>
64 </annotation>
65 </attribute>
66 <attribute name="contentType" type="string" use="required">
67 <annotation>
68 <documentation>
69 The target content-type for this extension. Content-types are defined as extension to the org.eclipse.core.contenttype.contentTypes extension point.
70 </documentation>
71 <appinfo>
72 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
73 </appinfo>
74 </annotation>
75 </attribute>
76 </complexType>
77 </element>
78
79 <element name="enabledWhen">
80 <annotation>
81 <documentation>
82 A core Expression that controls the enabled of the given character pair matcher. The viewer, editor, and editor input are registered in the evaluation context as variable:
83
84 * &lt;with variable=&quot;viewer&quot;/&gt; : use it if your expression requires the viewer.
85 * &lt;with variable=&quot;document&quot;/&gt; : use it if your expression requires the document.
86 * &lt;with variable=&quot;editor&quot;/&gt; : use it if your expression requires the editor (deprecated, not always set).
87 * &lt;with variable=&quot;editorInput&quot;/&gt; : use it if your expression requires the editor input (deprecated, not always set).
88 </documentation>
89 </annotation>
90 <complexType>
91 <choice minOccurs="0" maxOccurs="1">
92 <element ref="not"/>
93 <element ref="or"/>
94 <element ref="and"/>
95 <element ref="instanceof"/>
96 <element ref="test"/>
97 <element ref="systemTest"/>
98 <element ref="equals"/>
99 <element ref="count"/>
100 <element ref="with"/>
101 <element ref="resolve"/>
102 <element ref="adapt"/>
103 <element ref="iterate"/>
104 <element ref="reference"/>
105 </choice>
106 </complexType>
107 </element>
108
109 <annotation>
110 <appinfo>
111 <meta.section type="since"/>
112 </appinfo>
113 <documentation>
114 1.2
115 </documentation>
116 </annotation>
117
118 <annotation>
119 <appinfo>
120 <meta.section type="examples"/>
121 </appinfo>
122 <documentation>
123 Below is an example of how to use the character pair matchers extension point:
124
125 &lt;pre&gt;
126 &lt;extension point=&quot;org.eclipse.ui.genericeditor.characterPairMatchers&quot;&gt;
127 &lt;characterPairMatcher
128 class=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionCharacterPairMatchers&quot;
129 contentType=&quot;org.eclipse.pde.targetFile&quot;&gt;
130 &lt;enabledWhen&gt;
131 &lt;with variable=&quot;editor&quot;&gt;
132 &lt;test property=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionPropertyTester&quot;&gt;
133 &lt;/test&gt;
134 &lt;/with&gt;
135 &lt;/enabledWhen&gt;
136 &lt;/characterPairMatcher&gt;
137 &lt;/extension&gt;
138 &lt;/pre&gt;
139 </documentation>
140 </annotation>
141
142
143
144 <annotation>
145 <appinfo>
146 <meta.section type="copyright"/>
147 </appinfo>
148 <documentation>
149 Copyright (c) 2018 Angelo ZERR and others
150 All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v20.html&quot;&gt;http://www.eclipse.org/legal/epl-v20.html&lt;/a&gt;
151 </documentation>
152 </annotation>
153
154 </schema>
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="characterPairMatchers" name="Character pair matchers"/>
6 </appinfo>
7 <documentation>
8 This extension point is used to contribute character pair matchers for controlling the matching brackets on a file with a given content type.
9 </documentation>
10 </annotation>
11
12 <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
13
14 <element name="extension">
15 <annotation>
16 <appinfo>
17 <meta.element />
18 </appinfo>
19 </annotation>
20 <complexType>
21 <sequence minOccurs="1" maxOccurs="unbounded">
22 <element ref="characterPairMatcher"/>
23 </sequence>
24 <attribute name="point" type="string" use="required">
25 <annotation>
26 <documentation>
27 a fully qualified identifier of the target extension point
28 </documentation>
29 </annotation>
30 </attribute>
31 <attribute name="id" type="string">
32 <annotation>
33 <documentation>
34 an optional identifier of the extension instance
35 </documentation>
36 </annotation>
37 </attribute>
38 <attribute name="name" type="string">
39 <annotation>
40 <documentation>
41 an optional name of the extension instance
42 </documentation>
43 <appinfo>
44 <meta.attribute translatable="true"/>
45 </appinfo>
46 </annotation>
47 </attribute>
48 </complexType>
49 </element>
50
51 <element name="characterPairMatcher">
52 <complexType>
53 <sequence>
54 <element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
55 </sequence>
56 <attribute name="class" type="string" use="required">
57 <annotation>
58 <documentation>
59 The fully qualified class name implementing the interface &lt;code&gt;org.eclipse.jface.text.source.ICharacterPairMatcher&lt;/code&gt;
60 </documentation>
61 <appinfo>
62 <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.source.ICharacterPairMatcher"/>
63 </appinfo>
64 </annotation>
65 </attribute>
66 <attribute name="contentType" type="string" use="required">
67 <annotation>
68 <documentation>
69 The target content-type for this extension. Content-types are defined as extension to the org.eclipse.core.contenttype.contentTypes extension point.
70 </documentation>
71 <appinfo>
72 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
73 </appinfo>
74 </annotation>
75 </attribute>
76 </complexType>
77 </element>
78
79 <element name="enabledWhen">
80 <annotation>
81 <documentation>
82 A core Expression that controls the enabled of the given character pair matcher. The viewer, editor, and editor input are registered in the evaluation context as variable:
83
84 * &lt;with variable=&quot;viewer&quot;/&gt; : use it if your expression requires the viewer.
85 * &lt;with variable=&quot;document&quot;/&gt; : use it if your expression requires the document.
86 * &lt;with variable=&quot;editor&quot;/&gt; : use it if your expression requires the editor (deprecated, not always set).
87 * &lt;with variable=&quot;editorInput&quot;/&gt; : use it if your expression requires the editor input (deprecated, not always set).
88 </documentation>
89 </annotation>
90 <complexType>
91 <choice minOccurs="0" maxOccurs="1">
92 <element ref="not"/>
93 <element ref="or"/>
94 <element ref="and"/>
95 <element ref="instanceof"/>
96 <element ref="test"/>
97 <element ref="systemTest"/>
98 <element ref="equals"/>
99 <element ref="count"/>
100 <element ref="with"/>
101 <element ref="resolve"/>
102 <element ref="adapt"/>
103 <element ref="iterate"/>
104 <element ref="reference"/>
105 </choice>
106 </complexType>
107 </element>
108
109 <annotation>
110 <appinfo>
111 <meta.section type="since"/>
112 </appinfo>
113 <documentation>
114 1.2
115 </documentation>
116 </annotation>
117
118 <annotation>
119 <appinfo>
120 <meta.section type="examples"/>
121 </appinfo>
122 <documentation>
123 Below is an example of how to use the character pair matchers extension point:
124
125 &lt;pre&gt;
126 &lt;extension point=&quot;org.eclipse.ui.genericeditor.characterPairMatchers&quot;&gt;
127 &lt;characterPairMatcher
128 class=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionCharacterPairMatchers&quot;
129 contentType=&quot;org.eclipse.pde.targetFile&quot;&gt;
130 &lt;enabledWhen&gt;
131 &lt;with variable=&quot;editor&quot;&gt;
132 &lt;test property=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionPropertyTester&quot;&gt;
133 &lt;/test&gt;
134 &lt;/with&gt;
135 &lt;/enabledWhen&gt;
136 &lt;/characterPairMatcher&gt;
137 &lt;/extension&gt;
138 &lt;/pre&gt;
139 </documentation>
140 </annotation>
141
142
143
144 <annotation>
145 <appinfo>
146 <meta.section type="copyright"/>
147 </appinfo>
148 <documentation>
149 Copyright (c) 2018 Angelo ZERR and others
150 All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v20.html&quot;&gt;http://www.eclipse.org/legal/epl-v20.html&lt;/a&gt;
151 </documentation>
152 </annotation>
153
154 </schema>
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="foldingReconcilers" name="Folding reconcilers"/>
6 </appinfo>
7 <documentation>
8 This extension point is used to contribute folding reconcilers for controlling the folding on a file with a given content type.
9 </documentation>
10 </annotation>
11
12 <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
13
14 <element name="extension">
15 <annotation>
16 <appinfo>
17 <meta.element />
18 </appinfo>
19 </annotation>
20 <complexType>
21 <sequence minOccurs="1" maxOccurs="unbounded">
22 <element ref="foldingReconciler"/>
23 </sequence>
24 <attribute name="point" type="string" use="required">
25 <annotation>
26 <documentation>
27 a fully qualified identifier of the target extension point
28 </documentation>
29 </annotation>
30 </attribute>
31 <attribute name="id" type="string">
32 <annotation>
33 <documentation>
34 an optional identifier of the extension instance
35 </documentation>
36 </annotation>
37 </attribute>
38 <attribute name="name" type="string">
39 <annotation>
40 <documentation>
41 an optional name of the extension instance
42 </documentation>
43 <appinfo>
44 <meta.attribute translatable="true"/>
45 </appinfo>
46 </annotation>
47 </attribute>
48 </complexType>
49 </element>
50
51 <element name="foldingReconciler">
52 <complexType>
53 <sequence>
54 <element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
55 </sequence>
56 <attribute name="class" type="string" use="required">
57 <annotation>
58 <documentation>
59 The fully qualified class name implementing the interface &lt;code&gt;org.eclipse.jface.text.reconciler.IReconciler&lt;/code&gt;
60 To manipulate folding, the implementation reconciler needs to use ProjectionAnnotation and viewer.getProjectionModel(). You can find a sample in
61 org.eclipse.ui.internal.genericeditor.folding.DefaultFoldingReconciler.
62 </documentation>
63 <appinfo>
64 <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.reconciler.IReconciler"/>
65 </appinfo>
66 </annotation>
67 </attribute>
68 <attribute name="contentType" type="string" use="required">
69 <annotation>
70 <documentation>
71 The target content-type for this extension. Content-types are defined as extension to the org.eclipse.core.contenttype.contentTypes extension point.
72 </documentation>
73 <appinfo>
74 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
75 </appinfo>
76 </annotation>
77 </attribute>
78 </complexType>
79 </element>
80
81 <element name="enabledWhen">
82 <annotation>
83 <documentation>
84 A core Expression that controls the enabled of the given folding reconciler. The viewer, editor, and editor input are registered in the evaluation context as variable:
85
86 * &lt;with variable=&quot;viewer&quot;/&gt; : use it if your expression requires the viewer.
87 * &lt;with variable=&quot;document&quot;/&gt; : use it if your expression requires the document.
88 * &lt;with variable=&quot;editor&quot;/&gt; : use it if your expression requires the editor (deprecated, not always set).
89 * &lt;with variable=&quot;editorInput&quot;/&gt; : use it if your expression requires the editor input (deprecated, not always set).
90 </documentation>
91 </annotation>
92 <complexType>
93 <choice minOccurs="0" maxOccurs="1">
94 <element ref="not"/>
95 <element ref="or"/>
96 <element ref="and"/>
97 <element ref="instanceof"/>
98 <element ref="test"/>
99 <element ref="systemTest"/>
100 <element ref="equals"/>
101 <element ref="count"/>
102 <element ref="with"/>
103 <element ref="resolve"/>
104 <element ref="adapt"/>
105 <element ref="iterate"/>
106 <element ref="reference"/>
107 </choice>
108 </complexType>
109 </element>
110
111 <annotation>
112 <appinfo>
113 <meta.section type="since"/>
114 </appinfo>
115 <documentation>
116 1.1
117 </documentation>
118 </annotation>
119
120 <annotation>
121 <appinfo>
122 <meta.section type="examples"/>
123 </appinfo>
124 <documentation>
125 Below is an example of how to use the Folding Reconciler extension point:
126 &lt;pre&gt;
127 &lt;extension point=&quot;org.eclipse.ui.genericeditor.foldingReconcilers&quot;&gt;
128 &lt;foldingReconciler
129 class=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionFoldingReconciler&quot;
130 contentType=&quot;org.eclipse.pde.targetFile&quot;&gt;
131 &lt;enabledWhen&gt;
132 &lt;with variable=&quot;editor&quot;&gt;
133 &lt;test property=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionPropertyTester&quot;&gt;
134 &lt;/test&gt;
135 &lt;/with&gt;
136 &lt;/enabledWhen&gt;
137 &lt;/foldingReconciler&gt;
138 &lt;/extension&gt;
139 &lt;/pre&gt;
140 </documentation>
141 </annotation>
142
143
144
145 <annotation>
146 <appinfo>
147 <meta.section type="copyright"/>
148 </appinfo>
149 <documentation>
150 Copyright (c) 2017 Red Hat Inc. and others
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="foldingReconcilers" name="Folding reconcilers"/>
6 </appinfo>
7 <documentation>
8 This extension point is used to contribute folding reconcilers for controlling the folding on a file with a given content type.
9 </documentation>
10 </annotation>
11
12 <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
13
14 <element name="extension">
15 <annotation>
16 <appinfo>
17 <meta.element />
18 </appinfo>
19 </annotation>
20 <complexType>
21 <sequence minOccurs="1" maxOccurs="unbounded">
22 <element ref="foldingReconciler"/>
23 </sequence>
24 <attribute name="point" type="string" use="required">
25 <annotation>
26 <documentation>
27 a fully qualified identifier of the target extension point
28 </documentation>
29 </annotation>
30 </attribute>
31 <attribute name="id" type="string">
32 <annotation>
33 <documentation>
34 an optional identifier of the extension instance
35 </documentation>
36 </annotation>
37 </attribute>
38 <attribute name="name" type="string">
39 <annotation>
40 <documentation>
41 an optional name of the extension instance
42 </documentation>
43 <appinfo>
44 <meta.attribute translatable="true"/>
45 </appinfo>
46 </annotation>
47 </attribute>
48 </complexType>
49 </element>
50
51 <element name="foldingReconciler">
52 <complexType>
53 <sequence>
54 <element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
55 </sequence>
56 <attribute name="class" type="string" use="required">
57 <annotation>
58 <documentation>
59 The fully qualified class name implementing the interface &lt;code&gt;org.eclipse.jface.text.reconciler.IReconciler&lt;/code&gt;
60 To manipulate folding, the implementation reconciler needs to use ProjectionAnnotation and viewer.getProjectionModel(). You can find a sample in
61 org.eclipse.ui.internal.genericeditor.folding.DefaultFoldingReconciler.
62 </documentation>
63 <appinfo>
64 <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.reconciler.IReconciler"/>
65 </appinfo>
66 </annotation>
67 </attribute>
68 <attribute name="contentType" type="string" use="required">
69 <annotation>
70 <documentation>
71 The target content-type for this extension. Content-types are defined as extension to the org.eclipse.core.contenttype.contentTypes extension point.
72 </documentation>
73 <appinfo>
74 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
75 </appinfo>
76 </annotation>
77 </attribute>
78 </complexType>
79 </element>
80
81 <element name="enabledWhen">
82 <annotation>
83 <documentation>
84 A core Expression that controls the enabled of the given folding reconciler. The viewer, editor, and editor input are registered in the evaluation context as variable:
85
86 * &lt;with variable=&quot;viewer&quot;/&gt; : use it if your expression requires the viewer.
87 * &lt;with variable=&quot;document&quot;/&gt; : use it if your expression requires the document.
88 * &lt;with variable=&quot;editor&quot;/&gt; : use it if your expression requires the editor (deprecated, not always set).
89 * &lt;with variable=&quot;editorInput&quot;/&gt; : use it if your expression requires the editor input (deprecated, not always set).
90 </documentation>
91 </annotation>
92 <complexType>
93 <choice minOccurs="0" maxOccurs="1">
94 <element ref="not"/>
95 <element ref="or"/>
96 <element ref="and"/>
97 <element ref="instanceof"/>
98 <element ref="test"/>
99 <element ref="systemTest"/>
100 <element ref="equals"/>
101 <element ref="count"/>
102 <element ref="with"/>
103 <element ref="resolve"/>
104 <element ref="adapt"/>
105 <element ref="iterate"/>
106 <element ref="reference"/>
107 </choice>
108 </complexType>
109 </element>
110
111 <annotation>
112 <appinfo>
113 <meta.section type="since"/>
114 </appinfo>
115 <documentation>
116 1.1
117 </documentation>
118 </annotation>
119
120 <annotation>
121 <appinfo>
122 <meta.section type="examples"/>
123 </appinfo>
124 <documentation>
125 Below is an example of how to use the Folding Reconciler extension point:
126 &lt;pre&gt;
127 &lt;extension point=&quot;org.eclipse.ui.genericeditor.foldingReconcilers&quot;&gt;
128 &lt;foldingReconciler
129 class=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionFoldingReconciler&quot;
130 contentType=&quot;org.eclipse.pde.targetFile&quot;&gt;
131 &lt;enabledWhen&gt;
132 &lt;with variable=&quot;editor&quot;&gt;
133 &lt;test property=&quot;org.eclipse.ui.genericeditor.examples.TargetDefinitionPropertyTester&quot;&gt;
134 &lt;/test&gt;
135 &lt;/with&gt;
136 &lt;/enabledWhen&gt;
137 &lt;/foldingReconciler&gt;
138 &lt;/extension&gt;
139 &lt;/pre&gt;
140 </documentation>
141 </annotation>
142
143
144
145 <annotation>
146 <appinfo>
147 <meta.section type="copyright"/>
148 </appinfo>
149 <documentation>
150 Copyright (c) 2017 Red Hat Inc. and others
151151
152152 This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at &lt;a href=&quot;https://www.eclipse.org/legal/epl-2.0&quot;&gt;https://www.eclipse.org/legal/epl-v20.html&lt;/a&gt;/
153153
154 SPDX-License-Identifier: EPL-2.0
155 </documentation>
156 </annotation>
157
158 </schema>
154 SPDX-License-Identifier: EPL-2.0
155 </documentation>
156 </annotation>
157
158 </schema>
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="icons" name="GenericEditorIcons"/>
6 </appinfo>
7 <documentation>
8 The icons extension point provides a way of linking different types of icons to a particular content type.
9 </documentation>
10 </annotation>
11
12 <element name="extension">
13 <annotation>
14 <appinfo>
15 <meta.element />
16 </appinfo>
17 </annotation>
18 <complexType>
19 <sequence>
20 <element ref="icon" minOccurs="0" maxOccurs="unbounded"/>
21 </sequence>
22 <attribute name="point" type="string" use="required">
23 <annotation>
24 <documentation>
25
26 </documentation>
27 </annotation>
28 </attribute>
29 <attribute name="id" type="string">
30 <annotation>
31 <documentation>
32
33 </documentation>
34 </annotation>
35 </attribute>
36 <attribute name="name" type="string">
37 <annotation>
38 <documentation>
39
40 </documentation>
41 <appinfo>
42 <meta.attribute translatable="true"/>
43 </appinfo>
44 </annotation>
45 </attribute>
46 </complexType>
47 </element>
48
49 <element name="icon">
50 <annotation>
51 <appinfo>
52 <meta.element labelAttribute="contentType"/>
53 </appinfo>
54 <documentation>
55 The icon to associate with a particular content type.
56 </documentation>
57 </annotation>
58 <complexType>
59 <attribute name="contentType" type="string" use="required">
60 <annotation>
61 <documentation>
62 The identifier of the content type with which the icons should be associated.
63 </documentation>
64 <appinfo>
65 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
66 </appinfo>
67 </annotation>
68 </attribute>
69 <attribute name="icon" type="string" use="required">
70 <annotation>
71 <documentation>
72 The path to the icon which should be used.
73 </documentation>
74 <appinfo>
75 <meta.attribute kind="resource"/>
76 </appinfo>
77 </annotation>
78 </attribute>
79 </complexType>
80 </element>
81
82 <annotation>
83 <appinfo>
84 <meta.section type="since"/>
85 </appinfo>
86 <documentation>
87 1.1.500
88 </documentation>
89 </annotation>
90
91 <annotation>
92 <appinfo>
93 <meta.section type="examples"/>
94 </appinfo>
95 <documentation>
96 &lt;pre&gt;
97 &lt;extension
98 point=&quot;org.eclipse.ui.genericeditor.icons&quot;&gt;
99 &lt;icon
100 contentType=&quot;org.eclipse.core.runtime.xml&quot;
101 icon=&quot;icons/xml_content.png&quot; /&gt;
102 &lt;/extension&gt;
103 &lt;/pre&gt;
104 &lt;pre&gt;
105 &lt;extension
106 point=&quot;org.eclipse.ui.genericeditor.icons&quot;&gt;
107 &lt;icon
108 contentType=&quot;org.eclipse.core.runtime.text&quot;
109 icon=&quot;platform:/plugin/org.eclipse.ui.test/icons/text_content.png&quot; /&gt;
110 &lt;/extension&gt;
111 &lt;/pre&gt;
112 </documentation>
113 </annotation>
114
115
116
117 <annotation>
118 <appinfo>
119 <meta.section type="copyright"/>
120 </appinfo>
121 <documentation>
122 Copyright (c) 2019 Lakshminarayana Nekkanti(narayana.nekkanti@gmail.com)
123
124 This program and the accompanying materials are made available under the
125 terms of the Eclipse Public License 2.0 which is available at
126 http://www.eclipse.org/legal/epl-2.0.
127
128 SPDX-License-Identifier: EPL-2.0 3
129
130 Contributor
131 Lakshminarayana Nekkanti - initial API and implementation
132 </documentation>
133 </annotation>
134
135 </schema>
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="icons" name="GenericEditorIcons"/>
6 </appinfo>
7 <documentation>
8 The icons extension point provides a way of linking different types of icons to a particular content type.
9 </documentation>
10 </annotation>
11
12 <element name="extension">
13 <annotation>
14 <appinfo>
15 <meta.element />
16 </appinfo>
17 </annotation>
18 <complexType>
19 <sequence>
20 <element ref="icon" minOccurs="0" maxOccurs="unbounded"/>
21 </sequence>
22 <attribute name="point" type="string" use="required">
23 <annotation>
24 <documentation>
25
26 </documentation>
27 </annotation>
28 </attribute>
29 <attribute name="id" type="string">
30 <annotation>
31 <documentation>
32
33 </documentation>
34 </annotation>
35 </attribute>
36 <attribute name="name" type="string">
37 <annotation>
38 <documentation>
39
40 </documentation>
41 <appinfo>
42 <meta.attribute translatable="true"/>
43 </appinfo>
44 </annotation>
45 </attribute>
46 </complexType>
47 </element>
48
49 <element name="icon">
50 <annotation>
51 <appinfo>
52 <meta.element labelAttribute="contentType"/>
53 </appinfo>
54 <documentation>
55 The icon to associate with a particular content type.
56 </documentation>
57 </annotation>
58 <complexType>
59 <attribute name="contentType" type="string" use="required">
60 <annotation>
61 <documentation>
62 The identifier of the content type with which the icons should be associated.
63 </documentation>
64 <appinfo>
65 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
66 </appinfo>
67 </annotation>
68 </attribute>
69 <attribute name="icon" type="string" use="required">
70 <annotation>
71 <documentation>
72 The path to the icon which should be used.
73 </documentation>
74 <appinfo>
75 <meta.attribute kind="resource"/>
76 </appinfo>
77 </annotation>
78 </attribute>
79 </complexType>
80 </element>
81
82 <annotation>
83 <appinfo>
84 <meta.section type="since"/>
85 </appinfo>
86 <documentation>
87 1.1.500
88 </documentation>
89 </annotation>
90
91 <annotation>
92 <appinfo>
93 <meta.section type="examples"/>
94 </appinfo>
95 <documentation>
96 &lt;pre&gt;
97 &lt;extension
98 point=&quot;org.eclipse.ui.genericeditor.icons&quot;&gt;
99 &lt;icon
100 contentType=&quot;org.eclipse.core.runtime.xml&quot;
101 icon=&quot;icons/xml_content.png&quot; /&gt;
102 &lt;/extension&gt;
103 &lt;/pre&gt;
104 &lt;pre&gt;
105 &lt;extension
106 point=&quot;org.eclipse.ui.genericeditor.icons&quot;&gt;
107 &lt;icon
108 contentType=&quot;org.eclipse.core.runtime.text&quot;
109 icon=&quot;platform:/plugin/org.eclipse.ui.test/icons/text_content.png&quot; /&gt;
110 &lt;/extension&gt;
111 &lt;/pre&gt;
112 </documentation>
113 </annotation>
114
115
116
117 <annotation>
118 <appinfo>
119 <meta.section type="copyright"/>
120 </appinfo>
121 <documentation>
122 Copyright (c) 2019 Lakshminarayana Nekkanti(narayana.nekkanti@gmail.com)
123
124 This program and the accompanying materials are made available under the
125 terms of the Eclipse Public License 2.0 which is available at
126 http://www.eclipse.org/legal/epl-2.0.
127
128 SPDX-License-Identifier: EPL-2.0 3
129
130 Contributor
131 Lakshminarayana Nekkanti - initial API and implementation
132 </documentation>
133 </annotation>
134
135 </schema>
0 <?xml version='1.0' encoding='UTF-8'?>
1 <!-- Schema file written by PDE -->
2 <schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
3 <annotation>
4 <appinfo>
5 <meta.schema plugin="org.eclipse.ui.genericeditor" id="quickAssistProcessors" name="%ExtPoint.quickAssistProcessors"/>
6 </appinfo>
7 <documentation>
8 This extension point is used to contribute quick assist processors for quick content assist support to a given content type.
9 </documentation>
10 </annotation>
11
12 <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
13
14 <element name="extension">
15 <annotation>
16 <appinfo>
17 <meta.element />
18 </appinfo>
19 </annotation>
20 <complexType>
21 <sequence minOccurs="1" maxOccurs="unbounded">
22 <element ref="quickAssistProcessor"/>
23 </sequence>
24 <attribute name="point" type="string" use="required">
25 <annotation>
26 <documentation>
27
28 </documentation>
29 </annotation>
30 </attribute>
31 <attribute name="id" type="string">
32 <annotation>
33 <documentation>
34
35 </documentation>
36 </annotation>
37 </attribute>
38 <attribute name="name" type="string">
39 <annotation>
40 <documentation>
41
42 </documentation>
43 <appinfo>
44 <meta.attribute translatable="true"/>
45 </appinfo>
46 </annotation>
47 </attribute>
48 </complexType>
49 </element>
50
51 <element name="quickAssistProcessor">
52 <complexType>
53 <attribute name="class" type="string" use="required">
54 <annotation>
55 <documentation>
56
57 </documentation>
58 <appinfo>
59 <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.quickassist.IQuickAssistProcessor"/>
60 </appinfo>
61 </annotation>
62 </attribute>
63 <attribute name="contentType" type="string" use="required">
64 <annotation>
65 <documentation>
66 The target content-type for this extension. Content-types are defined as extension to the org.eclipse.core.contenttype.contentTypes extension point.
67 </documentation>
68 <appinfo>
69 <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
70 </appinfo>
71 </annotation>
72 </attribute>
73 </complexType>
74 </element>
75
76 <annotation>
77 <appinfo>
78 <meta.section type="since"/>
79 </appinfo>
80 <documentation>
81 1.1.600
82 </documentation>
83 </annotation>
84
85 <annotation>
86 <appinfo>
87 <meta.section type="examples"/>
88 </appinfo>
89 <documentation>
90 &lt;extension
91 point=&quot;org.eclipse.ui.genericeditor.quickAssistProcessors&quot;&gt;
92 &lt;quickAssistProcessor
93 class=&quot;org.eclipse.ui.genericeditor.tests.contributions.QuickAssistProcessor&quot;
94 contentType=&quot;org.eclipse.ui.genericeditor.tests.content-type&quot;&gt;
95 &lt;/quickAssistProcessor&gt;
96 &lt;/extension&gt;
97 </documentation>
98 </annotation>
99
100 <annotation>
101 <appinfo>
102 <meta.section type="apiinfo"/>
103 </appinfo>
104 <documentation>
105 This extension point does not require specific API&apos;s to use. Instead, it reuses IQuickAssistProcessor from org.jface.text.quickassist
106 </documentation>
107 </annotation>
108
109
110
111 </schema>
2727 * constructor.
2828 */
2929 public class AnnotationHoverDelegate implements ITextHover {
30
30
3131 private DefaultTextHover delegate;
3232 private ISourceViewer viewer;
3333
3434 * A registry of auto edit strategies provided by extension
3535 * <code>org.eclipse.ui.genericeditor.autoEditStrategy</code>. Those extensions
3636 * are specific to a given {@link IContentType}.
37 *
37 *
3838 * @since 1.1
3939 */
4040 public class AutoEditStrategyRegistry {
5959 /**
6060 * Get the contributed {@link IAutoEditStrategy}s that are relevant to hook
6161 * on source viewer according to document content types.
62 *
62 *
6363 * @param sourceViewer
6464 * the source viewer we're hooking completion to.
6565 * @param editor the text editor
3131 * A registry of character pair matchers provided by extension
3232 * <code>org.eclipse.ui.genericeditor.characterPairMatchers</code>. Those
3333 * extensions are specific to a given {@link IContentType}.
34 *
34 *
3535 * @since 1.2
3636 */
3737 public class CharacterPairMatcherRegistry {
5656 /**
5757 * Get the contributed {@link IPresentationReconciliers}s that are relevant to
5858 * hook on source viewer according to document content types.
59 *
59 *
6060 * @param sourceViewer the source viewer we're hooking completion to.
6161 * @param editor the text editor
6262 * @param contentTypes the content types of the document we're editing.
2828 * A content assist processor that delegates all content assist
2929 * operations to children provided in constructor and aggregates
3030 * the results.
31 *
31 *
3232 * @since 1.0
3333 */
3434 public class CompositeContentAssistProcessor implements IContentAssistProcessor {
2525 * A quick assist processor that delegates all content assist
2626 * operations to children provided in constructor and aggregates
2727 * the results.
28 *
28 *
2929 * @since 1.0
3030 */
3131 public class CompositeQuickAssistProcessor implements IQuickAssistProcessor {
1212 *******************************************************************************/
1313 package org.eclipse.ui.internal.genericeditor;
1414
15 import java.util.HashMap;
1615 import java.util.HashSet;
16 import java.util.LinkedHashMap;
1717 import java.util.List;
1818 import java.util.Map;
1919 import java.util.Set;
4141 /**
4242 * A registry of content assist processors provided by extension <code>org.eclipse.ui.genericeditor.contentAssistProcessors</code>.
4343 * Those extensions are specific to a given {@link IContentType}.
44 *
44 *
4545 * @since 1.0
4646 */
4747 public class ContentAssistProcessorRegistry {
129129 }
130130 }
131131
132 private Map<IConfigurationElement, GenericContentTypeRelatedExtension<IContentAssistProcessor>> extensions = new HashMap<>();
132 private Map<IConfigurationElement, GenericContentTypeRelatedExtension<IContentAssistProcessor>> extensions = new LinkedHashMap<>();
133133 private boolean outOfSync = true;
134134
135135 /**
146146
147147 /**
148148 * Get the contributed {@link IContentAssistProcessor}s that are relevant to hook on source viewer according
149 * to document content types.
149 * to document content types.
150150 * @param sourceViewer the source viewer we're hooking completion to.
151151 * @param editor the text editor
152152 * @param contentTypes the content types of the document we're editing.
5252 String[] tokens = text.split(NON_ALPHANUMERIC_REGEXP);
5353
5454 //remove duplicates
55 Set<String> tokenSet = new HashSet<String>(Arrays.asList(tokens));
55 Set<String> tokenSet = new HashSet<>(Arrays.asList(tokens));
5656
5757 //wordStartIndex is the index of the last non-alphanumeric before 'offset' in text 'text'
5858 int wordStartIndex = findStartingPoint(text, offset);
5959 String prefix = text.substring(wordStartIndex, offset);
6060
61 List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
61 List<ICompletionProposal> proposals = new ArrayList<>();
6262 for (String token : tokenSet) {
6363 if ((token==null)||(token.length()<2)) {
6464 continue;
104104 }
105105
106106 IAnnotationModel annotationModel = sourceViewer.getAnnotationModel();
107 synchronized (getLockObject(annotationModel)) {
108 if (annotationModel instanceof IAnnotationModelExtension) {
109 ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap);
110 } else {
111 removeOccurrenceAnnotations();
112 Iterator<Entry<Annotation, Position>> iter = annotationMap.entrySet().iterator();
113 while (iter.hasNext()) {
114 Entry<Annotation, Position> mapEntry = iter.next();
115 annotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
107 if (annotationModel != null) {
108 synchronized (getLockObject(annotationModel)) {
109 if (annotationModel instanceof IAnnotationModelExtension) {
110 ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap);
111 } else {
112 removeOccurrenceAnnotations();
113 Iterator<Entry<Annotation, Position>> iter = annotationMap.entrySet().iterator();
114 while (iter.hasNext()) {
115 Entry<Annotation, Position> mapEntry = iter.next();
116 annotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
117 }
116118 }
117 }
118 fOccurrenceAnnotations = annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
119 fOccurrenceAnnotations = annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
120 }
121 } else {
122 fOccurrenceAnnotations = null;
119123 }
120124 }
121125
5555 private ImageDescriptor contentTypeImageDescripter;
5656
5757 /**
58 *
58 *
5959 */
6060 public ExtensionBasedTextEditor() {
6161 configuration = new ExtensionBasedTextViewerConfiguration(this, getPreferenceStore());
100100
101101 /**
102102 * Configure the {@link ICharacterPairMatcher} from the "org.eclipse.ui.genericeditor.characterPairMatchers" extension point.
103 *
103 *
104104 * @param viewer
105105 * the source viewer.
106 *
106 *
107107 * @param support
108108 * the source viewer decoration support.
109109 */
1616 *******************************************************************************/
1717 package org.eclipse.ui.internal.genericeditor;
1818
19 import java.util.ArrayList;
1920 import java.util.Arrays;
2021 import java.util.Collections;
2122 import java.util.LinkedHashSet;
4344 import org.eclipse.jface.text.contentassist.IContentAssistant;
4445 import org.eclipse.jface.text.presentation.IPresentationReconciler;
4546 import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
47 import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
4648 import org.eclipse.jface.text.quickassist.QuickAssistAssistant;
4749 import org.eclipse.jface.text.reconciler.IReconciler;
4850 import org.eclipse.jface.text.source.ISourceViewer;
191193
192194 @Override public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
193195 QuickAssistAssistant quickAssistAssistant = new QuickAssistAssistant();
194 quickAssistAssistant.setQuickAssistProcessor(new MarkerResoltionQuickAssistProcessor());
196 List<IQuickAssistProcessor> quickAssistProcessors = new ArrayList<>();
197 quickAssistProcessors.add(new MarkerResoltionQuickAssistProcessor());
198 quickAssistProcessors.addAll(GenericEditorPlugin.getDefault().getQuickAssistProcessorRegistry().getQuickAssistProcessors(sourceViewer, editor, getContentTypes(sourceViewer)));
199 CompositeQuickAssistProcessor compQuickAssistProcessor = new CompositeQuickAssistProcessor(quickAssistProcessors);
200 quickAssistAssistant.setQuickAssistProcessor(compQuickAssistProcessor);
195201 quickAssistAssistant.setRestoreCompletionProposalSize(EditorsPlugin.getDefault().getDialogSettingsSection("quick_assist_proposal_size")); //$NON-NLS-1$
196202 quickAssistAssistant.setInformationControlCreator(parent -> new DefaultInformationControl(parent, EditorsPlugin.getAdditionalInfoAffordanceString()));
197203 return quickAssistAssistant;
2828
2929 /**
3030 * This class wraps and proxies an instance of T provided through extensions and loads it lazily when it can contribute to the editor, then delegates all operations to actual instance.
31 *
31 *
3232 * @param <T>
3333 * the actual type to proxy, typically the one defined on the extension point.
3434 */
1717 import org.eclipse.jface.text.ITextHover;
1818 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
1919 import org.eclipse.jface.text.presentation.IPresentationReconciler;
20 import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
2021 import org.eclipse.jface.text.reconciler.IReconciler;
2122 import org.eclipse.jface.text.source.ICharacterPairMatcher;
2223 import org.eclipse.jface.util.IPropertyChangeListener;
3132
3233 /**
3334 * Generic editor plugin activator and singletons.
34 *
35 *
3536 * @since 1.0
3637 */
3738 public class GenericEditorPlugin extends AbstractUIPlugin {
4243
4344 private TextHoverRegistry textHoversRegistry;
4445 private ContentAssistProcessorRegistry contentAssistProcessorsRegistry;
46 private QuickAssistProcessorRegistry quickAssistProcessorRegistry;
4547 private ReconcilerRegistry reconcilierRegistry;
4648 private PresentationReconcilerRegistry presentationReconcilierRegistry;
4749 private AutoEditStrategyRegistry autoEditStrategyRegistry;
106108 }
107109
108110 /**
111 * @return the registry allowing to access contributed
112 * {@link IQuickAssistProcessor}s.
113 * @since 1.2
114 */
115 public synchronized QuickAssistProcessorRegistry getQuickAssistProcessorRegistry() {
116 if (this.quickAssistProcessorRegistry == null) {
117 this.quickAssistProcessorRegistry = new QuickAssistProcessorRegistry();
118 }
119 return this.quickAssistProcessorRegistry;
120 }
121
122 /**
109123 * @return the registry allowing to access contributed {@link IReconciler}s.
110124 * @since 1.1
111125 */
2828 */
2929 public class GenericEditorWithIconAssociationOverride implements IEditorAssociationOverride {
3030
31 private Map<String, IEditorDescriptor> descriptorMap = new HashMap<String, IEditorDescriptor>();
31 private Map<String, IEditorDescriptor> descriptorMap = new HashMap<>();
3232
3333 @Override
3434 public IEditorDescriptor[] overrideEditors(IEditorInput editorInput, IContentType contentType,
3333 /**
3434 * A registry of presentation reconciliers provided by extension <code>org.eclipse.ui.genericeditor.presentationReconcilers</code>.
3535 * Those extensions are specific to a given {@link IContentType}.
36 *
36 *
3737 * @since 1.0
3838 */
3939 public class PresentationReconcilerRegistry {
5757
5858 /**
5959 * Get the contributed {@link IPresentationReconciliers}s that are relevant to hook on source viewer according
60 * to document content types.
60 * to document content types.
6161 * @param sourceViewer the source viewer we're hooking completion to.
6262 * @param editor the text editor
6363 * @param contentTypes the content types of the document we're editing.
0 /*******************************************************************************
1 * Copyright (c) 2016-2019 Red Hat Inc. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * - Andrew Obuchowicz (Red Hat Inc.)
12 *******************************************************************************/
13 package org.eclipse.ui.internal.genericeditor;
14
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.stream.Collectors;
21
22 import org.eclipse.core.runtime.IConfigurationElement;
23 import org.eclipse.core.runtime.IRegistryChangeEvent;
24 import org.eclipse.core.runtime.IRegistryChangeListener;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Platform;
27 import org.eclipse.core.runtime.Status;
28 import org.eclipse.core.runtime.content.IContentType;
29 import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
30 import org.eclipse.jface.text.source.ISourceViewer;
31 import org.eclipse.ui.texteditor.ITextEditor;
32
33 public class QuickAssistProcessorRegistry {
34
35 private static final String EXTENSION_POINT_ID = GenericEditorPlugin.BUNDLE_ID + ".quickAssistProcessors"; //$NON-NLS-1$
36 private Map<IConfigurationElement, GenericContentTypeRelatedExtension<IQuickAssistProcessor>> extensions = new HashMap<>();
37 private boolean outOfSync = true;
38
39 /**
40 * Creates the registry and binds it to the extension point.
41 */
42 public QuickAssistProcessorRegistry() {
43 Platform.getExtensionRegistry().addRegistryChangeListener(new IRegistryChangeListener() {
44 @Override
45 public void registryChanged(IRegistryChangeEvent event) {
46 outOfSync = true;
47 }
48 }, EXTENSION_POINT_ID);
49 }
50
51 /**
52 * Get the contributed {@link IQuickAssistProcessor}s
53 *
54 * @return the list of {@link IQuickAssistProcessor} contributed
55 */
56
57 public List<IQuickAssistProcessor> getQuickAssistProcessors(ISourceViewer sourceViewer, ITextEditor editor,
58 Set<IContentType> contentTypes) {
59 if (this.outOfSync) {
60 sync();
61 }
62 return this.extensions.values().stream()
63 .filter(ext -> contentTypes.contains(ext.targetContentType))
64 .filter(ext -> ext.matches(sourceViewer, editor))
65 .sorted(new ContentTypeSpecializationComparator<IQuickAssistProcessor>())
66 .map(GenericContentTypeRelatedExtension<IQuickAssistProcessor>::createDelegate)
67 .collect(Collectors.toList());
68 }
69
70 private void sync() {
71 Set<IConfigurationElement> toRemoveExtensions = new HashSet<>(this.extensions.keySet());
72 for (IConfigurationElement extension : Platform.getExtensionRegistry()
73 .getConfigurationElementsFor(EXTENSION_POINT_ID)) {
74 toRemoveExtensions.remove(extension);
75 if (!this.extensions.containsKey(extension)) {
76 try {
77 this.extensions.put(extension,
78 new GenericContentTypeRelatedExtension<IQuickAssistProcessor>(extension));
79 } catch (Exception ex) {
80 GenericEditorPlugin.getDefault().getLog()
81 .log(new Status(IStatus.ERROR, GenericEditorPlugin.BUNDLE_ID, ex.getMessage(), ex));
82 }
83 }
84 }
85 for (IConfigurationElement toRemove : toRemoveExtensions) {
86 this.extensions.remove(toRemove);
87 }
88 this.outOfSync = false;
89 }
90
91 }
6969 /**
7070 * Get the contributed {@link IReconciliers}s that are relevant to hook on
7171 * source viewer according to document content types.
72 *
72 *
7373 * @param sourceViewer the source viewer we're hooking completion to.
7474 * @param editor the text editor
7575 * @param contentTypes the content types of the document we're editing.
9292 /**
9393 * Get the contributed highlight {@link IReconciliers}s that are relevant to
9494 * hook on source viewer according to document content types.
95 *
95 *
9696 * @param sourceViewer the source viewer we're hooking completion to.
9797 * @param editor the text editor
9898 * @param contentTypes the content types of the document we're editing.
116116 /**
117117 * Get the contributed folding {@link IReconciliers}s that are relevant to hook
118118 * on source viewer according to document content types.
119 *
119 *
120120 * @param sourceViewer the source viewer we're hooking completion to.
121121 * @param editor the text editor
122122 * @param contentTypes the content types of the document we're editing.
66 * https://www.eclipse.org/legal/epl-2.0/
77 *
88 * SPDX-License-Identifier: EPL-2.0
9 *
9 *
1010 * Contributors:
1111 * IBM Corporation - initial API and implementation
1212 * Angelo Zerr <angelo.zerr@gmail.com> - adapt code org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingStrategy to support generic indent folding strategy.
13 * [generic editor] Default Code folding for generic editor should use IndentFoldingStrategy - Bug 520659
13 * [generic editor] Default Code folding for generic editor should use IndentFoldingStrategy - Bug 520659
1414 */
1515 package org.eclipse.ui.internal.genericeditor.folding;
1616
6767
6868 /**
6969 * Creates a new FoldingAnnotation.
70 *
70 *
7171 * @param isCollapsed true if this annotation should be collapsed, false
7272 * otherwise
7373 */
7979 /**
8080 * Does not paint hidden annotations. Annotations are hidden when they only span
8181 * one line.
82 *
82 *
8383 * @see ProjectionAnnotation#paint(org.eclipse.swt.graphics.GC,
8484 * org.eclipse.swt.widgets.Canvas, org.eclipse.swt.graphics.Rectangle)
8585 */
117117
118118 /**
119119 * The folding strategy must be associated with a viewer for it to function
120 *
120 *
121121 * @param viewer the viewer to associate this folding strategy with
122122 */
123123 public void setViewer(ProjectionViewer viewer) {
173173
174174 // these are what are passed off to the annotation model to
175175 // actually create and maintain the annotations
176 List<Annotation> modifications = new ArrayList<Annotation>();
177 List<FoldingAnnotation> deletions = new ArrayList<FoldingAnnotation>();
178 List<FoldingAnnotation> existing = new ArrayList<FoldingAnnotation>();
179 Map<Annotation, Position> additions = new HashMap<Annotation, Position>();
176 List<Annotation> modifications = new ArrayList<>();
177 List<FoldingAnnotation> deletions = new ArrayList<>();
178 List<FoldingAnnotation> existing = new ArrayList<>();
179 Map<Annotation, Position> additions = new HashMap<>();
180180
181181 // find and mark all folding annotations with length 0 for deletion
182182 markInvalidAnnotationsForDeletion(dirtyRegion, deletions, existing);
183183
184 List<LineIndent> previousRegions = new ArrayList<LineIndent>();
184 List<LineIndent> previousRegions = new ArrayList<>();
185185
186186 int tabSize = 1;
187187 int minimumRangeSize = 1;
290290
291291 /**
292292 * Returns the line state for line which starts with a given keyword.
293 *
293 *
294294 * @param lineContent line content.
295295 * @param lastLineForKeyword last line for the given keyword.
296296 * @return
313313
314314 /**
315315 * Compute indentation level of the given line by using the given tab size.
316 *
316 *
317317 * @param line the line text.
318318 * @param tabSize the tab size.
319319 * @return the indentation level of the given line by using the given tab size.
341341 /**
342342 * Given a {@link DirtyRegion} returns an {@link Iterator} of the already
343343 * existing annotations in that region.
344 *
344 *
345345 * @param dirtyRegion the {@link DirtyRegion} to check for existing annotations
346346 * in
347 *
347 *
348348 * @return an {@link Iterator} over the annotations in the given
349349 * {@link DirtyRegion}. The iterator could have no annotations in it. Or
350350 * <code>null</code> if projection has been disabled.
361361
362362 /**
363363 * Update annotations.
364 *
364 *
365365 * @param modifications the folding annotations to update.
366366 * @param deletions the folding annotations to delete.
367367 * @param existing the existing folding annotations.
386386
387387 /**
388388 * Update annotations.
389 *
389 *
390390 * @param existingAnnotation the existing annotations that need to be updated
391391 * based on the given dirtied IndexRegion
392392 * @param newPos the new position that caused the annotations need
423423 * These {@link FoldingAnnotation}s are then added to the {@link List} of
424424 * {@link FoldingAnnotation}s to be deleted
425425 * </p>
426 *
426 *
427427 * @param dirtyRegion find the now invalid {@link FoldingAnnotation}s in this
428428 * {@link DirtyRegion}
429429 * @param deletions the current list of {@link FoldingAnnotation}s marked for
112112 } while (thisIterator.hasNext());
113113 return true;
114114 }
115
115
116116
117117 @Override
118118 public IInformationControl createInformationControl(Shell parent) {
3737 * <p>
3838 * Value is of type <code>Boolean</code>.
3939 * </p>
40 *
40 *
4141 * @since 1.2
4242 */
4343 public final static String EDITOR_MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1$
5151 *
5252 * @see org.eclipse.jface.resource.StringConverter
5353 * @see org.eclipse.jface.preference.PreferenceConverter
54 *
54 *
5555 * @since 1.2
5656 */
5757 public final static String EDITOR_MATCHING_BRACKETS_COLOR = "matchingBracketsColor"; //$NON-NLS-1$
6262 * <p>
6363 * Value is of type <code>Boolean</code>.
6464 * </p>
65 *
65 *
6666 * @since 1.2
6767 */
6868 public final static String EDITOR_HIGHLIGHT_BRACKET_AT_CARET_LOCATION = "highlightBracketAtCaretLocation"; //$NON-NLS-1$
7373 * <p>
7474 * Value is of type <code>Boolean</code>.
7575 * </p>
76 *
76 *
7777 * @since 1.2
7878 */
7979 public final static String EDITOR_ENCLOSING_BRACKETS = "enclosingBrackets"; //$NON-NLS-1$
11 Bundle-ManifestVersion: 2
22 Bundle-Name: Examples for Generic Editor
33 Bundle-SymbolicName: org.eclipse.ui.genericeditor.examples;singleton:=true
4 Bundle-Version: 1.1.400.qualifier
4 Bundle-Version: 1.1.500.qualifier
55 Bundle-Vendor: Eclipse.org
66 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
77 Require-Bundle: org.eclipse.ui.genericeditor;bundle-version="1.0.0",
+0
-23
org.eclipse.ui.genericeditor.examples/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2016 Red Hat Inc. and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Mickael Istria (Red Hat Inc.) - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.ui</groupId>
19 <artifactId>org.eclipse.ui.genericeditor.examples</artifactId>
20 <version>1.1.400-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
3838 import org.eclipse.ui.texteditor.spelling.SpellingService;
3939
4040 public class SpellCheckDocumentListener implements IDocumentListener {
41
41
4242 Job lastJob = null;
4343 SpellingService service = EditorsUI.getSpellingService();
4444
7272 Region region = new Region(commentStart, commentEnd - commentStart);
7373 service.check(event.getDocument(), new Region[] { region }, new SpellingContext(), new ISpellingProblemCollector() {
7474 private Map<SpellingAnnotation, Position> annotations = new HashMap<>();
75
75
7676 @Override
7777 public void endCollecting() {
7878 Set<SpellingAnnotation> previous = new HashSet<>();
8585 ((IAnnotationModelExtension)model).replaceAnnotations(
8686 previous.toArray(new SpellingAnnotation[previous.size()]),
8787 annotations);
88
88
8989 } else {
9090 previous.forEach(model::removeAnnotation);
9191 annotations.forEach(model::addAnnotation);
9292 }
9393 }
94
94
9595 @Override
9696 public void beginCollecting() {
9797 }
98
98
9999 @Override
100100 public void accept(SpellingProblem problem) {
101101 this.annotations.put(new SpellingAnnotation(problem), new Position(problem.getOffset(), problem.getLength()));
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %Plugin.name
33 Bundle-SymbolicName: org.eclipse.ui.genericeditor.tests;singleton:=true
4 Bundle-Version: 1.1.400.qualifier
4 Bundle-Version: 1.1.500.qualifier
55 Bundle-Vendor: %Plugin.providerName
66 Bundle-Localization: plugin
77 Export-Package: org.eclipse.ui.genericeditor.tests,
1212 org.eclipse.text;bundle-version="[3.5.0,4.0.0)",
1313 org.eclipse.ui.genericeditor,
1414 org.eclipse.core.resources;bundle-version="3.11.0",
15 org.eclipse.jface.text;bundle-version="3.11.0",
15 org.eclipse.jface.text;bundle-version="3.16.0",
1616 org.eclipse.ui;bundle-version="3.108.0",
1717 org.eclipse.ui.workbench.texteditor;bundle-version="3.10.0",
1818 org.eclipse.ui.ide;bundle-version="3.11.0",
3434 </test>
3535 </enabledWhen>
3636 </contentAssistProcessor>
37 <contentAssistProcessor
38 class="org.eclipse.ui.genericeditor.tests.contributions.ToUpperCaseContentAssistProcessor"
39 contentType="org.eclipse.ui.genericeditor.tests.content-type">
40 </contentAssistProcessor>
3741 </extension>
3842 <extension
3943 point="org.eclipse.ui.genericeditor.hoverProviders">
274278 contentType="org.eclipse.ui.genericeditor.tests.sub-specialized-content-type"
275279 icon="platform:/plugin/org.eclipse.ui.ide/icons/full/etool16/newprj_wiz.png"/>
276280 </extension>
281 <extension
282 point="org.eclipse.ui.genericeditor.quickAssistProcessors">
283 <quickAssistProcessor
284 class="org.eclipse.ui.genericeditor.tests.contributions.MockQuickAssistProcessor"
285 contentType="org.eclipse.ui.genericeditor.tests.content-type">
286 </quickAssistProcessor>
287 </extension>
277288 </plugin>
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.ui</groupId>
2020 <artifactId>org.eclipse.ui.genericeditor.tests</artifactId>
21 <version>1.1.400-SNAPSHOT</version>
21 <version>1.1.500-SNAPSHOT</version>
2222 <packaging>eclipse-test-plugin</packaging>
2323 <properties>
2424 <testSuite>${project.artifactId}</testSuite>
4040 /**
4141 * Closes intro, create {@link #project}, create {@link #file} and open {@link #editor}; and clean up.
4242 * Also contains additional utility methods
43 * @since 1.0
43 * @since 1.0
4444 */
4545 public class AbstratGenericEditorTest {
46
46
4747 protected IProject project;
4848 protected IFile file;
4949 protected ExtensionBasedTextEditor editor;
5050 protected IWorkbenchWindow window;
51
51
5252 /**
5353 * Closes intro, create {@link #project}, create {@link #file} and open {@link #editor}
5454 * @throws Exception ex
6969 protected void createAndOpenFile() throws Exception {
7070 createAndOpenFile("foo.txt", "bar 'bar'");
7171 }
72
72
7373 /**
7474 * Creates a new file in the project, opens it, and associate that file with the test state
7575 * @param name name of the file in the project
102102 file = null;
103103 }
104104 }
105
105
106106 protected SourceViewer getSourceViewer() {
107107 SourceViewer sourceViewer= (SourceViewer) new Accessor(editor, AbstractTextEditor.class).invoke("getSourceViewer", new Object[0]);
108108 return sourceViewer;
109109 }
110
110
111111 @After
112112 public void tearDown() throws Exception {
113113 cleanFileAndEditor();
123123 UITestCase.processEvents();
124124 }
125125 }
126
126
127127 public static void waitAndDispatch(long milliseconds) {
128128 long timeout = milliseconds; //ms
129129 long start = System.currentTimeMillis();
2828 import org.eclipse.swt.custom.StyledText;
2929 import org.eclipse.swt.widgets.Composite;
3030 import org.eclipse.swt.widgets.Control;
31 import org.eclipse.swt.widgets.Display;
3132 import org.eclipse.swt.widgets.Event;
3233 import org.eclipse.swt.widgets.Shell;
3334 import org.eclipse.swt.widgets.Table;
5556 @Test
5657 public void testCompletion() throws Exception {
5758 final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
58 openConentAssist();
59 this.completionShell= findNewShell(beforeShells);
59 editor.selectAndReveal(3, 0);
60 openConentAssist();
61 this.completionShell= findNewShell(beforeShells, editor.getSite().getShell().getDisplay());
6062 final Table completionProposalList = findCompletionSelectionControl(completionShell);
6163 checkCompletionContent(completionProposalList);
6264 // TODO find a way to actually trigger completion and verify result against Editor content
6466 }
6567
6668 @Test
69 public void testCompletionUsingViewerSelection() throws Exception {
70 final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
71 editor.getDocumentProvider().getDocument(editor.getEditorInput()).set("abc");
72 editor.selectAndReveal(0, 3);
73 openConentAssist();
74 this.completionShell= findNewShell(beforeShells, editor.getSite().getShell().getDisplay());
75 final Table completionProposalList = findCompletionSelectionControl(completionShell);
76 assertTrue(new DisplayHelper() {
77 @Override
78 protected boolean condition() {
79 return Arrays.stream(completionProposalList.getItems()).map(TableItem::getText).anyMatch("ABC"::equals);
80 }
81 }.waitForCondition(completionProposalList.getDisplay(), 200));
82 }
83
84 @Test
6785 public void testEnabledWhenCompletion() throws Exception {
6886 // Confirm that when disabled, a completion shell is present
6987 EnabledPropertyTester.setEnabled(false);
7088 createAndOpenFile("enabledWhen.txt", "bar 'bar'");
7189 final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
90 editor.selectAndReveal(3, 0);
7291 openConentAssist();
7392 Shell[] afterShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells())
7493 .filter(Shell::isVisible)
81100 EnabledPropertyTester.setEnabled(true);
82101 createAndOpenFile("enabledWhen.txt", "bar 'bar'");
83102 final Set<Shell> beforeEnabledShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
84 openConentAssist();
85 assertNotNull(findNewShell(beforeEnabledShells));
103 editor.selectAndReveal(3, 0);
104 openConentAssist();
105 assertNotNull(findNewShell(beforeEnabledShells, editor.getSite().getShell().getDisplay()));
86106 }
87107
88108 private void openConentAssist() {
89 editor.selectAndReveal(3, 0);
90109 ContentAssistAction action = (ContentAssistAction) editor.getAction(ITextEditorActionConstants.CONTENT_ASSIST);
91110 action.update();
92111 action.run();
102121 */
103122 private void checkCompletionContent(final Table completionProposalList) {
104123 // should be instantaneous, but happens to go asynchronous on CI so let's allow a wait
105 new DisplayHelper() {
124 assertTrue(new DisplayHelper() {
106125 @Override
107126 protected boolean condition() {
108127 return completionProposalList.getItemCount() == 2;
109128 }
110 }.waitForCondition(completionProposalList.getDisplay(), 200);
111 assertEquals(2, completionProposalList.getItemCount());
129 }.waitForCondition(completionProposalList.getDisplay(), 200));
112130 final TableItem computingItem = completionProposalList.getItem(0);
113131 assertTrue("Missing computing info entry", computingItem.getText().contains("Computing")); //$NON-NLS-1$ //$NON-NLS-2$
114132 TableItem completionProposalItem = completionProposalList.getItem(1);
129147 assertEquals("Addition of completion proposal should keep selection", selectedProposal, completionProposalList.getSelection()[0].getData());
130148 }
131149
132 private Shell findNewShell(Set<Shell> beforeShells) {
133 Shell[] afterShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells())
150 public static Shell findNewShell(Set<Shell> beforeShells, Display display) {
151 Shell[] afterShells = Arrays.stream(display.getShells())
134152 .filter(Shell::isVisible)
135153 .filter(shell -> !beforeShells.contains(shell))
136154 .toArray(Shell[]::new);
141159 @Test
142160 public void testCompletionFreeze_bug521484() throws Exception {
143161 final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
144 openConentAssist();
145 this.completionShell= findNewShell(beforeShells);
162 editor.selectAndReveal(3, 0);
163 openConentAssist();
164 this.completionShell= findNewShell(beforeShells, editor.getSite().getShell().getDisplay());
146165 final Table completionProposalList = findCompletionSelectionControl(this.completionShell);
147166 // should be instantaneous, but happens to go asynchronous on CI so let's allow a wait
148167 new DisplayHelper() {
169188 testCompletion();
170189 emulatePressLeftArrowKey();
171190 DisplayHelper.sleep(editor.getSite().getShell().getDisplay(), LongRunningBarContentAssistProcessor.DELAY + 500); // adding delay is a workaround for bug521484, use only 100ms without the bug
172 this.completionShell= findNewShell(beforeShells);
191 this.completionShell= findNewShell(beforeShells, editor.getSite().getShell().getDisplay());
173192 final Table completionProposalList = findCompletionSelectionControl(this.completionShell);
174193 assertEquals("Missing proposals from a Processor", 2, completionProposalList.getItemCount()); // replace with line below when #5214894 is done
175194 // checkCompletionContent(completionProposalList); // use this instead of assert above when #521484 is done
186205 styledText.notifyListeners(ST.VerifyKey, e);
187206 }
188207
189 private Table findCompletionSelectionControl(Widget control) {
208 public static Table findCompletionSelectionControl(Widget control) {
190209 if (control instanceof Table) {
191210 return (Table)control;
192211 } else if (control instanceof Composite) {
3333 import org.eclipse.jface.text.source.SourceViewer;
3434
3535 import org.eclipse.ui.genericeditor.tests.contributions.BarContentAssistProcessor;
36 import org.eclipse.ui.tests.harness.util.UITestCase;
3637
3738 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
3839 import org.eclipse.ui.texteditor.TextOperationAction;
5354 TextOperationAction action = (TextOperationAction) editor.getAction(ITextEditorActionConstants.CONTENT_ASSIST_CONTEXT_INFORMATION);
5455
5556 editor.selectAndReveal(4, 0);
57 UITestCase.processEvents();
58
5659 action.update();
5760 action.run();
58 waitAndDispatch(100);
5961 this.completionShell= findNewShell(beforeShells);
6062 assertEquals("idx= 0", getInfoText(this.completionShell));
6163
6264 editor.selectAndReveal(8, 0);
65 UITestCase.processEvents();
66
6367 action.update();
6468 action.run();
65 waitAndDispatch(100);
6669 this.completionShell= findNewShell(beforeShells);
6770 assertEquals("idx= 1", getInfoText(this.completionShell));
6871 }
7679 TextOperationAction action = (TextOperationAction) editor.getAction(ITextEditorActionConstants.CONTENT_ASSIST_CONTEXT_INFORMATION);
7780
7881 editor.selectAndReveal(4, 0);
82 UITestCase.processEvents();
83
7984 action.update();
8085 action.run();
81 waitAndDispatch(100);
8286 this.completionShell= findNewShell(beforeShells);
8387
8488 editor.selectAndReveal(8, 0);
89 UITestCase.processEvents();
90
8591 action.update();
8692 action.run();
87 waitAndDispatch(100);
8893 this.completionShell= findNewShell(beforeShells);
8994
9095 editor.getAction(ITextEditorActionConstants.DELETE_LINE).run();
96101
97102
98103 private Shell findNewShell(Set<Shell> beforeShells) {
104 waitAndDispatch(100);
105 Shell[] afterShells= findNewShells(beforeShells);
106 if(afterShells.length == 0) {
107 waitAndDispatch(1000);
108 }
109 afterShells= findNewShells(beforeShells);
110 assertEquals("No new shell found", 1, afterShells.length);
111 return afterShells[0];
112 }
113
114 private Shell[] findNewShells(Set<Shell> beforeShells) {
99115 Shell[] afterShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells())
100116 .filter(Shell::isVisible)
101117 .filter(shell -> !beforeShells.contains(shell))
102118 .toArray(Shell[]::new);
103 assertEquals("No new shell found", 1, afterShells.length);
104 return afterShells[0];
119 return afterShells;
105120 }
106121
107122 private String getInfoText(final Shell shell) {
4545 Assert.assertTrue(editorTextWidget.getWordWrap());
4646 Assert.assertTrue(this.editor.isWordWrapEnabled());
4747 }
48
48
4949 @Test
5050 public void testGenericEditorCanShowWhitespaceCharacters() throws Exception {
5151 this.editor.setFocus();
2828 AutoEditTest.class,
2929 ReconcilerTest.class,
3030 HighlightTest.class,
31 IconsTest.class
31 IconsTest.class,
32 TestQuickAssist.class
3233 })
3334 public class GenericEditorTestSuite {
3435 // see @SuiteClasses
0 /*******************************************************************************
1 * Copyright (c) 2016-2019 Red Hat Inc. and others
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Andrew Obuchowicz (Red Hat Inc.)
12 *******************************************************************************/
13 package org.eclipse.ui.genericeditor.tests;
14
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertTrue;
17
18 import java.util.Arrays;
19 import java.util.Set;
20 import java.util.stream.Collectors;
21
22 import org.junit.After;
23 import org.junit.Test;
24
25 import org.eclipse.swt.widgets.Shell;
26 import org.eclipse.swt.widgets.Table;
27 import org.eclipse.swt.widgets.TableItem;
28
29 import org.eclipse.jface.text.tests.util.DisplayHelper;
30
31 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
32 import org.eclipse.ui.texteditor.TextOperationAction;
33
34 /**
35 * @since 1.2
36 */
37 public class TestQuickAssist extends AbstratGenericEditorTest {
38
39 private Shell completionShell;
40
41 @Test
42 public void testCompletion() throws Exception {
43 final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
44 openQuickAssist();
45 this.completionShell= CompletionTest.findNewShell(beforeShells, editor.getSite().getShell().getDisplay());
46 final Table completionProposalList = CompletionTest.findCompletionSelectionControl(completionShell);
47 checkCompletionContent(completionProposalList);
48 }
49
50 private void openQuickAssist() {
51 editor.selectAndReveal(3, 0);
52 TextOperationAction action = (TextOperationAction) editor.getAction(ITextEditorActionConstants.QUICK_ASSIST);
53 action.update();
54 action.run();
55 waitAndDispatch(100);
56 }
57
58 /**
59 * Checks that a mock quick assist proposal comes up
60 * @param completionProposalList the quick assist proposal list
61 */
62 private void checkCompletionContent(final Table completionProposalList) {
63 // should be instantaneous, but happens to go asynchronous on CI so let's allow a wait
64 new DisplayHelper() {
65 @Override
66 protected boolean condition() {
67 return completionProposalList.getItemCount() == 1;
68 }
69 }.waitForCondition(completionProposalList.getDisplay(), 200);
70 assertEquals(1, completionProposalList.getItemCount());
71 final TableItem quickAssistItem = completionProposalList.getItem(0);
72 assertTrue("Missing quick assist proposal", quickAssistItem.getText().contains("QUICK ASSIST PROPOSAL")); //$NON-NLS-1$ //$NON-NLS-2$
73
74 }
75
76
77 @After
78 public void closeShell() {
79 if (this.completionShell != null && !completionShell.isDisposed()) {
80 completionShell.close();
81 }
82 }
83 }
6767 }
6868
6969 /**
70 * Creates context info "idx= <word index in #PROPOSAL>" at the end of a word.
70 * Creates context info "idx= &lt;word index in #PROPOSAL&gt;" at the end of a word.
7171 **/
7272 @Override
7373 public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
2727 public class MarkerResolutionGenerator implements IMarkerResolutionGenerator {
2828
2929 public static final String FIXME= MarkerResolutionGenerator.class.getName() + ".fixme";
30
30
3131 private static class MarkerResolution implements IMarkerResolution2 {
3232 @Override
3333 public String getDescription() {
5050 e.printStackTrace();
5151 }
5252 }
53
53
5454 }
5555
5656 @Override
0 /*******************************************************************************
1 * Copyright (c) 2019 Red Hat Inc. and others
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *
10 * Contributors:
11 * Andrew Obuchowicz (Red Hat Inc.)
12 *******************************************************************************/
13 package org.eclipse.ui.genericeditor.tests.contributions;
14
15 import org.eclipse.jface.text.contentassist.CompletionProposal;
16 import org.eclipse.jface.text.contentassist.ICompletionProposal;
17 import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
18 import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
19 import org.eclipse.jface.text.source.Annotation;
20
21 public class MockQuickAssistProcessor implements IQuickAssistProcessor{
22
23 @Override
24 public String getErrorMessage() {
25 return "A MOCK ERROR MESSAGE";
26 }
27
28 @Override
29 public boolean canFix(Annotation annotation) {
30 return true;
31 }
32
33 @Override
34 public boolean canAssist(IQuickAssistInvocationContext invocationContext) {
35 return true;
36 }
37
38 @Override
39 public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
40 CompletionProposal proposal = new CompletionProposal("QUICK ASSIST PROPOSAL", 0, 10, 0);
41 ICompletionProposal[] proposals = {proposal};
42 return proposals;
43 }
44
45 }
0 /*******************************************************************************
1 * Copyright (c) 2019 Red Hat Inc. and others.
2 *
3 * This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
7 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10 package org.eclipse.ui.genericeditor.tests.contributions;
11
12 import org.eclipse.jface.text.BadLocationException;
13 import org.eclipse.jface.text.ITextSelection;
14 import org.eclipse.jface.text.ITextViewer;
15 import org.eclipse.jface.text.ITextViewerExtension9;
16 import org.eclipse.jface.text.contentassist.CompletionProposal;
17 import org.eclipse.jface.text.contentassist.ICompletionProposal;
18 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
19 import org.eclipse.jface.text.contentassist.IContextInformation;
20 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
21
22 public class ToUpperCaseContentAssistProcessor implements IContentAssistProcessor {
23
24 @Override
25 public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
26 if (!(viewer instanceof ITextViewerExtension9)) {
27 return new ICompletionProposal[0];
28 }
29 ITextSelection selection= ((ITextViewerExtension9)viewer).getLastKnownSelection();
30 if (selection.isEmpty() || selection.getLength() == 0) {
31 return new ICompletionProposal[0];
32 }
33 String initialText;
34 try {
35 initialText= viewer.getDocument().get(selection.getOffset(), selection.getLength());
36 return new ICompletionProposal[] {
37 new CompletionProposal(initialText.toUpperCase(), selection.getOffset(), initialText.length(), selection.getOffset() + initialText.length())
38 };
39 } catch (BadLocationException e) {
40 return new ICompletionProposal[0];
41 }
42
43 }
44
45 @Override
46 public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
47 return new IContextInformation[0];
48 }
49
50 @Override
51 public char[] getCompletionProposalAutoActivationCharacters() {
52 return new char[0];
53 }
54
55 @Override
56 public char[] getContextInformationAutoActivationCharacters() {
57 return new char[0];
58 }
59
60 @Override
61 public String getErrorMessage() {
62 return getClass().getName();
63 }
64
65 @Override
66 public IContextInformationValidator getContextInformationValidator() {
67 return null;
68 }
69
70 }
11 Bundle-ManifestVersion: 2
22 Bundle-Name: %pluginName
33 Bundle-SymbolicName: org.eclipse.ui.workbench.texteditor; singleton:=true
4 Bundle-Version: 3.13.0.qualifier
4 Bundle-Version: 3.14.0.qualifier
55 Bundle-Activator: org.eclipse.ui.internal.texteditor.TextEditorPlugin
66 Bundle-ActivationPolicy: lazy
77 Bundle-Vendor: %providerName
+0
-23
org.eclipse.ui.workbench.texteditor/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Copyright (c) 2012, 2019 Eclipse Foundation and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Eclipse Distribution License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/org/documents/edl-v10.php
7
8 Contributors:
9 Igor Fedorenko - initial implementation
10 -->
11 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
12 <modelVersion>4.0.0</modelVersion>
13 <parent>
14 <artifactId>eclipse.platform.text</artifactId>
15 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
17 </parent>
18 <groupId>org.eclipse.ui</groupId>
19 <artifactId>org.eclipse.ui.workbench.texteditor</artifactId>
20 <version>3.13.0-SNAPSHOT</version>
21 <packaging>eclipse-plugin</packaging>
22 </project>
901901 */
902902 private void reinitOnError(Exception e) {
903903 if (DEBUG)
904 System.err.println("reinitializing quickdiff:\n" + e.getLocalizedMessage() + "\n" + e.getStackTrace()); //$NON-NLS-1$//$NON-NLS-2$
904 System.err.println("reinitializing quickdiff:\n" + e.getLocalizedMessage() + "\n" + Arrays.toString(e.getStackTrace())); //$NON-NLS-1$//$NON-NLS-2$
905905 initialize();
906906 }
907907
67526752 boolean showOffset = getPreferenceStore().getBoolean(PREFERENCE_SHOW_CARET_OFFSET);
67536753 Point selectedRange = fSourceViewer.getSelectedRange();
67546754 int selectionLength = selectedRange != null ? selectedRange.y : 0;
6755 fOffsetLabel.fValue = selectionLength == 0 ? caret : selectionLength;
67566755 showSelection = showSelection && selectionLength > 0;
6756 fOffsetLabel.fValue = showSelection ? selectionLength : caret;
67576757 if (!showSelection) {
67586758 if (!showOffset) {
67596759 // shows line : column
72737273 TabsToSpacesConverter tabToSpacesConverter= new TabsToSpacesConverter();
72747274 tabToSpacesConverter.setLineTracker(new DefaultLineTracker());
72757275 tabToSpacesConverter.setNumberOfSpacesPerTab(tabWidth);
7276 tabToSpacesConverter.setDeleteSpacesAsTab(isSpacesAsTabsDeletionEnabled());
72767277 ((ITextViewerExtension7)fSourceViewer).setTabsToSpacesConverter(tabToSpacesConverter);
72777278 updateIndentPrefixes();
72787279 }
73037304 * @since 3.3
73047305 */
73057306 protected boolean isTabsToSpacesConversionEnabled() {
7307 return false;
7308 }
7309
7310 /**
7311 * Tells whether delete and backspace keys should remove multiple spaces as
7312 * if they were a tab. Only relevant when
7313 * {@link #isTabsToSpacesConversionEnabled()} returns true.
7314 *
7315 * <p>
7316 * Subclasses may override this method.
7317 * </p>
7318 *
7319 * @return <code>true</code> if spaces should be removed as tabs
7320 * @since 3.14
7321 */
7322 protected boolean isSpacesAsTabsDeletionEnabled() {
73067323 return false;
73077324 }
73087325
5353 * line</li>
5454 * <li><code>setActiveEditor</code> - extend to react to editor changes</li>
5555 * </ul>
56 *
56 *
5757 * @see org.eclipse.ui.texteditor.ITextEditorActionConstants
5858 */
5959 public class BasicTextEditorActionContributor extends EditorActionBarContributor {
1010 # Contributors:
1111 # IBM Corporation - initial API and implementation
1212 # Pierre-Yves B., pyvesdev@gmail.com - Bug 121634: [find/replace] status bar must show the string being searched when "String Not Found"
13 # Pierre-Yves B., pyvesdev@gmail.com - Bug 552069: Clarify "File Changed" dialog
1314 ###############################################################################
1415
1516
3132 Editor_error_activated_outofsync_title=File Changed
3233 Editor_error_activated_outofsync_message=The file ''{0}'' has been changed on the file system. Do you want to replace the editor contents with these changes?
3334
34 Editor_error_replace_button_label=&Replace
35 Editor_error_dontreplace_button_label=&Do not replace
35 Editor_error_replace_button_label=&Replace editor content
36 Editor_error_dontreplace_button_label=&Ignore file change
3637
3738 Editor_error_activated_deleted_save_title=File Not Accessible
3839 Editor_error_activated_deleted_save_message=The file ''{0}'' has been deleted or is not accessible. Do you want to save your changes or close the editor without saving?
397397 */
398398 private String getFirstLine(String selection) {
399399 if (!selection.isEmpty()) {
400 int[] info= TextUtilities.indexOf(TextUtilities.DELIMITERS, selection, 0);
401 if (info[0] > 0)
402 return selection.substring(0, info[0]);
403 else if (info[0] == -1)
404 return selection;
400 int delimiterOffset = TextUtilities.nextDelimiter(selection, 0).delimiterIndex;
401 if (delimiterOffset > 0)
402 return selection.substring(0, delimiterOffset);
405403 }
406404 return selection;
407405 }
10471047 */
10481048 private String getFirstLine(String selection) {
10491049 if (!selection.isEmpty()) {
1050 int[] info= TextUtilities.indexOf(TextUtilities.DELIMITERS, selection, 0);
1051 if (info[0] > 0)
1052 return selection.substring(0, info[0]);
1053 else if (info[0] == -1)
1050 int delimiterOffset = TextUtilities.nextDelimiter(selection, 0).delimiterIndex;
1051 if (delimiterOffset > 0)
1052 return selection.substring(0, delimiterOffset);
1053 else if (delimiterOffset == -1)
10541054 return selection;
10551055 }
10561056 return ""; //$NON-NLS-1$
3131
3232 import org.eclipse.ui.internal.texteditor.CompoundEditExitStrategy;
3333 import org.eclipse.ui.internal.texteditor.HippieCompletionEngine;
34 import org.eclipse.ui.internal.texteditor.ICompoundEditListener;
3534 import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
3635
3736
211210 */
212211 HippieCompleteAction(ResourceBundle bundle, String prefix, ITextEditor editor) {
213212 super(bundle, prefix, editor);
214 fExitStrategy.addCompoundListener(new ICompoundEditListener() {
215 @Override
216 public void endCompoundEdit() {
217 clearState();
218 }
219 });
213 fExitStrategy.addCompoundListener(this::clearState);
220214 }
221215
222216 /**
484484 * </p>
485485 * (value
486486 * <code>"org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"</code>).
487 *
487 *
488488 * @since 3.2
489489 */
490490 String QUICK_ASSIST= "org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"; //$NON-NLS-1$
3131 import org.eclipse.jface.text.TextUtilities;
3232
3333 import org.eclipse.ui.internal.texteditor.CompoundEditExitStrategy;
34 import org.eclipse.ui.internal.texteditor.ICompoundEditListener;
3534
3635 /**
3736 * Action for moving selected lines in an editor.
9190 fCopy= copy;
9291 String[] commandIds= copy ? new String[] {ITextEditorActionDefinitionIds.COPY_LINES_UP, ITextEditorActionDefinitionIds.COPY_LINES_DOWN } : new String[] {ITextEditorActionDefinitionIds.MOVE_LINES_UP, ITextEditorActionDefinitionIds.MOVE_LINES_DOWN };
9392 fStrategy= new CompoundEditExitStrategy(commandIds);
94 fStrategy.addCompoundListener(new ICompoundEditListener() {
95 @Override
96 public void endCompoundEdit() {
97 MoveLinesAction.this.endCompoundEdit();
98 }
99 });
93 fStrategy.addCompoundListener(MoveLinesAction.this::endCompoundEdit);
10094 update();
10195 }
10296
5757 * Default number of characters that should fit into the item.
5858 * @since 3.0
5959 */
60 static final int DEFAULT_WIDTH_IN_CHARS= 14;
60 static final int DEFAULT_WIDTH_IN_CHARS = 19;
6161 /**
6262 * Pre-computed label width hint.
6363 * @since 2.1
268268 }
269269
270270 /**
271 * Escapes '&' with '&' in the given text.
271 * Escapes '&amp;' with '&amp;' in the given text.
272272 *
273273 * @param text the text to escape, can be <code>null</code>
274274 * @return the escaped string or <code>null</code> if text was <code>null</code>
1313 <parent>
1414 <artifactId>tests-pom</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 <relativePath>../tests-pom/</relativePath>
1818 </parent>
1919 <groupId>org.eclipse.ui</groupId>
1414 <parent>
1515 <groupId>org.eclipse</groupId>
1616 <artifactId>eclipse-platform-parent</artifactId>
17 <version>4.13.0-SNAPSHOT</version>
17 <version>4.14.0-SNAPSHOT</version>
1818 <relativePath>../eclipse-platform-parent</relativePath>
1919 </parent>
2020
2121 <groupId>eclipse.platform.text</groupId>
2222 <artifactId>eclipse.platform.text</artifactId>
23 <version>4.13.0-SNAPSHOT</version>
23 <version>4.14.0-SNAPSHOT</version>
2424 <packaging>pom</packaging>
2525
2626 <properties>
1313 <parent>
1414 <artifactId>eclipse.platform.text</artifactId>
1515 <groupId>eclipse.platform.text</groupId>
16 <version>4.13.0-SNAPSHOT</version>
16 <version>4.14.0-SNAPSHOT</version>
1717 </parent>
1818 <artifactId>tests-pom</artifactId>
19 <version>4.13.0-SNAPSHOT</version>
19 <version>4.14.0-SNAPSHOT</version>
2020 <packaging>pom</packaging>
2121 <properties>
2222 <code.ignoredWarnings>${tests.ignoredWarnings}</code.ignoredWarnings>