/*
* 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.lang.parser.decl;
import consulo.csharp.lang.parser.CSharpBuilderWrapper;
import consulo.csharp.lang.parser.SharedParsingHelpers;
import consulo.csharp.lang.psi.CSharpSoftTokens;
import consulo.csharp.lang.psi.CSharpTokens;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
/**
* @author VISTALL
* @since 30.11.13.
*/
public class GenericParameterParsing extends SharedParsingHelpers
{
private static final TokenSet ourGenericStoppers = TokenSet.create(GT, LBRACE, LPAR, RBRACE);
public static void parseList(CSharpBuilderWrapper builder)
{
if(builder.getTokenType() != LT)
{
return;
}
PsiBuilder.Marker mark = builder.mark();
builder.advanceLexer();
while(!builder.eof())
{
parseGenericParameter(builder);
if(builder.getTokenType() == COMMA)
{
builder.advanceLexer();
}
else if(ourGenericStoppers.contains(builder.getTokenType()))
{
break;
}
else if(!ourGenericStoppers.contains(builder.getTokenType()))
{
PsiBuilder.Marker errorMarker = builder.mark();
builder.advanceLexer();
errorMarker.error("Expected identifier");
}
}
expect(builder, GT, "'>' expected");
mark.done(GENERIC_PARAMETER_LIST);
}
public static void parseGenericParameter(CSharpBuilderWrapper builder)
{
PsiBuilder.Marker marker = builder.mark();
parseModifierListWithAttributes(builder, STUB_SUPPORT);
if(!expectOrReportIdentifier(builder, STUB_SUPPORT))
{
marker.drop();
}
else
{
marker.done(GENERIC_PARAMETER);
}
}
public static PsiBuilder.Marker parseGenericConstraintList(CSharpBuilderWrapper builder)
{
PsiBuilder.Marker marker = builder.mark();
boolean empty = true;
while(!builder.eof())
{
builder.enableSoftKeyword(CSharpSoftTokens.WHERE_KEYWORD);
IElementType elementType = builder.getTokenType();
builder.disableSoftKeyword(CSharpSoftTokens.WHERE_KEYWORD);
if(elementType == CSharpSoftTokens.WHERE_KEYWORD)
{
PsiBuilder.Marker genericConstraint = parseGenericConstraint(builder);
if(genericConstraint == null)
{
break;
}
else
{
empty = false;
}
}
else
{
break;
}
}
if(empty)
{
marker.drop();
}
else
{
marker.done(GENERIC_CONSTRAINT_LIST);
}
return marker;
}
private static PsiBuilder.Marker parseGenericConstraint(CSharpBuilderWrapper builder)
{
if(builder.getTokenType() != WHERE_KEYWORD)
{
return null;
}
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
doneOneElement(builder, CSharpTokens.IDENTIFIER, REFERENCE_EXPRESSION, "Identifier expected");
if(expect(builder, COLON, "Colon expected"))
{
while(!builder.eof())
{
PsiBuilder.Marker value = builder.mark();
IElementType doneElement = null;
if(builder.getTokenType() == CLASS_KEYWORD || builder.getTokenType() == STRUCT_KEYWORD || builder.getTokenType() == NEW_KEYWORD)
{
boolean newKeyword = builder.getTokenType() == NEW_KEYWORD;
builder.advanceLexer();
if(newKeyword)
{
expect(builder, LPAR, "'(' expected");
expect(builder, RPAR, "')' expected");
}
doneElement = GENERIC_CONSTRAINT_KEYWORD_VALUE;
}
else
{
if(parseType(builder, STUB_SUPPORT) == null)
{
builder.error("Type expected");
}
doneElement = GENERIC_CONSTRAINT_TYPE_VALUE;
}
value.done(doneElement);
if(builder.getTokenType() == COMMA)
{
builder.advanceLexer();
}
else
{
break;
}
}
}
marker.done(GENERIC_CONSTRAINT);
return marker;
}
}