/*
* Copyright 2013-2017 consulo.io
*
* 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 consulo.csharp.ide.parameterInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import consulo.annotations.RequiredReadAction;
import consulo.csharp.lang.psi.CSharpIndexMethodDeclaration;
import consulo.csharp.lang.psi.CSharpSimpleLikeMethod;
import consulo.csharp.lang.psi.CSharpSimpleParameterInfo;
import consulo.csharp.lang.psi.CSharpTypeRefPresentationUtil;
import consulo.csharp.lang.psi.impl.source.CSharpIndexAccessExpressionImpl;
import consulo.csharp.lang.psi.impl.source.resolve.type.CSharpStaticTypeRef;
import consulo.dotnet.psi.DotNetExpression;
import consulo.dotnet.psi.DotNetVariable;
import consulo.dotnet.resolve.DotNetTypeRef;
import consulo.dotnet.util.ArrayUtil2;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UnfairTextRange;
import com.intellij.psi.PsiElement;
import com.intellij.xml.util.XmlStringUtil;
/**
* @author VISTALL
* @since 11.05.14
*/
public class CSharpParametersInfo
{
public static final char[] ourBrackets = {
'[',
']'
};
public static final char[] ourParentheses = {
'(',
')'
};
private static final TextRange EMPTY = new UnfairTextRange(-1, -1);
@NotNull
public static char[] getOpenAndCloseTokens(@Nullable Object callable)
{
if(callable instanceof CSharpIndexAccessExpressionImpl || callable instanceof CSharpIndexMethodDeclaration)
{
return ourBrackets;
}
return ourParentheses;
}
@NotNull
public static CSharpParametersInfo build(@NotNull CSharpSimpleLikeMethod callable, @NotNull PsiElement scope)
{
CSharpSimpleParameterInfo[] parameters = callable.getParameterInfos();
DotNetTypeRef returnType = callable.getReturnTypeRef();
char[] bounds = getOpenAndCloseTokens(callable);
int length = 0;
CSharpParametersInfo parametersInfo = new CSharpParametersInfo(parameters.length);
if(CodeInsightSettings.getInstance().SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO)
{
String textOfReturnType = CSharpTypeRefPresentationUtil.buildShortText(returnType, scope);
parametersInfo.myBuilder.append(textOfReturnType);
parametersInfo.myBuilder.append(" ").append(bounds[0]);
length = XmlStringUtil.escapeString(textOfReturnType).length() + 2; // space and brace
}
if(parameters.length > 0)
{
for(int i = 0; i < parameters.length; i++)
{
if(i != 0)
{
length += parametersInfo.appendComma();
}
final int startOffset = length;
CSharpSimpleParameterInfo parameter = parameters[i];
length += parametersInfo.buildParameter(parameter, scope);
parametersInfo.myParameterRanges[i] = new TextRange(startOffset, length);
}
}
else
{
String text = "<no parameters>";
parametersInfo.myBuilder.append(text);
parametersInfo.myParameterRanges[0] = new TextRange(length, length + XmlStringUtil.escapeString(text).length());
}
if(CodeInsightSettings.getInstance().SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO)
{
parametersInfo.myBuilder.append(bounds[1]);
}
return parametersInfo;
}
private TextRange[] myParameterRanges;
private int myParameterCount;
private StringBuilder myBuilder = new StringBuilder();
public CSharpParametersInfo(int count)
{
myParameterCount = count;
myParameterRanges = new TextRange[myParameterCount == 0 ? 1 : myParameterCount];
}
@RequiredReadAction
private int buildParameter(@NotNull CSharpSimpleParameterInfo o, @NotNull PsiElement scope)
{
String text = CSharpTypeRefPresentationUtil.buildShortText(o.getTypeRef(), scope);
myBuilder.append(text);
int nameOffset = 0;
if(o.getTypeRef() != CSharpStaticTypeRef.__ARGLIST_TYPE)
{
myBuilder.append(" ");
String notNullName = o.getNotNullName();
myBuilder.append(notNullName);
nameOffset += notNullName.length() + 1;
}
PsiElement element = o.getElement();
if(element instanceof DotNetVariable)
{
DotNetExpression initializer = ((DotNetVariable) element).getInitializer();
if(initializer != null)
{
String initializerText = initializer.getText();
myBuilder.append(" = ").append(initializerText);
nameOffset += initializerText.length() + 3;
}
}
return XmlStringUtil.escapeString(text).length() + nameOffset;
}
@NotNull
public TextRange getParameterRange(int i)
{
if(i == -1)
{
if(myParameterCount == 0)
{
return myParameterRanges[0];
}
return EMPTY;
}
if(myParameterCount == 0)
{
return EMPTY;
}
TextRange textRange = ArrayUtil2.safeGet(myParameterRanges, i);
return textRange == null ? EMPTY : textRange;
}
private int appendComma()
{
myBuilder.append(", ");
return 2;
}
@NotNull
public String getText()
{
return myBuilder.toString();
}
}