Skip to main content
summaryrefslogtreecommitdiffstats
blob: 7886745f476439b02c32a6b68e0df2dc6c5e0548 (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Technical University Berlin - adapted for Object Teams
 *******************************************************************************/
package org.eclipse.jdt.core.tests.eval;

import java.util.Map;

import junit.framework.Test;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.eval.GlobalVariable;
/**
 * Negative tests for code snippet. Only compilation problems should be reported in
 * these tests.
 */
public class NegativeCodeSnippetTest extends EvaluationTest implements ProblemSeverities, ProblemReasons {
/**
 * Creates a new NegativeCodeSnippetTest.
 */
public NegativeCodeSnippetTest(String name) {
	super(name);
}
public static Test suite() {
	return setupSuite(testClass());
}
/**
 * Test a scenario where the change of the package declaration causes a problem in a code snippet.
 */
public void testChangePackage() {
	if (isJRockitVM()) return;
	try {
		// define the package
		this.context.setPackageName("java.util.zip".toCharArray());

		// evaluate a code snippet that uses this variable
		char[] codeSnippet = "new InflaterInputStream(new java.io.ByteArrayInputStream(new byte[0])).len".toCharArray();
		evaluateWithExpectedDisplayString(
			codeSnippet,
			"0".toCharArray());

		// back to the default package but with correct import
		this.context.setPackageName(new char[0]);
		this.context.setImports(new char[][] {"java.util.zip.*".toCharArray()});

		// evaluate same code snippet
		evaluateWithExpectedProblem(
			codeSnippet,
			newProblem(IProblem.NotVisibleField, Error, 71, 73, 1)); // The field len is not visible

		// back to the default package and with no imports
		this.context.setImports(new char[0][]);

		// evaluate same code snippet
		evaluateWithExpectedProblem(
			codeSnippet,
			newProblem(IProblem.UndefinedType, Error, 4, 22, 1)); // The type InflaterInputStream is undefined
	} finally {
		// Clean up
		this.context.setPackageName(new char[0]);
		this.context.setImports(new char[0][]);
	}
}
public static Class testClass() {
	return NegativeCodeSnippetTest.class;
}
/**
 * Test a code snippet which declares a class that uses an expression as a returned statement
 * in one of its methods.
 */
public void testExpressionInInnerClass() {
	//TODO (david) Syntax error diagnose should be improved in this case.
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"class X {",
		"	int foo() {",
		"		1 + 1",
		"	}",
		"}",
		"return new X().foo();"}),
		newProblem(IProblem.ParsingError, Error, 21, 21, 2)); // Syntax error on token "+"
}
/**
 * Test extra closing curly bracket.
 */
public void testExtraClosingCurlyBracket() {
	//TODO (david) Syntax error diagnose should be improved in this case.
	// just an expression with an extra curly bracket
	evaluateWithExpectedProblem(
		"1 + 2}".toCharArray(),
		newProblem(IProblem.ParsingError, Error, 0, 0, 1)); // Unmatched bracket

	// a statement followed by an unreachable expression with an extra curly bracket
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"return 1 + 1;",
		" 2 + 2}"}),
		newProblem(IProblem.ParsingError, Error, 15, 15, 2)); // Unmatched bracket
}
/**
 * Test extra open round bracket.
 */
public void testExtraOpenRoundBracket() {
	evaluateWithExpectedProblem(
		"foo((a);".toCharArray(),
		newProblem(IProblem.ParsingErrorInsertToComplete, Error, 6, 6, 1)); // Unmatched bracket
}
/**
 * Test a code snippet that contains an expression followed by a semi-colon.
 */
public void testExtraSemiColonInExpression() {
	evaluateWithExpectedProblem(
		"1;".toCharArray(),
		newProblem(IProblem.ParsingErrorInsertToComplete, Error, 0, 0, 1)); // Syntax error on token EOF
}
/**
 * Test access to a non existing field.
 * (regression test for bug 25250 Scrapbook shows wrong error message)
 */
public void testInvalidField() {
	evaluateWithExpectedProblem(
		("String s = \"\";\n" +
		"s.length").toCharArray(),
		"length cannot be resolved or is not a field\n");
}
/**
 * Test a code snippet which is valid but the evaluation context imports have problems.
 */
public void testInvalidImport() {
	try {
		// problem on the first import
		this.context.setImports(new char[][] {"bar.Y".toCharArray()});
		evaluateWithExpectedImportProblem(buildCharArray(new String[] {
			"class X {",
			"	Y foo = new Y();",
			"}",
			"return new X().foo;"}),
			"bar.Y".toCharArray(),
			newProblem(IProblem.ImportNotFound, Error, 0, 4, 1)); // The import bar.Y could not be resolved

		// problem on the second import
		this.context.setImports(new char[][] {"java.io.*".toCharArray(), "{".toCharArray()});
		evaluateWithExpectedImportProblem(buildCharArray(new String[] {
			"new File(\"c:\\temp\")"}),
			"{".toCharArray(),
//{ObjectTeams: our grammar yields a slightly different error:
/* orig:			
			newProblem(IProblem.ParsingError, Error, 0, 0, 1)); // Syntax error on token "{", "Identifier" expected
  :giro */			
			newProblem(IProblem.ParsingErrorInvalidToken, Error, 0, 0, 1)); // Syntax error on token "{", "Identifier" expected
// SH}		
	} finally {
		// Clean up
		this.context.setImports(new char[0][]);
	}
}
/**
 * Test use of this.
 */
public void testInvalidUseOfThisInSnippet() {
	evaluateWithExpectedProblem(
		"this".toCharArray(),
		"Cannot use this in a static context\n");
}
/**
 * Test use of this.
 */
public void testInvalidUseOfThisInSnippet2() {
	// just an expression with an extra curly bracket
	evaluateWithExpectedProblem(
		"return this;".toCharArray(),
		"Cannot use this in a static context\n");
}
/**
 * Test a code snippet that misses a closing round bracket.
 */
public void testMissingClosingRoundBracket() {
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"System.out.println(\"3 + 3\";"}),
		newProblem(IProblem.ParsingErrorInsertToComplete, Error, 19, 25, 1)); // Unmatched bracket
}
/**
 * Test a code snippet that contains a string that misses the closing double quote .
 */
public void testMissingDoubleQuote() {
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"System.out.println(\"3 + 3 = );",
		"3 + 3"}),
		newProblem(IProblem.UnterminatedString , Error, 19, 29, 1)); // String literal is not properly closed by a double-quote
}
/**
 * Test an expression which is not the last statement.
 */
public void testNonLastExpressionStatement() {
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"1 == '1';",
		"true"}),
		newProblem(IProblem.ParsingErrorInvalidToken, Error, 2, 3, 1)); // Syntax error on token "=="
}
/**
 * Test a problem in the returned expression.
 */
public void testProblemInExpression() {
	evaluateWithExpectedProblem(
		"new Object(); 3 + ".toCharArray(),
		newProblem(IProblem.ParsingErrorDeleteToken, Error, 16, 16, 1)); // Syntax error on token '+'
}
/**
 * Test a problem in the returned expression.
 */
public void testProblemInExpression2() {
	evaluateWithExpectedProblem(
		"new UnknownClass()".toCharArray(),
		newProblem(IProblem.UndefinedType, Error, 4, 15, 1)); // UnknownClass cannot be resolved to a type
}
/**
 * Test a code snippet which declares a class that has a problem.
 */
public void testProblemInInnerClass() {
	// class declared before the last expression
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"class X {",
		"	Y foo = new Y();",
		"}",
		"return new X().foo;"}),
		newProblem(IProblem.UndefinedType, Error, 11, 11, 2)); // The type Y is undefined

	// class declared as part of the last expression
	evaluateWithExpectedWarningAndDisplayString(buildCharArray(new String[] {
		"return new Object() {",
		"	public String toString() {",
		"		int i = 0;",
		"		return \"an inner class\";",
		"	}",
		"};"}),
		new CategorizedProblem[] {
			newProblem(IProblem.LocalVariableIsNeverUsed, Warning, 56, 56, 3), // The local variable i is never used
		},
		"an inner class".toCharArray());
}
/**
 * Test a problem in the statement before the returned expression.
 */
