/*
* Copyright (C) 2012-2016 NS Solutions Corporation
*
* 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.htmlhifive.tools.codeassist.core.proposal.checker;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.eclipse.wst.jsdt.core.ast.IASTNode;
import org.eclipse.wst.jsdt.core.ast.IAssignment;
import org.eclipse.wst.jsdt.core.ast.ILocalDeclaration;
import org.eclipse.wst.jsdt.core.ast.IObjectLiteralField;
import org.eclipse.wst.jsdt.core.ast.IStatement;
import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnMemberAccess;
import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
import com.htmlhifive.tools.codeassist.core.config.bean.FunctionBean;
import com.htmlhifive.tools.codeassist.core.config.bean.ObjectLiteralBean;
import com.htmlhifive.tools.codeassist.core.proposal.collector.FunctionNameVisitor;
import com.htmlhifive.tools.codeassist.core.proposal.collector.MemberAccessVisitor;
import com.htmlhifive.tools.codeassist.core.proposal.collector.NodeCollector;
/**
*
* チェッカのユーティルクラス.
*
* @author NS Solutions Corporation
*
*/
@SuppressWarnings("restriction")
public final class CheckerUtils {
/**
* プロパティ(変数名)のパターン.
*/
private static final Pattern KEY_PATTERN = Pattern.compile("[A-Za-z]\\w*");
/**
* コンストラクタ.
*/
private CheckerUtils() {
// no create
}
/**
* コード補完時の文字列から呼び出し元のオブジェクト名を取得する.
*
* @param codeAssistStr コード補完時の文字列.
* @return 呼び出し元
*/
public static String getRootObject(String codeAssistStr) {
String[] codeAssistStrParts = StringUtils.split(codeAssistStr, ".");
// ひとつ前のアシスト部.
String beforePart = null;
for (String part : codeAssistStrParts) {
if (KEY_PATTERN.matcher(part).matches() || beforePart == null) {
beforePart = part;
continue;
}
return beforePart;
}
return beforePart;
}
/**
* 構文木のルートとコレクターから、ノード情報を取得する.
*
* @param collector コレクタ
* @param unitDeclaration jsFileの構文木ルート.
* @return ノード情報
*/
static SuffixAssistNodeInfo getAssistNodeInfo(NodeCollector collector, CompilationUnitDeclaration unitDeclaration) {
// 収集したノードを取り出す
IStatement[] collectedNodes = (IStatement[]) collector.getNodes();
// List<IStatement> relateControllerNodes = new ArrayList<IStatement>();
SuffixAssistNodeInfo info = new SuffixAssistNodeInfo();
// コード補完時のノードを取得
MemberAccessVisitor visitor = new MemberAccessVisitor();
unitDeclaration.traverse(visitor);
info.setMemberAccess(visitor.getMemberAccess());
for (IStatement collectedNode : collectedNodes) {
visitor = new MemberAccessVisitor();
collectedNode.traverse(visitor);
if (visitor.getMemberAccess() != null) {
// relateControllerNodes.add(controller);
info.setMemberAccess(visitor.getMemberAccess());
// ノード内にコード補完ノードがあった場合対象ノードを追加
info.addTargetNodeList(collectedNode);
}
}
return info;
}
/**
* コード補完文字列から補完する必要があるか判定する.
*
* @param bean オブジェクトリテラルビーン
* @param codeAssistNode 補完文字列
* @return コード補完する必要があるかどうか
*/
static boolean checkCodeAssistNode(ObjectLiteralBean bean, CompletionOnMemberAccess codeAssistNode) {
FunctionNameVisitor visitor = new FunctionNameVisitor();
codeAssistNode.traverse(visitor);
List<String> funcNames = visitor.getLastFunctionNames();
if (funcNames.size() == 0) {
return true;
}
FunctionBean[] elems = bean.getFunctions();
for (FunctionBean elem : elems) {
if (funcNames.contains(elem.getName())) {
return true;
}
}
return false;
}
/**
* astNodeの名前がサフィックスにマッチする場合ソース終了位置を返す.<br>
* そうでない場合は-1を返す.<br>
* ILocalDeclarationとIObjectLiteralFieldが対象.
*
* @param suffixPattern サフィックスの正規表現.
* @param astNode 検査対象ノード
* @return そのオブジェクトリテラルのソース終了位置.
*/
static int getInitializerSourceEnd(Pattern suffixPattern, IASTNode astNode) {
String name = null;
int result = 0;
if (astNode instanceof ILocalDeclaration) {
ILocalDeclaration localDec = (ILocalDeclaration) astNode;
name = String.valueOf(localDec.getName());
result = localDec.getInitialization().sourceEnd();
} else if (astNode instanceof IObjectLiteralField) {
IObjectLiteralField objectLit = (IObjectLiteralField) astNode;
name = objectLit.getFieldName().toString();
result = objectLit.getInitializer().sourceEnd();
} else if (astNode instanceof IAssignment) {
// xxxSuffix.prototypeの時
IAssignment assignment = (IAssignment) astNode;
// xxxSuffixの取得
name = StringUtils.split(assignment.getLeftHandSide().toString(), '.')[0];
result = assignment.getExpression().sourceEnd();
}
if (name != null && suffixPattern.matcher(name).matches()) {
return result;
}
return -1;
}
}