JavaCCを利用して、「 -{ 」と「 }- 」で囲んだ文字列を取得する

JavaCCを利用して、「 -{ 」と「 }- 」で囲んだ文字列を取得する時の方法。
「 /* 」と「 */ 」に置き換えれば、C言語複数行コメントの中身を取得するときに利用できる。


SPECIAL_TOKENに、「 -{ 」と「 }- 」で囲まれる文字列を指定するのが肝要。SPECIAL_TOKENで指定したパターンにヒットした文字列は、その後にヒットしたTokenで
(Token名).specialToken.image
を呼び出すことで取得できる。


jjtファイル

options {
//(略)
    UNICODE_INPUT=true;      //日本語が扱えるようにUnicodeの入力にする
//(略)
}
//               (前略)
TOKEN: {
  <NATIVE_CODE_START: "-{" (" ")? >: NATIVE_CODE      // -{ にマッチ
}
<NATIVE_CODE> TOKEN : {
  <NATIVE_CODE_END: (" ")? "}-" >: DEFAULT            // }- にマッチ
}
<NATIVE_CODE> SPECIAL_TOKEN: {
  <NATIVE_CODE_BLOCK: (~["}"] | "}" ~["-"])+ >        // }- 以外にマッチ
}

//              (中略)

//ノード生成部
void NativeCodeBlock(): { Token t; } {
  // native code block is a SPECIAL_TOKEN, so we need to get it from NATIVE_CODE_END
  <NATIVE_CODE_START> t=<NATIVE_CODE_END> 
    { jjtThis.jjtSetValue(t.specialToken.image); } Type()
}

参考:
hlang/HLisp.jjt at 630a4a439f507729cc8c4833cd37e91e1b8e96f2 · hrehfeld/hlang · GitHub

GWTの正規表現(RegExp)でsオプションを指定したいとき

GWTでは正規表現にはRegExpクラスを使用するが、RegExpクラスはsオプション(シングルラインとして処理)が指定できない。
つまり、「.」は「\n」にマッチしない。

すべての文字と改行をマッチさせたいときは

[\s\S]

を利用するとよい。

参考:How to use JavaScript regex over multiple lines? - Stack Overflow

private MatchResult _matchSentenceBlock(String target) {
	String regex = "([\\s\\S]*?)_\\[([\\s\\S]+?)\\]_([\\s\\S]*)";
	RegExp pattern = RegExp.compile(regex, "g");
	return pattern.exec(target);
}

GWTのTextBoxで透かし文字を入れたいとき

GWTのTextBoxで、テキストボックスに入力を開始すると消える透かし文字の入れ方。
html5では、inputタグにplaceholder属性を指定すると実現できる。これを利用する。

参考
テキストボックスに透かし文字を表示する方法 | JavaScript プログラミング解説
html - How to add a placeholder to a GWT text input field - Stack Overflow

TextBox tb = new TextBox();
tb.getElement().setPropertyString("placeholder", "enter your first name");

GWTコンパイルをantから行う

2015.4.18

下のantソースコードを実行すればいい。
参照するパスなどは必要に応じて書き換えること。

コンパイルするGWTモジュールは

<property name="gwt.module" value="com.example.project.Model com.example.project.Client" />

の部分で指定する。半角スペースで区切ることで複数指定できる。

参考:
GWT Project


build-gwtc.xml

