Просмотр исходного кода

moved import proposal and validation to open source

make API more explicit with Optionals.
andreas muelder 8 лет назад
Родитель
Сommit
020aff1b50

+ 2 - 2
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/StructureMapping.xtend

@@ -79,8 +79,8 @@ class StructureMapping {
 		for (String importString : scope.imports){
 			val pkgImport = mapper.findPackageImport(scope.eResource,importString)
 			
-			if (pkgImport !== null && URIConverter.INSTANCE.exists(pkgImport.getUri(), null)) {
-				val packageForNamespace = scope.eResource.resourceSet.getResource(pkgImport.uri, true).contents.
+			if (pkgImport.isPresent && URIConverter.INSTANCE.exists(pkgImport.get.getUri(), null)) {
+				val packageForNamespace = scope.eResource.resourceSet.getResource(pkgImport.get.uri, true).contents.
 					head as Package
 				packageForNamespace.member.filter(Declaration).toList.forEach[createImportDeclaration(_scope)]
 			}

+ 64 - 0
plugins/org.yakindu.sct.model.stext.ui/src/org/yakindu/sct/model/stext/ui/contentassist/STextProposalProvider.java

@@ -13,14 +13,23 @@ package org.yakindu.sct.model.stext.ui.contentassist;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.eclipse.emf.common.util.BasicEList;
 import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
 import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.jface.resource.ImageRegistry;
 import org.eclipse.jface.text.contentassist.ICompletionProposal;
 import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.StyledString.Styler;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.widgets.Display;
 import org.eclipse.xtext.Assignment;
 import org.eclipse.xtext.CrossReference;
 import org.eclipse.xtext.EnumLiteralDeclaration;
@@ -37,6 +46,8 @@ import org.yakindu.base.expressions.expressions.FeatureCall;
 import org.yakindu.base.types.Operation;
 import org.yakindu.base.types.Type;
 import org.yakindu.sct.model.sgraph.State;
+import org.yakindu.sct.model.stext.scoping.IPackageImport2URIMapper;
+import org.yakindu.sct.model.stext.scoping.IPackageImport2URIMapper.PackageImport;
 import org.yakindu.sct.model.stext.services.STextGrammarAccess;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
@@ -44,6 +55,7 @@ import org.yakindu.sct.model.stext.stext.SimpleScope;
 import org.yakindu.sct.model.stext.stext.StatechartSpecification;
 import org.yakindu.sct.model.stext.stext.TransitionSpecification;
 import org.yakindu.sct.model.stext.stext.VariableDefinition;
+import org.yakindu.sct.model.stext.ui.internal.STextActivator;
 
 import com.google.common.base.Function;
 import com.google.inject.Inject;
@@ -55,6 +67,8 @@ import com.google.inject.Inject;
  */
 public class STextProposalProvider extends AbstractSTextProposalProvider {
 
+	protected static final String ICONS_INCLUDE = "icons/Package.png";
+
 	@Inject
 	protected STextGrammarAccess grammarAccess;
 	private ComposedAdapterFactory composedAdapterFactory = new ComposedAdapterFactory(
@@ -62,6 +76,24 @@ public class STextProposalProvider extends AbstractSTextProposalProvider {
 	@Inject
 	@ContentProposalLabelProvider
 	private ILabelProvider labelProvider;
+	@Inject
+	private IPackageImport2URIMapper mapper;
+
+	public static class StrikeThroughStyler extends Styler {
+
+		@Override
+		public void applyStyles(TextStyle textStyle) {
+			textStyle.strikeout = true;
+		}
+	}
+
+	public static class GreyoutStyler extends Styler {
+
+		@Override
+		public void applyStyles(TextStyle textStyle) {
+			textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
+		}
+	}
 
 	/**
 	 * Validates if a keyword should be viewed by the proposal view.
@@ -221,6 +253,38 @@ public class STextProposalProvider extends AbstractSTextProposalProvider {
 		}
 	}
 
+	@Override
+	public void completeImportScope_Imports(EObject model, Assignment assignment, ContentAssistContext context,
+			ICompletionProposalAcceptor acceptor) {
+		StringProposalDelegate stringProposalDelegate = new StringProposalDelegate(acceptor, context);
+		Set<PackageImport> allImports = mapper.getAllImports(model.eResource());
+		for (PackageImport pkgImport : allImports) {
+
+			ConfigurableCompletionProposal doCreateProposal = doCreateProposal("\"" + pkgImport.getName() + "\"",
+					computePackageStyledString(pkgImport), getIncludeImage(), pkgImport.getUri().isFile() ? -1 : 1,
+					context);
+
+			stringProposalDelegate.accept(doCreateProposal);
+		}
+	}
+
+	protected Image getIncludeImage() {
+		final ImageRegistry imageRegistry = STextActivator.getInstance().getImageRegistry();
+		return imageRegistry.get(ICONS_INCLUDE);
+	}
+
+	protected StyledString computePackageStyledString(PackageImport pkgImport) {
+		StyledString firstPart = new StyledString(pkgImport.getName());
+		StyledString secondPart = getPackageImportStyleString(pkgImport.getUri());
+		return firstPart.append(secondPart);
+	}
+
+	protected StyledString getPackageImportStyleString(URI uri) {
+		String headerFilePath = uri.isPlatform() ? uri.toPlatformString(true) : uri.toFileString();
+		StyledString secondPart = new StyledString(" - " + headerFilePath, new GreyoutStyler());
+		return secondPart;
+	}
+
 	protected ICompletionProposalAcceptor getCustomAcceptor(EObject model, String typeName,
 			ICompletionProposalAcceptor acceptor) {
 		ICompletionProposalAcceptor priorityOptimizer = acceptor;

+ 59 - 0
plugins/org.yakindu.sct.model.stext.ui/src/org/yakindu/sct/model/stext/ui/contentassist/StringProposalDelegate.java

@@ -0,0 +1,59 @@
+/**
+* Copyright (c) 2017 itemis AG - All rights Reserved
+* Unauthorized copying of this file, via any medium is strictly prohibited
+* 
+* Contributors:
+* 	Johannes Dicks - itemis AG
+*
+*/
+package org.yakindu.sct.model.stext.ui.contentassist;
+
+import org.apache.log4j.Logger;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal;
+import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor;
+import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor.Delegate;
+
+/**
+ * String adjusting Acceptor, which removes the last " of a completion proposal,
+ * if the document continues with one.
+ * 
+ * @author Johannes Dicks
+ */
+public class StringProposalDelegate extends Delegate {
+
+	private static final Logger LOG = Logger.getLogger(StringProposalDelegate.class);
+
+	org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext ctx;
+
+	public StringProposalDelegate(ICompletionProposalAcceptor delegate,
+			org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext ctx) {
+		super(delegate);
+		this.ctx = ctx;
+	}
+
+	@Override
+	public void accept(ICompletionProposal proposal) {
+		if (proposal instanceof ConfigurableCompletionProposal) {
+			ConfigurableCompletionProposal configurableCompletionProposal = (ConfigurableCompletionProposal) proposal;
+			int endPos = configurableCompletionProposal.getReplacementOffset()
+					+ configurableCompletionProposal.getReplacementLength();
+			if (ctx.getDocument() != null && ctx.getDocument().getLength() > endPos) {
+				// We are not at the end of the file
+				try {
+					if ("\"".equals(ctx.getDocument().get(endPos, 1))) {
+						configurableCompletionProposal
+								.setReplacementLength(configurableCompletionProposal.getReplacementLength() - 1);
+						configurableCompletionProposal
+								.setReplacementString(configurableCompletionProposal.getReplacementString().substring(0,
+										configurableCompletionProposal.getReplacementString().length() - 1));
+					}
+				} catch (BadLocationException e) {
+					LOG.debug("Skipped propsal adjustment.", e);
+				}
+			}
+		}
+		super.accept(proposal);
+	}
+}

+ 12 - 8
plugins/org.yakindu.sct.model.stext.ui/src/org/yakindu/sct/model/stext/ui/hyperlink/PackageImportHyperlinkHelper.java

@@ -10,6 +10,8 @@
  */
 package org.yakindu.sct.model.stext.ui.hyperlink;
 
+import java.util.Optional;
+
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.jface.text.Region;
@@ -51,14 +53,16 @@ public class PackageImportHyperlinkHelper extends HyperlinkHelper {
 			ImportScope importScope = (ImportScope) node.getSemanticElement();
 			EList<String> imports = importScope.getImports();
 			for (String pkgImport : imports) {
-				PackageImport mappedImport = mapper.findPackageImport(resource, pkgImport);
-				final URI targetURI = mappedImport.getUri();
-				XtextHyperlink result = getHyperlinkProvider().get();
-				result.setURI(targetURI);
-				Region region = new Region(node.getOffset(), node.getLength());
-				result.setHyperlinkRegion(region);
-				result.setHyperlinkText(targetURI.toString());
-				acceptor.accept(result);
+				Optional<PackageImport> mappedImport = mapper.findPackageImport(resource, pkgImport);
+				if (mappedImport.isPresent()) {
+					final URI targetURI = mappedImport.get().getUri();
+					XtextHyperlink result = getHyperlinkProvider().get();
+					result.setURI(targetURI);
+					Region region = new Region(node.getOffset(), node.getLength());
+					result.setHyperlinkRegion(region);
+					result.setHyperlinkText(targetURI.toString());
+					acceptor.accept(result);
+				}
 			}
 
 		}

+ 6 - 4
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/scoping/IPackageImport2URIMapper.java

@@ -10,6 +10,8 @@
  */
 package org.yakindu.sct.model.stext.scoping;
 
+import java.util.Collections;
+import java.util.Optional;
 import java.util.Set;
 
 import org.eclipse.emf.common.util.URI;
@@ -26,7 +28,7 @@ import com.google.inject.ImplementedBy;
 @ImplementedBy(NullImpl.class)
 public interface IPackageImport2URIMapper {
 
-	public PackageImport findPackageImport(Resource context, String packageImport);
+	public Optional<PackageImport> findPackageImport(Resource context, String packageImport);
 
 	public Set<PackageImport> getAllImports(Resource context);
 
@@ -114,13 +116,13 @@ public interface IPackageImport2URIMapper {
 	public static class NullImpl implements IPackageImport2URIMapper {
 
 		@Override
-		public PackageImport findPackageImport(Resource context, String packageImport) {
-			return null;
+		public Optional<PackageImport> findPackageImport(Resource context, String packageImport) {
+			return Optional.empty();
 		}
 
 		@Override
 		public Set<PackageImport> getAllImports(Resource context) {
-			return null;
+			return Collections.emptySet();
 		}
 	}
 

+ 5 - 3
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/scoping/STextGlobalScopeProvider.java

@@ -16,6 +16,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Optional;
 
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.URI;
@@ -158,9 +159,10 @@ public class STextGlobalScopeProvider extends ImportUriGlobalScopeProvider {
 
 	protected void collectPackageImports(Resource resource, String packageImport, IAcceptor<String> acceptor,
 			LinkedHashSet<URI> uniqueImportURIs) {
-		PackageImport pkgImport = mapper.findPackageImport(resource, packageImport);
-		if (pkgImport != null && pkgImport.getUri() != null && URIConverter.INSTANCE.exists(pkgImport.getUri(), null)) {
-			acceptor.accept(pkgImport.getUri().toString());
+		Optional<PackageImport> pkgImport = mapper.findPackageImport(resource, packageImport);
+		PackageImport currentImport = pkgImport.get();
+		if (pkgImport.isPresent() && currentImport.getUri() != null && URIConverter.INSTANCE.exists(currentImport.getUri(), null)) {
+			acceptor.accept(currentImport.getUri().toString());
 		}
 	}
 

+ 4 - 3
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/scoping/StextImportAwareScopeProvider.java

@@ -12,6 +12,7 @@ package org.yakindu.sct.model.stext.scoping;
 import static java.util.Collections.singletonList;
 
 import java.util.List;
+import java.util.Optional;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
@@ -86,9 +87,9 @@ public class StextImportAwareScopeProvider extends ImportedNamespaceAwareLocalSc
 		List<ImportNormalizer> importedNamespaceResolvers = Lists.newArrayList();
 		ImportScope importScope = (ImportScope) scope;
 		for (String child : importScope.getImports()) {
-			PackageImport pkgImport = mapper.findPackageImport(scope.eResource(), child);
-			if (pkgImport != null) {
-				ImportNormalizer resolver = createImportedNamespaceResolver(pkgImport.getNamespace(), ignoreCase);
+			Optional<PackageImport> pkgImport = mapper.findPackageImport(scope.eResource(), child);
+			if (pkgImport.isPresent()) {
+				ImportNormalizer resolver = createImportedNamespaceResolver(pkgImport.get().getNamespace(), ignoreCase);
 				if (resolver != null)
 					importedNamespaceResolvers.add(resolver);
 			}

+ 49 - 7
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/STextJavaValidator.java

@@ -11,9 +11,9 @@
  */
 package org.yakindu.sct.model.stext.validation;
 
-import static org.yakindu.sct.model.stext.lib.StatechartAnnotations.EVENT_DRIVEN_ANNOTATION;
-import static org.yakindu.sct.model.stext.lib.StatechartAnnotations.CYCLE_BASED_ANNOTATION;
 import static org.yakindu.sct.model.stext.lib.StatechartAnnotations.CHILD_FIRST_ANNOTATION;
+import static org.yakindu.sct.model.stext.lib.StatechartAnnotations.CYCLE_BASED_ANNOTATION;
+import static org.yakindu.sct.model.stext.lib.StatechartAnnotations.EVENT_DRIVEN_ANNOTATION;
 import static org.yakindu.sct.model.stext.lib.StatechartAnnotations.PARENT_FIRST_ANNOTATION;
 
 import java.util.Collections;
@@ -21,6 +21,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 import org.eclipse.emf.common.util.EList;
@@ -29,6 +30,7 @@ import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.URIConverter;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.xtext.Constants;
 import org.eclipse.xtext.EcoreUtil2;
@@ -78,6 +80,8 @@ import org.yakindu.sct.model.sgraph.resource.AbstractSCTResource;
 import org.yakindu.sct.model.sgraph.util.ContextElementAdapter;
 import org.yakindu.sct.model.sgraph.validation.SCTResourceValidator;
 import org.yakindu.sct.model.sgraph.validation.SGraphJavaValidator;
+import org.yakindu.sct.model.stext.scoping.IPackageImport2URIMapper;
+import org.yakindu.sct.model.stext.scoping.IPackageImport2URIMapper.PackageImport;
 import org.yakindu.sct.model.stext.services.STextGrammarAccess;
 import org.yakindu.sct.model.stext.stext.ArgumentedAnnotation;
 import org.yakindu.sct.model.stext.stext.DefaultTrigger;
@@ -90,6 +94,7 @@ import org.yakindu.sct.model.stext.stext.EventValueReferenceExpression;
 import org.yakindu.sct.model.stext.stext.ExitEvent;
 import org.yakindu.sct.model.stext.stext.ExitPointSpec;
 import org.yakindu.sct.model.stext.stext.Guard;
+import org.yakindu.sct.model.stext.stext.ImportScope;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
 import org.yakindu.sct.model.stext.stext.LocalReaction;
@@ -115,7 +120,8 @@ import com.google.inject.name.Named;
  * @author muelder
  * 
  */
-@ComposedChecks(validators = { SGraphJavaValidator.class, SCTResourceValidator.class, ExpressionsJavaValidator.class, STextNamesAreUniqueValidator.class })
+@ComposedChecks(validators = { SGraphJavaValidator.class, SCTResourceValidator.class, ExpressionsJavaValidator.class,
+		STextNamesAreUniqueValidator.class })
 public class STextJavaValidator extends AbstractSTextJavaValidator implements STextValidationMessages {
 
 	@Inject
@@ -130,6 +136,8 @@ public class STextJavaValidator extends AbstractSTextJavaValidator implements ST
 	@Inject(optional = true)
 	@Named(DomainRegistry.DOMAIN_ID)
 	private String domainID = BasePackage.Literals.DOMAIN_ELEMENT__DOMAIN_ID.getDefaultValueLiteral();
+	@Inject(optional = true)
+	private IPackageImport2URIMapper mapper;
 
 	@Check(CheckType.FAST)
 	public void checkExpression(VariableDefinition expression) {
@@ -666,7 +674,8 @@ public class STextJavaValidator extends AbstractSTextJavaValidator implements ST
 			if (element instanceof NamedElement) {
 				elementName = ((NamedElement) element).getName();
 			}
-			error(String.format("'%s' is not an event.", elementName), StextPackage.Literals.EVENT_RAISING_EXPRESSION__EVENT, -1);
+			error(String.format("'%s' is not an event.", elementName),
+					StextPackage.Literals.EVENT_RAISING_EXPRESSION__EVENT, -1);
 		}
 	}
 
@@ -689,7 +698,7 @@ public class STextJavaValidator extends AbstractSTextJavaValidator implements ST
 	public void checkReactionEffectActions(ReactionEffect effect) {
 		for (Expression exp : effect.getActions()) {
 
-			if (!(exp instanceof AssignmentExpression) && !(exp instanceof EventRaisingExpression) 
+			if (!(exp instanceof AssignmentExpression) && !(exp instanceof EventRaisingExpression)
 					&& !(exp instanceof PostFixUnaryExpression)) {
 
 				if (exp instanceof FeatureCall) {
@@ -756,8 +765,8 @@ public class STextJavaValidator extends AbstractSTextJavaValidator implements ST
 			if (tokenText == null || tokenText.isEmpty())
 				return;
 			if (tokenText.contains(Direction.LOCAL.getLiteral())) {
-				warning(String.format(STextValidationMessages.DECLARATION_DEPRECATED, Direction.LOCAL.getLiteral()), event,
-						TypesPackage.Literals.EVENT__DIRECTION);
+				warning(String.format(STextValidationMessages.DECLARATION_DEPRECATED, Direction.LOCAL.getLiteral()),
+						event, TypesPackage.Literals.EVENT__DIRECTION);
 			}
 		}
 	}
@@ -800,6 +809,39 @@ public class STextJavaValidator extends AbstractSTextJavaValidator implements ST
 			warning(CHOICE_ONE_OUTGOING_DEFAULT_TRANSITION, SGraphPackage.Literals.VERTEX__OUTGOING_TRANSITIONS);
 	}
 
+	@Check
+	public void checkDuplicateImport(ImportScope importScope) {
+		EList<Scope> allScopes = EcoreUtil2.getContainerOfType(importScope, ScopedElement.class).getScopes();
+
+		nextImportOfCurrentScope: for (String importToCheck : importScope.getImports()) {
+			Set<String> allImports = Sets.newHashSet();
+			for (Scope scope : allScopes) {
+				if (!(scope instanceof ImportScope))
+					continue;// exclude internal & interface scopes
+				for (String anImport : ((ImportScope) scope).getImports()) {
+					if (anImport.equals(importToCheck) && !allImports.add(anImport)) {
+						warning(String.format(DUPLICATE_IMPORT, importToCheck), importScope,
+								StextPackage.Literals.IMPORT_SCOPE__IMPORTS,
+								importScope.getImports().indexOf(importToCheck));
+						continue nextImportOfCurrentScope;
+					}
+				}
+			}
+		}
+	}
+
+	@Check
+	public void checkImportExists(ImportScope scope) {
+		EList<String> imports = scope.getImports();
+		for (String packageImport : imports) {
+			Optional<PackageImport> pkImport = mapper.findPackageImport(scope.eResource(), packageImport);
+			if (!pkImport.isPresent() || !URIConverter.INSTANCE.exists(pkImport.get().getUri(), null)) {
+				error(String.format(IMPORT_NOT_RESOLVED_MSG, packageImport), scope,
+						StextPackage.Literals.IMPORT_SCOPE__IMPORTS, imports.indexOf(packageImport));
+			}
+		}
+	}
+
 	protected void checkElementReferenceEffect(ElementReferenceExpression refExp) {
 		if (!(refExp.getReference() instanceof Operation)) {
 			if (refExp.getReference() instanceof Property) {

+ 1 - 0
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/STextValidationMessages.java

@@ -55,5 +55,6 @@ public interface STextValidationMessages {
 	public static final String VALUE_OF_REQUIRES_EVENT = "valueof() expression requires event as argument.";
 	public static final String IMPORT_NOT_RESOLVED_MSG = "Import '%s' cannot be resolved.";
 	public static final String IMPORT_NOT_RESOLVED_CODE = "ImportNotResolved";
+	public static final String DUPLICATE_IMPORT = "Duplicate import '%s'.";
 	public static final String CONTRADICTORY_ANNOTATIONS = "Some annotations (%s) have contradictory effects.";
 }

+ 13 - 2
test-plugins/org.yakindu.sct.model.stext.test/src/org/yakindu/sct/model/stext/test/validation/STextJavaValidatorTest.java

@@ -48,7 +48,7 @@ import org.yakindu.sct.model.sgraph.Statechart;
 import org.yakindu.sct.model.sgraph.Transition;
 import org.yakindu.sct.model.sgraph.Trigger;
 import org.yakindu.sct.model.stext.inferrer.STextTypeInferrer;
-import org.yakindu.sct.model.stext.stext.EventDefinition;
+import org.yakindu.sct.model.stext.stext.ImportScope;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
 import org.yakindu.sct.model.stext.stext.OperationDefinition;
@@ -56,7 +56,6 @@ import org.yakindu.sct.model.stext.stext.ReactionEffect;
 import org.yakindu.sct.model.stext.stext.ReactionTrigger;
 import org.yakindu.sct.model.stext.stext.StatechartSpecification;
 import org.yakindu.sct.model.stext.stext.TransitionSpecification;
-import org.yakindu.sct.model.stext.stext.VariableDefinition;
 import org.yakindu.sct.model.stext.stext.impl.StextFactoryImpl;
 import org.yakindu.sct.model.stext.test.util.STextInjectorProvider;
 import org.yakindu.sct.model.stext.test.util.StextTestFactory;
@@ -845,6 +844,18 @@ public class STextJavaValidatorTest extends AbstractSTextValidationTest implemen
 		assertIssueCount(diagnostics, 5);
 		assertWarning(diagnostics, INTERNAL_DECLARATION_UNUSED);
 	}
+	
+	@Test
+	public void checkImportExists() {
+		Scope context = (Scope) parseExpression("import: does.not.exist", ImportScope.class.getSimpleName());
+		AssertableDiagnostics validationResult = tester.validate(context);
+		validationResult.assertErrorContains(String.format(STextValidationMessages.IMPORT_NOT_RESOLVED_MSG,"does.not.exist"));
+	}
+	
+	@Test
+	public void checkDuplicateImport() {
+		//Can't be checked here
+	}
 
 	@Test
 	public void transitionsWithNoTrigger() {