/*
* Copyright 2010 Jean-Paul Balabanian and Yngve Devik Hammersland
*
* This file is part of glsl4idea.
*
* Glsl4idea is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Glsl4idea is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with glsl4idea. If not, see <http://www.gnu.org/licenses/>.
*/
package glslplugin.annotation.impl;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.HighlightSeverity;
import glslplugin.annotation.Annotator;
import glslplugin.lang.elements.expressions.GLSLFunctionCallExpression;
import glslplugin.lang.elements.types.*;
import glslplugin.lang.elements.types.constructors.GLSLAggregateParamConstructor;
import org.jetbrains.annotations.NotNull;
/**
* Creates an error annotation if trying to pass invalid amount of arguments to a constructor.
*/
public class ConstructorParamCountAnnotation extends Annotator<GLSLFunctionCallExpression> {
@Override
public void annotate(GLSLFunctionCallExpression expr, AnnotationHolder holder) {
if (!expr.isConstructor()) return;
final GLSLType constructorType = expr.getType();
// We don't handle array constructors
if (constructorType instanceof GLSLArrayType) return;
final GLSLType[] parameters = expr.getParameterTypes();
// Make sure we're only dealing with known types
for (GLSLType paramType : parameters) {
if (!paramType.isValidType()) {
return;
}
}
final GLSLFunctionType[] constructors = constructorType.getConstructors();
if(constructors.length == 0) return; //Huh, this one does not have any constructors, don't report anything then
boolean found = false;
for (GLSLFunctionType constructor : constructors) {
if(constructor.getParameterCompatibilityLevel(parameters) != GLSLTypeCompatibilityLevel.INCOMPATIBLE){
found = true;
break;
}
}
if(!found){
StringBuilder sb = new StringBuilder();
sb.append("Cannot resolve constructor '").append(constructorType.getTypename()).append('(');
if(parameters.length != 0){
final String PARAMETER_SEPARATOR = ", ";
for (GLSLType parameter : parameters) {
sb.append(parameter.getTypename()).append(PARAMETER_SEPARATOR);
}
sb.setLength(sb.length() - PARAMETER_SEPARATOR.length());
}
sb.append(")'");
final String baseMessage = sb.toString();
sb.setLength(0);
sb.append("<html><body>");
sb.append(baseMessage);
sb.append("<br/>");
if((constructorType instanceof GLSLMatrixType) && GLSLAggregateParamConstructor.containsMatrixType(parameters) && parameters.length > 1){
sb.append("Matrix constructor from matrix may not contain any other parameters<br/>");
} else if(constructorType instanceof GLSLVectorType || constructorType instanceof GLSLMatrixType){
sb.append(GLSLAggregateParamConstructor.countVectorOrMatrixConstructorElements(parameters));
sb.append(" elements found<br/>");
}
sb.append("Try:<hr/><code>");
for (GLSLFunctionType constructor : constructors) {
sb.append(constructor.getTypename()).append("<br/>");
}
sb.append("</code></body></html>");
holder.createAnnotation(HighlightSeverity.ERROR, expr.getTextRange(), baseMessage, sb.toString());
}
}
@NotNull
@Override
public Class<GLSLFunctionCallExpression> getElementType() {
return GLSLFunctionCallExpression.class;
}
}