diff --git a/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java
index 2fff37ec1..06a67cbb7 100644
--- a/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java
+++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java
@@ -25,6 +25,15 @@ public void ignoreLinesByPrefix(String prefix) {
this.ignoreByCondition(line -> line.trim().startsWith(prefix));
}
+ /**
+ * Ignores lines that match the given regular expression. Whitespaces to the left and right of the line will be trimmed
+ * first.
+ * @param regex The regular expression
+ */
+ public void ignoreLinesByRegex(String regex) {
+ this.ignoreByCondition(line -> line.trim().matches(regex));
+ }
+
public void ignoreLinesByContains(String content) {
this.ignoreByCondition(line -> line.contains(content));
}
diff --git a/languages/csharp/pom.xml b/languages/csharp/pom.xml
index 9bf5f4b66..12213357f 100644
--- a/languages/csharp/pom.xml
+++ b/languages/csharp/pom.xml
@@ -13,6 +13,11 @@
org.antlr
antlr4-runtime
+
+ de.jplag
+ language-antlr-utils
+ ${revision}
+
diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java
index 401727bf6..aeeb53728 100644
--- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java
+++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java
@@ -1,29 +1,21 @@
package de.jplag.csharp;
-import java.io.File;
-import java.util.List;
-import java.util.Set;
-
import org.kohsuke.MetaInfServices;
-import de.jplag.ParsingException;
-import de.jplag.Token;
+import de.jplag.antlr.AbstractAntlrLanguage;
/**
* C# language with full support of C# 6 features and below.
- * @author Timur Saglam
*/
@MetaInfServices(de.jplag.Language.class)
-public class CSharpLanguage implements de.jplag.Language {
+public class CSharpLanguage extends AbstractAntlrLanguage {
private static final String NAME = "C# 6 Parser";
private static final String IDENTIFIER = "csharp";
private static final String[] FILE_ENDINGS = new String[] {".cs", ".CS"};
private static final int DEFAULT_MIN_TOKEN_MATCH = 8;
- private final CSharpParserAdapter parser;
-
public CSharpLanguage() {
- parser = new CSharpParserAdapter();
+ super(new CSharpParserAdapter());
}
@Override
@@ -45,9 +37,4 @@ public String getIdentifier() {
public int minimumTokenMatch() {
return DEFAULT_MIN_TOKEN_MATCH;
}
-
- @Override
- public List parse(Set files) throws ParsingException {
- return parser.parse(files);
- }
}
diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java
index 65d04d5b7..6cc568505 100644
--- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java
+++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java
@@ -19,7 +19,6 @@
import static de.jplag.csharp.CSharpTokenType.CONTINUE;
import static de.jplag.csharp.CSharpTokenType.DELEGATE;
import static de.jplag.csharp.CSharpTokenType.DESTRUCTOR;
-import static de.jplag.csharp.CSharpTokenType.DO;
import static de.jplag.csharp.CSharpTokenType.ENUM;
import static de.jplag.csharp.CSharpTokenType.ENUMERAL;
import static de.jplag.csharp.CSharpTokenType.ENUM_BEGIN;
@@ -28,8 +27,6 @@
import static de.jplag.csharp.CSharpTokenType.FIELD;
import static de.jplag.csharp.CSharpTokenType.FINALLY;
import static de.jplag.csharp.CSharpTokenType.FIXED;
-import static de.jplag.csharp.CSharpTokenType.FOR;
-import static de.jplag.csharp.CSharpTokenType.FOREACH;
import static de.jplag.csharp.CSharpTokenType.GOTO;
import static de.jplag.csharp.CSharpTokenType.IF;
import static de.jplag.csharp.CSharpTokenType.IF_BEGIN;
@@ -41,9 +38,12 @@
import static de.jplag.csharp.CSharpTokenType.INVOCATION;
import static de.jplag.csharp.CSharpTokenType.LOCAL_VARIABLE;
import static de.jplag.csharp.CSharpTokenType.LOCK;
+import static de.jplag.csharp.CSharpTokenType.LOOP_BEGIN;
+import static de.jplag.csharp.CSharpTokenType.LOOP_END;
import static de.jplag.csharp.CSharpTokenType.METHOD;
import static de.jplag.csharp.CSharpTokenType.METHOD_BEGIN;
import static de.jplag.csharp.CSharpTokenType.METHOD_END;
+import static de.jplag.csharp.CSharpTokenType.NAMESPACE;
import static de.jplag.csharp.CSharpTokenType.NAMESPACE_BEGIN;
import static de.jplag.csharp.CSharpTokenType.NAMESPACE_END;
import static de.jplag.csharp.CSharpTokenType.OBJECT_CREATION;
@@ -59,25 +59,39 @@
import static de.jplag.csharp.CSharpTokenType.TRY;
import static de.jplag.csharp.CSharpTokenType.UNCHECKED;
import static de.jplag.csharp.CSharpTokenType.UNSAFE;
-import static de.jplag.csharp.CSharpTokenType.USING;
import static de.jplag.csharp.CSharpTokenType.USING_DIRECTIVE;
-import static de.jplag.csharp.CSharpTokenType.WHILE;
-
-import org.antlr.v4.runtime.Token;
-
+import static de.jplag.csharp.grammar.CSharpParser.ELSE;
+import static de.jplag.csharp.grammar.CSharpParser.OP_ADD_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_AND_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_COALESCING_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_DEC;
+import static de.jplag.csharp.grammar.CSharpParser.OP_DIV_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_INC;
+import static de.jplag.csharp.grammar.CSharpParser.OP_MOD_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_MULT_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_OR_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_SUB_ASSIGNMENT;
+import static de.jplag.csharp.grammar.CSharpParser.OP_XOR_ASSIGNMENT;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+
+import de.jplag.antlr.AbstractAntlrListener;
import de.jplag.csharp.grammar.CSharpParser.Accessor_bodyContext;
import de.jplag.csharp.grammar.CSharpParser.Accessor_declarationsContext;
import de.jplag.csharp.grammar.CSharpParser.Array_initializerContext;
import de.jplag.csharp.grammar.CSharpParser.Assignment_operatorContext;
import de.jplag.csharp.grammar.CSharpParser.AttributeContext;
+import de.jplag.csharp.grammar.CSharpParser.BodyContext;
import de.jplag.csharp.grammar.CSharpParser.BreakStatementContext;
-import de.jplag.csharp.grammar.CSharpParser.Catch_clausesContext;
+import de.jplag.csharp.grammar.CSharpParser.CheckedExpressionContext;
import de.jplag.csharp.grammar.CSharpParser.CheckedStatementContext;
import de.jplag.csharp.grammar.CSharpParser.Class_bodyContext;
import de.jplag.csharp.grammar.CSharpParser.Class_definitionContext;
+import de.jplag.csharp.grammar.CSharpParser.Common_member_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.Constant_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.Constructor_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.ContinueStatementContext;
+import de.jplag.csharp.grammar.CSharpParser.Conversion_operator_declaratorContext;
import de.jplag.csharp.grammar.CSharpParser.Delegate_definitionContext;
import de.jplag.csharp.grammar.CSharpParser.Destructor_definitionContext;
import de.jplag.csharp.grammar.CSharpParser.DoStatementContext;
@@ -94,425 +108,160 @@
import de.jplag.csharp.grammar.CSharpParser.IfStatementContext;
import de.jplag.csharp.grammar.CSharpParser.If_bodyContext;
import de.jplag.csharp.grammar.CSharpParser.Indexer_declarationContext;
-import de.jplag.csharp.grammar.CSharpParser.Interface_bodyContext;
import de.jplag.csharp.grammar.CSharpParser.Interface_definitionContext;
+import de.jplag.csharp.grammar.CSharpParser.Local_constant_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.Local_variable_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.LockStatementContext;
import de.jplag.csharp.grammar.CSharpParser.Method_bodyContext;
import de.jplag.csharp.grammar.CSharpParser.Method_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.Method_invocationContext;
import de.jplag.csharp.grammar.CSharpParser.Namespace_bodyContext;
+import de.jplag.csharp.grammar.CSharpParser.Namespace_declarationContext;
+import de.jplag.csharp.grammar.CSharpParser.Namespace_or_type_nameContext;
import de.jplag.csharp.grammar.CSharpParser.Object_creation_expressionContext;
import de.jplag.csharp.grammar.CSharpParser.Operator_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.Property_declarationContext;
import de.jplag.csharp.grammar.CSharpParser.ReturnStatementContext;
+import de.jplag.csharp.grammar.CSharpParser.Shift_expressionContext;
+import de.jplag.csharp.grammar.CSharpParser.Specific_catch_clauseContext;
import de.jplag.csharp.grammar.CSharpParser.Struct_bodyContext;
import de.jplag.csharp.grammar.CSharpParser.Struct_definitionContext;
import de.jplag.csharp.grammar.CSharpParser.SwitchStatementContext;
import de.jplag.csharp.grammar.CSharpParser.Switch_sectionContext;
import de.jplag.csharp.grammar.CSharpParser.ThrowStatementContext;
import de.jplag.csharp.grammar.CSharpParser.TryStatementContext;
+import de.jplag.csharp.grammar.CSharpParser.Type_argument_listContext;
import de.jplag.csharp.grammar.CSharpParser.UncheckedExpressionContext;
+import de.jplag.csharp.grammar.CSharpParser.UncheckedStatementContext;
import de.jplag.csharp.grammar.CSharpParser.UnsafeStatementContext;
-import de.jplag.csharp.grammar.CSharpParser.UsingStatementContext;
-import de.jplag.csharp.grammar.CSharpParser.Using_directivesContext;
+import de.jplag.csharp.grammar.CSharpParser.UsingAliasDirectiveContext;
+import de.jplag.csharp.grammar.CSharpParser.UsingNamespaceDirectiveContext;
+import de.jplag.csharp.grammar.CSharpParser.UsingStaticDirectiveContext;
import de.jplag.csharp.grammar.CSharpParser.WhileStatementContext;
-import de.jplag.csharp.grammar.CSharpParserBaseListener;
/**
- * Listener class for visiting the C# ANTLR parse tree. Transforms selected ANTLR token into JPlag tokens.
- * @author Timur Saglam
+ * Extracts tokens for the {@link CSharpLanguage}
*/
-public class CSharpListener extends CSharpParserBaseListener {
-
- private final CSharpParserAdapter parserAdapter;
-
- /**
- * Creates the listener.
- * @param parserAdapter is the JPlag parser adapter which receives the transformed tokens.
- */
- public CSharpListener(CSharpParserAdapter parserAdapter) {
- this.parserAdapter = parserAdapter;
- }
-
- /**
- * Transforms an ANTLR Token into a JPlag token and transfers it to the token adapter.
- * @param targetType is the type of the JPlag token to be created.
- * @param token is the ANTLR token.
- */
- private void transformToken(CSharpTokenType targetType, Token token) {
- parserAdapter.addToken(targetType, token.getLine(), token.getCharPositionInLine() + 1, token.getText().length());
- }
-
- @Override
- public void enterMethod_invocation(Method_invocationContext context) {
- transformToken(INVOCATION, context.getStart());
- super.enterMethod_invocation(context);
- }
-
- @Override
- public void enterObject_creation_expression(Object_creation_expressionContext context) {
- transformToken(OBJECT_CREATION, context.getStart());
- super.enterObject_creation_expression(context);
- }
-
- @Override
- public void enterArray_initializer(Array_initializerContext context) {
- transformToken(ARRAY_CREATION, context.getStart());
- super.enterArray_initializer(context);
- }
-
- @Override
- public void enterAssignment_operator(Assignment_operatorContext context) {
- transformToken(ASSIGNMENT, context.getStart());
- super.enterAssignment_operator(context);
- }
-
- @Override
- public void enterIfStatement(IfStatementContext context) {
- transformToken(IF, context.getStart());
- super.enterIfStatement(context);
- }
-
- @Override
- public void enterIf_body(If_bodyContext context) {
- transformToken(IF_BEGIN, context.getStart());
- super.enterIf_body(context);
- }
-
- @Override
- public void exitIf_body(If_bodyContext context) {
- transformToken(IF_END, context.getStop());
- super.exitIf_body(context);
- }
-
- @Override
- public void enterSwitch_section(Switch_sectionContext context) {
- transformToken(SWITCH_BEGIN, context.getStart());
- super.enterSwitch_section(context);
- }
-
- @Override
- public void exitSwitch_section(Switch_sectionContext context) {
- transformToken(SWITCH_END, context.getStop());
- super.exitSwitch_section(context);
- }
-
- @Override
- public void enterSwitchStatement(SwitchStatementContext context) {
- transformToken(CASE, context.getStart());
- super.enterSwitchStatement(context);
- }
-
- @Override
- public void enterDoStatement(DoStatementContext context) {
- transformToken(DO, context.getStart());
- super.enterDoStatement(context);
- }
-
- @Override
- public void enterWhileStatement(WhileStatementContext context) {
- transformToken(WHILE, context.getStart());
- super.enterWhileStatement(context);
- }
-
- @Override
- public void enterForStatement(ForStatementContext context) {
- transformToken(FOR, context.getStart());
- super.enterForStatement(context);
- }
-
- @Override
- public void enterForeachStatement(ForeachStatementContext context) {
- transformToken(FOREACH, context.getStart());
- super.enterForeachStatement(context);
- }
-
- @Override
- public void enterBreakStatement(BreakStatementContext context) {
- transformToken(BREAK, context.getStart());
- super.enterBreakStatement(context);
- }
-
- @Override
- public void enterContinueStatement(ContinueStatementContext context) {
- transformToken(CONTINUE, context.getStart());
- super.enterContinueStatement(context);
- }
-
- @Override
- public void enterGotoStatement(GotoStatementContext context) {
- transformToken(GOTO, context.getStart());
- super.enterGotoStatement(context);
- }
-
- @Override
- public void enterReturnStatement(ReturnStatementContext context) {
- transformToken(RETURN, context.getStart());
- super.enterReturnStatement(context);
- }
-
- @Override
- public void enterThrowStatement(ThrowStatementContext context) {
- transformToken(THROW, context.getStart());
- super.enterThrowStatement(context);
- }
-
- @Override
- public void enterCheckedStatement(CheckedStatementContext context) {
- transformToken(CHECKED, context.getStart());
- super.enterCheckedStatement(context);
- }
-
- @Override
- public void enterUncheckedExpression(UncheckedExpressionContext context) {
- transformToken(UNCHECKED, context.getStart());
- super.enterUncheckedExpression(context);
- }
-
- @Override
- public void enterLockStatement(LockStatementContext context) {
- transformToken(LOCK, context.getStart());
- super.enterLockStatement(context);
- }
-
- @Override
- public void enterUsingStatement(UsingStatementContext context) {
- transformToken(USING, context.getStart());
- super.enterUsingStatement(context);
- }
-
- @Override
- public void enterTryStatement(TryStatementContext context) {
- transformToken(TRY, context.getStart());
- super.enterTryStatement(context);
- }
-
- @Override
- public void enterCatch_clauses(Catch_clausesContext context) {
- transformToken(CATCH, context.getStart());
- super.enterCatch_clauses(context);
- }
-
- @Override
- public void enterFinally_clause(Finally_clauseContext context) {
- transformToken(FINALLY, context.getStart());
- super.enterFinally_clause(context);
- }
-
- @Override
- public void enterNamespace_body(Namespace_bodyContext context) {
- transformToken(NAMESPACE_BEGIN, context.getStart());
- super.enterNamespace_body(context);
- }
-
- @Override
- public void exitNamespace_body(Namespace_bodyContext context) {
- transformToken(NAMESPACE_END, context.getStop());
- super.exitNamespace_body(context);
- }
-
- @Override
- public void enterUsing_directives(Using_directivesContext context) {
- transformToken(USING_DIRECTIVE, context.getStart());
- super.enterUsing_directives(context);
- }
-
- @Override
- public void enterClass_definition(Class_definitionContext context) {
- transformToken(CLASS, context.getStart());
- super.enterClass_definition(context);
- }
-
- @Override
- public void enterClass_body(Class_bodyContext context) {
- transformToken(CLASS_BEGIN, context.getStart());
- super.enterClass_body(context);
- }
-
- @Override
- public void exitClass_body(Class_bodyContext context) {
- transformToken(CLASS_END, context.getStop());
- super.exitClass_body(context);
- }
-
- @Override
- public void enterMethod_declaration(Method_declarationContext context) {
- transformToken(METHOD, context.getStart());
- super.enterMethod_declaration(context);
- }
-
- @Override
- public void enterMethod_body(Method_bodyContext context) {
- transformToken(METHOD_BEGIN, context.getStart());
- super.enterMethod_body(context);
- }
-
- @Override
- public void exitMethod_body(Method_bodyContext context) {
- transformToken(METHOD_END, context.getStop());
- super.exitMethod_body(context);
- }
-
- @Override
- public void enterProperty_declaration(Property_declarationContext context) {
- transformToken(PROPERTY, context.getStart());
- super.enterProperty_declaration(context);
- }
-
- @Override
- public void enterEvent_declaration(Event_declarationContext context) {
- transformToken(EVENT, context.getStart());
- super.enterEvent_declaration(context);
- }
-
- @Override
- public void enterIndexer_declaration(Indexer_declarationContext context) {
- transformToken(INDEXER, context.getStart());
- super.enterIndexer_declaration(context);
- }
-
- @Override
- public void enterOperator_declaration(Operator_declarationContext context) {
- transformToken(OPERATOR, context.getStart());
- super.enterOperator_declaration(context);
- }
-
- @Override
- public void enterConstructor_declaration(Constructor_declarationContext context) {
- transformToken(CONSTRUCTOR, context.getStart());
- super.enterConstructor_declaration(context);
- }
-
- @Override
- public void enterDestructor_definition(Destructor_definitionContext context) {
- transformToken(DESTRUCTOR, context.getStart());
- super.enterDestructor_definition(context);
- }
-
- @Override
- public void enterStruct_definition(Struct_definitionContext context) {
- transformToken(STRUCT, context.getStart());
- super.enterStruct_definition(context);
- }
-
- @Override
- public void enterStruct_body(Struct_bodyContext context) {
- transformToken(STRUCT_BEGIN, context.getStart());
- super.enterStruct_body(context);
- }
-
- @Override
- public void exitStruct_body(Struct_bodyContext context) {
- transformToken(STRUCT_END, context.getStop());
- super.exitStruct_body(context);
- }
-
- @Override
- public void enterInterface_definition(Interface_definitionContext context) {
- transformToken(INTERFACE, context.getStart());
- super.enterInterface_definition(context);
- }
-
- @Override
- public void enterInterface_body(Interface_bodyContext context) {
- transformToken(INTERFACE_BEGIN, context.getStart());
- super.enterInterface_body(context);
- }
-
- @Override
- public void exitInterface_body(Interface_bodyContext context) {
- transformToken(INTERFACE_END, context.getStart());
- super.exitInterface_body(context);
- }
-
- @Override
- public void enterEnum_definition(Enum_definitionContext context) {
- transformToken(ENUM, context.getStart());
- super.enterEnum_definition(context);
- }
-
- @Override
- public void enterEnum_body(Enum_bodyContext context) {
- transformToken(ENUM_BEGIN, context.getStart());
- super.enterEnum_body(context);
- }
-
- @Override
- public void exitEnum_body(Enum_bodyContext context) {
- transformToken(ENUM_END, context.getStop());
- super.exitEnum_body(context);
- }
-
- @Override
- public void enterEnum_member_declaration(Enum_member_declarationContext context) {
- transformToken(ENUMERAL, context.getStart());
- super.enterEnum_member_declaration(context);
- }
-
- @Override
- public void enterAttribute(AttributeContext context) {
- transformToken(ATTRIBUTE, context.getStart());
- super.enterAttribute(context);
- }
-
- @Override
- public void enterDelegate_definition(Delegate_definitionContext context) {
- transformToken(DELEGATE, context.getStart());
- super.enterDelegate_definition(context);
- }
-
- @Override
- public void enterUnsafeStatement(UnsafeStatementContext context) {
- transformToken(UNSAFE, context.getStart());
- super.enterUnsafeStatement(context);
- }
-
- @Override
- public void enterFixedStatement(FixedStatementContext context) {
- transformToken(FIXED, context.getStart());
- super.enterFixedStatement(context);
- }
-
- @Override
- public void enterAccessor_declarations(Accessor_declarationsContext context) {
- transformToken(ACCESSORS_BEGIN, context.getStart());
- super.enterAccessor_declarations(context);
- }
-
- @Override
- public void exitAccessor_declarations(Accessor_declarationsContext context) {
- transformToken(ACCESSORS_END, context.getStart());
- super.enterAccessor_declarations(context);
- }
-
- @Override
- public void enterAccessor_body(Accessor_bodyContext context) {
- transformToken(ACCESSOR_BEGIN, context.getStart());
- super.enterAccessor_body(context);
- }
-
- @Override
- public void exitAccessor_body(Accessor_bodyContext context) {
- transformToken(ACCESSOR_END, context.getStart());
- super.exitAccessor_body(context);
- }
-
- @Override
- public void enterConstant_declaration(Constant_declarationContext context) {
- transformToken(CONSTANT, context.getStart());
- super.enterConstant_declaration(context);
- }
-
- @Override
- public void enterField_declaration(Field_declarationContext context) {
- transformToken(FIELD, context.getStart());
- super.enterField_declaration(context);
+public class CSharpListener extends AbstractAntlrListener {
+ public CSharpListener() {
+ visit(UsingNamespaceDirectiveContext.class).map(USING_DIRECTIVE);
+ visit(UsingAliasDirectiveContext.class, this::isAliasUsageAlsoImport).map(USING_DIRECTIVE);
+ visit(UsingStaticDirectiveContext.class).map(USING_DIRECTIVE);
+
+ visit(Method_invocationContext.class).map(INVOCATION);
+ visit(Object_creation_expressionContext.class).map(OBJECT_CREATION);
+ visit(Array_initializerContext.class).map(ARRAY_CREATION);
+ visit(Assignment_operatorContext.class).map(ASSIGNMENT);
+ visit(IfStatementContext.class).map(IF);
+ visit(ELSE).map(IF);
+ visit(If_bodyContext.class).map(IF_BEGIN, IF_END);
+ visit(Switch_sectionContext.class).map(SWITCH_BEGIN, SWITCH_END);
+ visit(SwitchStatementContext.class).map(CASE);
+
+ visit(DoStatementContext.class).map(LOOP_BEGIN, LOOP_END);
+ visit(WhileStatementContext.class).map(LOOP_BEGIN, LOOP_END);
+ visit(ForStatementContext.class).map(LOOP_BEGIN, LOOP_END);
+ visit(ForeachStatementContext.class).map(LOOP_BEGIN, LOOP_END);
+
+ visit(BreakStatementContext.class).map(BREAK);
+ visit(ContinueStatementContext.class).map(CONTINUE);
+ visit(GotoStatementContext.class).map(GOTO);
+
+ visit(ReturnStatementContext.class).map(RETURN);
+ visit(ThrowStatementContext.class).map(THROW);
+
+ visit(CheckedStatementContext.class).map(CHECKED);
+ visit(CheckedExpressionContext.class).map(CHECKED);
+ visit(UncheckedStatementContext.class).map(UNCHECKED);
+ visit(UncheckedExpressionContext.class).map(UNCHECKED);
+
+ visit(LockStatementContext.class).map(LOCK);
+
+ visit(TryStatementContext.class).map(TRY);
+ visit(Specific_catch_clauseContext.class).map(CATCH);
+ visit(Finally_clauseContext.class).map(FINALLY);
+
+ visit(Namespace_declarationContext.class).map(NAMESPACE);
+ visit(Namespace_bodyContext.class).map(NAMESPACE_BEGIN, NAMESPACE_END);
+ visit(Class_definitionContext.class).map(CLASS);
+ visit(Class_bodyContext.class, this::isClassBody).map(CLASS_BEGIN, CLASS_END);
+ visit(Method_declarationContext.class).map(METHOD);
+ visit(Method_bodyContext.class).map(METHOD_BEGIN, METHOD_END);
+ visit(Property_declarationContext.class).map(PROPERTY);
+ visit(Event_declarationContext.class).map(EVENT);
+ visit(Indexer_declarationContext.class).map(INDEXER);
+ visit(Operator_declarationContext.class).map(OPERATOR);
+ visit(BodyContext.class, this::isOperatorBody).map(METHOD_BEGIN, METHOD_END);
+ visit(Conversion_operator_declaratorContext.class).map(OPERATOR);
+ visit(BodyContext.class, this::isConversionOperatorBody).map(METHOD_BEGIN, METHOD_END);
+ visit(Constructor_declarationContext.class).map(CONSTRUCTOR);
+ visit(BodyContext.class, this::isConstructorBody).map(METHOD_BEGIN, METHOD_END);
+ visit(Destructor_definitionContext.class).map(DESTRUCTOR);
+ visit(Struct_definitionContext.class).map(STRUCT);
+ visit(Struct_bodyContext.class).map(STRUCT_BEGIN, STRUCT_END);
+ visit(Interface_definitionContext.class).map(INTERFACE);
+ visit(Class_bodyContext.class, this::isInterfaceBody).map(INTERFACE_BEGIN, INTERFACE_END);
+ visit(Enum_definitionContext.class).map(ENUM);
+ visit(Enum_bodyContext.class).map(ENUM_BEGIN, ENUM_END);
+ visit(Enum_member_declarationContext.class).map(ENUMERAL);
+ visit(AttributeContext.class).map(ATTRIBUTE);
+ visit(Delegate_definitionContext.class).map(DELEGATE);
+ visit(UnsafeStatementContext.class).map(UNSAFE);
+ visit(FixedStatementContext.class).map(FIXED);
+ visit(Accessor_declarationsContext.class).map(ACCESSORS_BEGIN, ACCESSORS_END);
+ visit(Accessor_bodyContext.class).map(ACCESSOR_BEGIN, ACCESSOR_END);
+ visit(Constant_declarationContext.class).map(CONSTANT);
+ visit(Field_declarationContext.class).map(FIELD);
+ visit(Local_variable_declarationContext.class).map(LOCAL_VARIABLE);
+ visit(Local_constant_declarationContext.class).map(LOCAL_VARIABLE);
+
+ registerUnaryOperatorVisitors();
+ }
+
+ private void registerUnaryOperatorVisitors() {
+ visit(OP_DEC).map(ASSIGNMENT);
+ visit(OP_INC).map(ASSIGNMENT);
+
+ visit(Shift_expressionContext.class, expr -> expr.additive_expression().size() == 2).map(ASSIGNMENT);
+
+ visit(OP_ADD_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_SUB_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_AND_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_DIV_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_MOD_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_OR_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_XOR_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_MULT_ASSIGNMENT).map(ASSIGNMENT);
+ visit(OP_COALESCING_ASSIGNMENT).map(ASSIGNMENT);
+ }
+
+ private boolean isClassBody(ParserRuleContext context) {
+ return hasAncestor(context, Class_definitionContext.class, Interface_definitionContext.class);
+ }
+
+ private boolean isInterfaceBody(ParserRuleContext context) {
+ return hasAncestor(context, Interface_definitionContext.class, Class_definitionContext.class);
+ }
+
+ private boolean isConstructorBody(BodyContext context) {
+ return context.parent instanceof Constructor_declarationContext;
+ }
+
+ private boolean isOperatorBody(BodyContext context) {
+ return context.parent instanceof Operator_declarationContext;
+ }
+
+ private boolean isConversionOperatorBody(BodyContext context) {
+ if (!(context.parent instanceof Common_member_declarationContext parent)) {
+ return false;
+ }
+
+ return parent.conversion_operator_declarator() != null;
}
- @Override
- public void enterLocal_variable_declaration(Local_variable_declarationContext context) {
- transformToken(LOCAL_VARIABLE, context.getStart());
- super.enterLocal_variable_declaration(context);
+ private boolean isAliasUsageAlsoImport(UsingAliasDirectiveContext context) {
+ Namespace_or_type_nameContext namespace = getDescendant(context, Namespace_or_type_nameContext.class);
+
+ return namespace != null && (!namespace.DOT().isEmpty() && getDescendant(namespace, Type_argument_listContext.class) == null);
}
}
diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java
index 3b2b0d8a2..7d0b8951d 100644
--- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java
+++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java
@@ -1,80 +1,37 @@
package de.jplag.csharp;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.antlr.v4.runtime.tree.ParseTreeWalker;
-import de.jplag.AbstractParser;
-import de.jplag.ParsingException;
-import de.jplag.Token;
-import de.jplag.TokenType;
+import de.jplag.antlr.AbstractAntlrListener;
+import de.jplag.antlr.AbstractAntlrParserAdapter;
import de.jplag.csharp.grammar.CSharpLexer;
import de.jplag.csharp.grammar.CSharpParser;
-import de.jplag.util.FileUtils;
/**
* Parser adapter for the ANTLR 4 CSharp Parser and Lexer. It receives file to parse and passes them to the ANTLR
* pipeline. Then it walks the produced parse tree and creates JPlag token with the {@link CSharpListener}.
- * @author Timur Saglam
*/
-public class CSharpParserAdapter extends AbstractParser {
- private List tokens;
- private File currentFile;
-
- /**
- * Creates the parser adapter.
- */
- public CSharpParserAdapter() {
- super();
+public class CSharpParserAdapter extends AbstractAntlrParserAdapter {
+ @Override
+ protected Lexer createLexer(CharStream input) {
+ return new CSharpLexer(input);
}
- /**
- * Parses all tokens from a set of files.
- * @param files is the set of files.
- * @return the list of parsed tokens.
- */
- public List parse(Set files) throws ParsingException {
- tokens = new ArrayList<>();
- for (File file : files) {
- parseFile(file);
- tokens.add(Token.fileEnd(file));
- }
- return tokens;
+ @Override
+ protected CSharpParser createParser(CommonTokenStream tokenStream) {
+ return new CSharpParser(tokenStream);
}
- private void parseFile(File file) throws ParsingException {
- try (BufferedReader reader = FileUtils.openFileReader(file)) {
- currentFile = file;
-
- // create a lexer, a parser and a buffer between them.
- CSharpLexer lexer = new CSharpLexer(CharStreams.fromReader(reader));
- CommonTokenStream tokens = new CommonTokenStream(lexer);
- CSharpParser parser = new CSharpParser(tokens);
-
- // Create a tree walker and the entry context defined by the parser grammar
- ParserRuleContext entryContext = parser.compilation_unit();
- ParseTreeWalker treeWalker = new ParseTreeWalker();
-
- // Walk over the parse tree:
- for (int i = 0; i < entryContext.getChildCount(); i++) {
- ParseTree parseTree = entryContext.getChild(i);
- treeWalker.walk(new CSharpListener(this), parseTree);
- }
- } catch (IOException exception) {
- throw new ParsingException(file, exception.getMessage(), exception);
- }
+ @Override
+ protected ParserRuleContext getEntryContext(CSharpParser parser) {
+ return parser.compilation_unit();
}
- /* package-private */ void addToken(TokenType type, int line, int column, int length) {
- tokens.add(new Token(type, currentFile, line, column, length));
+ @Override
+ protected AbstractAntlrListener getListener() {
+ return new CSharpListener();
}
}
diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java
index f8d6a4347..3895ed55e 100644
--- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java
+++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java
@@ -17,10 +17,6 @@ public enum CSharpTokenType implements TokenType {
SWITCH_BEGIN("SWITCH{"),
SWITCH_END("}SWITCH"),
CASE("CASE"),
- DO("DO"),
- WHILE("WHILE"),
- FOR("FOR"),
- FOREACH("FOREACH"),
BREAK("BREAK"),
CONTINUE("CONTINUE"),
GOTO("GOTO"),
@@ -29,10 +25,10 @@ public enum CSharpTokenType implements TokenType {
CHECKED("CHECKED"),
UNCHECKED("UNCHECKED"),
LOCK("LOCK"),
- USING("USING"),
TRY("TRY"),
CATCH("CATCH"),
FINALLY("FINALLY"),
+ NAMESPACE("NAMESPACE"),
NAMESPACE_BEGIN("NAMESPACE{"),
NAMESPACE_END("}NAMESPACE"),
USING_DIRECTIVE("USING"),
@@ -67,7 +63,10 @@ public enum CSharpTokenType implements TokenType {
ACCESSORS_BEGIN("ACCESSORS{"),
ACCESSORS_END("}ACCESSORS"),
ACCESSOR_BEGIN("ACCESSOR{"),
- ACCESSOR_END("}ACCESSOR");
+ ACCESSOR_END("}ACCESSOR"),
+
+ LOOP_BEGIN("LOOP{"),
+ LOOP_END("}LOOP");
private final String description;
diff --git a/languages/csharp/src/test/java/de/jplag/csharp/CSharpTest.java b/languages/csharp/src/test/java/de/jplag/csharp/CSharpTest.java
new file mode 100644
index 000000000..2acbe4d98
--- /dev/null
+++ b/languages/csharp/src/test/java/de/jplag/csharp/CSharpTest.java
@@ -0,0 +1,56 @@
+package de.jplag.csharp;
+
+import static de.jplag.csharp.CSharpTokenType.ACCESSORS_BEGIN;
+import static de.jplag.csharp.CSharpTokenType.ACCESSORS_END;
+import static de.jplag.csharp.CSharpTokenType.ACCESSOR_BEGIN;
+import static de.jplag.csharp.CSharpTokenType.ACCESSOR_END;
+import static de.jplag.csharp.CSharpTokenType.ASSIGNMENT;
+import static de.jplag.csharp.CSharpTokenType.CLASS;
+import static de.jplag.csharp.CSharpTokenType.CLASS_BEGIN;
+import static de.jplag.csharp.CSharpTokenType.CLASS_END;
+import static de.jplag.csharp.CSharpTokenType.CONSTRUCTOR;
+import static de.jplag.csharp.CSharpTokenType.FIELD;
+import static de.jplag.csharp.CSharpTokenType.IF;
+import static de.jplag.csharp.CSharpTokenType.IF_BEGIN;
+import static de.jplag.csharp.CSharpTokenType.IF_END;
+import static de.jplag.csharp.CSharpTokenType.INVOCATION;
+import static de.jplag.csharp.CSharpTokenType.LOCAL_VARIABLE;
+import static de.jplag.csharp.CSharpTokenType.METHOD;
+import static de.jplag.csharp.CSharpTokenType.METHOD_BEGIN;
+import static de.jplag.csharp.CSharpTokenType.METHOD_END;
+import static de.jplag.csharp.CSharpTokenType.PROPERTY;
+import static de.jplag.csharp.CSharpTokenType.RETURN;
+
+import de.jplag.testutils.LanguageModuleTest;
+import de.jplag.testutils.datacollector.TestDataCollector;
+import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector;
+
+public class CSharpTest extends LanguageModuleTest {
+ public CSharpTest() {
+ super(new CSharpLanguage(), CSharpTokenType.class);
+ }
+
+ @Override
+ protected void collectTestData(TestDataCollector collector) {
+ collector.testFile("TestClass.cs").testSourceCoverage().testTokenSequence(CLASS, CLASS_BEGIN, FIELD, CONSTRUCTOR, METHOD_BEGIN,
+ LOCAL_VARIABLE, METHOD_END, METHOD, METHOD_BEGIN, IF, IF_BEGIN, INVOCATION, IF_END, IF, IF_BEGIN, INVOCATION, IF_END, METHOD_END,
+ PROPERTY, ACCESSORS_BEGIN, ACCESSOR_BEGIN, ACCESSOR_END, ACCESSOR_BEGIN, ACCESSOR_END, ACCESSORS_END, FIELD, PROPERTY,
+ ACCESSORS_BEGIN, ACCESSOR_BEGIN, RETURN, ACCESSOR_END, ACCESSOR_BEGIN, ASSIGNMENT, ACCESSOR_END, ACCESSORS_END, CLASS_END);
+
+ collector.testFile("AllInOneNoPreprocessor.cs").testSourceCoverage().testTokenCoverage();
+ }
+
+ @Override
+ protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) {
+ collector.ignoreMultipleLines("/*", "*/");
+ collector.ignoreLinesByPrefix("//");
+ collector.ignoreLinesByRegex(".*//test-ignore");
+
+ // Using (import) as alias
+ collector.ignoreLinesByRegex("using.*=.*<.*>.*;");
+ collector.ignoreLinesByRegex("using.*=[^.]+;");
+
+ collector.ignoreLinesByPrefix("extern");
+ collector.ignoreByCondition(line -> line.trim().matches("[a-zA-Z0-9]+:.*"));
+ }
+}
diff --git a/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java b/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java
deleted file mode 100644
index e4f710ab0..000000000
--- a/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package de.jplag.csharp;
-
-import static de.jplag.csharp.CSharpTokenType.ACCESSORS_BEGIN;
-import static de.jplag.csharp.CSharpTokenType.ACCESSORS_END;
-import static de.jplag.csharp.CSharpTokenType.ACCESSOR_BEGIN;
-import static de.jplag.csharp.CSharpTokenType.ACCESSOR_END;
-import static de.jplag.csharp.CSharpTokenType.ASSIGNMENT;
-import static de.jplag.csharp.CSharpTokenType.CLASS;
-import static de.jplag.csharp.CSharpTokenType.CLASS_BEGIN;
-import static de.jplag.csharp.CSharpTokenType.CLASS_END;
-import static de.jplag.csharp.CSharpTokenType.CONSTRUCTOR;
-import static de.jplag.csharp.CSharpTokenType.FIELD;
-import static de.jplag.csharp.CSharpTokenType.IF;
-import static de.jplag.csharp.CSharpTokenType.IF_BEGIN;
-import static de.jplag.csharp.CSharpTokenType.IF_END;
-import static de.jplag.csharp.CSharpTokenType.INVOCATION;
-import static de.jplag.csharp.CSharpTokenType.LOCAL_VARIABLE;
-import static de.jplag.csharp.CSharpTokenType.METHOD;
-import static de.jplag.csharp.CSharpTokenType.METHOD_BEGIN;
-import static de.jplag.csharp.CSharpTokenType.METHOD_END;
-import static de.jplag.csharp.CSharpTokenType.PROPERTY;
-import static de.jplag.csharp.CSharpTokenType.RETURN;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Set;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import de.jplag.ParsingException;
-import de.jplag.SharedTokenType;
-import de.jplag.Token;
-import de.jplag.TokenPrinter;
-import de.jplag.TokenType;
-
-class MinimalCSharpTest {
- private final Logger logger = LoggerFactory.getLogger(MinimalCSharpTest.class);
-
- private static final Path BASE_PATH = Path.of("src", "test", "resources", "de", "jplag", "csharp");
- private static final String TEST_SUBJECT = "TestClass.cs";
-
- private de.jplag.Language language;
- private File baseDirectory;
-
- @BeforeEach
- public void setUp() {
- language = new CSharpLanguage();
- baseDirectory = BASE_PATH.toFile();
- assertTrue(baseDirectory.exists(), "Could not find base directory!");
- }
-
- @Test
- void testParsingTestClass() throws ParsingException {
- List expectedToken = List.of(CLASS, CLASS_BEGIN, FIELD, CONSTRUCTOR, LOCAL_VARIABLE, METHOD, METHOD_BEGIN, IF, IF_BEGIN,
- INVOCATION, IF_END, IF_BEGIN, INVOCATION, IF_END, METHOD_END, PROPERTY, ACCESSORS_BEGIN, ACCESSOR_BEGIN, ACCESSOR_END, ACCESSOR_BEGIN,
- ACCESSOR_END, ACCESSORS_END, FIELD, PROPERTY, ACCESSORS_BEGIN, ACCESSOR_BEGIN, RETURN, ACCESSOR_END, ACCESSOR_BEGIN, ASSIGNMENT,
- ACCESSOR_END, ACCESSORS_END, CLASS_END, SharedTokenType.FILE_END);
-
- // Parse test input
- List result = language.parse(Set.of(new File(baseDirectory, TEST_SUBJECT)));
- logger.info(TokenPrinter.printTokens(result, baseDirectory));
-
- // Compare parsed tokens:
- assertEquals(expectedToken.size(), result.size());
- List actualToken = result.stream().map(Token::getType).toList();
- assertEquals(expectedToken, actualToken);
- }
-
-}
diff --git a/languages/csharp/src/test/resources/de/jplag/csharp/AllInOneNoPreprocessor.cs b/languages/csharp/src/test/resources/de/jplag/csharp/AllInOneNoPreprocessor.cs
new file mode 100644
index 000000000..b819b136b
--- /dev/null
+++ b/languages/csharp/src/test/resources/de/jplag/csharp/AllInOneNoPreprocessor.cs
@@ -0,0 +1,1050 @@
+//From https://github.com/antlr/grammars-v4/tree/master/csharp/examples
+
+extern alias Foo;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using M = System.Math;
+
+using ConsoleApplication2.Test;
+
+/**/
+/* the previous comment is an empty delimited comment and not a document comment */
+/** this is a document comment */
+// this one is a single line comment
+
+using X = int1;
+using Y = ABC.X;
+
+using static System.Math;
+using static System.DayOfWeek;
+using static System.Linq.Enumerable;
+
+[assembly: System.Copyright(@"(C)""2009")]
+[module: System.Copyright("\n\t\u0123(C) \"2009" + "\u0123")]
+
+class TopLevelType : IDisposable
+{
+ void IDisposable.Dispose() { }
+}
+
+namespace My
+{
+ using A.B;
+
+ interface CoContra { }
+ delegate void CoContra2<[System.Obsolete()] out T, in K> () where T : struct;
+
+ public unsafe partial class A : C, I
+ {
+ [DllImport("kernel32", SetLastError = true)]
+ static extern bool CreateDirectory(string name, SecurityAttribute sa);
+
+ private const int global = int.MinValue - 1;
+
+ static A()
+ {
+ }
+
+ [method: Obsolete]
+ public A([param: Obsolete] int foo) : base(1) {
+ L: { //test-ignore
+ int i = sizeof(int);
+ ++i;
+ var s1 = $"x {1 , -2 :d}";
+ var s2 = $@"x {1 , -2 :d}";
+ } //test-ignore
+
+
+ Console.WriteLine(export.iefSupplied.command);
+
+ const int? local = int.MaxValue;
+ const Guid? local0 = new Guid(r.ToString());
+
+ var привет = local;
+ var мир = local;
+ int local3 = 0, local4 = 1;
+ local3 = local4 = 1;
+ var local5 = null as Action ?? null;
+ var local6 = local5 is Action;
+
+ var u = 1u;
+ var U = 1U;
+ long hex = 0xBADC0DE, Hex = 0XDEADBEEF, l = -1L, L = 1L, l2 = 2l;
+ ulong ul = 1ul, Ul = 1Ul, uL = 1uL, UL = 1UL, lu = 1lu, Lu = 1Lu, lU = 1lU, LU = 1LU;
+ int minInt32Value = -2147483648;
+ int minInt64Value = -9223372036854775808L;
+
+ bool @bool;
+ byte @byte;
+ char @char = 'c', \u0066 = '\u0066', hexchar = '\x0130', hexchar2 = (char)0xBAD;
+ string \U00000065 = "\U00000065";
+ decimal @decimal = 1.44M;
+ @decimal = 1.2m;
+ dynamic @dynamic;
+ double @double = M.PI;
+ @double = 1d;
+ @double = 1D;
+ @double = -1.2e3;
+ float @float = 1.2f;
+ @float = 1.44F;
+ int @int = local ?? -1;
+ long @long;
+ object @object;
+ sbyte @sbyte;
+ short @short;
+ string @string = @"""/*";
+ uint @uint;
+ ulong @ulong;
+ ushort @ushort;
+
+ dynamic dynamic = local5;
+ var add = 0;
+ var alias = 0;
+ var arglist = 0;
+ var ascending = 0;
+ var async = 0;
+ var await = 0;
+ var by = 0;
+ var descending = 0;
+ var dynamic = 0;
+ var equals = 0;
+ var from = 0;
+ var get = 0;
+ var group = 0;
+ var into = 0;
+ var join = 0;
+ var let = 0;
+ var nameof = 0;
+ var on = 0;
+ var orderby = 0;
+ var partial = 0;
+ var remove = 0;
+ var select = 0;
+ var set = 0;
+ var var = 0;
+ var when = 0;
+ var where = 0;
+ var yield = 0;
+ var __ = 0;
+ where = yield = 0;
+
+ if (i > 0)
+ {
+ return;
+ }
+ else if (i == 0)
+ {
+ throw new Exception();
+ }
+ var o1 = new MyObject();
+ var o2 = new MyObject(var);
+ var o3 = new MyObject { A = i };
+ var o4 = new MyObject(@dynamic)
+ { A = 0, B = 0, C = 0 };//test-ignore
+ var o5 = new { A = 0 };
+ var dictionaryInitializer = new Dictionary
+ { //test-ignore
+ {1, ""}, //test-ignore
+ {2, "a"} //test-ignore
+ };//test-ignore
+ float[] a = new float[]
+ { 0f, 1.1f };//test-ignore
+ int[, ,] cube = { { { 111, 112, }, { 121, 122 } }, { { 211, 212 }, { 221, 222 } } };
+ int[][] jagged = { { 111 }, { 121, 122 } };
+ int[][,] arr = new int[5][,]; // as opposed to new int[][5,5]
+ arr[0] = new int[5,5]; // as opposed to arr[0,0] = new int[5];
+ arr[0][0,0] = 47;
+ int[] arrayTypeInference = new[] { 0, 1, };
+ switch (3) { }
+ switch (i)
+ {//test-ignore
+ case 0: case 1:
+ {//test-ignore
+ goto case 2;
+ }//test-ignore
+ case 2 + 3:
+ {//test-ignore
+ goto default;
+ break;
+ }//test-ignore
+ default:
+ {//test-ignore
+ return;
+ }//test-ignore
+ }//test-ignore
+ while (i < 10) {
+ ++i;
+ if (true) continue;
+ break;
+ }
+ do {
+ ++i;
+ if (true) continue;
+ break;
+ } while (i < 10);
+ for (int j = 0; j < 100; ++j) {
+ for(;;) {
+ for (int i = 0, j = 0; i < length; i++, j++) { }
+ if (true) continue;
+ break;
+ }
+ }
+ label:
+ goto label;
+ label2: ;
+ foreach (var i in Items()) {
+ if (i == 7)
+ return;
+ else
+ continue;
+ }
+ checked
+ {//test-ignore
+ checked(++i);
+ }//test-ignore
+ unchecked
+ {//test-ignore
+ unchecked(++i);
+ }//test-ignore
+ lock (sync)
+ process();
+ using (var v = BeginScope())
+ using (A a = new A())
+ using (A a = new A(), b = new A())
+ using (BeginScope())
+ return;
+ yield return this.items[3];//test-ignore
+ yield break; //test-ignore
+ fixed (int* p = stackalloc int[100], q = &y)
+ { //test-ignore
+ *intref = 1;
+ } //test-ignore
+ fixed (int* p = stackalloc int[100])
+ { //test-ignore
+ *intref = 1;
+ } //test-ignore
+ unsafe
+ { //test-ignore
+ int* p = null;
+ } //test-ignore
+ try
+ { //test-ignore
+ throw null;
+ } //test-ignore
+ catch (System.AccessViolationException av)
+ { //test-ignore
+ throw av;
+ } //test-ignore
+ catch (Exception)
+ { //test-ignore
+ throw;
+ } //test-ignore
+ finally
+ { //test-ignore
+ try { } catch { }
+ } //test-ignore
+ var anonymous =
+ {
+ A = 1,
+ B = 2,
+ C = 3,
+ }; //test-ignore
+ var query = from c in customers
+ let d = c//test-ignore
+ where d != null//test-ignore
+ join c1 in customers on c1.GetHashCode() equals c.GetHashCode()
+ join c1 in customers on c1.GetHashCode() equals c.GetHashCode() into e
+ group c by c.Country//test-ignore
+ into g //test-ignore
+ orderby g.Count() ascending
+ orderby g.Key descending //test-ignore
+ select new { Country = g.Key, CustCount = g.Count() };
+ query = from c in customers
+ select c into d//test-ignore
+ select d;//test-ignore
+ }
+ ~A()
+ { //test-ignore
+ } //test-ignore
+ private readonly int f1;
+ [Obsolete]
+ [NonExisting]
+ [Foo::NonExisting(var, 5)]
+ [CLSCompliant(false)]
+ [Obsolete, System.NonSerialized, NonSerialized, CLSCompliant(true || false & true)]
+ private volatile int f2;
+ [return: Obsolete]
+ [method: Obsolete]
+ public void Handler(object value)
+ {
+ }
+ public int m(T t) where T : class, new()
+ {
+ base.m(t);
+ return 1;
+ }
+ public string P
+ { //test-ignore
+ get
+ {
+ return "A";
+ }
+ set;
+ } //test-ignore
+ public abstract string P
+ { //test-ignore
+ get;
+ } //test-ignore
+ public abstract int this[int index]
+ { //test-ignore
+ protected internal get;
+ internal protected set;
+ } //test-ignore
+ [method: Obsolete]
+ [field: Obsolete]
+ [event: Obsolete]
+ public readonly event Event E;
+ [event: Test]
+ public event Action E1
+ { //test-ignore
+ [Obsolete]
+ add { value = value; }
+ [Obsolete]
+ [return: Obsolete]
+ remove { E += Handler; E -= Handler; }
+ } //test-ignore
+ public static A operator +(A first, A second)
+ {
+ Delegate handler = new Delegate(Handler);
+ return first.Add(second);
+ }
+ [method: Obsolete]
+ [return: Obsolete]
+ public static bool operator true(A a)
+ {
+ return true;
+ }
+ public static bool operator false(A a)
+ {
+ return false;
+ }
+ class C
+ {
+ }
+ }
+ public struct S : I
+ {
+ public S()
+ {
+ }
+ private int f1;
+ [Obsolete("Use Script instead", error: false)]
+ private volatile int f2;
+ public abstract int m(T t) where T : struct
+ {
+ return 1;
+ }
+ public string P
+ { //test-ignore
+ get
+ {
+ int value = 0;
+ return "A";
+ }
+ set;
+ } //test-ignore
+ public abstract string P
+ { //test-ignore
+ get;
+ } //test-ignore
+ public abstract int this[int index]
+ { //test-ignore
+ get;
+ internal protected set;
+ } //test-ignore
+ public event Event E;
+ public static A operator +(A first, A second)
+ {
+ return first.Add(second);
+ }
+ fixed int field[10];//test-ignore
+ class C
+ {
+ }
+ }
+ public interface I
+ {
+ void A(int value);
+ string Value
+ { //test-ignore
+ get;
+ set;
+ } //test-ignore
+ unsafe void UpdateSignatureByHashingContent([In]byte* buffer, int size);
+ }
+ [type: Flags]
+ public enum E
+ {
+ A,
+ B = A,
+ C = 2 + A,
+ D,
+ }
+
+ public delegate void Delegate(object P);
+ namespace Test
+ {
+ using System;
+ using System.Collections;
+ public class Список
+ {
+ public static IEnumerable Power(int number, int exponent)
+ {
+ Список Список = new Список();
+ Список.Main();
+ int counter = (0 + 0);
+ int אתר = 0;
+ while (++counter++ < --exponent--) {
+ result = result * number + +number+++++number;
+ yield return result;//test-ignore
+ }
+ }
+ static void Main()
+ {
+ foreach (int i in Power(2, 8))
+ { //test-ignore
+ Console.Write("{0} ", i);
+ }
+ }
+ async void Wait()
+ {
+ await System.Threading.Tasks.Task.Delay(0);
+ }
+ void AsyncAnonymous() // C # 5 feature
+ {
+ var task = Task.Factory.StartNew(async () =>
+ { //test-ignore
+ return await new WebClient().DownloadStringTaskAsync("http://example.com");
+ }); //test-ignore
+ }
+ }
+ }
+}
+
+namespace ConsoleApplication1
+{
+ namespace RecursiveGenericBaseType
+ {
+ class A : B, A> where T : A
+ {
+ protected virtual A M() { }
+ protected abstract B, A> N() { }
+ static B, A> O() { }
+ }
+
+ sealed class B : A>
+ {
+ protected override A M() { }
+ protected sealed override B, A> N() { }
+ new static A O() { }
+ }
+ }
+
+ namespace Boo
+ {
+ public class Bar where T : IComparable
+ {
+ public T f;
+ public class Foo : IEnumerable
+ {
+ public void Method(K k, T t, U u)
+ where K : IList, IList, IList //test-ignore
+ where V : IList //test-ignore
+ {
+ A a;
+ M(A(5));
+ }
+ };
+ };
+ };
+
+ class Test
+ {
+ void Bar3()
+ {
+ var x = new Boo.Bar.Foo