public void testProblemInPreviousStatement() {
	//TODO (david) Syntax error diagnose should be improved in this case.
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"return foo(a a);",
		"1 + 3"}),
		newProblem(IProblem.ParsingErrorDeleteToken, Error, 13, 13, 1)); //  Syntax error on token "a"
}
/**
 * Test a code snippet that has a problem in a return statement.
 */
public void testProblemInReturnStatement() {
	evaluateWithExpectedProblem(
		"return 1 ++ 1;".toCharArray(),
		newProblem(IProblem.InvalidUnaryExpression, Error, 7, 7, 1)); // Invalid argument to operation ++/--
}
/**
 * Test a scenario where the removal of an import causes a problem in a code snippet.
 */
public void testRemoveImport() {
	try {
		// define the import
		this.context.setImports(new char[][] {"java.io.*".toCharArray()});

		// evaluate a code snippet that uses this variable
		char[] codeSnippet = "new File(\"c:\\\\temp\")".toCharArray();
		evaluateWithExpectedDisplayString(
			codeSnippet,
			"c:\\temp".toCharArray());

		// remove the import
		this.context.setImports(new char[0][]);

		// evaluate same code snippet
		evaluateWithExpectedProblem(
			codeSnippet,
			newProblem(IProblem.UndefinedType, Error, 4, 7, 1)); // The type File is undefined
	} finally {
		// Clean up
		this.context.setImports(new char[0][]);
	}
}
/**
 * Test a scenario where the removal of a variable causes a problem in a code snippet.
 */
public void testRemoveVariable() {
	GlobalVariable var = null;
	try {
		// define the variable
		var = this.context.newVariable("int".toCharArray(), "i".toCharArray(), "1".toCharArray());
		installVariables(1);

		// evaluate a code snippet that uses this variable
		char[] codeSnippet = "i".toCharArray();
		evaluateWithExpectedDisplayString(
			codeSnippet,
			"1".toCharArray());

		// remove the variable
		this.context.deleteVariable(var);
		installVariables(0);

		// evaluate same code snippet
		evaluateWithExpectedProblem(
			codeSnippet,
			newProblem(IProblem.UnresolvedVariable, Error, 0, 0, 1)); // i cannot be resolved to a variable
	} finally {
		// Clean up
		if (var != null) {
			this.context.deleteVariable(var);
		}
	}
}
/**
 * Test a code snippet that contains an expression which is not reachable.
 */
public void testUnreachableExpression() {
	evaluateWithExpectedProblem(buildCharArray(new String[] {
		"return 1 + 1;",
		"2 + 2"}),
		newProblem(IProblem.CodeCannotBeReached, Error, 14, 18, 2)); // Unreachable code
}
/**
 * Test a code snippet which is valid but never uses the evaluation context imports.
 * (regression test for bug 18922 Scrapbook does not come back when errors in snippet)
 */
public void testUnusedImport() {
	try {
		this.context.setImports(new char[][] {"java.util.*".toCharArray()});

		// evaluate with import as error
		Map options = getCompilerOptions();
		options.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.ERROR);

		// force evaluation so that the following evaluation will use a CodeSnippetEvaluator instead
		// of a VariableEvualator
		evaluateWithExpectedValue("1".toCharArray(), "1".toCharArray(), "int".toCharArray());

		evaluateWithExpectedImportProblem(
			"new String(\"NOPE\")".toCharArray(),
			"java.util.*".toCharArray(),
			options,
			newProblem(IProblem.UnusedImport, Error, 0, 10, 1)); // The import java.util.* is unused
	} finally {
		// Clean up
		this.context.setImports(new char[0][]);
	}
}
/**
 * Test a code snippet that has warnings but no errors.
 */
public void testWarning() {
	evaluateWithExpectedWarningAndDisplayString(buildCharArray(new String[] {
		"int i;",
		"1 + 1"}),
		new CategorizedProblem[] {
			newProblem(IProblem.LocalVariableIsNeverUsed, Warning, 4, 4, 1), // The local variable i is never used
		},
		"2".toCharArray());
}
}

Back to the top