Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 21cfc2b8cc448b7b3718b8dad6e7b86912cdddc9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*******************************************************************************
 * Copyright (c) 2010, 2011 IBM Corporation and others.
 *
 * 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
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 ******************************************************************************/
package org.eclipse.equinox.bidi.internal.consumable;

import org.eclipse.equinox.bidi.advanced.IStructuredTextExpert;
import org.eclipse.equinox.bidi.custom.*;
import org.eclipse.equinox.bidi.internal.StructuredTextActivator;

/**
 *  Handler for structured text composed of Java statements.
 *  Such a structured text may span multiple lines.
 *  <p>
 *  In applications like an editor where parts of the text might be modified
 *  while other parts are not, the user may want to call
 *  {@link IStructuredTextExpert#leanToFullText}
 *  separately on each line and save the initial state of each line (this is
 *  the final state of the previous line which can be retrieved using
 *  {@link IStructuredTextExpert#getState()}).
 *  If both the content
 *  of a line and its initial state have not changed, the user can be sure that
 *  the last <i>full</i> text computed for this line has not changed either.
 *
 *  @see IStructuredTextExpert explanation of state
 */
public class StructuredTextJava extends StructuredTextTypeHandler {
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
	static final String lineSep = StructuredTextActivator.getProperty("line.separator"); //$NON-NLS-1$
	private static final Integer STATE_SLASH_ASTER_COMMENT = Integer.valueOf(3);

	public StructuredTextJava() {
		super("[](){}.+-<>=~!&*/%^|?:,;\t"); //$NON-NLS-1$
	}

	/**
	 *  @return 4 as the number of special cases handled by this handler.
	 */
	@Override
	public int getSpecialsCount(IStructuredTextExpert expert) {
		return 4;
	}

	/**
	 *  Locates occurrences of 4 special strings:
	 *  <ol>
	 *    <li>spaces</li>
	 *    <li>literals starting with quotation mark</li>
	 *    <li>comments starting with slash-asterisk</li>
	 *    <li>comments starting with slash-slash</li>
	 *  </ol>
	 */
	@Override
	public int indexOfSpecial(IStructuredTextExpert expert, String text, StructuredTextCharTypes charTypes, StructuredTextOffsets offsets, int caseNumber, int fromIndex) {
		switch (caseNumber) {
			case 1 : /* space */
				return text.indexOf(' ', fromIndex);
			case 2 : /* literal */
				return text.indexOf('"', fromIndex);
			case 3 : /* slash-aster comment */
				return text.indexOf("/*", fromIndex); //$NON-NLS-1$
			case 4 : /* slash-slash comment */
				return text.indexOf("//", fromIndex); //$NON-NLS-1$
		}
		// we should never get here
		return -1;
	}

	/**
	 *  Processes the 4 special cases as follows.
	 *  <ol>
	 *    <li>skip the run of spaces</li>
	 *    <li>look for a matching quotation mark and skip until after it</li>
	 *    <li>skip until after the closing asterisk-slash</li>
	 *    <li>skip until after a line separator</li>
	 *  </ol>
	 */
	@Override
	public int processSpecial(IStructuredTextExpert expert, String text, StructuredTextCharTypes charTypes, StructuredTextOffsets offsets, int caseNumber, int separLocation) {
		int location, counter, i;

		StructuredTextTypeHandler.processSeparator(text, charTypes, offsets, separLocation);
		if (separLocation < 0) {
			caseNumber = ((Integer) expert.getState()).intValue(); // TBD guard against "undefined"
			expert.clearState();
		}
		switch (caseNumber) {
			case 1 : /* space */
				separLocation++;
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
					charTypes.setBidiTypeAt(separLocation, WS);
					separLocation++;
				}
				return separLocation;
			case 2 : /* literal */
				location = separLocation + 1;
				while (true) {
					location = text.indexOf('"', location);
					if (location < 0)
						return text.length();
					for (counter = 0, i = location - 1; text.charAt(i) == '\\'; i--) {
						counter++;
					}
					location++;
					if ((counter & 1) == 0)
						return location;
				}
			case 3 : /* slash-aster comment */
				if (separLocation < 0) { // continuation line
					location = 0;
				} else
					location = separLocation + 2; // skip the opening slash-aster
				location = text.indexOf("*/", location); //$NON-NLS-1$
				if (location < 0) {
					expert.setState(STATE_SLASH_ASTER_COMMENT);
					return text.length();
				}
				// we need to call processSeparator since text may follow the
				//  end of comment immediately without even a space
				StructuredTextTypeHandler.processSeparator(text, charTypes, offsets, location);
				return location + 2;
			case 4 : /* slash-slash comment */
				location = text.indexOf(lineSep, separLocation + 2);
				if (location < 0)
					return text.length();
				return location + lineSep.length();
		}
		// we should never get here
		return text.length();
	}
}

Back to the top