<?xml version="1.0" encoding="utf-8" ?>
<project name="gwt-compile" default="build" basedir=".">
	
	<!-- コンパイルしたいgwtモジュール 複数指定するときはスペース区切り -->
	<property name="gwt.module" value="com.example.project.Model com.example.project.Client" />
	<!-- gwt SDKのあるディレクトリを指定 -->
	<property name="gwt.sdk" location="C:\MyPrograms\eclipse_4.4\plugins\com.google.gwt.eclipse.sdkbundle_2.6.0\gwt-2.6.0" />
	<!-- コンパイルしたいソースファイルの存在するディレクトリ -->
	<path id="source.path">
		<pathelement location=".apt_generated" />
		<pathelement location="src" />
	</path>

	<!-- javaファイルのコンパイルに必要なファイルは lib か war/WEB-INF/lib に入れておくこと -->
	<path id="project.class.path">
		<pathelement location="war/WEB-INF/classes" />
		<pathelement location="${gwt.sdk}/gwt-user.jar" />
		<fileset dir="${gwt.sdk}" includes="gwt-dev*.jar" />
		<!-- Add any additional non-server libs (such as JUnit) -->
		<fileset dir="war/WEB-INF/lib" includes="**/*.jar" />
		<fileset dir="lib" includes="**/*.jar" />
	</path>


	<target name="delombok and gwtc" depends="delombok,gwtc" description="delombok before GWT compile" />
		
	<!-- 1.delombok 2.javac 3.gwtc -->
	<target name="gwtc" depends="javac" description="GWT compile to JavaScript">
		<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
			<classpath>
				<path refid="source.path" />
				<path refid="project.class.path" />
			</classpath>
			<!-- add jvmarg -Xss16M or similar if you see a StackOverflowError -->
			<jvmarg value="-Xmx256M" />
			<!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
			<arg line="${gwt.module}" />
		</java>
	</target>

	<target name="libs" description="Copy libs to WEB-INF/lib">
		<mkdir dir="war/WEB-INF/lib" />
		<copy todir="war/WEB-INF/lib" file="${gwt.sdk}/gwt-servlet.jar" />
		<!-- Add any additional server libs that need to be copied -->
	</target>

	<target name="javac" depends="libs">
		<mkdir dir="war/WEB-INF/classes" />
		<javac includes="**" encoding="utf-8" destdir="war/WEB-INF/classes" source="1.5" target="1.5" nowarn="true" debug="true" debuglevel="lines,vars,source">
			<classpath refid="project.class.path" />
			<src refid="source.path" />
		</javac>
		<copy todir="war/WEB-INF/classes">
			<fileset dir="src" excludes="**/*.java" />
		</copy>
	</target>

	<target name="build" depends="gwtc" description="Build this project" />

	<target name="war" depends="build" description="Create a war file">
		<zip destfile="Foo.war" basedir="war" />
	</target>

	<target name="clean" description="Cleans this project">
		<delete dir="war/WEB-INF/classes" failonerror="false" />
		<delete dir="war/foo" failonerror="false" />
	</target>

</project>

GWT + delombok でantタスクからGWTコンパイルする

2015.4.14

このブログの内容を行う前の注意

動機

lombokでjavaファイルのボイラーコードを減らしたかったが、lombokでAST変換してからGWTコンパイルすると、以前にコンパイルが通ったjavaファイルでエラーが出るという問題が出たので、delombokを利用するようにした。

環境

antのビルドタスクの作成

  • 記事末尾のxmlファイル2つをプロジェクトのトップディレクトリに置くこと
  • パスなどを適宜修正すること

delombokするファイルについての注意

  • delombokしたいファイルの末尾にはBaseをつけること(*Base.java)。delombokターゲット実行時に、ファイル名・クラス名からBaseを除外したjavaファイルが作成される(*.java)。

ex. ModelDataBase.java(ModelDataBaseクラスを含む)
 -> ModelData.java(ModelDataクラスを含む)

  • ファイルを修正したいときは、いったん *Base.java を編集してから再度delombokターゲットを実行すること。

 (junit実行時などはこれがすごく手間)

  • 他のクラスから利用するときは、*Baseクラスではなく、delombokで生成したクラスのほうを使用すること。

テスト(JUNIT)実行手順

  1. *Base.java の修正
  2. delombokターゲット実行
  3. プロジェクトのリフレッシュ
  4. JUNIT実行

GWT Super Dev Modeでのデバッグ手順

(すでにGWT Super Dev Modeでローカルサーバ実行中の前提で)

  1. *Base.java の修正
  2. gwtcターゲット実行
  3. プロジェクトのリフレッシュ
  4. HTMLページを再読み込み


build-gwtc.xml  (GWT Project からデバッグとテストの内容を除外したもの)

