Skip to content

Instantly share code, notes, and snippets.

@ashigeru
Created July 30, 2010 20:45
Show Gist options
  • Save ashigeru/501282 to your computer and use it in GitHub Desktop.
Save ashigeru/501282 to your computer and use it in GitHub Desktop.
Eclipseのコンパイラに介入するプログラムスタブ
/*
* Copyright 2010 @ashigeru.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package com.ashigeru.example.javaex.core;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.BuildContext;
import org.eclipse.jdt.core.compiler.CompilationParticipant;
import org.eclipse.jdt.core.compiler.ReconcileContext;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
/**
* Eclipse JDTのコンパイルフェーズに参加する。
*/
public class MyCompilationParticipant extends CompilationParticipant {
@Override
public boolean isActive(IJavaProject project) {
return true;
}
@Override
public void reconcile(ReconcileContext context) {
CompilationUnit ast;
try {
ast = context.getAST3();
if (ast == null) {
return;
}
}
catch (JavaModelException e) {
return;
}
String fileName = context.getWorkingCopy().getElementName();
List<MyProblem> problems = verify(fileName, ast);
context.putProblems(
MyProblem.MARKER_ID,
problems.toArray(new MyProblem[problems.size()]));
}
@Override
public void buildStarting(BuildContext[] files, boolean isBatch) {
for (BuildContext context : files) {
String fileNAme = context.getFile().getName();
CompilationUnit ast = parse(context.getFile());
List<MyProblem> problems = verify(fileNAme, ast);
context.recordNewProblems(
problems.toArray(new MyProblem[problems.size()]));
}
}
CompilationUnit parse(IFile file) {
ICompilationUnit cu = JavaCore.createCompilationUnitFrom(file);
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(cu);
parser.setResolveBindings(true);
CompilationUnit ast = (CompilationUnit) parser.createAST(null);
return ast;
}
List<MyProblem> verify(String fileName, CompilationUnit ast) {
MyVerifier verifier = new MyVerifier(fileName, ast);
return verifier.verify();
}
}
/*
* Copyright 2010 @ashigeru.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package com.ashigeru.example.javaex.core;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.IProblem;
/**
* 問題情報を表すモデル。
*/
public class MyProblem extends CategorizedProblem {
/**
* 対象となるマーカーの識別子。
*/
public static final String MARKER_ID = "com.ashigeru.example.javaex.problem";
/**
* 問題の種類。
*/
public enum Kind {
/**
* 致命的な問題。
*/
ERROR,
/**
* 警告レベルの問題。
*/
WARNING,
}
private Kind kind;
private String message;
private String fileName;
private int sourceStart;
private int sourceEnd;
private int lineNumber;
/**
* インスタンスを生成する。
* @param kind 問題の種類
* @param message メッセージ
* @param fileName ファイル名
*/
public MyProblem(Kind kind, String message, String fileName) {
this.kind = kind;
this.message = message;
this.fileName = fileName;
}
@Override
public int getCategoryID() {
return CategorizedProblem.CAT_UNSPECIFIED;
}
@Override
public String getMarkerType() {
return MARKER_ID;
}
public String[] getArguments() {
return new String[0];
}
public int getID() {
return IProblem.ExternalProblemNotFixable;
}
public String getMessage() {
return message;
}
public char[] getOriginatingFileName() {
return fileName.toCharArray();
}
public boolean isError() {
return kind == Kind.ERROR;
}
public boolean isWarning() {
return kind == Kind.WARNING;
}
public int getSourceStart() {
return sourceStart;
}
public int getSourceEnd() {
return sourceEnd;
}
public int getSourceLineNumber() {
return lineNumber;
}
public void setSourceStart(int sourceStart) {
this.sourceStart = sourceStart;
}
public void setSourceEnd(int sourceEnd) {
this.sourceEnd = sourceEnd;
}
public void setSourceLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
}
/*
* Copyright 2010 @ashigeru.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package com.ashigeru.example.javaex.core;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import com.ashigeru.example.javaex.core.MyProblem.Kind;
/**
* Javaのプログラムを検証する。
*/
public class MyVerifier {
final String fileName;
final CompilationUnit root;
/**
* インスタンスを生成する。
* @param fileName 対象のファイルパス
* @param compilationUnit 対象のコンパイル単位
*/
public MyVerifier(String fileName, CompilationUnit compilationUnit) {
this.fileName = fileName;
this.root = compilationUnit;
}
/**
* このオブジェクトが対象とするプログラムを検証し、検出した問題の一覧を返す。
* @return 検出した問題の一覧
*/
public List<MyProblem> verify() {
Engine engine = new Engine();
root.accept(engine);
return engine.problems;
}
/**
* 検証器の本体。
*/
class Engine extends ASTVisitor {
// FIXME 検証プログラム
@Override
public boolean visit(MethodDeclaration node) {
SimpleName name = node.getName();
if (name.getIdentifier().startsWith("error")) {
report(
Kind.ERROR,
"errorメソッドを発見",
name,
0,
name.getLength());
}
return true;
}
List<MyProblem> problems = new ArrayList<MyProblem>();
/**
* 現在のセッションに指定の問題情報を追加する。
* @param kind 問題の種類
* @param message メッセージ
* @param node 問題が発生したノード
* @param offset 問題発生位置の、ノードから見たテキストオフセット
* @param length 問題発生位置からのテキストの長さ
*/
void report(
Kind kind,
String message,
ASTNode node,
int offset,
int length) {
MyProblem prom = new MyProblem(kind, message, fileName);
int start = node.getStartPosition() + offset;
int end = start + length;
prom.setSourceStart(start);
prom.setSourceEnd(end - 1);
prom.setSourceLineNumber(root.getLineNumber(start));
problems.add(prom);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment