diff --git a/languages/swift/pom.xml b/languages/swift/pom.xml
index c8af77b57..d60871616 100644
--- a/languages/swift/pom.xml
+++ b/languages/swift/pom.xml
@@ -14,6 +14,11 @@
org.antlr
antlr4-runtime
+
+ de.jplag
+ language-antlr-utils
+ ${revision}
+
diff --git a/languages/swift/src/main/java/de/jplag/swift/JPlagSwiftListener.java b/languages/swift/src/main/java/de/jplag/swift/JPlagSwiftListener.java
deleted file mode 100644
index 90e1e8249..000000000
--- a/languages/swift/src/main/java/de/jplag/swift/JPlagSwiftListener.java
+++ /dev/null
@@ -1,573 +0,0 @@
-package de.jplag.swift;
-
-import static de.jplag.swift.SwiftTokenType.ASSIGNMENT;
-import static de.jplag.swift.SwiftTokenType.BREAK;
-import static de.jplag.swift.SwiftTokenType.CATCH_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.CATCH_BODY_END;
-import static de.jplag.swift.SwiftTokenType.CLASS_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.CLASS_BODY_END;
-import static de.jplag.swift.SwiftTokenType.CLASS_DECLARATION;
-import static de.jplag.swift.SwiftTokenType.CLOSURE_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.CLOSURE_BODY_END;
-import static de.jplag.swift.SwiftTokenType.CONTINUE;
-import static de.jplag.swift.SwiftTokenType.DEFER_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.DEFER_BODY_END;
-import static de.jplag.swift.SwiftTokenType.DO_TRY_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.DO_TRY_BODY_END;
-import static de.jplag.swift.SwiftTokenType.ENUM_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.ENUM_BODY_END;
-import static de.jplag.swift.SwiftTokenType.ENUM_DECLARATION;
-import static de.jplag.swift.SwiftTokenType.ENUM_LITERAL;
-import static de.jplag.swift.SwiftTokenType.FALLTHROUGH;
-import static de.jplag.swift.SwiftTokenType.FOR_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.FOR_BODY_END;
-import static de.jplag.swift.SwiftTokenType.FUNCTION;
-import static de.jplag.swift.SwiftTokenType.FUNCTION_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.FUNCTION_BODY_END;
-import static de.jplag.swift.SwiftTokenType.FUNCTION_CALL;
-import static de.jplag.swift.SwiftTokenType.FUNCTION_PARAMETER;
-import static de.jplag.swift.SwiftTokenType.IF_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.IF_BODY_END;
-import static de.jplag.swift.SwiftTokenType.IMPORT;
-import static de.jplag.swift.SwiftTokenType.PROPERTY_ACCESSOR_BEGIN;
-import static de.jplag.swift.SwiftTokenType.PROPERTY_ACCESSOR_END;
-import static de.jplag.swift.SwiftTokenType.PROPERTY_DECLARATION;
-import static de.jplag.swift.SwiftTokenType.PROTOCOL_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.PROTOCOL_BODY_END;
-import static de.jplag.swift.SwiftTokenType.PROTOCOL_DECLARATION;
-import static de.jplag.swift.SwiftTokenType.REPEAT_WHILE_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.REPEAT_WHILE_BODY_END;
-import static de.jplag.swift.SwiftTokenType.RETURN;
-import static de.jplag.swift.SwiftTokenType.STRUCT_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.STRUCT_BODY_END;
-import static de.jplag.swift.SwiftTokenType.STRUCT_DECLARATION;
-import static de.jplag.swift.SwiftTokenType.SWITCH_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.SWITCH_BODY_END;
-import static de.jplag.swift.SwiftTokenType.SWITCH_CASE;
-import static de.jplag.swift.SwiftTokenType.THROW;
-import static de.jplag.swift.SwiftTokenType.WHILE_BODY_BEGIN;
-import static de.jplag.swift.SwiftTokenType.WHILE_BODY_END;
-
-import org.antlr.v4.runtime.Token;
-
-import de.jplag.swift.grammar.Swift5Parser.Binary_operatorContext;
-import de.jplag.swift.grammar.Swift5Parser.Break_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Catch_clauseContext;
-import de.jplag.swift.grammar.Swift5Parser.Class_bodyContext;
-import de.jplag.swift.grammar.Swift5Parser.Class_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.Closure_expressionContext;
-import de.jplag.swift.grammar.Swift5Parser.Code_blockContext;
-import de.jplag.swift.grammar.Swift5Parser.Constant_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.Continue_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Defer_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.DidSet_clauseContext;
-import de.jplag.swift.grammar.Swift5Parser.Do_blockContext;
-import de.jplag.swift.grammar.Swift5Parser.Else_clauseContext;
-import de.jplag.swift.grammar.Swift5Parser.Enum_nameContext;
-import de.jplag.swift.grammar.Swift5Parser.Fallthrough_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.For_in_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Function_bodyContext;
-import de.jplag.swift.grammar.Swift5Parser.Function_call_suffixContext;
-import de.jplag.swift.grammar.Swift5Parser.Function_nameContext;
-import de.jplag.swift.grammar.Swift5Parser.Function_resultContext;
-import de.jplag.swift.grammar.Swift5Parser.Getter_clauseContext;
-import de.jplag.swift.grammar.Swift5Parser.Getter_setter_blockContext;
-import de.jplag.swift.grammar.Swift5Parser.Guard_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.If_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Import_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.InitializerContext;
-import de.jplag.swift.grammar.Swift5Parser.Initializer_bodyContext;
-import de.jplag.swift.grammar.Swift5Parser.Initializer_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.ParameterContext;
-import de.jplag.swift.grammar.Swift5Parser.Protocol_bodyContext;
-import de.jplag.swift.grammar.Swift5Parser.Protocol_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.Protocol_initializer_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.Protocol_property_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.Raw_value_assignmentContext;
-import de.jplag.swift.grammar.Swift5Parser.Raw_value_style_enumContext;
-import de.jplag.swift.grammar.Swift5Parser.Raw_value_style_enum_caseContext;
-import de.jplag.swift.grammar.Swift5Parser.Raw_value_style_enum_membersContext;
-import de.jplag.swift.grammar.Swift5Parser.Repeat_while_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Return_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Setter_clauseContext;
-import de.jplag.swift.grammar.Swift5Parser.Struct_bodyContext;
-import de.jplag.swift.grammar.Swift5Parser.Struct_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.Switch_caseContext;
-import de.jplag.swift.grammar.Swift5Parser.Switch_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Throw_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.Union_style_enumContext;
-import de.jplag.swift.grammar.Swift5Parser.Union_style_enum_caseContext;
-import de.jplag.swift.grammar.Swift5Parser.Union_style_enum_membersContext;
-import de.jplag.swift.grammar.Swift5Parser.Variable_declarationContext;
-import de.jplag.swift.grammar.Swift5Parser.While_statementContext;
-import de.jplag.swift.grammar.Swift5Parser.WillSet_clauseContext;
-import de.jplag.swift.grammar.Swift5ParserBaseListener;
-
-public class JPlagSwiftListener extends Swift5ParserBaseListener {
- private final SwiftParserAdapter parserAdapter;
-
- public JPlagSwiftListener(SwiftParserAdapter parserAdapter) {
- this.parserAdapter = parserAdapter;
- }
-
- /**
- * Passes a token of the given tokenType to the parserAdapter, representing the grammar's token given by token.
- * @param tokenType the custom token type that occurred.
- * @param token the corresponding grammar's token
- */
- private void transformToken(SwiftTokenType tokenType, Token token) {
- parserAdapter.addToken(tokenType, token.getLine(), token.getCharPositionInLine() + 1, token.getText().length());
- }
-
- /**
- * Passes a token of the given tokenType to the parserAdapter, representing the current grammatical context given by
- * start and end.
- * @param tokenType the custom token type that occurred.
- * @param start the first Token of the context
- * @param end the last Token of the context
- */
- private void transformToken(SwiftTokenType tokenType, Token start, Token end) {
- parserAdapter.addToken(tokenType, start.getLine(), start.getCharPositionInLine() + 1, end.getStopIndex() - start.getStartIndex() + 1);
- }
-
- @Override
- public void enterImport_declaration(Import_declarationContext context) {
- transformToken(IMPORT, context.getStart(), context.getStop());
- super.enterImport_declaration(context);
- }
-
- @Override
- public void enterClass_declaration(Class_declarationContext context) {
- transformToken(CLASS_DECLARATION, context.getStart(), context.getStop());
- super.enterClass_declaration(context);
- }
-
- @Override
- public void enterClass_body(Class_bodyContext context) {
- transformToken(CLASS_BODY_BEGIN, context.getStart());
- super.enterClass_body(context);
- }
-
- @Override
- public void exitClass_body(Class_bodyContext context) {
- transformToken(CLASS_BODY_END, context.getStop());
- super.exitClass_body(context);
- }
-
- @Override
- public void enterStruct_declaration(Struct_declarationContext context) {
- transformToken(STRUCT_DECLARATION, context.getStart(), context.getStop());
- super.enterStruct_declaration(context);
- }
-
- @Override
- public void enterStruct_body(Struct_bodyContext context) {
- transformToken(STRUCT_BODY_BEGIN, context.getStart());
- super.enterStruct_body(context);
- }
-
- @Override
- public void exitStruct_body(Struct_bodyContext context) {
- transformToken(STRUCT_BODY_END, context.getStop());
- super.exitStruct_body(context);
- }
-
- @Override
- public void enterEnum_name(Enum_nameContext context) {
- transformToken(ENUM_DECLARATION, context.getStart(), context.getStop());
- super.enterEnum_name(context);
- }
-
- @Override
- public void enterRaw_value_style_enum_members(Raw_value_style_enum_membersContext context) {
- transformToken(ENUM_BODY_BEGIN, context.getStart());
- super.enterRaw_value_style_enum_members(context);
- }
-
- @Override
- public void exitRaw_value_style_enum(Raw_value_style_enumContext context) {
- transformToken(ENUM_BODY_END, context.getStop());
- super.exitRaw_value_style_enum(context);
- }
-
- @Override
- public void enterRaw_value_style_enum_case(Raw_value_style_enum_caseContext context) {
- transformToken(ENUM_LITERAL, context.getStart(), context.getStop());
- super.enterRaw_value_style_enum_case(context);
- }
-
- @Override
- public void enterUnion_style_enum_members(Union_style_enum_membersContext context) {
- transformToken(ENUM_BODY_BEGIN, context.getStart());
- super.enterUnion_style_enum_members(context);
- }
-
- @Override
- public void exitUnion_style_enum(Union_style_enumContext context) {
- transformToken(ENUM_BODY_END, context.getStop());
- super.exitUnion_style_enum(context);
- }
-
- @Override
- public void enterUnion_style_enum_case(Union_style_enum_caseContext context) {
- transformToken(ENUM_LITERAL, context.getStart(), context.getStop());
- super.enterUnion_style_enum_case(context);
- }
-
- @Override
- public void enterProtocol_declaration(Protocol_declarationContext context) {
- transformToken(PROTOCOL_DECLARATION, context.getStart(), context.getStop());
- super.enterProtocol_declaration(context);
- }
-
- @Override
- public void enterProtocol_body(Protocol_bodyContext context) {
- transformToken(PROTOCOL_BODY_BEGIN, context.getStart());
- super.enterProtocol_body(context);
- }
-
- @Override
- public void exitProtocol_body(Protocol_bodyContext context) {
- transformToken(PROTOCOL_BODY_END, context.getStop());
- super.exitProtocol_body(context);
- }
-
- @Override
- public void enterVariable_declaration(Variable_declarationContext context) {
- transformToken(PROPERTY_DECLARATION, context.getStart(), context.getStop());
- super.enterVariable_declaration(context);
- }
-
- @Override
- public void enterProtocol_property_declaration(Protocol_property_declarationContext context) {
- transformToken(PROPERTY_DECLARATION, context.getStart(), context.getStop());
- super.enterProtocol_property_declaration(context);
- }
-
- @Override
- public void enterConstant_declaration(Constant_declarationContext context) {
- transformToken(PROPERTY_DECLARATION, context.getStart(), context.getStop());
- super.enterConstant_declaration(context);
- }
-
- @Override
- public void enterGetter_clause(Getter_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_BEGIN, context.getStart());
- super.enterGetter_clause(context);
- }
-
- @Override
- public void exitGetter_clause(Getter_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_END, context.getStop());
- super.exitGetter_clause(context);
- }
-
- @Override
- public void enterSetter_clause(Setter_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_BEGIN, context.getStart());
- super.enterSetter_clause(context);
- }
-
- @Override
- public void exitSetter_clause(Setter_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_END, context.getStop());
- super.exitSetter_clause(context);
- }
-
- @Override
- public void enterWillSet_clause(WillSet_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_BEGIN, context.getStart());
- super.enterWillSet_clause(context);
- }
-
- @Override
- public void enterGetter_setter_block(Getter_setter_blockContext context) {
- if (isComputedReadOnlyVariableGetterContext(context)) {
- transformToken(PROPERTY_ACCESSOR_BEGIN, context.getStart());
- }
- super.enterGetter_setter_block(context);
- }
-
- @Override
- public void exitGetter_setter_block(Getter_setter_blockContext context) {
- if (isComputedReadOnlyVariableGetterContext(context)) {
- transformToken(PROPERTY_ACCESSOR_END, context.getStop());
- }
- super.exitGetter_setter_block(context);
- }
-
- /**
- * Indicates whether the given context encodes a computed read-only variable getter. An example of this is
- * var example: Int { return 1 }
.
- * @param context
- * @return
- */
- private boolean isComputedReadOnlyVariableGetterContext(Getter_setter_blockContext context) {
- return context.getChildCount() == 1 && context.getChild(0) instanceof Code_blockContext;
- }
-
- @Override
- public void exitWillSet_clause(WillSet_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_END, context.getStop());
- super.exitWillSet_clause(context);
- }
-
- @Override
- public void enterDidSet_clause(DidSet_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_BEGIN, context.getStart());
- super.enterDidSet_clause(context);
- }
-
- @Override
- public void exitDidSet_clause(DidSet_clauseContext context) {
- transformToken(PROPERTY_ACCESSOR_END, context.getStop());
- super.exitDidSet_clause(context);
- }
-
- @Override
- public void enterInitializer_declaration(Initializer_declarationContext context) {
- transformToken(FUNCTION, context.getStart(), context.getStop());
- super.enterInitializer_declaration(context);
- }
-
- @Override
- public void enterProtocol_initializer_declaration(Protocol_initializer_declarationContext context) {
- transformToken(FUNCTION, context.getStart(), context.getStop());
- super.enterProtocol_initializer_declaration(context);
- }
-
- @Override
- public void enterInitializer_body(Initializer_bodyContext context) {
- transformToken(FUNCTION_BODY_BEGIN, context.getStart());
- super.enterInitializer_body(context);
- }
-
- @Override
- public void exitInitializer_body(Initializer_bodyContext context) {
- transformToken(FUNCTION_BODY_END, context.getStop());
- super.exitInitializer_body(context);
- }
-
- @Override
- public void enterFunction_name(Function_nameContext context) {
- transformToken(FUNCTION, context.getStart(), context.getStop());
- super.enterFunction_name(context);
- }
-
- @Override
- public void enterParameter(ParameterContext context) {
- transformToken(FUNCTION_PARAMETER, context.getStart(), context.getStop());
- super.enterParameter(context);
- }
-
- @Override
- public void enterFunction_result(Function_resultContext context) {
- transformToken(FUNCTION_PARAMETER, context.getStart(), context.getStop());
- super.enterFunction_result(context);
- }
-
- @Override
- public void enterFunction_body(Function_bodyContext context) {
- transformToken(FUNCTION_BODY_BEGIN, context.getStart());
- super.enterFunction_body(context);
- }
-
- @Override
- public void exitFunction_body(Function_bodyContext context) {
- transformToken(FUNCTION_BODY_END, context.getStop());
- super.exitFunction_body(context);
- }
-
- @Override
- public void enterClosure_expression(Closure_expressionContext context) {
- transformToken(CLOSURE_BODY_BEGIN, context.getStart());
- super.enterClosure_expression(context);
- }
-
- @Override
- public void exitClosure_expression(Closure_expressionContext context) {
- transformToken(CLOSURE_BODY_END, context.getStop());
- super.exitClosure_expression(context);
- }
-
- @Override
- public void enterFor_in_statement(For_in_statementContext context) {
- transformToken(FOR_BODY_BEGIN, context.getStart());
- super.enterFor_in_statement(context);
- }
-
- @Override
- public void exitFor_in_statement(For_in_statementContext context) {
- transformToken(FOR_BODY_END, context.getStop());
- super.exitFor_in_statement(context);
- }
-
- @Override
- public void enterIf_statement(If_statementContext context) {
- transformToken(IF_BODY_BEGIN, context.getStart());
- super.enterIf_statement(context);
- }
-
- @Override
- public void exitIf_statement(If_statementContext context) {
- transformToken(IF_BODY_END, context.getStop());
- super.exitIf_statement(context);
- }
-
- @Override
- public void enterElse_clause(Else_clauseContext context) {
- transformToken(IF_BODY_END, context.getStart());
- // Check that current context is not `else if` but rather `else`
- if (!(context.getChild(1) instanceof If_statementContext)) {
- transformToken(IF_BODY_BEGIN, context.getStart());
- }
- super.enterElse_clause(context);
- }
-
- @Override
- public void enterGuard_statement(Guard_statementContext context) {
- transformToken(IF_BODY_BEGIN, context.getStart());
- super.enterGuard_statement(context);
- }
-
- @Override
- public void exitGuard_statement(Guard_statementContext context) {
- transformToken(IF_BODY_END, context.getStop());
- super.exitGuard_statement(context);
- }
-
- @Override
- public void enterSwitch_statement(Switch_statementContext context) {
- transformToken(SWITCH_BODY_BEGIN, context.getStart());
- super.enterSwitch_statement(context);
- }
-
- @Override
- public void exitSwitch_statement(Switch_statementContext context) {
- transformToken(SWITCH_BODY_END, context.getStop());
- super.exitSwitch_statement(context);
- }
-
- @Override
- public void enterSwitch_case(Switch_caseContext context) {
- transformToken(SWITCH_CASE, context.getStart());
- super.enterSwitch_case(context);
- }
-
- @Override
- public void enterWhile_statement(While_statementContext context) {
- transformToken(WHILE_BODY_BEGIN, context.getStart());
- super.enterWhile_statement(context);
- }
-
- @Override
- public void exitWhile_statement(While_statementContext context) {
- transformToken(WHILE_BODY_END, context.getStop());
- super.exitWhile_statement(context);
- }
-
- @Override
- public void enterRepeat_while_statement(Repeat_while_statementContext context) {
- transformToken(REPEAT_WHILE_BODY_BEGIN, context.getStart());
- super.enterRepeat_while_statement(context);
- }
-
- @Override
- public void exitRepeat_while_statement(Repeat_while_statementContext context) {
- transformToken(REPEAT_WHILE_BODY_END, context.getStop());
- super.exitRepeat_while_statement(context);
- }
-
- @Override
- public void enterDefer_statement(Defer_statementContext context) {
- transformToken(DEFER_BODY_BEGIN, context.getStart());
- super.enterDefer_statement(context);
- }
-
- @Override
- public void exitDefer_statement(Defer_statementContext context) {
- transformToken(DEFER_BODY_END, context.getStop());
- super.exitDefer_statement(context);
- }
-
- @Override
- public void enterDo_block(Do_blockContext context) {
- transformToken(DO_TRY_BODY_BEGIN, context.getStart());
- super.enterDo_block(context);
- }
-
- @Override
- public void exitDo_block(Do_blockContext context) {
- transformToken(DO_TRY_BODY_END, context.getStop());
- super.exitDo_block(context);
- }
-
- @Override
- public void enterCatch_clause(Catch_clauseContext context) {
- transformToken(CATCH_BODY_BEGIN, context.getStart());
- super.enterCatch_clause(context);
- }
-
- @Override
- public void exitCatch_clause(Catch_clauseContext context) {
- transformToken(CATCH_BODY_END, context.getStop());
- super.exitCatch_clause(context);
- }
-
- @Override
- public void enterThrow_statement(Throw_statementContext context) {
- transformToken(THROW, context.getStart(), context.getStop());
- super.enterThrow_statement(context);
- }
-
- @Override
- public void enterReturn_statement(Return_statementContext context) {
- transformToken(RETURN, context.getStart(), context.getStop());
- super.enterReturn_statement(context);
- }
-
- @Override
- public void enterContinue_statement(Continue_statementContext context) {
- transformToken(CONTINUE, context.getStart(), context.getStop());
- super.enterContinue_statement(context);
- }
-
- @Override
- public void enterBreak_statement(Break_statementContext context) {
- transformToken(BREAK, context.getStart(), context.getStop());
- super.enterBreak_statement(context);
- }
-
- @Override
- public void enterFallthrough_statement(Fallthrough_statementContext context) {
- transformToken(FALLTHROUGH, context.getStart(), context.getStop());
- super.enterFallthrough_statement(context);
- }
-
- @Override
- public void enterInitializer(InitializerContext context) {
- transformToken(ASSIGNMENT, context.getStart(), context.getStop());
- super.enterInitializer(context);
- }
-
- @Override
- public void enterRaw_value_assignment(Raw_value_assignmentContext context) {
- transformToken(ASSIGNMENT, context.getStart(), context.getStop());
- super.enterRaw_value_assignment(context);
- }
-
- @Override
- public void enterBinary_operator(Binary_operatorContext context) {
- String operator = context.getText();
- if (operator.contains("=") && !operator.contains("==")) {
- transformToken(ASSIGNMENT, context.getStart(), context.getStop());
- }
- super.enterBinary_operator(context);
- }
-
- @Override
- public void enterFunction_call_suffix(Function_call_suffixContext context) {
- transformToken(FUNCTION_CALL, context.getStart(), context.getStop());
- super.enterFunction_call_suffix(context);
- }
-}
diff --git a/languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java b/languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java
index 82a56d11e..abc088ef2 100644
--- a/languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java
+++ b/languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java
@@ -1,29 +1,23 @@
package de.jplag.swift;
-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;
/**
* This represents the Swift language as a language supported by JPlag.
*/
@MetaInfServices(de.jplag.Language.class)
-public class SwiftLanguage implements de.jplag.Language {
+public class SwiftLanguage extends AbstractAntlrLanguage {
private static final String IDENTIFIER = "swift";
private static final String NAME = "Swift";
private static final int DEFAULT_MIN_TOKEN_MATCH = 8;
private static final String[] FILE_EXTENSIONS = {".swift"};
- private final SwiftParserAdapter parserAdapter;
public SwiftLanguage() {
- this.parserAdapter = new SwiftParserAdapter();
+ super(new SwiftParserAdapter());
}
@Override
@@ -45,9 +39,4 @@ public String getIdentifier() {
public int minimumTokenMatch() {
return DEFAULT_MIN_TOKEN_MATCH;
}
-
- @Override
- public List parse(Set files, boolean normalize) throws ParsingException {
- return parserAdapter.parse(files);
- }
}
diff --git a/languages/swift/src/main/java/de/jplag/swift/SwiftListener.java b/languages/swift/src/main/java/de/jplag/swift/SwiftListener.java
new file mode 100644
index 000000000..3b95d98ac
--- /dev/null
+++ b/languages/swift/src/main/java/de/jplag/swift/SwiftListener.java
@@ -0,0 +1,97 @@
+package de.jplag.swift;
+
+import static de.jplag.swift.SwiftTokenType.*;
+
+import de.jplag.antlr.AbstractAntlrListener;
+import de.jplag.swift.grammar.Swift5Parser.*;
+
+public class SwiftListener extends AbstractAntlrListener {
+ public SwiftListener() {
+ this.registerDataStructureRules();
+ this.registerFunctionRules();
+ this.registerControlStructureRules();
+
+ this.visit(Import_declarationContext.class).mapRange(IMPORT);
+
+ this.visit(Variable_declarationContext.class).map(PROPERTY_DECLARATION);
+ this.visit(Protocol_property_declarationContext.class).mapRange(PROPERTY_DECLARATION);
+ this.visit(Constant_declarationContext.class).mapRange(PROPERTY_DECLARATION);
+
+ this.visit(Fallthrough_statementContext.class).mapRange(FALLTHROUGH);
+ this.visit(InitializerContext.class).mapRange(ASSIGNMENT);
+ this.visit(Raw_value_assignmentContext.class).mapRange(ASSIGNMENT);
+
+ this.visit(Binary_operatorContext.class, context -> context.getText().contains("=") && !context.getText().contains("=="))
+ .mapRange(ASSIGNMENT);
+ this.visit(Closure_expressionContext.class).map(CLOSURE_BODY_BEGIN, CLOSURE_BODY_END);
+ }
+
+ private void registerDataStructureRules() {
+ this.visit(Class_declarationContext.class).map(CLASS_DECLARATION);
+ this.visit(Class_bodyContext.class).map(CLASS_BODY_BEGIN, CLASS_BODY_END);
+ this.visit(Closure_expressionContext.class).map(CLASS_BODY_BEGIN, CLASS_BODY_END);
+
+ this.visit(Struct_declarationContext.class).map(STRUCT_DECLARATION);
+ this.visit(Struct_bodyContext.class).map(STRUCT_BODY_BEGIN, STRUCT_BODY_END);
+
+ this.visit(Enum_nameContext.class).map(ENUM_DECLARATION);
+ this.visit(Raw_value_style_enum_membersContext.class).map(ENUM_BODY_BEGIN);
+ this.visit(Union_style_enum_membersContext.class).map(ENUM_BODY_BEGIN);
+ this.visit(Raw_value_style_enumContext.class).mapExit(ENUM_BODY_END);
+ this.visit(Union_style_enumContext.class).mapExit(ENUM_BODY_END);
+
+ this.visit(Raw_value_style_enum_caseContext.class).mapRange(ENUM_LITERAL);
+ this.visit(Union_style_enum_caseContext.class).mapRange(ENUM_LITERAL);
+
+ this.visit(Protocol_declarationContext.class).mapRange(PROTOCOL_DECLARATION);
+ this.visit(Protocol_bodyContext.class).map(PROTOCOL_BODY_BEGIN, PROTOCOL_BODY_END);
+ }
+
+ private void registerFunctionRules() {
+ this.visit(Initializer_declarationContext.class).mapRange(FUNCTION);
+ this.visit(Protocol_initializer_declarationContext.class).mapRange(FUNCTION);
+ this.visit(Function_nameContext.class).mapRange(FUNCTION);
+ this.visit(Initializer_bodyContext.class).map(FUNCTION_BODY_BEGIN, FUNCTION_BODY_END);
+ this.visit(ParameterContext.class).mapRange(FUNCTION_PARAMETER);
+ this.visit(Function_resultContext.class).mapRange(FUNCTION_PARAMETER);
+ this.visit(Function_bodyContext.class).map(FUNCTION_BODY_BEGIN, FUNCTION_BODY_END);
+ this.visit(Function_call_suffixContext.class).mapRange(FUNCTION_CALL);
+
+ this.visit(Getter_clauseContext.class).map(PROPERTY_ACCESSOR_BEGIN, PROPERTY_ACCESSOR_END);
+ this.visit(Setter_clauseContext.class).map(PROPERTY_ACCESSOR_BEGIN, PROPERTY_ACCESSOR_END);
+ this.visit(WillSet_clauseContext.class).map(PROPERTY_ACCESSOR_BEGIN, PROPERTY_ACCESSOR_END);
+ this.visit(Getter_setter_blockContext.class, this::isComputedReadOnlyVariableGetterContext).map(PROPERTY_ACCESSOR_BEGIN,
+ PROPERTY_ACCESSOR_END);
+ this.visit(DidSet_clauseContext.class).map(PROPERTY_ACCESSOR_BEGIN, PROPERTY_ACCESSOR_END);
+ }
+
+ private void registerControlStructureRules() {
+ this.visit(For_in_statementContext.class).map(FOR_BODY_BEGIN, FOR_BODY_END);
+ this.visit(If_statementContext.class).map(IF_BODY_BEGIN, IF_BODY_END);
+ this.visit(Else_clauseContext.class).map(IF_BODY_END);
+ this.visit(Else_clauseContext.class, context -> !(context.getChild(0) instanceof If_statementContext)).map(IF_BODY_BEGIN);
+ this.visit(Guard_statementContext.class).map(IF_BODY_BEGIN, IF_BODY_END);
+ this.visit(Switch_statementContext.class).map(SWITCH_BODY_BEGIN, SWITCH_BODY_END);
+ this.visit(Switch_caseContext.class).map(SWITCH_CASE);
+ this.visit(While_statementContext.class).map(WHILE_BODY_BEGIN, WHILE_BODY_END);
+ this.visit(Repeat_while_statementContext.class).map(REPEAT_WHILE_BODY_BEGIN, REPEAT_WHILE_BODY_END);
+ this.visit(Defer_statementContext.class).map(DEFER_BODY_BEGIN, DEFER_BODY_END);
+
+ this.visit(Do_blockContext.class).map(DO_TRY_BODY_BEGIN, DO_TRY_BODY_END);
+ this.visit(Catch_clauseContext.class).map(CATCH_BODY_BEGIN, CATCH_BODY_END);
+ this.visit(Throw_statementContext.class).mapRange(THROW);
+ this.visit(Return_statementContext.class).mapRange(RETURN);
+ this.visit(Continue_statementContext.class).mapRange(CONTINUE);
+ this.visit(Break_statementContext.class).mapRange(BREAK);
+ }
+
+ /**
+ * Indicates whether the given context encodes a computed read-only variable getter. An example of this is
+ * var example: Int { return 1 }
.
+ * @param context
+ * @return
+ */
+ private boolean isComputedReadOnlyVariableGetterContext(Getter_setter_blockContext context) {
+ return context.getChildCount() == 1 && context.getChild(0) instanceof Code_blockContext;
+ }
+}
diff --git a/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java b/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java
index 26c8025a8..047c08c87 100644
--- a/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java
+++ b/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java
@@ -1,81 +1,33 @@
package de.jplag.swift;
-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.antlr.AbstractAntlrListener;
+import de.jplag.antlr.AbstractAntlrParserAdapter;
import de.jplag.swift.grammar.Swift5Lexer;
import de.jplag.swift.grammar.Swift5Parser;
-import de.jplag.util.FileUtils;
-
-public class SwiftParserAdapter extends AbstractParser {
-
- public static final int NOT_SET = -1;
- private File currentFile;
- private List tokens;
- /**
- * Creates the SwiftParserAdapter
- */
- public SwiftParserAdapter() {
- super();
+public class SwiftParserAdapter extends AbstractAntlrParserAdapter {
+ @Override
+ protected Lexer createLexer(CharStream input) {
+ return new Swift5Lexer(input);
}
- /**
- * Parsers a set of files into a single list of {@link Token}s.
- * @param files the set of files.
- * @return a list containing all tokens of all files.
- */
- public List parse(Set files) throws ParsingException {
- tokens = new ArrayList<>();
- for (File file : files) {
- parse(file);
- tokens.add(Token.fileEnd(file));
- }
- return tokens;
+ @Override
+ protected Swift5Parser createParser(CommonTokenStream tokenStream) {
+ return new Swift5Parser(tokenStream);
}
- private void parse(File file) throws ParsingException {
- try (BufferedReader reader = FileUtils.openFileReader(file)) {
- currentFile = file;
-
- Swift5Lexer lexer = new Swift5Lexer(CharStreams.fromReader(reader));
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
- Swift5Parser parser = new Swift5Parser(tokenStream);
-
- ParserRuleContext entryContext = parser.top_level();
- ParseTreeWalker treeWalker = new ParseTreeWalker();
-
- JPlagSwiftListener listener = new JPlagSwiftListener(this);
- for (int i = 0; i < entryContext.getChildCount(); i++) {
- ParseTree parseTree = entryContext.getChild(i);
- treeWalker.walk(listener, parseTree);
- }
- } catch (IOException exception) {
- throw new ParsingException(file, exception.getMessage(), exception);
- }
+ @Override
+ protected ParserRuleContext getEntryContext(Swift5Parser parser) {
+ return parser.top_level();
}
- /**
- * Adds a new {@link Token} to the current token list.
- * @param tokenType the type of the new {@link Token}
- * @param line the line of the Token in the current file
- * @param column the start column of the Token in the line
- * @param length the length of the Token
- */
- /* package-private */ void addToken(SwiftTokenType tokenType, int line, int column, int length) {
- tokens.add(new Token(tokenType, currentFile, line, column, length));
+ @Override
+ protected AbstractAntlrListener getListener() {
+ return new SwiftListener();
}
}
diff --git a/languages/swift/src/test/java/de/jplag/swift/SwiftLanguageTest.java b/languages/swift/src/test/java/de/jplag/swift/SwiftLanguageTest.java
new file mode 100644
index 000000000..eeb67f480
--- /dev/null
+++ b/languages/swift/src/test/java/de/jplag/swift/SwiftLanguageTest.java
@@ -0,0 +1,21 @@
+package de.jplag.swift;
+
+import de.jplag.testutils.LanguageModuleTest;
+import de.jplag.testutils.datacollector.TestDataCollector;
+import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector;
+
+public class SwiftLanguageTest extends LanguageModuleTest {
+ public SwiftLanguageTest() {
+ super(new SwiftLanguage(), SwiftTokenType.class);
+ }
+
+ @Override
+ protected void collectTestData(TestDataCollector collector) {
+ collector.testFile("Complete.swift").testCoverages();
+ }
+
+ @Override
+ protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) {
+ collector.ignoreLinesByContains("//NO TOKEN");
+ }
+}