<?xml version="1.0" encoding="utf-8" ?>
<project name="gwt-compile" default="build" basedir=".">
	<import file="build-delombok.xml" />
	
	<!-- コンパイルしたいgwtモジュール 複数指定するときはスペース区切り -->
	<property name="gwt.module" value="com.example.project.Model com.example.project.Client" />
	
	<!-- gwt SDKのあるディレクトリを指定 -->
	<property name="gwt.sdk" location="C:\MyPrograms\eclipse_4.4\plugins\com.google.gwt.eclipse.sdkbundle_2.6.0\gwt-2.6.0" />
	<!-- javaファイルのコンパイルに必要なファイルは lib か war/WEB-INF/lib に入れておくこと -->
	<path id="project.class.path">
		<pathelement location="war/WEB-INF/classes" />
		<pathelement location="${gwt.sdk}/gwt-user.jar" />
		<fileset dir="${gwt.sdk}" includes="gwt-dev*.jar" />
		<!-- Add any additional non-server libs (such as JUnit) -->
		<fileset dir="war/WEB-INF/lib" includes="**/*.jar" />
		<fileset dir="lib" includes="**/*.jar" />
	</path>
	<!-- コンパイルしたいソースファイルの存在するディレクトリ -->
	<path id="source.path">
		<pathelement location=".apt_generated" />
		<pathelement location="src" />
	</path>


	<target name="delombok and gwtc" depends="delombok,gwtc" description="delombok before GWT compile" />
		
	<!-- 1.delombok 2.javac 3.gwtc -->
	<target name="gwtc" depends="javac" description="GWT compile to JavaScript">
		<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
			<classpath>
				<path refid="source.path" />
				<path refid="project.class.path" />
			</classpath>
			<!-- add jvmarg -Xss16M or similar if you see a StackOverflowError -->
			<jvmarg value="-Xmx256M" />
			<!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
			<arg line="${gwt.module}" />
		</java>
	</target>

	<target name="libs" description="Copy libs to WEB-INF/lib">
		<mkdir dir="war/WEB-INF/lib" />
		<copy todir="war/WEB-INF/lib" file="${gwt.sdk}/gwt-servlet.jar" />
		<!-- Add any additional server libs that need to be copied -->
	</target>

	<target name="javac" depends="libs">
		<mkdir dir="war/WEB-INF/classes" />
		<javac includes="**" encoding="utf-8" destdir="war/WEB-INF/classes" source="1.5" target="1.5" nowarn="true" debug="true" debuglevel="lines,vars,source">
			<classpath refid="project.class.path" />
			<src refid="source.path" />
		</javac>
		<copy todir="war/WEB-INF/classes">
			<fileset dir="src" excludes="**/*.java" />
		</copy>
	</target>

	<target name="build" depends="gwtc" description="Build this project" />

	<target name="war" depends="build" description="Create a war file">
		<zip destfile="Foo.war" basedir="war" />
	</target>

	<target name="clean" description="Cleans this project">
		<delete dir="war/WEB-INF/classes" failonerror="false" />
		<delete dir="war/foo" failonerror="false" />
	</target>

</project>

build-delombok.xml

<?xml version="1.0" encoding="utf-8" ?>
<project name="delombok" default="delombok" basedir=".">

	<!-- delombokする前のファイルの一時フォルダ -->
	<property name="dir.delombok.pickup" value=".delombok_generated/source" />
	<!-- delombokした後のファイルの一時フォルダ -->
	<property name="dir.delombok.generated" value=".delombok_generated/dist" />
	<!-- delombokするjavaクラスの接尾辞 -->
	<property name="delombok.template.suffix" value="Base" />

	<target name="delombok" description="">
		<fileset dir="src" id="delombok-src">
			<include name="**/*${delombok.template.suffix}.java" />
			<!--    <exclude name="exclude"/> -->
		</fileset>
		<taskdef classname="lombok.delombok.ant.Tasks$Delombok" classpath="lib/lombok.jar" name="delombok" />

		<delete dir="${dir.delombok.pickup}" />
		<mkdir dir="${dir.delombok.pickup}" />
		<delete dir="${dir.delombok.generated}" />
		<mkdir dir="${dir.delombok.generated}" />
		<_copy-delombok-source />
		<delombok verbose="true" encoding="UTF-8" to="${dir.delombok.generated}" from="${dir.delombok.pickup}">
			<format value="suppressWarnings:skip" />
		</delombok>
		<_copy-delombok-dist />
