1 /*******************************************************************************
2  * Copyright (c) 2000, 2009 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.core.tests.compiler.parser;
15 
16 import java.util.Locale;
17 
18 import org.eclipse.jdt.core.compiler.CharOperation;
19 import org.eclipse.jdt.internal.codeassist.select.SelectionParser;
20 import org.eclipse.jdt.internal.codeassist.select.SelectionScanner;
21 import org.eclipse.jdt.internal.compiler.CompilationResult;
22 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
23 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
24 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
25 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
26 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
27 import org.eclipse.jdt.internal.compiler.ast.Initializer;
28 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
29 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
30 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
31 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
32 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
33 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
34 
35 public class SelectionTest2 extends AbstractSelectionTest {
36 
SelectionTest2(String testName)37 public SelectionTest2(String testName) {
38 	super(testName);
39 }
40 boolean thereWasAnNPE = false;
41 class SpecialSelectionParser extends SelectionParser {
SpecialSelectionParser(ProblemReporter problemReporter)42 	public SpecialSelectionParser(ProblemReporter problemReporter) {
43 		super(problemReporter);
44 	}
doNPEInParser()45 	public void doNPEInParser(){
46 		this.stack = null;
47 	}
48 }
49 
createParser()50  SpecialSelectionParser createParser(){
51 	CompilerOptions options = new CompilerOptions(getCompilerOptions());
52 	SpecialSelectionParser parser =
53 		new SpecialSelectionParser(
54 			new ProblemReporter(
55 				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
56 				options,
57 				new DefaultProblemFactory(Locale.getDefault())));
58 	return parser;
59 }
checkMethodParse( SelectionParser parser, char[] source, int selectionStart, int selectionEnd, String expectedSelection, String expectedUnitToString, String expectedSelectionIdentifier, String expectedSelectedSource, String testName)60 void checkMethodParse(
61 		SelectionParser parser,
62 		char[] source,
63 		int selectionStart,
64 		int selectionEnd,
65 		String expectedSelection,
66 		String expectedUnitToString,
67 		String expectedSelectionIdentifier,
68 		String expectedSelectedSource,
69 
70 		String testName) {
71 
72 	ICompilationUnit sourceUnit = new CompilationUnit(source, testName, null);
73 	CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
74 
75 	CompilationUnitDeclaration unit = parser.dietParse(sourceUnit, compilationResult, selectionStart, selectionEnd);
76 
77 	ASTNode foundMethod = null;
78 	if (unit.types != null) {
79 		for (int i = 0; i < unit.types.length; i++) {
80 			TypeDeclaration type = unit.types[i];
81 			ASTNode method = findMethod(type, selectionStart);
82 			if (method != null) {
83 				foundMethod = method;
84 				break;
85 			}
86 		}
87 	}
88 	assertTrue("no method found at cursor location", foundMethod != null);
89 	if (foundMethod instanceof AbstractMethodDeclaration) {
90 		parser.parseBlockStatements((AbstractMethodDeclaration)foundMethod, unit);
91 	} else {
92 		TypeDeclaration type = (TypeDeclaration)foundMethod;
93 		if (type.fields != null) {
94 			for (int i = 0; i < type.fields.length; i++) {
95 				FieldDeclaration field = type.fields[i];
96 				if (field instanceof Initializer && field.sourceStart <= selectionStart && selectionStart <= field.sourceEnd) {
97 					parser.parseBlockStatements((Initializer)field, type, unit);
98 					break;
99 				}
100 			}
101 		}
102 	}
103 
104 	String computedUnitToString = unit.toString();
105 	//System.out.println(computedUnitToString);
106 	//System.out.println(Util.displayString(computedUnitToString));
107 	//System.out.println(expectedUnitToString);
108 
109 	String computedCompletion = parser.assistNode == null
110 								? NONE
111 								: parser.assistNode.toString();
112 	assertEquals(
113 		"invalid selection node-" + testName,
114 		expectedSelection,
115 		computedCompletion);
116 
117 	assertEquals(
118 		"invalid selection location-"+testName,
119 		expectedUnitToString,
120 		computedUnitToString);
121 
122 	if (expectedSelectionIdentifier != null){
123 		char[] chars = ((SelectionScanner)parser.scanner).selectionIdentifier;
124 		String computedSelectionIdentifier = chars == null ? NONE : new String(chars);
125 		assertEquals(
126 			"invalid selection identifier-" + testName,
127 			expectedSelectionIdentifier,
128 			computedSelectionIdentifier);
129 	}
130 	if (expectedSelectedSource != null){
131 		char[] chars = null;
132 		if (parser.assistNode != null){
133 			chars = CharOperation.subarray(
134 				parser.scanner.source,
135 				parser.assistNode.sourceStart,
136 				parser.assistNode.sourceEnd + 1);
137 		} else {
138 			if (parser.assistIdentifier() != null){
139 				if (((SelectionScanner)parser.scanner).selectionEnd
140 					>= ((SelectionScanner)parser.scanner).selectionStart){
141 					chars = CharOperation.subarray(
142 						parser.scanner.source,
143 						((SelectionScanner)parser.scanner).selectionStart,
144 						((SelectionScanner)parser.scanner).selectionEnd + 1);
145 				}
146 			}
147 		}
148 		String computedReplacedSource  = chars == null ? NONE : new String(chars);
149 		assertEquals(
150 			"invalid replaced source-" + testName,
151 			expectedSelectedSource,
152 			computedReplacedSource);
153 	}
154 }
155 /*
156  * http://dev.eclipse.org/bugs/show_bug.cgi?id=30946
157  */
testBug30946()158 public void testBug30946() {
159 	final SpecialSelectionParser parser = createParser();
160 	Thread query = new Thread(
161 		new Runnable(){
162 			@Override
163 			public void run(){
164 				String str =
165 					"public class A {\n" +
166 					"	void foo() {\n" +
167 					"		if (true) {\n" +
168 					"			if()\n" +
169 					"			switch (1) {\n" +
170 					"				case A.B:\n" +
171 					"					C d= (C) s;\n" +
172 					"					here\n" +
173 					"			}\n" +
174 					"		}\n" +
175 					"	}\n" +
176 					"}n";
177 
178 				String selection = "here";
179 
180 				String expectedCompletionNodeToString = "<SelectOnName:here>";
181 
182 				String completionIdentifier = "here";
183 				String expectedUnitDisplayString =
184 					"public class A {\n" +
185 					"  public A() {\n" +
186 					"  }\n" +
187 					"  void foo() {\n" +
188 					"    {\n" +
189 					"      {\n" +
190 					"        C d;\n" +
191 					"        <SelectOnName:here>;\n" +
192 					"      }\n" +
193 					"    }\n" +
194 					"  }\n" +
195 					"}\n";
196 				String expectedReplacedSource = "here";
197 				String testName = "<inifinite loop test>";
198 
199 				int selectionStart = str.lastIndexOf(selection);
200 				int selectionEnd = str.lastIndexOf(selection) + selection.length() - 1;
201 
202 				try {
203 					SelectionTest2.this.checkMethodParse(
204 						parser,
205 						str.toCharArray(),
206 						selectionStart,
207 						selectionEnd,
208 						expectedCompletionNodeToString,
209 						expectedUnitDisplayString,
210 						completionIdentifier,
211 						expectedReplacedSource,
212 						testName);
213 				} catch (NullPointerException e) {
214 					SelectionTest2.this.thereWasAnNPE = true;
215 				}
216 		}
217 	});
218 
219 	query.start();
220 	try {
221 		Thread.sleep(500);
222 	} catch (InterruptedException e) {
223 	}
224 	// force parser to stop
225 	parser.doNPEInParser();
226 	try {
227 		Thread.sleep(500);
228 	} catch (InterruptedException e) {
229 	}
230 	assertTrue("there is an infinite loop", !this.thereWasAnNPE);
231 
232 }
233 }
234