Commit 82d939aa authored by Daniel Honsel's avatar Daniel Honsel
Browse files

split validator into several classes which can be enabled in the mwe2 workflow if desired

parent 8978f51a
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@ module de.ugoe.cs.swe.GenerateTTCN3
import org.eclipse.emf.mwe.utils.*
import org.eclipse.xtext.generator.*
import org.eclipse.xtext.ui.generator.*
import de.ugoe.cs.swe.scoping.TTCN3ImportNamespaceScopingFragment

var grammarURI = "classpath:/de/ugoe/cs/swe/TTCN3.xtext"
var fileExtensions = "ttcn3,ttcn,3mp"
@@ -75,6 +74,19 @@ Workflow {
			fragment = validation.ValidatorFragment auto-inject {
			//    composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
			//    composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
			
				// validators for the standalone app according to t3q tools
				// can only be used in standalone app, throws an error in eclipse editor
				//composedCheck = "de.ugoe.cs.swe.validation.NamingConventionsValidator"
				//composedCheck = "de.ugoe.cs.swe.validation.StructureOfDataValidator"
				//composedCheck = "de.ugoe.cs.swe.validation.CodeStyleValidator"
				//composedCheck = "de.ugoe.cs.swe.validation.ModularizationValidator"
				//composedCheck = "de.ugoe.cs.swe.validation.MiscFeatureValidator"
				
				// name clash validator
				// can currently only be used with the eclipse editor, does not work 
				// in the standalone app 
				composedCheck = "de.ugoe.cs.swe.validation.NameClashValidator"
			}

			// old scoping and exporting API
@@ -82,7 +94,7 @@ Workflow {
			// fragment = exporting.SimpleNamesFragment auto-inject {}

			// scoping and exporting API
			fragment = TTCN3ImportNamespaceScopingFragment auto-inject {}
			fragment = de.ugoe.cs.swe.scoping.TTCN3ImportNamespaceScopingFragment auto-inject {}
			fragment = exporting.QualifiedNamesFragment auto-inject {}
			fragment = builder.BuilderIntegrationFragment auto-inject {}

+1 −1
Original line number Diff line number Diff line
@@ -1876,7 +1876,7 @@ terminal CSTRING returns ecore::EString:
	// TODO: complete CHAR
terminal fragment CHAR:
	EXTENDED_ALPHA_NUM | LPAREN | RPAREN | LBRACKET | RBRACKET | SQUAREOPEN | SQUARECLOSE | ' ' | QUESTIONMARK | STAR |
	BACKSLASH | SLASH | SEMICOLON | MINUS | PLUS | SHARP | AT | COLON | STRINGOP | '=';
	BACKSLASH | SLASH | SEMICOLON | MINUS | PLUS | SHARP | AT | COLON | STRINGOP | '=' | GREATERTHAN | LESSTHAN | '%' | '$';

terminal HSTRING returns ecore::EString:
	SINGLEQUOTE HEX* SINGLEQUOTE 'H';
+1010 −0

File added.

Preview size limit exceeded, changes collapsed.

+39 −0
Original line number Diff line number Diff line
package de.ugoe.cs.swe.validation

import de.ugoe.cs.swe.TTCN3Configuration.QualityCheckProfile
import de.ugoe.cs.swe.common.ConfigTools
import de.ugoe.cs.swe.tTCN3.ImportDef
import de.ugoe.cs.swe.tTCN3.TTCN3Module

import org.eclipse.xtext.validation.AbstractDeclarativeValidator
import org.eclipse.xtext.validation.Check
import org.eclipse.xtext.validation.EValidatorRegistrar

import static extension org.eclipse.xtext.EcoreUtil2.*

class MiscFeatureValidator extends AbstractDeclarativeValidator {
	val ConfigTools configTools = ConfigTools.getInstance;
	var QualityCheckProfile activeProfile = configTools.selectedProfile as QualityCheckProfile

	@Check
	def addModuleToStatisticProvider(TTCN3Module module) {

		//TODO: do this only in standalone app?
		TTCN3StatisticsProvider.getInstance().addModule(module);
	}

	@Check
	def listImports(TTCN3Module module) {
		if (activeProfile.featureListImportedModuleNames || activeProfile.featureListImportedModuleFileNames ||
			activeProfile.featureListImportingModuleNames || activeProfile.featureListImportingModuleFileNames) {

			for (i : module.getAllContentsOfType(ImportDef)) {
				TTCN3StatisticsProvider.getInstance().addImport(module.name, i.moduleNamespace)
			}
		}
	}

	override register(EValidatorRegistrar registrar) {
		//not needed for classes used as ComposedCheck
	}
}
+229 −0
Original line number Diff line number Diff line
package de.ugoe.cs.swe.validation

import de.ugoe.cs.swe.TTCN3Configuration.QualityCheckProfile
import de.ugoe.cs.swe.common.ConfigTools
import de.ugoe.cs.swe.common.MiscTools
import de.ugoe.cs.swe.common.logging.LoggingInterface.MessageClass
import de.ugoe.cs.swe.tTCN3.FunctionDef
import de.ugoe.cs.swe.tTCN3.ImportDef
import de.ugoe.cs.swe.tTCN3.ModuleDefinition
import de.ugoe.cs.swe.tTCN3.StartTCStatement
import de.ugoe.cs.swe.tTCN3.StartTimerStatement
import de.ugoe.cs.swe.tTCN3.TTCN3Module
import de.ugoe.cs.swe.tTCN3.TTCN3Package
import de.ugoe.cs.swe.tTCN3.TypeDef

import java.util.regex.Matcher
import java.util.regex.Pattern

import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer

import org.eclipse.xtext.nodemodel.INode
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
import org.eclipse.xtext.validation.AbstractDeclarativeValidator
import org.eclipse.xtext.validation.Check
import org.eclipse.xtext.validation.EValidatorRegistrar

import static extension de.ugoe.cs.swe.common.TTCN3ScopeHelper.*
import static extension org.eclipse.xtext.EcoreUtil2.*

class ModularizationValidator extends AbstractDeclarativeValidator {
	val ConfigTools configTools = ConfigTools.getInstance;
	var QualityCheckProfile activeProfile = configTools.selectedProfile as QualityCheckProfile
	var ModuleContentHelper moduleHelper = new ModuleContentHelper(activeProfile)

	@Check
	def checkModuleContainment(TTCN3Module module) {
		if (activeProfile.checkTypesAndValuesModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.TypesAndValuesModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.TypesAndValuesModuleIDSubstring)
		} else if (activeProfile.checkTemplatesModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.TemplatesModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.TemplatesModuleIDSubstring)
		} else if (activeProfile.checkFunctionsModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.FunctionsModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.FunctionsModuleIDSubstring)
		} else if (activeProfile.checkTestcasesModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.TestcasesModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.TestcasesModuleIDSubstring)
		} else if (activeProfile.checkModuleParamsModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.ModuleParamsModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.ModuleParamsModuleIDSubstring)
		} else if (activeProfile.checkInterfaceModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.InterfaceModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.InterfaceModuleIDSubstring)
		} else if (activeProfile.checkTestSystemModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.TestSystemModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.TestSystemModuleIDSubstring)
		} else if (activeProfile.checkTestControlModuleContainmentCheck &&
			module.name.contains(ModuleContentHelper.TestControlModuleIDSubstring)) {
			module.checkModuleContainmentDefinitions(ModuleContentHelper.TestControlModuleIDSubstring)
		}
	}

	private def checkModuleContainmentDefinitions(TTCN3Module module, String moduleRestriction) {
		for (d : module.getAllContentsOfType(ModuleDefinition)) {
			var EObject definition = null
			if (moduleRestriction == ModuleContentHelper.TestSystemModuleIDSubstring) {
				definition = d.def
				if (definition instanceof TypeDef) {
					if (definition.body.structured != null && definition.body.structured.component != null) {
						definition = definition.body.structured.component
					}
				}
			} else {
				definition = d.def
			}
			if (!moduleHelper.typePermittedInRestrictedModule(moduleRestriction, definition.eClass)) {
				TTCN3StatisticsProvider.getInstance.incrementCountModularization
				val message = "Definition in " + moduleRestriction +
					" module is not of the permissible definition type(s)!"
				val INode node = NodeModelUtils.getNode(definition)
				warning(
					message,
					null, //TODO: EStructuralFeature
					MessageClass.MODULARIZATION.toString,
					node.startLine.toString,
					node.endLine.toString,
					"7.x, " + MiscTools.getMethodName()
				);
			} else {
				if (moduleRestriction == ModuleContentHelper.TestcasesModuleIDSubstring &&
					definition instanceof FunctionDef) {
					if (!(definition as FunctionDef).functionStartBehavior(module)) {
						TTCN3StatisticsProvider.getInstance.incrementCountModularization
						val message = "Definition in " + moduleRestriction +
							" module is not of the permissible definition type(s)! Function " +
							(definition as FunctionDef).name + " is never referenced in a start statement!"
						val INode node = NodeModelUtils.getNode(definition)
						warning(
							message,
							null, //TODO: EStructuralFeature
							MessageClass.MODULARIZATION.toString,
							node.startLine.toString,
							node.endLine.toString,
							"7.x, " + MiscTools.getMethodName()
						);
					}
				}
			}
		}
	}

	private def boolean functionStartBehavior(FunctionDef function, TTCN3Module module) {
		val references = UsageCrossReferencer.find(function, module)

		for (r : references) {
			val startTC = r.EObject.findDesiredParent(StartTCStatement)
			val startTimer = r.EObject.findDesiredParent(StartTimerStatement)
			if (startTC != null || startTimer != null) {
				return true
			}
		}

		return false
	}

	@Check
	def checkModuleSize(TTCN3Module module) {
		if (!activeProfile.checkModuleSize) {
			return
		}

		val INode node = NodeModelUtils.getNode(module)
		val moduleSize = node.getEndOffset() - node.getOffset();
		val referenceSize = activeProfile.getMaximumAllowedModuleSizeInBytes();
		if (moduleSize > referenceSize) {
			TTCN3StatisticsProvider.getInstance.incrementCountModularization
			val message = "Module \"" + module.name + "\" is greater (" + moduleSize +
				" bytes) than the maximum allowed module size (" + referenceSize + " bytes)!"
			warning(
				message,
				TTCN3Package.eINSTANCE.TTCN3Reference_Name,
				MessageClass.MODULARIZATION.toString,
				node.startLine.toString,
				node.endLine.toString,
				"7.21, " + MiscTools.getMethodName()
			);
		}
	}

	@Check
	def checkTypesAndValuesModuleImportsLibNames(TTCN3Module module) {
		if (!activeProfile.checkTypesAndValuesModuleImportsLibNames)
			return;

		val Pattern typesAndValuesImportsLibNamesExcludedPattern = Pattern.compile(
			activeProfile.getTypesAndValuesImportsLibNamesExcludedRegExp())
		val Matcher typesAndValuesImportsLibNamesExcludedMatcher = typesAndValuesImportsLibNamesExcludedPattern.
			matcher(module.name)

		if (!module.name.contains(ModuleContentHelper.TypesAndValuesModuleIDSubstring) ||
			typesAndValuesImportsLibNamesExcludedMatcher.matches())
			return;

		val Pattern typesAndValuesImportsLibNamesPattern = Pattern.compile(
			activeProfile.getTypesAndValuesImportsLibNamesRegExp());
		var Matcher typesAndValuesImportsLibNamesMatcher = null;
		var libCommonReferenceFound = false;

		for (i : module.getAllContentsOfType(ImportDef)) {
			typesAndValuesImportsLibNamesMatcher = typesAndValuesImportsLibNamesPattern.matcher(i.moduleNamespace)
			if (typesAndValuesImportsLibNamesMatcher.matches()) {
				libCommonReferenceFound = true
			}
		}

		if (!libCommonReferenceFound) {
			TTCN3StatisticsProvider.getInstance.incrementCountModularization
			val message = "Required import from \"" + activeProfile.getTypesAndValuesImportsLibNamesRegExp() +
				"\" not found!!"
			val INode node = NodeModelUtils.getNode(module)
			warning(
				message,
				TTCN3Package.eINSTANCE.TTCN3Reference_Name,
				MessageClass.MODULARIZATION.toString,
				node.startLine.toString,
				node.endLine.toString,
				"7.3, " + MiscTools.getMethodName()
			);
		}
	}

	@Check
	def checkTestcasesModuleImportsLibCommon_Sync(TTCN3Module module) {
		if (!activeProfile.checkTestcasesModuleImportsLibCommon_Sync)
			return;

		if ((!module.name.contains("Testcases")) || module.name.contains("LibCommon_Sync")) {
			return
		}

		var libCommonReferenceFound = false;

		for (i : module.getAllContentsOfType(ImportDef)) {
			if (i.moduleNamespace.contains("LibCommon_Sync")) {
				libCommonReferenceFound = true
			}
		}

		if (!libCommonReferenceFound) {
			TTCN3StatisticsProvider.getInstance.incrementCountModularization
			val message = "Required import from \"LibCommon_Sync\" not found!"
			val INode node = NodeModelUtils.getNode(module)
			warning(
				message,
				TTCN3Package.eINSTANCE.TTCN3Reference_Name,
				MessageClass.MODULARIZATION.toString,
				node.startLine.toString,
				node.endLine.toString,
				"7.11, " + MiscTools.getMethodName()
			);
		}
	}

	override register(EValidatorRegistrar registrar) {
		//not needed for classes used as ComposedCheck
	}
}
Loading