<!--		<eclipse.refreshLocal /> -->
	</target>

	<!-- delombokされたファイルをsrcにコピー -->
	<macrodef name="_copy-delombok-dist">
		<sequential>
			<echo message="delombokされたファイルをsrcにコピー" />


			<replaceregexp byline="true" flags="g">
				<regexp pattern="(\w+)${delombok.template.suffix}" />
				<substitution expression="\1" />
				<fileset dir="${dir.delombok.generated}" id="_delombok-dist">
					<include name="**/*${delombok.template.suffix}.java" />
				</fileset>
			</replaceregexp>

			<!-- delombokした後のjavaファイルのサブパッケージ 
			<property name="delombok.package.generated" value="generated" /> 
			<replaceregexp byline="true" flags="g">
				<regexp pattern="^package\s(.+);$" />
				<substitution expression="package \1.${delombok.package.generated};" />
				<fileset dir="${dir.delombok.generated}" id="_delombok-dist">
					<include name="**/*${delombok.template.suffix}.java" />
				</fileset>
			</replaceregexp>
			-->

			<copy todir="src" overwrite="true">
				<fileset dir="${dir.delombok.generated}" id="_delombok-dist">
					<include name="**/*${delombok.template.suffix}.java" />
				</fileset>
				<mapper type="glob" from="*${delombok.template.suffix}.java" to="*.java" />
				<!--				<mapper type="regexp" from="^(.+)/([^/]+)${delombok.template.suffix}.java" to="\1/${delombok.package.generated}/\2.java" /> -->
			</copy>
			<pathconvert property="convert-path" refid="_delombok-dist" />
			<echo message="${convert-path}" />
		</sequential>
	</macrodef>


	<!-- delombokするファイルをsrcからコピー -->
	<macrodef name="_copy-delombok-source">
		<sequential>
			<echo message="delombokするファイルをsrcにコピー" />
			<copy todir="${dir.delombok.pickup}" overwrite="true">
				<fileset dir="src" id="_delombok-source">
					<include name="**/*${delombok.template.suffix}.java" />
					<!--    <exclude name="exclude"/> -->
				</fileset>
			</copy>
			<pathconvert property="convert-path" refid="_delombok-source" />
			<echo message="${convert-path}" />
		</sequential>
	</macrodef>

</project>

その他

gwt+scalaなんてのもあるみたいだけど手はださなかった


参考:
delombok
GWT Project

Eclipse Plugin for LESSを無効にしたい

2015/4/12

bootstrap.lessを使おうとしたが、Eclipse Plugin for LESSでエラーが大量に出てうっとうしかったので。

Package Explorerでプロジェクトを右クリック → Configure → Remove LESS Nature

プラグインを無効化できる。
無効化すると、ProblemsビューにLESSのエラーが表示されなくなる。
でも、lessファイルをLessEditorで開けば、 Ctrl+Space のサジェスションなどは行ってくれる。

GWTでlombokを使用する

  1. eclipseにlombokをインストール
  2. (lombokを使用してjavaファイルを作成)
  3. GWT Compile Project -> Advanced -> VM arguments: に次の文を追加
  • javaagent:lib/lombok.jar=ECJ (プロジェクトのlibフォルダにlombok.jarを入れているとき)

「(ゲッター名)is undefined for the type」のようなエラーが出たとき

対象のフィールドにいったん @Getterをつけてから再コンパイルすると直ることがある。

参考:
Project Lombok


@Data
@Model(schemaVersion = 1)
public class MyModel implements Serializable {
    private static final long serialVersionUID = 1L;

    @Attribute(primaryKey = true)
    private Key key;
    @Attribute(version = true)
    private Long version;
    
//    @Getter
    private String title;
    @Attribute(unindexed=true)
    private String content; 
    @Attribute(lob=true)
    private String description; 
}