Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: de07b6600f7589074078371ff1f298971f1aa030 (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
/*******************************************************************************
 * Copyright (c) 2000, 2012 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
 *******************************************************************************/
package org.eclipse.jdt.internal.eval;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.core.util.Util;

/**
 * A evaluator builds a compilation unit and compiles it into class files.
 * If the compilation unit has problems, reports the problems using the
 * requestor.
 */
public abstract class Evaluator {
	EvaluationContext context;
	INameEnvironment environment;
	Map options;
	IRequestor requestor;
	IProblemFactory problemFactory;
/**
 * Creates a new evaluator.
 */
Evaluator(EvaluationContext context, INameEnvironment environment, Map options, IRequestor requestor, IProblemFactory problemFactory) {
	this.context = context;
	this.environment = environment;
	this.options = options;
	this.requestor = requestor;
	this.problemFactory = problemFactory;
}
/**
 * Adds the given problem to the corresponding evaluation result in the given table. If the evaluation
 * result doesn't exist yet, adds it in the table. Its evaluation id and evaluation type
 * are computed so that they correspond to the given problem. If it is found to be an internal problem,
 * then the evaluation id of the result is the given compilation unit source.
 */
protected abstract void addEvaluationResultForCompilationProblem(Map resultsByIDs,CategorizedProblem problem, char[] cuSource);
/**
 * Returns the evaluation results that converts the given compilation result that has problems.
 * If the compilation result has more than one problem, then the problems are broken down so that
 * each evaluation result has the same evaluation id.
 */
protected EvaluationResult[] evaluationResultsForCompilationProblems(CompilationResult result, char[] cuSource) {
	// Break down the problems and group them by ids in evaluation results
	CategorizedProblem[] problems = result.getAllProblems();
	HashMap resultsByIDs = new HashMap(5);
	for (int i = 0; i < problems.length; i++) {
		addEvaluationResultForCompilationProblem(resultsByIDs, problems[i], cuSource);
	}

	// Copy results
	int size = resultsByIDs.size();
	EvaluationResult[] evalResults = new EvaluationResult[size];
	Iterator results = resultsByIDs.values().iterator();
	for (int i = 0; i < size; i++) {
		evalResults[i] = (EvaluationResult)results.next();
	}

	return evalResults;
}
/**
 * Compiles and returns the class definitions for the current compilation unit.
 * Returns null if there are any errors.
 */
ClassFile[] getClasses() {
	final char[] source = getSource();
	final ArrayList classDefinitions = new ArrayList();

	// The requestor collects the class definitions and problems
	class CompilerRequestor implements ICompilerRequestor {
		boolean hasErrors = false;
		public void acceptResult(CompilationResult result) {
			if (result.hasProblems()) {
				EvaluationResult[] evalResults = evaluationResultsForCompilationProblems(result, source);
				for (int i = 0; i < evalResults.length; i++) {
					EvaluationResult evalResult = evalResults[i];
					CategorizedProblem[] problems = evalResult.getProblems();
					for (int j = 0; j < problems.length; j++) {
						Evaluator.this.requestor.acceptProblem(problems[j], evalResult.getEvaluationID(), evalResult.getEvaluationType());
					}
				}
			}
			if (result.hasErrors()) {
				this.hasErrors = true;
			} else {
				ClassFile[] classFiles = result.getClassFiles();
				for (int i = 0; i < classFiles.length; i++) {
					ClassFile classFile = classFiles[i];
/*

					char[] filename = classFile.fileName();
					int length = filename.length;
					char[] relativeName = new char[length + 6];
					System.arraycopy(filename, 0, relativeName, 0, length);
					System.arraycopy(".class".toCharArray(), 0, relativeName, length, 6);
					CharOperation.replace(relativeName, '/', java.io.File.separatorChar);
					ClassFile.writeToDisk("d:/test/snippet", new String(relativeName), classFile.getBytes());
					String str = "d:/test/snippet" + "/" + new String(relativeName);
					System.out.println(org.eclipse.jdt.core.tools.classfmt.disassembler.ClassFileDisassembler.disassemble(str));
 */
					classDefinitions.add(classFile);
				}
			}
		}
	}

	// Compile compilation unit
	CompilerRequestor compilerRequestor = new CompilerRequestor();
	Compiler compiler = getCompiler(compilerRequestor);
	compiler.compile(new ICompilationUnit[] {new ICompilationUnit() {
		public char[] getFileName() {
			 // Name of class is name of CU
			return CharOperation.concat(Evaluator.this.getClassName(), Util.defaultJavaExtension().toCharArray());
		}
		public char[] getContents() {
			return source;
		}
		public char[] getMainTypeName() {
			return Evaluator.this.getClassName();
		}
		public char[][] getPackageName() {
			return null;
		}
		public boolean ignoreOptionalProblems() {
			return false;
		}
	}});
	if (compilerRequestor.hasErrors) {
		return null;
	} else {
		ClassFile[] result = new ClassFile[classDefinitions.size()];
		classDefinitions.toArray(result);
		return result;
	}
}
/**
 * Returns the name of the current class. This is the simple name of the class.
 * This doesn't include the extension ".java" nor the name of the package.
 */
protected abstract char[] getClassName();
/**
 * Creates and returns a compiler for this evaluator.
 */
Compiler getCompiler(ICompilerRequestor compilerRequestor) {
	CompilerOptions compilerOptions = new CompilerOptions(this.options);
	compilerOptions.performMethodsFullRecovery = true;
	compilerOptions.performStatementsRecovery = true;
	return new Compiler(
		this.environment,
		DefaultErrorHandlingPolicies.exitAfterAllProblems(),
		compilerOptions,
		compilerRequestor,
		this.problemFactory);
}
/**
 * Builds and returns the source for the current compilation unit.
 */
protected abstract char[] getSource();
}

Back to the top