blob: 0eae21c828d47aafd4a737bd00963d7599559fb2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 xored software, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.xotcl.internal.core.parser.structure;
import org.eclipse.dltk.tcl.ast.TclArgument;
import org.eclipse.dltk.tcl.ast.TclCommand;
import org.eclipse.dltk.tcl.core.ITclCommandDetector.CommandInfo;
import org.eclipse.dltk.tcl.structure.ITclModelBuildContext;
import org.eclipse.dltk.tcl.structure.ITclModelBuilderDetector;
import org.eclipse.dltk.tcl.structure.TclModelBuilderUtil;
import org.eclipse.dltk.xotcl.internal.core.XOTclKeywords;
import org.eclipse.dltk.xotcl.internal.core.parser.XOTclCommandDetector.XOTclGlobalClassParameter;
public class XOTclModelDetector extends TclModelBuilderUtil implements
ITclModelBuilderDetector {
private static final String CLASS_PREFIX = "#Class#"; //$NON-NLS-1$
private static final String OBJECT_PREFIX = "#Object#"; //$NON-NLS-1$
static final String CREATE = "create"; //$NON-NLS-1$
static final String INSTPROC = "instproc"; //$NON-NLS-1$
static final String PROC = "proc"; //$NON-NLS-1$
private static final String CLASS_CREATE = CLASS_PREFIX + CREATE;
private static final String CLASS_NEW_INSTANCE = CLASS_PREFIX
+ "$newInstance"; //$NON-NLS-1$
// private static final String CLASS_PROC_CALL = CLASS_PREFIX + "$ProcCall"; //$NON-NLS-1$
private static final String OBJECT_CREATE = OBJECT_PREFIX + CREATE;
private static final boolean INTERPRET_CLASS_UNKNOWN_AS_CREATE = true;
private static final boolean INTERPRET_OBJECT_UNKNOWN_AS_CREATE = true;
public String detect(String commandName, TclCommand command,
ITclModelBuildContext context) {
if (commandName == null) {
return null;
}
commandName = normalize(commandName);
if (CLASS.equals(commandName)) {
return checkClass(command, commandName, context);
} else if (OBJECT.equals(commandName)) {
return checkObject(command, commandName, context);
} else {
return checkInstanceOperations(command, commandName, context);
}
}
/**
* @param command
* @param context
* @return
*/
private String checkClass(TclCommand command, String commandName,
ITclModelBuildContext context) {
if (command.getArguments().isEmpty()) {
return null;
}
TclArgument subcmd = command.getArguments().get(0);
if (isSymbol(subcmd)) {
String value = asSymbol(subcmd);
// XOTclClassAttribute type = findXOTclType("Class");
// if (type != null) {
// context.addAttribute(type);
// }
if (contains(value, XOTclKeywords.XOTclCommandClassArgs)) {
return CLASS_PREFIX + value;
}
String info = checkCreateType(context, command, commandName,
subcmd, value);
if (info != null) {
return info;
}
if (INTERPRET_CLASS_UNKNOWN_AS_CREATE) {
return CLASS_CREATE;
}
}
return null;
}
private String checkObject(TclCommand command, String commandName,
ITclModelBuildContext context) {
if (command.getArguments().isEmpty()) {
return null;
}
TclArgument subcmd = command.getArguments().get(0);
if (isSymbol(subcmd)) {
String value = asSymbol(subcmd);
// XOTclClassAttribute type = findXOTclType("Object");
// if (type != null) {
// context.addAttribute(type);
// }
if (contains(value, XOTclKeywords.XOTclCommandObjectArgs)) {
return OBJECT_PREFIX + value;
}
String info = checkCreateType(context, command, commandName,
subcmd, value);
if (info != null) {
return info;
}
// // Else unknown command or create command.
if (INTERPRET_OBJECT_UNKNOWN_AS_CREATE) {
return OBJECT_CREATE;
}
}
return null;
}
private String checkCreateType(ITclModelBuildContext context,
TclCommand command, String commandName, TclArgument arg,
String value) {
if (value.equals(INSTPROC) || value.equals(PROC) || value.equals("set")) {
// context.addAttribute(new XOTclClassAttribute(commandName, command
// .getName()));
String info = checkCommands(value);
if (info != null) {
return info;
}
}
return null;
}
private String checkCommands(String value) {
if (contains(value, XOTclKeywords.XOTclCommandClassArgs)) {
return CLASS_PREFIX + value;
}
if (contains(value, XOTclKeywords.XOTclCommandObjectArgs)) {
return OBJECT_PREFIX + value;
}
return null;
}
private boolean contains(String value, String[] commands) {
for (int q = 0; q < commands.length; q++) {
if (value.equals(commands[q])) {
return true;
}
}
return false;
}
/**
* @param command
* @param commandName
* @param context
* @return
*/
private String checkInstanceOperations(TclCommand command,
String commandName, ITclModelBuildContext context) {
if (command.getArguments().isEmpty()) {
return null;
}
final TclArgument subcmd = command.getArguments().get(0);
if (isSymbol(subcmd)) {
final XOTclNames names = XOTclNames.get(context);
if (names != null) {
final XOTclType type = names.resolve(commandName);
if (type != null) {
type.saveTo(context);
return check(subcmd);
}
}
}
// externally defined class?
if (commandName.length() >= 3) {
if (commandName.startsWith("::")) {
commandName = commandName.substring(2);
}
if (commandName.indexOf("::") > 0
|| Character.isUpperCase(commandName.charAt(0))) {
if (asSymbol(subcmd).equals(CREATE)) {
new XOTclType(commandName, null).saveTo(context);
return CLASS_NEW_INSTANCE;
}
}
}
return null;
}
/**
* @param subcmd
*/
private String check(TclArgument subcmd) {
String value = asSymbol(subcmd);
if (!CREATE.equals(value)) {
String info = checkCommands(value);
if (info != null) {
return info;
}
} else {
return CLASS_NEW_INSTANCE;
}
return null;
}
@SuppressWarnings("nls")
private static final String[] NAMESPACES = new String[] { "::xotcl::",
"xotcl::" };
private static final String CLASS = "Class"; //$NON-NLS-1$
private static final String OBJECT = "Object"; //$NON-NLS-1$
/**
* Remove XOTcl namespaces from the specified command name
*
* @param commandName
* @return command name without namespace
*/
private String normalize(String commandName) {
for (String namespace : NAMESPACES) {
if (commandName.startsWith(namespace)) {
return commandName.substring(namespace.length());
}
}
return commandName;
}
}