From 9216c01fb8f5e9a6864cf5978646fdbe58c7977b Mon Sep 17 00:00:00 2001 From: Timotei Dolean Date: Thu, 4 Aug 2011 19:16:23 +0000 Subject: [PATCH] eclipse plugin: Implement the remaining of the validation... ...routines, and allow the user to enable/disable the WML validation --- .../src/org/wesnoth/Constants.java | 3 +- .../preferences/AdvancedPreferencePage.java | 19 ++- .../org/wesnoth/preferences/Preferences.java | 10 +- .../preprocessor/PreprocessorUtils.java | 2 +- .../src/org/wesnoth/utils/ResourceUtils.java | 12 ++ .../wesnoth/validation/WMLJavaValidator.java | 149 ++++++++++++++---- 6 files changed, 157 insertions(+), 38 deletions(-) diff --git a/utils/umc_dev/org.wesnoth/src/org/wesnoth/Constants.java b/utils/umc_dev/org.wesnoth/src/org/wesnoth/Constants.java index a5db8d0ab7d..d1b8a7eb6b5 100644 --- a/utils/umc_dev/org.wesnoth/src/org/wesnoth/Constants.java +++ b/utils/umc_dev/org.wesnoth/src/org/wesnoth/Constants.java @@ -62,7 +62,8 @@ public class Constants public static final String P_WAU_PORT = "wau_port"; //$NON-NLS-1$ /** Advanced preferences */ - public static final String P_ADV_NO_TERRAIN_GFX = "adv_no_terrain_gfx"; //$NON-NLS-1$ + public static final String P_NO_TERRAIN_GFX = "adv_no_terrain_gfx"; //$NON-NLS-1$ + public static final String P_WML_VALIDATION = "adv_wml_validation"; //$NON-NLS-1$ /** Install preferences */ public static final String P_INST_DEFAULT_INSTALL = "inst_default"; //$NON-NLS-1$ diff --git a/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/AdvancedPreferencePage.java b/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/AdvancedPreferencePage.java index b798c1df5ef..a879d6b7115 100644 --- a/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/AdvancedPreferencePage.java +++ b/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/AdvancedPreferencePage.java @@ -8,11 +8,12 @@ *******************************************************************************/ package org.wesnoth.preferences; -import org.eclipse.jface.preference.BooleanFieldEditor; import org.wesnoth.Constants; import org.wesnoth.Messages; import org.wesnoth.WesnothPlugin; +import org.eclipse.jface.preference.BooleanFieldEditor; + public class AdvancedPreferencePage extends AbstractPreferencePage { public AdvancedPreferencePage() @@ -26,9 +27,17 @@ public class AdvancedPreferencePage extends AbstractPreferencePage @Override protected void createFieldEditors() { - addField(new BooleanFieldEditor( - Constants.P_ADV_NO_TERRAIN_GFX, Messages.AdvancedPreferencePage_1, 1, - getFieldEditorParent()), - Messages.AdvancedPreferencePage_2); + addField( new BooleanFieldEditor( + Constants.P_NO_TERRAIN_GFX, Messages.AdvancedPreferencePage_1, + BooleanFieldEditor.SEPARATE_LABEL, + getFieldEditorParent( ) ), + Messages.AdvancedPreferencePage_2 ); + + addField( new BooleanFieldEditor( + Constants.P_WML_VALIDATION, "WML Validation, parent", + BooleanFieldEditor.SEPARATE_LABEL, + getFieldEditorParent( ) ), + "If checked, the WML Editor will validate some of the " + + "written WML to check for semantic errors." ); } } diff --git a/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/Preferences.java b/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/Preferences.java index faaf57716dc..e2a6dd36255 100644 --- a/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/Preferences.java +++ b/utils/umc_dev/org.wesnoth/src/org/wesnoth/preferences/Preferences.java @@ -11,13 +11,14 @@ package org.wesnoth.preferences; import java.util.HashMap; import java.util.Map; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; -import org.eclipse.jface.preference.IPreferenceStore; import org.wesnoth.Constants; import org.wesnoth.WesnothPlugin; import org.wesnoth.utils.StringUtils; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + /** * Class used to initialize default preference values. */ @@ -57,7 +58,8 @@ public class Preferences extends AbstractPreferenceInitializer store.setDefault(Constants.P_WAU_PORT, 15002); // advanced - store.setDefault(Constants.P_ADV_NO_TERRAIN_GFX, true); + store.setDefault(Constants.P_NO_TERRAIN_GFX, true); + store.setDefault( Constants.P_WML_VALIDATION, false ); // installs store.setDefault(Constants.P_INST_DEFAULT_INSTALL, ""); //$NON-NLS-1$ diff --git a/utils/umc_dev/org.wesnoth/src/org/wesnoth/preprocessor/PreprocessorUtils.java b/utils/umc_dev/org.wesnoth/src/org/wesnoth/preprocessor/PreprocessorUtils.java index cb8501d5b13..13cca7c482e 100644 --- a/utils/umc_dev/org.wesnoth/src/org/wesnoth/preprocessor/PreprocessorUtils.java +++ b/utils/umc_dev/org.wesnoth/src/org/wesnoth/preprocessor/PreprocessorUtils.java @@ -135,7 +135,7 @@ public class PreprocessorUtils arguments.add(macrosFile); } - if (Preferences.getBool(Constants.P_ADV_NO_TERRAIN_GFX)) + if (Preferences.getBool(Constants.P_NO_TERRAIN_GFX)) { if (defines == null) defines = new ArrayList(); diff --git a/utils/umc_dev/org.wesnoth/src/org/wesnoth/utils/ResourceUtils.java b/utils/umc_dev/org.wesnoth/src/org/wesnoth/utils/ResourceUtils.java index 75a2b57ad3b..7d1b441a4c6 100644 --- a/utils/umc_dev/org.wesnoth/src/org/wesnoth/utils/ResourceUtils.java +++ b/utils/umc_dev/org.wesnoth/src/org/wesnoth/utils/ResourceUtils.java @@ -580,6 +580,18 @@ public class ResourceUtils } } + /** + * Returns the corresponding {@link IResource} from the specified + * EMF Resource + * @param emfResource The EMF Resource + * @return An {@link IResource} instance + */ + public static IResource getWorkspaceResource( Resource emfResource ) + { + return ResourcesPlugin.getWorkspace( ).getRoot( ). + getFile( new Path( emfResource.getURI( ).toPlatformString( true ) ) ); + } + /** * Gets the WML Grammar root of the specified file * @param file The file to get the WML model from diff --git a/utils/umc_dev/org.wesnoth/src/org/wesnoth/validation/WMLJavaValidator.java b/utils/umc_dev/org.wesnoth/src/org/wesnoth/validation/WMLJavaValidator.java index 03f7b4ffa13..4f6d400bb4f 100644 --- a/utils/umc_dev/org.wesnoth/src/org/wesnoth/validation/WMLJavaValidator.java +++ b/utils/umc_dev/org.wesnoth/src/org/wesnoth/validation/WMLJavaValidator.java @@ -8,18 +8,19 @@ *******************************************************************************/ package org.wesnoth.validation; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.Path; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.xtext.nodemodel.ICompositeNode; -import org.eclipse.xtext.nodemodel.ILeafNode; -import org.eclipse.xtext.nodemodel.util.NodeModelUtils; -import org.eclipse.xtext.validation.Check; -import org.eclipse.xtext.validation.CheckType; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.wesnoth.Constants; import org.wesnoth.Messages; import org.wesnoth.installs.WesnothInstallsUtils; +import org.wesnoth.preferences.Preferences; +import org.wesnoth.projects.ProjectCache; +import org.wesnoth.projects.ProjectUtils; import org.wesnoth.schema.SchemaParser; +import org.wesnoth.utils.ResourceUtils; +import org.wesnoth.utils.WMLUtils; import org.wesnoth.wml.WMLExpression; import org.wesnoth.wml.WMLKey; import org.wesnoth.wml.WMLMacroCall; @@ -27,6 +28,16 @@ import org.wesnoth.wml.WMLRoot; import org.wesnoth.wml.WMLTag; import org.wesnoth.wml.WmlPackage; +import org.eclipse.core.resources.IResource; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.nodemodel.ICompositeNode; +import org.eclipse.xtext.nodemodel.ILeafNode; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.validation.Check; +import org.eclipse.xtext.validation.CheckType; + +import com.google.common.collect.Iterables; + /** * This represents the validator for config files * @@ -38,16 +49,39 @@ import org.wesnoth.wml.WmlPackage; */ public class WMLJavaValidator extends AbstractWMLJavaValidator { -// @Check(CheckType.FAST) + /** + * Returns the {@link SchemaParser} from the specified {@link EObject} + * @param object + * @return + */ + private SchemaParser getSchema( EObject object ) + { + return SchemaParser.getInstance( + WesnothInstallsUtils.getInstallNameForResource( + ResourceUtils.getWorkspaceResource( object.eResource( ) ) ) ); + } + + private boolean isValidationEnabled( ) + { + return Preferences.getBool( Constants.P_WML_VALIDATION ); + } + + @Check(CheckType.FAST) public void checkFastTagName(WMLTag tag) { + if ( !isValidationEnabled( ) ) + return; + if (!tag.getName().equals(tag.getEndName())) warning( Messages.WMLJavaValidator_0, WmlPackage.Literals.WML_TAG__END_NAME); } -// @Check(CheckType.NORMAL) + @Check(CheckType.NORMAL) public void checkNormalTagName(WMLTag tag) { + if ( !isValidationEnabled( ) ) + return; + ICompositeNode node = NodeModelUtils.getNode( tag ); if (node != null) { @@ -61,12 +95,7 @@ public class WMLJavaValidator extends AbstractWMLJavaValidator searchName = "root"; //$NON-NLS-1$ } - Resource resource = getCurrentObject( ).eResource( ); - IResource file = ResourcesPlugin.getWorkspace( ).getRoot( ). - getFile( new Path( resource.getURI( ).toPlatformString( true ) ) ); - - WMLTag schemaTag = SchemaParser.getInstance( - WesnothInstallsUtils.getInstallNameForResource( file ) ).getTags().get(searchName); + WMLTag schemaTag = getSchema( tag ).getTags( ).get( searchName ); if ( schemaTag != null ) { @@ -79,33 +108,99 @@ public class WMLJavaValidator extends AbstractWMLJavaValidator } } if (found == false) - warning( Messages.WMLJavaValidator_1, WmlPackage.Literals.WML_EXPRESSION__NAME ); + warning( Messages.WMLJavaValidator_1, + WmlPackage.Literals.WML_EXPRESSION__NAME ); } } } - @Check(CheckType.EXPENSIVE) - public void checkExpensiveKeyValue(WMLKey key) + private void checkTagsCardinalities( SchemaParser schema, + Iterable< WMLTag > tags ) { - //TODO: add regex checking here - System.out.println(Messages.WMLJavaValidator_2); + Map< String, Integer > ocurrences = new HashMap( ); + + for ( WMLTag tag : tags ) { + Integer currentValue = ocurrences.get( tag.getName( ) ); + if ( currentValue == null ) + currentValue = 0; + + ocurrences.put( tag.getName( ), currentValue + 1 ); + } + + for ( Entry entry : ocurrences.entrySet( ) ) { + WMLTag schemaTag = schema.getTags( ).get( entry.getKey( ) ); + + if ( schemaTag == null ) + continue; + + if ( schemaTag.getAllowedCount( ) < entry.getValue( ) ) + warning( "Tag " + entry.getKey( ) + " cannot appear more" + + "than " + schemaTag.getAllowedCount( ) + " times. ", + WmlPackage.Literals.WML_EXPRESSION__NAME ); + } } + private void checkKeysCardinalities( WMLTag parentTag, + Iterable< WMLKey > keys ) + { + Map< String, Integer > ocurrences = new HashMap( ); + + for ( WMLKey key : keys ) { + Integer currentValue = ocurrences.get( key.getName( ) ); + if ( currentValue == null ) + currentValue = 0; + + ocurrences.put( key.getName( ), currentValue + 1 ); + } + + for ( Entry entry : ocurrences.entrySet( ) ) { + WMLKey schemaKey = WMLUtils.getKeyByName( parentTag, entry.getKey( ) ); + + if ( schemaKey == null ) + continue; + + if ( schemaKey.getAllowedCount( ) < entry.getValue( ) ) + warning( "Key " + entry.getKey( ) + ", in tag " + parentTag.getName( ) + + "cannot appear more than " + + schemaKey.getAllowedCount( ) + " times. ", + WmlPackage.Literals.WML_EXPRESSION__NAME ); + } + } + @Check(CheckType.NORMAL) public void checkNormalWMLRootCardinality(WMLRoot root) { - //TODO: add check for subtags cardinality + if ( !isValidationEnabled( ) ) + return; + + checkTagsCardinalities( getSchema( root ), + Iterables.filter( root.getExpressions( ), WMLTag.class ) ); } @Check(CheckType.NORMAL) public void checkNormalWMLTagCardinality(WMLTag tag) { - //TODO: add check for subtags/subkeys cardinality + if ( !isValidationEnabled( ) ) + return; + + SchemaParser schema = getSchema( tag ); + checkTagsCardinalities( schema, + Iterables.filter( tag.getExpressions( ), WMLTag.class ) ); + + checkKeysCardinalities( tag, + Iterables.filter( tag.getExpressions( ), WMLKey.class ) ); } - @Check(CheckType.FAST) - public void checkNormalWMLMacroExistance(WMLMacroCall call) + @Check(CheckType.NORMAL) + public void checkNormalWMLMacroExistance( WMLMacroCall call ) { - //TODO: add check for macro existance - by name + if ( !isValidationEnabled( ) ) + return; + + IResource resource = ResourceUtils.getWorkspaceResource( call.eResource( ) ); + ProjectCache cache = ProjectUtils.getCacheForProject( resource.getProject( ) ); + if ( ! cache.getDefines( ).containsKey( call.getName( ) ) ) + warning( "Undefined macro: " + call.getName( ), + WmlPackage.Literals.WML_EXPRESSION__NAME ); } }