/*******************************************************************************
* Copyright (c) 2008, 2017 xored software, Inc. 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:
* xored software, Inc. - initial API and Implementation (Andrei Sobolev)
*******************************************************************************/
package org.eclipse.dltk.tcl.internal.validators.checks;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.builder.ISourceLineTracker;
import org.eclipse.dltk.tcl.ast.TclArgument;
import org.eclipse.dltk.tcl.ast.TclArgumentList;
import org.eclipse.dltk.tcl.ast.TclCommand;
import org.eclipse.dltk.tcl.internal.validators.ICheckKinds;
import org.eclipse.dltk.tcl.parser.ITclErrorReporter;
import org.eclipse.dltk.tcl.parser.TclParserUtils;
import org.eclipse.dltk.tcl.parser.TclVisitor;
import org.eclipse.dltk.tcl.parser.definitions.ArgumentDefinition;
import org.eclipse.dltk.tcl.validators.ITclCheck;
public class ArgumentsDefinitionCheck implements ITclCheck {
public ArgumentsDefinitionCheck() {
// TODO Auto-generated constructor stub
}
@Override
public void checkCommands(List<TclCommand> commands,
final ITclErrorReporter reporter, Map<String, String> options,
IScriptProject project, ISourceLineTracker sourceLineTracker) {
TclParserUtils.traverse(commands, new TclVisitor() {
@Override
public boolean visit(TclCommand tclCommand) {
Assert.isNotNull(tclCommand);
if (tclCommand.getDefinition() == null
|| !tclCommand.isMatched()) {
return true;
}
if ("proc".equals(tclCommand.getDefinition().getName())) {
Assert.isLegal(tclCommand.getArguments().size() >= 3);
return check(tclCommand.getArguments().get(1));
}
if ("apply".equals(tclCommand.getDefinition().getName())) {
Assert.isLegal(tclCommand.getArguments().size() >= 2);
TclArgument tclArgument = tclCommand.getArguments().get(0);
Assert.isLegal(tclArgument instanceof TclArgumentList);
TclArgumentList tclArgumentList = (TclArgumentList) tclArgument;
Assert.isLegal(tclArgumentList.getArguments().size() >= 2);
return check(tclArgumentList.getArguments().get(0));
}
return true;
}
public boolean check(TclArgument tclArgument) {
List<ArgumentDefinition> list = ArgumentDefinition
.get(tclArgument);
boolean wasArgs = false;
boolean wasDef = false;
for (int i = 0; i < list.size(); i++) {
ArgumentDefinition definition = list.get(i);
if (definition.getName() == null) {
reporter.report(ICheckKinds.CHECK_BAD_ARG_DEFINITION,
"Bad argument definition", null,
definition.getArgument().getStart(),
definition.getArgument().getEnd(),
ITclErrorReporter.WARNING);
} else {
for (int j = 0; j < i; j++) {
ArgumentDefinition other = list.get(j);
if (definition.getName().equals(other.getName()))
reporter.report(ICheckKinds.CHECK_SAME_ARG_NAME,
"Argument with the same name "
+ "has been declared",
null,
definition.getArgument().getStart(),
definition.getArgument().getEnd(),
ITclErrorReporter.WARNING);
}
}
if ("args".equals(definition.getName())) {
wasArgs = true;
if (definition.isDefaulted()
&& !definition.isDefaultEmtpy()) {
reporter.report(ICheckKinds.CHECK_ARGS_DEFAULT,
"\"args\" cannot be defaulted. Default value is ignored.",
null, definition.getArgument().getStart(),
definition.getArgument().getEnd(),
ITclErrorReporter.WARNING);
}
} else {
if (wasArgs) {
reporter.report(ICheckKinds.CHECK_ARG_AFTER_ARGS,
"Argument specified after \"args\"", null,
definition.getArgument().getStart(),
definition.getArgument().getEnd(),
ITclErrorReporter.WARNING);
}
if (definition.isDefaulted()) {
wasDef = true;
} else if (wasDef) {
reporter.report(ICheckKinds.CHECK_NON_DEF_AFTER_DEF,
"Non-default arg specified after default",
null, definition.getArgument().getStart(),
definition.getArgument().getEnd(),
ITclErrorReporter.WARNING);
}
}
}
return true;
}
});
}
}