diff --git a/src/language/builtins/safe-ds-annotations.ts b/src/language/builtins/safe-ds-annotations.ts index 678098066..74212c980 100644 --- a/src/language/builtins/safe-ds-annotations.ts +++ b/src/language/builtins/safe-ds-annotations.ts @@ -1,12 +1,27 @@ -import { isSdsAnnotation, SdsAnnotatedObject, SdsAnnotation, SdsModule, SdsParameter } from '../generated/ast.js'; -import { getArguments, findFirstAnnotationCallOf, hasAnnotationCallOf } from '../helpers/nodeProperties.js'; +import { + isSdsAnnotation, + isSdsEnum, + SdsAnnotatedObject, + SdsAnnotation, + SdsEnumVariant, + SdsModule, + SdsParameter, +} from '../generated/ast.js'; +import { + findFirstAnnotationCallOf, + getArguments, + getEnumVariants, + getParameters, + hasAnnotationCallOf, +} from '../helpers/nodeProperties.js'; import { SafeDsModuleMembers } from './safe-ds-module-members.js'; import { resourceNameToUri } from '../../helpers/resources.js'; -import { URI } from 'langium'; +import { EMPTY_STREAM, getContainerOfType, Stream, stream, URI } from 'langium'; import { SafeDsServices } from '../safe-ds-module.js'; import { SafeDsNodeMapper } from '../helpers/safe-ds-node-mapper.js'; -import { EvaluatedNode, StringConstant } from '../partialEvaluation/model.js'; +import { EvaluatedEnumVariant, EvaluatedList, EvaluatedNode, StringConstant } from '../partialEvaluation/model.js'; import { SafeDsPartialEvaluator } from '../partialEvaluation/safe-ds-partial-evaluator.js'; +import { SafeDsEnums } from './safe-ds-enums.js'; const ANNOTATION_USAGE_URI = resourceNameToUri('builtins/safeds/lang/annotationUsage.sdsstub'); const CODE_GENERATION_URI = resourceNameToUri('builtins/safeds/lang/codeGeneration.sdsstub'); @@ -14,12 +29,14 @@ const IDE_INTEGRATION_URI = resourceNameToUri('builtins/safeds/lang/ideIntegrati const MATURITY_URI = resourceNameToUri('builtins/safeds/lang/maturity.sdsstub'); export class SafeDsAnnotations extends SafeDsModuleMembers { + private readonly builtinEnums: SafeDsEnums; private readonly nodeMapper: SafeDsNodeMapper; private readonly partialEvaluator: SafeDsPartialEvaluator; constructor(services: SafeDsServices) { super(services); + this.builtinEnums = services.builtins.Enums; this.nodeMapper = services.helpers.NodeMapper; this.partialEvaluator = services.evaluation.PartialEvaluator; } @@ -82,6 +99,32 @@ export class SafeDsAnnotations extends SafeDsModuleMembers { return this.getAnnotation(ANNOTATION_USAGE_URI, 'Repeatable'); } + streamValidTargets(node: SdsAnnotation | undefined): Stream { + // If no targets are specified, every target is valid + if (!hasAnnotationCallOf(node, this.Target)) { + return stream(getEnumVariants(this.builtinEnums.AnnotationTarget)); + } + + // If targets are specified, but we could not evaluate them to a list, no target is valid + const value = this.getArgumentValue(node, this.Target, 'targets'); + if (!(value instanceof EvaluatedList)) { + return EMPTY_STREAM; + } + + // Otherwise, filter the elements of the list and keep only variants of the AnnotationTarget enum + return stream(value.elements) + .filter( + (it) => + it instanceof EvaluatedEnumVariant && + getContainerOfType(it.variant, isSdsEnum) === this.builtinEnums.AnnotationTarget, + ) + .map((it) => (it).variant); + } + + get Target(): SdsAnnotation | undefined { + return this.getAnnotation(ANNOTATION_USAGE_URI, 'Target'); + } + private getAnnotation(uri: URI, name: string): SdsAnnotation | undefined { return this.getModuleMember(uri, name, isSdsAnnotation); } @@ -96,9 +139,17 @@ export class SafeDsAnnotations extends SafeDsModuleMembers { parameterName: string, ): EvaluatedNode { const annotationCall = findFirstAnnotationCallOf(node, annotation); - const argumentValue = getArguments(annotationCall).find( + + // Parameter is set explicitly + const argument = getArguments(annotationCall).find( (it) => this.nodeMapper.argumentToParameter(it)?.name === parameterName, - )?.value; - return this.partialEvaluator.evaluate(argumentValue); + ); + if (argument) { + return this.partialEvaluator.evaluate(argument.value); + } + + // Parameter is not set explicitly, so we use the default value + const parameter = getParameters(annotation).find((it) => it.name === parameterName); + return this.partialEvaluator.evaluate(parameter?.defaultValue); } } diff --git a/src/language/builtins/safe-ds-enums.ts b/src/language/builtins/safe-ds-enums.ts new file mode 100644 index 000000000..b4b251e56 --- /dev/null +++ b/src/language/builtins/safe-ds-enums.ts @@ -0,0 +1,16 @@ +import { isSdsEnum, SdsEnum } from '../generated/ast.js'; +import { SafeDsModuleMembers } from './safe-ds-module-members.js'; +import { resourceNameToUri } from '../../helpers/resources.js'; +import { URI } from 'langium'; + +const ANNOTATION_USAGE_URI = resourceNameToUri('builtins/safeds/lang/annotationUsage.sdsstub'); + +export class SafeDsEnums extends SafeDsModuleMembers { + get AnnotationTarget(): SdsEnum | undefined { + return this.getEnum(ANNOTATION_USAGE_URI, 'AnnotationTarget'); + } + + private getEnum(uri: URI, name: string): SdsEnum | undefined { + return this.getModuleMember(uri, name, isSdsEnum); + } +} diff --git a/src/language/helpers/nodeProperties.ts b/src/language/helpers/nodeProperties.ts index a698142ad..1aa03d369 100644 --- a/src/language/helpers/nodeProperties.ts +++ b/src/language/helpers/nodeProperties.ts @@ -153,6 +153,10 @@ export const getAnnotationCalls = (node: SdsAnnotatedObject | undefined): SdsAnn } }; +export const getAnnotationCallTarget = (node: SdsAnnotationCall | undefined): SdsDeclaration | undefined => { + return getContainerOfType(node, isSdsDeclaration); +}; + export const findFirstAnnotationCallOf = ( node: SdsAnnotatedObject | undefined, expected: SdsAnnotation | undefined, diff --git a/src/language/safe-ds-module.ts b/src/language/safe-ds-module.ts index 31912ff63..5c82b6c82 100644 --- a/src/language/safe-ds-module.ts +++ b/src/language/safe-ds-module.ts @@ -29,6 +29,7 @@ import { SafeDsCoreTypes } from './typing/safe-ds-core-types.js'; import { SafeDsNodeKindProvider } from './lsp/safe-ds-node-kind-provider.js'; import { SafeDsDocumentSymbolProvider } from './lsp/safe-ds-document-symbol-provider.js'; import { SafeDsDocumentBuilder } from './workspace/safe-ds-document-builder.js'; +import { SafeDsEnums } from './builtins/safe-ds-enums.js'; /** * Declaration of custom services - add your own service classes here. @@ -37,6 +38,7 @@ export type SafeDsAddedServices = { builtins: { Annotations: SafeDsAnnotations; Classes: SafeDsClasses; + Enums: SafeDsEnums; }; evaluation: { PartialEvaluator: SafeDsPartialEvaluator; @@ -70,6 +72,7 @@ export const SafeDsModule: Module new SafeDsAnnotations(services), Classes: (services) => new SafeDsClasses(services), + Enums: (services) => new SafeDsEnums(services), }, evaluation: { PartialEvaluator: (services) => new SafeDsPartialEvaluator(services), diff --git a/src/language/validation/builtins/target.ts b/src/language/validation/builtins/target.ts new file mode 100644 index 000000000..08c5f8153 --- /dev/null +++ b/src/language/validation/builtins/target.ts @@ -0,0 +1,156 @@ +import { ValidationAcceptor } from 'langium'; +import { + isSdsAnnotation, + isSdsAttribute, + isSdsClass, + isSdsEnum, + isSdsEnumVariant, + isSdsFunction, + isSdsModule, + isSdsParameter, + isSdsPipeline, + isSdsResult, + isSdsSegment, + isSdsTypeParameter, + SdsAnnotation, + SdsAnnotationCall, +} from '../../generated/ast.js'; +import { SafeDsServices } from '../../safe-ds-module.js'; +import { duplicatesBy, isEmpty } from '../../../helpers/collectionUtils.js'; +import { pluralize } from '../../../helpers/stringUtils.js'; +import { findFirstAnnotationCallOf, getAnnotationCallTarget } from '../../helpers/nodeProperties.js'; + +export const CODE_TARGET_DUPLICATE_TARGET = 'target/duplicate-target'; +export const CODE_TARGET_WRONG_TARGET = 'target/wrong-target'; + +export const targetShouldNotHaveDuplicateEntries = (services: SafeDsServices) => { + const builtinAnnotations = services.builtins.Annotations; + + return (node: SdsAnnotation, accept: ValidationAcceptor) => { + const annotationCall = findFirstAnnotationCallOf(node, builtinAnnotations.Target); + if (!annotationCall) { + return; + } + + const validTargets = builtinAnnotations.streamValidTargets(node).map((it) => `'${it.name}'`); + const duplicateTargets = duplicatesBy(validTargets, (it) => it) + .distinct() + .toArray(); + + if (isEmpty(duplicateTargets)) { + return; + } + + const noun = pluralize(duplicateTargets.length, 'target'); + const duplicateTargetString = duplicateTargets.join(', '); + const verb = pluralize(duplicateTargets.length, 'occurs', 'occur'); + + accept('warning', `The ${noun} ${duplicateTargetString} ${verb} multiple times.`, { + node: annotationCall, + property: 'annotation', + code: CODE_TARGET_DUPLICATE_TARGET, + }); + }; +}; + +export const annotationCallMustHaveCorrectTarget = (services: SafeDsServices) => { + const builtinAnnotations = services.builtins.Annotations; + + return (node: SdsAnnotationCall, accept: ValidationAcceptor) => { + const annotation = node.annotation?.ref; + if (!annotation) { + return; + } + + const actualTarget = getActualTarget(node); + /* c8 ignore start */ + if (!actualTarget) { + return; + } + /* c8 ignore stop */ + + const validTargets = builtinAnnotations + .streamValidTargets(annotation) + .map((it) => it.name) + .toSet(); + + if (!validTargets.has(actualTarget.enumVariantName)) { + accept('error', `The annotation '${annotation.name}' cannot be applied to ${actualTarget.prettyName}.`, { + node, + property: 'annotation', + code: CODE_TARGET_WRONG_TARGET, + }); + } + }; +}; + +const getActualTarget = (node: SdsAnnotationCall): GetActualTargetResult | void => { + const annotatedObject = getAnnotationCallTarget(node); + + if (isSdsAnnotation(annotatedObject)) { + return { + enumVariantName: 'Annotation', + prettyName: 'an annotation', + }; + } else if (isSdsAttribute(annotatedObject)) { + return { + enumVariantName: 'Attribute', + prettyName: 'an attribute', + }; + } else if (isSdsClass(annotatedObject)) { + return { + enumVariantName: 'Class', + prettyName: 'a class', + }; + } else if (isSdsEnum(annotatedObject)) { + return { + enumVariantName: 'Enum', + prettyName: 'an enum', + }; + } else if (isSdsEnumVariant(annotatedObject)) { + return { + enumVariantName: 'EnumVariant', + prettyName: 'an enum variant', + }; + } else if (isSdsFunction(annotatedObject)) { + return { + enumVariantName: 'Function', + prettyName: 'a function', + }; + } else if (isSdsModule(annotatedObject)) { + return { + enumVariantName: 'Module', + prettyName: 'a module', + }; + } else if (isSdsParameter(annotatedObject)) { + return { + enumVariantName: 'Parameter', + prettyName: 'a parameter', + }; + } else if (isSdsPipeline(annotatedObject)) { + return { + enumVariantName: 'Pipeline', + prettyName: 'a pipeline', + }; + } else if (isSdsResult(annotatedObject)) { + return { + enumVariantName: 'Result', + prettyName: 'a result', + }; + } else if (isSdsSegment(annotatedObject)) { + return { + enumVariantName: 'Segment', + prettyName: 'a segment', + }; + } else if (isSdsTypeParameter(annotatedObject)) { + return { + enumVariantName: 'TypeParameter', + prettyName: 'a type parameter', + }; + } +}; + +interface GetActualTargetResult { + enumVariantName: string; + prettyName: string; +} diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index 618b96196..a9ef8c3cc 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -126,6 +126,7 @@ import { literalTypeMustNotContainMapLiteral, literalTypeShouldNotHaveDuplicateLiteral, } from './other/types/literalTypes.js'; +import { annotationCallMustHaveCorrectTarget, targetShouldNotHaveDuplicateEntries } from './builtins/target.js'; /** * Register custom validation checks. @@ -150,12 +151,14 @@ export const registerValidationChecks = function (services: SafeDsServices) { annotationMustContainUniqueNames, annotationParameterListShouldNotBeEmpty, annotationParameterShouldNotHaveConstModifier, + targetShouldNotHaveDuplicateEntries(services), ], SdsAnnotationCall: [ annotationCallAnnotationShouldNotBeDeprecated(services), annotationCallAnnotationShouldNotBeExperimental(services), annotationCallArgumentListShouldBeNeeded, annotationCallArgumentsMustBeConstant(services), + annotationCallMustHaveCorrectTarget(services), annotationCallMustNotLackArgumentList, ], SdsArgument: [ diff --git a/src/resources/builtins/safeds/lang/annotationUsage.sdsstub b/src/resources/builtins/safeds/lang/annotationUsage.sdsstub index 82ce3d9d1..41e335416 100644 --- a/src/resources/builtins/safeds/lang/annotationUsage.sdsstub +++ b/src/resources/builtins/safeds/lang/annotationUsage.sdsstub @@ -1,51 +1,83 @@ package safeds.lang -@Description("The annotation can target these declaration types. If the @Target annotation is not used any declaration type can be targeted.") +/** + * The annotation must target only the specified declaration types. By default, any declaration type can be targeted. + * + * @param targets An exhaustive list of the valid targets. + */ @Target([AnnotationTarget.Annotation]) annotation Target( - @Description("The valid targets.") targets: List ) -@Description("The declaration types that can be targeted by annotations.") +/** + * The declaration types that can be targeted by annotations. + */ enum AnnotationTarget { - @Description("The annotation can be called on annotations.") + + /** + * The annotation can be called on annotations. + */ Annotation - @Description("The annotation can be called on attributes.") + /** + * The annotation can be called on attributes. + */ Attribute - @Description("The annotation can be called on classes.") + /** + * The annotation can be called on classes. + */ Class - @Description("The annotation can be called on enums.") + /** + * The annotation can be called on enums. + */ Enum - @Description("The annotation can be called on enum variants.") + /** + * The annotation can be called on enum variants. + */ EnumVariant - @Description("The annotation can be called on functions.") + /** + * The annotation can be called on functions. + */ Function - @Description("The annotation can be called on modules (i.e. files).") + /** + * The annotation can be called on modules (i.e. files). + */ Module - @Description("The annotation can be called on parameters.") + /** + * The annotation can be called on parameters. + */ Parameter - @Description("The annotation can be called on pipelines.") + /** + * The annotation can be called on pipelines. + */ Pipeline - @Description("The annotation can be called on results.") + /** + * The annotation can be called on results. + */ Result - @Description("The annotation can be called on segments.") + /** + * The annotation can be called on segments. + */ Segment - @Description("The annotation can be called on type parameters.") + /** + * The annotation can be called on type parameters. + */ TypeParameter } -@Description("The annotation can be called multiple times for the same declaration.") +/** + * The annotation can be called multiple times for the same declaration. + */ @Target([AnnotationTarget.Annotation]) annotation Repeatable diff --git a/src/resources/builtins/safeds/lang/codeGeneration.sdsstub b/src/resources/builtins/safeds/lang/codeGeneration.sdsstub index ca7ec40ce..83b09a0e1 100644 --- a/src/resources/builtins/safeds/lang/codeGeneration.sdsstub +++ b/src/resources/builtins/safeds/lang/codeGeneration.sdsstub @@ -1,13 +1,16 @@ package safeds.lang -@Description("The qualified name of the corresponding Python module (default is the qualified name of the package).") +/** + * The qualified name of the corresponding Python module. By default, this is the qualified name of the package. + */ @Target([AnnotationTarget.Module]) annotation PythonModule( - @Description("The qualified name of the corresponding Python module.") qualifiedName: String ) -@Description("The name of the corresponding API element in Python (default is the name of the declaration in the stubs).") +/** + * The name of the corresponding API element in Python. By default, this is the name of the declaration in the stubs. + */ @Target([ AnnotationTarget.Attribute, AnnotationTarget.Class, @@ -19,6 +22,5 @@ annotation PythonModule( AnnotationTarget.Segment, ]) annotation PythonName( - @Description("The name of the corresponding API element in Python.") name: String ) diff --git a/src/resources/builtins/safeds/lang/coreClasses.sdsstub b/src/resources/builtins/safeds/lang/coreClasses.sdsstub index 1d966c47e..a3fe9a769 100644 --- a/src/resources/builtins/safeds/lang/coreClasses.sdsstub +++ b/src/resources/builtins/safeds/lang/coreClasses.sdsstub @@ -1,28 +1,46 @@ package safeds.lang -@Description("The common superclass of all classes.") +/** + * The common superclass of all classes. + */ class Any -@Description("The common subclass of all classes.") +/** + * The common subclass of all classes. + */ class Nothing -@Description("A truth value.") +/** + * A truth value. + */ class Boolean -@Description("A number.") +/** + * A number. + */ class Number -@Description("An integer.") +/** + * An integer. + */ class Int sub Number -@Description("A floating-point number.") +/** + * A floating-point number. + */ class Float sub Number -@Description("A list of elements.") +/** + * A list of elements. + */ class List -@Description("A map of keys to values.") +/** + * A map of keys to values. + */ class Map -@Description("Some text.") +/** + * Some text. + */ class String diff --git a/src/resources/builtins/safeds/lang/documentation.sdsstub b/src/resources/builtins/safeds/lang/documentation.sdsstub deleted file mode 100644 index c94d885cc..000000000 --- a/src/resources/builtins/safeds/lang/documentation.sdsstub +++ /dev/null @@ -1,13 +0,0 @@ -package safeds.lang - -@Description("The purpose of a declaration.") -annotation Description( - @Description("The purpose of a declaration.") - description: String -) - -@Description("The version in which a declaration was added.") -annotation Since( - @Description("The version in which a declaration was added.") - version: String -) diff --git a/src/resources/builtins/safeds/lang/ideIntegration.sdsstub b/src/resources/builtins/safeds/lang/ideIntegration.sdsstub index 812c18e25..9eed1615d 100644 --- a/src/resources/builtins/safeds/lang/ideIntegration.sdsstub +++ b/src/resources/builtins/safeds/lang/ideIntegration.sdsstub @@ -1,6 +1,8 @@ package safeds.lang +/** + * This parameter should only be used by expert users. + */ @Experimental -@Description("This parameter should only be used by expert users.") @Target([AnnotationTarget.Parameter]) annotation Expert diff --git a/src/resources/builtins/safeds/lang/maturity.sdsstub b/src/resources/builtins/safeds/lang/maturity.sdsstub index 2b53d06a8..509f20d62 100644 --- a/src/resources/builtins/safeds/lang/maturity.sdsstub +++ b/src/resources/builtins/safeds/lang/maturity.sdsstub @@ -1,6 +1,13 @@ package safeds.lang -@Description("The declaration should no longer be used.") +/** + * The declaration should no longer be used. + * + * @param alternative What to use instead. + * @param reason Why the declaration was deprecated. + * @param sinceVersion When the declaration was deprecated. + * @param removalVersion When the declaration will be removed. + */ @Target([ AnnotationTarget.Annotation, AnnotationTarget.Attribute, @@ -13,20 +20,15 @@ package safeds.lang AnnotationTarget.Segment, ]) annotation Deprecated( - @Description("What to use instead.") alternative: String? = null, - - @Description("Why the declaration was deprecated.") reason: String? = null, - - @Description("When the declaration was deprecated.") sinceVersion: String? = null, - - @Description("When the declaration will be removed.") removalVersion: String? = null, ) -@Description("The declaration might change without a major version bump.") +/** + * The declaration might change without a major version bump. + */ @Target([ AnnotationTarget.Annotation, AnnotationTarget.Attribute, diff --git a/src/resources/builtins/safeds/lang/purity.sdsstub b/src/resources/builtins/safeds/lang/purity.sdsstub index 5ce277f46..8353c1610 100644 --- a/src/resources/builtins/safeds/lang/purity.sdsstub +++ b/src/resources/builtins/safeds/lang/purity.sdsstub @@ -1,11 +1,12 @@ package safeds.lang +/** + * Indicates that the function has no side effects and always returns the same results given the same arguments. + * + * Calls to such a function may be eliminated, if the result is not used. Moreover, the function can be memoized, i.e. + * we can remember its results for a set of arguments. Finally, a pure function can be called at any time, allowing + * reordering of calls or parallelization. + */ @Experimental -@Description("The function has no side effects and returns the same results for the same arguments.") @Target([AnnotationTarget.Function]) annotation Pure - -@Experimental -@Description("The function has no side effects.") -@Target([AnnotationTarget.Function]) -annotation NoSideEffects diff --git a/tests/resources/validation/builtins/annotations/target/duplicate target/main.sdstest b/tests/resources/validation/builtins/annotations/target/duplicate target/main.sdstest new file mode 100644 index 000000000..fed72a6d3 --- /dev/null +++ b/tests/resources/validation/builtins/annotations/target/duplicate target/main.sdstest @@ -0,0 +1,48 @@ +package tests.validation.builtins.annotations.target.duplicateTarget + +// $TEST$ no warning r"The targets? occurs? multiple times." +@»Target«([AnnotationTarget.Annotation]) + +/* + * We already show another error if the `@Target` annotation is called multiple times. + */ + +// $TEST$ no warning r"The targets? occurs? multiple times." +@»Target«([ + AnnotationTarget.Annotation, + AnnotationTarget.Annotation, +]) +annotation TestAnnotation1 + +// $TEST$ warning "The target 'Annotation' occurs multiple times." +@»Target«([ + AnnotationTarget.Annotation, + AnnotationTarget.Annotation, +]) +annotation TestAnnotation2 + +// $TEST$ warning "The targets 'Class', 'Annotation' occur multiple times." +@»Target«([ + AnnotationTarget.Class, + AnnotationTarget.Class, + AnnotationTarget.Class, + AnnotationTarget.Annotation, + AnnotationTarget.Annotation, + AnnotationTarget.Annotation, +]) +annotation TestAnnotation3 + +/* + * We already show another error if an annotation is called with arguments of invalid type. + */ + + // $TEST$ no warning r"The targets? occurs? multiple times." +@»Target«(1) +annotation TestAnnotation4 + +// $TEST$ no warning r"The targets? occurs? multiple times." +@»Target«([ + 1, + 1, +]) +annotation TestAnnotation5 diff --git a/tests/resources/validation/builtins/annotations/target/duplicate target/no target annotation.sdstest b/tests/resources/validation/builtins/annotations/target/duplicate target/no target annotation.sdstest new file mode 100644 index 000000000..8bf700aac --- /dev/null +++ b/tests/resources/validation/builtins/annotations/target/duplicate target/no target annotation.sdstest @@ -0,0 +1,5 @@ +package tests.validation.builtins.annotations.target.duplicateTarget + +// $TEST$ no warning r"The targets? occurs? multiple times." + +annotation TestAnnotation6 diff --git a/tests/resources/validation/builtins/annotations/target/wrong target/main.sdstest b/tests/resources/validation/builtins/annotations/target/wrong target/main.sdstest new file mode 100644 index 000000000..b506ff37c --- /dev/null +++ b/tests/resources/validation/builtins/annotations/target/wrong target/main.sdstest @@ -0,0 +1,172 @@ +// $TEST$ error "The annotation 'AnnotationForEnums' cannot be applied to a module." +@»AnnotationForEnums« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForModules« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForMultipleTargets« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« + +package tests.validation.builtins.annotations.target.wrongTarget + +@Target([AnnotationTarget.Annotation]) +annotation AnnotationForAnnotations + +@Target([AnnotationTarget.Attribute]) +annotation AnnotationForAttributes + +@Target([AnnotationTarget.Class]) +annotation AnnotationForClasses + +@Target([AnnotationTarget.Enum]) +annotation AnnotationForEnums + +@Target([AnnotationTarget.EnumVariant]) +annotation AnnotationForEnumVariants + +@Target([AnnotationTarget.Function]) +annotation AnnotationForFunctions + +@Target([AnnotationTarget.Module]) +annotation AnnotationForModules + +@Target([AnnotationTarget.Parameter]) +annotation AnnotationForParameters + +@Target([AnnotationTarget.Result]) +annotation AnnotationForResults + +@Target([AnnotationTarget.TypeParameter]) +annotation AnnotationForTypeParameters + +@Target([AnnotationTarget.Pipeline]) +annotation AnnotationForPipelines + +@Target([AnnotationTarget.Segment]) +annotation AnnotationForSegments + +@Target([AnnotationTarget.Module, AnnotationTarget.Class]) +annotation AnnotationForMultipleTargets + +annotation AnnotationForAnything + +/* Test declarations -------------------------------------------------------- */ + +// $TEST$ error "The annotation 'AnnotationForAttributes' cannot be applied to an annotation." +@»AnnotationForAttributes« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnnotations« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« +annotation TestAnnotation + +// $TEST$ error "The annotation 'AnnotationForModules' cannot be applied to a class." +@»AnnotationForModules« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForClasses« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForMultipleTargets« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« +class TestClass< + + // $TEST$ error "The annotation 'AnnotationForPipelines' cannot be applied to a type parameter." + @»AnnotationForPipelines« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForTypeParameters« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForAnything« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»Unresolved« + TEST_TYPE_PARAMETER +> { + + // $TEST$ error "The annotation 'AnnotationForClasses' cannot be applied to an attribute." + @»AnnotationForClasses« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForAttributes« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForAnything« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»Unresolved« + attr testAttribute: Int +} + +// $TEST$ error "The annotation 'AnnotationForEnumVariants' cannot be applied to an enum." +@»AnnotationForEnumVariants« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForEnums« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« +enum TestEnum { + + // $TEST$ error "The annotation 'AnnotationForFunctions' cannot be applied to an enum variant." + @»AnnotationForFunctions« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForEnumVariants« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForAnything« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»Unresolved« + TestEnumVariant +} + +// $TEST$ error "The annotation 'AnnotationForParameters' cannot be applied to a function." +@»AnnotationForParameters« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForFunctions« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« +fun testFunction( + + // $TEST$ error "The annotation 'AnnotationForResults' cannot be applied to a parameter." + @»AnnotationForResults« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForParameters« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForAnything« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»Unresolved« + testParameter: Int +) -> ( + + // $TEST$ error "The annotation 'AnnotationForTypeParameters' cannot be applied to a result." + @»AnnotationForTypeParameters« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForResults« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»AnnotationForAnything« + // $TEST$ no error r"This annotation '.*' cannot be applied to .*" + @»Unresolved« + testResult: Int +) + +// $TEST$ error "The annotation 'AnnotationForSegments' cannot be applied to a pipeline." +@»AnnotationForSegments« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForPipelines« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« +pipeline testPipeline {} + +// $TEST$ error "The annotation 'AnnotationForAnnotations' cannot be applied to a segment." +@»AnnotationForAnnotations« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForSegments« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»AnnotationForAnything« +// $TEST$ no error r"This annotation '.*' cannot be applied to .*" +@»Unresolved« +segment testSegment() {} diff --git a/tests/resources/validation/skip-old/arguments.sdstest b/tests/resources/validation/skip-old/arguments.sdstest new file mode 100644 index 000000000..75895a631 --- /dev/null +++ b/tests/resources/validation/skip-old/arguments.sdstest @@ -0,0 +1,336 @@ +package tests.validation.typeChecking.arguments + +step myStep(vararg variadicParam: Int) { + + // $TEST$ no error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»f2«); + // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»B()«); + // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(callableType = »C()«); + // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»maybeC()«); + // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»someVariantOfMyEnum2()«); + // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»MyEnum1.Variant1«); + // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»aOrC()«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type '(Int) -> (Int)'." + f1(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f1(unresolved = »1«); + + // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'C'." + f2(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'C'." + f2(»f2«); + // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'C'." + f2(»B()«); + // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'C'." + f2(classType = »C()«); + // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'C'." + f2(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'C'." + f2(»maybeC()«); + // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'C'." + f2(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'C'." + f2(»someVariantOfMyEnum2()«); + // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'C'." + f2(»MyEnum1.Variant1«); + // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'C'." + f2(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'C'." + f2(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'C'." + f2(»aOrC()«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'C'." + f2(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'C'." + f2(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'C'." + f2(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f2(unresolved = »1«); + + // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»f2«); + // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»B()«); + // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type 'MyEnum1'." + f3(enumType = »C()«); + // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»maybeC()«); + // $TEST$ no error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»someVariantOfMyEnum2()«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»MyEnum1.Variant1«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»aOrC()«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'MyEnum1'." + f3(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f3(unresolved = »1«); + + // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»f2«); + // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»B()«); + // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(enumVariantType = »C()«); + // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»maybeC()«); + // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»someVariantOfMyEnum2()«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»MyEnum1.Variant1«); + // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»aOrC()«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." + f4(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f4(unresolved = »1«); + + // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'union'." + f5(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'union'." + f5(»f2«); + // $TEST$ no error "An argument of type 'B' cannot be assigned to a parameter of type 'union'." + f5(»B()«); + // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'union'." + f5(unionType = »C()«); + // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'union'." + f5(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'union'." + f5(»maybeC()«); + // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'union'." + f5(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'union'." + f5(»someVariantOfMyEnum2()«); + // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'union'." + f5(»MyEnum1.Variant1«); + // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'union'." + f5(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'union'." + f5(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'union'." + f5(»aOrC()«); + // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'union'." + f5(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'union'." + f5(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'union'." + f5(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f5(unresolved = »1«); + + // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type '$Unresolved'." + f6(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type '$Unresolved'." + f6(»f2«); + // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type '$Unresolved'." + f6(»B()«); + // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type '$Unresolved'." + f6(unresolvedType = »C()«); + // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type '$Unresolved'." + f6(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type '$Unresolved'." + f6(»maybeC()«); + // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type '$Unresolved'." + f6(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type '$Unresolved'." + f6(»someVariantOfMyEnum2()«); + // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type '$Unresolved'." + f6(»MyEnum1.Variant1«); + // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type '$Unresolved'." + f6(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type '$Unresolved'." + f6(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '$Unresolved'." + f6(»aOrC()«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '$Unresolved'." + f6(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type '$Unresolved'." + f6(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type '$Unresolved'." + f6(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f6(unresolved = »1«); + + // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'vararg'." + f7(»intToInt«); + // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'vararg'." + f7(»f2«); + // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'vararg'." + f7(»B()«); + // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'vararg'." + f7(unresolvedType = »C()«); + // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'vararg'." + f7(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'vararg'." + f7(»maybeC()«); + // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'vararg'." + f7(»someVariantOfMyEnum1()«); + // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'vararg'." + f7(»someVariantOfMyEnum2()«); + // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'vararg'." + f7(»MyEnum1.Variant1«); + // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'vararg'." + f7(»MyEnum1.Variant2«); + // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'vararg'." + f7(»MyEnum2.Variant1«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'vararg'." + f7(»aOrC()«); + // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'vararg'." + f7(»bOrC()«); + // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'vararg'." + f7(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'vararg'." + f7(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f7(unresolved = »1«); + + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f8(»(vararg a: Int) {}«); + + // $TEST$ no error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'Any'." + f9(»intToInt«); + // $TEST$ no error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'Any'." + f9(»f2«); + // $TEST$ no error "An argument of type 'B' cannot be assigned to a parameter of type 'Any'." + f9(»B()«); + // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'Any'." + f9(callableType = »C()«); + // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'Any'." + f9(»D()«); + // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'Any'." + f9(»maybeC()«); + // $TEST$ no error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'Any'." + f9(»someVariantOfMyEnum1()«); + // $TEST$ no error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'Any'." + f9(»someVariantOfMyEnum2()«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'Any'." + f9(»MyEnum1.Variant1«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'Any'." + f9(»MyEnum1.Variant2«); + // $TEST$ no error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'Any'." + f9(»MyEnum2.Variant1«); + // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any'." + f9(»aOrC()«); + // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any'." + f9(»bOrC()«); + // $TEST$ no error "An argument of type 'vararg' cannot be assigned to a parameter of type 'Any'." + f9(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'Any'." + f9(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f9(unresolved = »1«); + + // $TEST$ no error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'Any?'." + f10(»intToInt«); + // $TEST$ no error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'Any?'." + f10(»f2«); + // $TEST$ no error "An argument of type 'B' cannot be assigned to a parameter of type 'Any?'." + f10(»B()«); + // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'Any?'." + f10(callableType = »C()«); + // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'Any?'." + f10(»D()«); + // $TEST$ no error "An argument of type 'C?' cannot be assigned to a parameter of type 'Any?'." + f10(»maybeC()«); + // $TEST$ no error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'Any?'." + f10(»someVariantOfMyEnum1()«); + // $TEST$ no error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'Any?'." + f10(»someVariantOfMyEnum2()«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'Any?'." + f10(»MyEnum1.Variant1«); + // $TEST$ no error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'Any?'." + f10(»MyEnum1.Variant2«); + // $TEST$ no error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'Any?'." + f10(»MyEnum2.Variant1«); + // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any?'." + f10(»aOrC()«); + // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any?'." + f10(»bOrC()«); + // $TEST$ no error "An argument of type 'vararg' cannot be assigned to a parameter of type 'Any?'." + f10(»variadicParam«); + // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'Any?'." + f10(»unresolved«); + // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." + f10(unresolved = »1«); +} + +fun f1(callableType: (a: Int) -> (r: Int)) +fun f2(classType: C) +fun f3(enumType: MyEnum1) +fun f4(enumVariantType: MyEnum1.Variant1) +fun f5(unionType: union) +fun f6(unresolvedType: Unresolved) +fun f7(vararg variadicType: C) +fun f8(callableType: (vararg a: Int) -> ()) +fun f9(any: Any) +fun f10(anyOrNull: Any?) + +class A() +class B() +class C() +class D() sub C + +enum MyEnum1 { + Variant1 + Variant2 +} +enum MyEnum2 { + Variant1 + Variant2 +} + +fun maybeC() -> instanceOrNull: C? +fun aOrC() -> instance: union +fun bOrC() -> instance: union +fun someVariantOfMyEnum1() -> variant: MyEnum1 +fun someVariantOfMyEnum2() -> variant: MyEnum2 +fun intToInt(a: Int) -> (r: Int) diff --git a/tests/resources/validation/skip-old/assignments/hasNoEffect.sdstest b/tests/resources/validation/skip-old/assignments/hasNoEffect.sdstest new file mode 100644 index 000000000..729ecb48d --- /dev/null +++ b/tests/resources/validation/skip-old/assignments/hasNoEffect.sdstest @@ -0,0 +1,19 @@ +step myFunction() -> a: Int { + // $TEST$ warning "This statement does nothing." + »_ = 1 + 2;« + + // $TEST$ no warning "This statement does nothing." + »val a = 1;« + // $TEST$ no warning "This statement does nothing." + »yield a = 1;« + + () { + // $TEST$ warning "This statement does nothing." + »_ = 1 + 2;« + + // $TEST$ no warning "This statement does nothing." + »val a = 1;« + // $TEST$ no warning "This statement does nothing." + »yield a = 1;« + }; +} diff --git a/tests/resources/validation/skip-old/defaultValues.sdstest b/tests/resources/validation/skip-old/defaultValues.sdstest new file mode 100644 index 000000000..f1ce05cde --- /dev/null +++ b/tests/resources/validation/skip-old/defaultValues.sdstest @@ -0,0 +1,19 @@ +package tests.validation.typeChecking.defaultValues + +fun myFun( + // $TEST$ no error "An default value of type 'Int' cannot be assigned to a parameter of type 'Int'." + param1: Int = »1«, + + // $TEST$ error "A default value of type 'String' cannot be assigned to a parameter of type 'Int'." + param2: Int = »""«, +) + +fun myOtherFun(callback: (a: Int) -> ()) + +step myStep() { + // $TEST$ no error "An default value of type 'Int' cannot be assigned to a parameter of type 'Int'." + myOtherFun((a = »1«) {}); + + // $TEST$ error "A default value of type 'String' cannot be assigned to a parameter of type 'Int'." + myOtherFun((a = »""«) {}); +} diff --git a/tests/resources/validation/skip-old/expressionStatements/hasNoEffect.sdstest b/tests/resources/validation/skip-old/expressionStatements/hasNoEffect.sdstest new file mode 100644 index 000000000..9e2e40079 --- /dev/null +++ b/tests/resources/validation/skip-old/expressionStatements/hasNoEffect.sdstest @@ -0,0 +1,78 @@ +package tests.validation.statements.expressionStatements.hasNoEffect + +fun impureFunction() +@Pure fun pureFunction() -> a: Int + +class MyClass() { + fun impureFunction() + @Pure fun pureFunction() +} + +step pureStep() { + val a = pureFunction(); +} + +step impureStep() { + impureFunction(); +} + +step recursiveA() { + recursiveB(); +} + +step recursiveB() { + recursiveA(); +} + +step myStep() { + // $TEST$ warning "This statement does nothing." + »1 + 2;« + // $TEST$ warning "This statement does nothing." + »pureFunction();« + // $TEST$ warning "This statement does nothing." + »MyClass().pureFunction();« + + // $TEST$ no warning "This statement does nothing." + »impureFunction();« + // $TEST$ no warning "This statement does nothing." + »MyClass().impureFunction();« + + () { + // $TEST$ warning "This statement does nothing." + »1 + 2;« + // $TEST$ warning "This statement does nothing." + »pureFunction();« + // $TEST$ warning "This statement does nothing." + »MyClass().pureFunction();« + + // $TEST$ no warning "This statement does nothing." + »impureFunction();« + // $TEST$ no warning "This statement does nothing." + »MyClass().impureFunction();« + }; + + // $TEST$ warning "This statement does nothing." + »(() { + pureFunction(); + MyClass().pureFunction(); + })();« + + // $TEST$ warning "This statement does nothing." + »pureStep();« + + // $TEST$ no warning "This statement does nothing." + »(() { + impureFunction(); + })();« + + // $TEST$ no warning "This statement does nothing." + »(() { + MyClass().impureFunction(); + })();« + + // $TEST$ no warning "This statement does nothing." + »impureStep();« + + // $TEST$ no warning "This statement does nothing." + »recursiveA();« +} diff --git a/tests/resources/validation/skip-old/indexedAccesses.sdstest b/tests/resources/validation/skip-old/indexedAccesses.sdstest new file mode 100644 index 000000000..c741d5379 --- /dev/null +++ b/tests/resources/validation/skip-old/indexedAccesses.sdstest @@ -0,0 +1,39 @@ +package tests.validation.typeChecking.indexedAccesses + +step f(a: Int, vararg b: Int) { + // $TEST$ error "The receiver of an indexed access must refer to a variadic parameter." + »a«[0]; + + // $TEST$ no error "The receiver of an indexed access must refer to a variadic parameter." + »b«[0]; + + // $TEST$ no error "The receiver of an indexed access must refer to a variadic parameter." + »unresolved«[0]; + + // $TEST$ no error "The receiver of an indexed access must refer to a variadic parameter." + »C.unresolved«[0]; + + // $TEST$ no error "The index of an indexed access must be an instance of the class 'Int'." + b[»0«]; + + // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." + b[»""«]; + + // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." + b[»g«]; + + // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." + b[»h()«]; + + // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." + b[»b«]; + + // $TEST$ no error "The index of an indexed access must be an instance of the class 'Int'." + b[»unresolved«]; + + // $TEST$ no error "The index of an indexed access must be an instance of the class 'Int'." + b[»C.unresolved«]; +} + +fun g() +fun h() -> index: Int? diff --git a/tests/resources/validation/skip-old/infixOperations.sdstest b/tests/resources/validation/skip-old/infixOperations.sdstest new file mode 100644 index 000000000..418927427 --- /dev/null +++ b/tests/resources/validation/skip-old/infixOperations.sdstest @@ -0,0 +1,230 @@ +package tests.validation.typeChecking.infixOperations + +step f(vararg a: Int) { + + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »true« or »true« ; + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »false« or »false«; + // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »i()« or »i()«; + // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »0« or »0«; + // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »a« or »a«; + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »unresolved« or »unresolved«; + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »C.unresolved« or »C.unresolved«; + + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »true« and »true«; + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »false« and »false«; + // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »i()« and »i()«; + // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »0« and »0«; + // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »a« and »a«; + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »unresolved« and »unresolved«; + // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." + // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." + »C.unresolved« and »C.unresolved«; + + + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0.0« + »0.0«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0« + »0«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »h()« + »h()«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »""« + »""«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »a« + »a«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »unresolved« + »unresolved«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« + »C.unresolved«; + + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0.0« - »0.0«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0« - »0«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »h()« - »h()«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »""« - »""«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »a« - »a«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »unresolved« - »unresolved«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« - »C.unresolved«; + + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0.0« * »0.0«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0« * »0«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »h()« * »h()«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »""« * »""«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »a« * »a«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »unresolved« * »unresolved«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« * »C.unresolved«; + + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0.0« / »0.0«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »0« / »0«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »h()« / »h()«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »""« / »""«; + // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »a« / »a«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »unresolved« / »unresolved«; + // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« / »C.unresolved«; + + + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0.0« < »0.0«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0« < »0«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »h()« < »h()«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »""« < »""«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »a« < »a«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »unresolved« < »unresolved«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« < »C.unresolved«; + + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0.0« <= »0.0«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0« <= »0«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »h()« <= »h()«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »""« <= »""«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »a« <= »a«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »unresolved« <= »unresolved«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« <= »C.unresolved«; + + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0.0« >= »0.0«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0« >= »0«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »h()« >= »h()«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »""« >= »""«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »a« >= »a«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »unresolved« >= »unresolved«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« >= »C.unresolved«; + + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0.0« > »0.0«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »0« > »0«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »h()« > »h()«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »""« > »""«; + // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »a« > »a«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »unresolved« > »unresolved«; + // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." + »C.unresolved« > »C.unresolved«; +} + +fun g() +fun h() -> index: Int? +fun i() -> isTrue: Boolean? diff --git a/tests/resources/validation/skip-old/parameter types.sdstest b/tests/resources/validation/skip-old/parameter types.sdstest new file mode 100644 index 000000000..28f3f9237 --- /dev/null +++ b/tests/resources/validation/skip-old/parameter types.sdstest @@ -0,0 +1,52 @@ +package tests.validation.declarations.annotations.parameterTypes + +class MyClass + +enum ConstantEnum { + Variant1 + Variant2 +} + +enum NonConstantEnum { + Variant1(param: Int) + Variant2 +} + +annotation MyAnnotation( + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + booleanParam: »Boolean«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableBooleanParam: »Boolean?«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + floatParam: »Float«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableFloatParam: »Float?«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + intParam: »Int«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableIntParam: »Int?«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + stringParam: »String«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableStringParam: »String?«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + constantEnumParam: »ConstantEnum«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableConstantEnumParam: »ConstantEnum?«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nonConstantEnumParam: »NonConstantEnum«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableNonConstantEnumParam: »NonConstantEnum?«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + classParam: »MyClass«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableClassParam: »MyClass?«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + unresolvedParam: »Unresolved«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + nullableUnresolvedParam: »Unresolved?«, + // $TEST$ error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + callableParam: »() -> ()«, + // $TEST$ no error "Parameters of annotations must have type Boolean, Float, Int, String, or a constant enum." + vararg variadicParameter: »Int«, +) diff --git a/tests/resources/validation/skip-old/prefixOperations.sdstest b/tests/resources/validation/skip-old/prefixOperations.sdstest new file mode 100644 index 000000000..d2c43af31 --- /dev/null +++ b/tests/resources/validation/skip-old/prefixOperations.sdstest @@ -0,0 +1,38 @@ +package tests.validation.typeChecking.prefixOperations + +step f(vararg a: Int) { + + // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »true«; + // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »false«; + // $TEST$ error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »i()«; + // $TEST$ error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »0«; + // $TEST$ error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »a«; + // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »unresolved«; + // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." + not »C.unresolved«; + + // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»0.0«; + // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»0«; + // $TEST$ error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»h()«; + // $TEST$ error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»""«; + // $TEST$ error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»a«; + // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»unresolved«; + // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." + -»C.unresolved«; +} + +fun g() +fun h() -> index: Int? +fun i() -> isTrue: Boolean? diff --git a/tests/resources/validation/skip-old/purePropagates.sdstest b/tests/resources/validation/skip-old/purePropagates.sdstest new file mode 100644 index 000000000..4f0f3706c --- /dev/null +++ b/tests/resources/validation/skip-old/purePropagates.sdstest @@ -0,0 +1,21 @@ +package tests.validation.declarations.functions.purePropagates + +class MyOpenClass { + @Pure fun pureFunction1() + @Pure fun pureFunction2() + fun impureFunction1() +} + +class MyClass sub MyOpenClass { + // $TEST$ no error "One of the supertypes of this class declares a pure function with this name, so this must be pure as well." + @Pure fun »ownPureFunction«() + // $TEST$ no error "One of the supertypes of this class declares a pure function with this name, so this must be pure as well." + fun »ownImpureFunction«() + + // $TEST$ error "One of the supertypes of this class declares a pure function with this name, so this must be pure as well." + fun »pureFunction1«() + // $TEST$ no error "One of the supertypes of this class declares a pure function with this name, so this must be pure as well." + @Pure fun »pureFunction2«() + // $TEST$ no error "One of the supertypes of this class declares a pure function with this name, so this must be pure as well." + @Pure fun »impureFunction1«() +} diff --git a/tests/resources/validation/skip-old/recursion.sdstest b/tests/resources/validation/skip-old/recursion.sdstest new file mode 100644 index 000000000..2f308d90d --- /dev/null +++ b/tests/resources/validation/skip-old/recursion.sdstest @@ -0,0 +1,68 @@ +package tests.validation.expressions.calls.recursion + + +pipeline p { + // $TEST$ error "Recursive calls are not allowed." + »a«(); + // $TEST$ error "Recursive calls are not allowed." + »b«(); + // $TEST$ error "Recursive calls are not allowed." + »c«(); + // $TEST$ no error "Recursive calls are not allowed." + »d«(); + // $TEST$ no error "Recursive calls are not allowed." + »f«(); +} + +step a() { + // $TEST$ error "Recursive calls are not allowed." + »a«(); + // $TEST$ error "Recursive calls are not allowed." + »b«(); + // $TEST$ error "Recursive calls are not allowed." + »c«(); + // $TEST$ no error "Recursive calls are not allowed." + »d«(); + // $TEST$ no error "Recursive calls are not allowed." + »f«(); + + () { + // $TEST$ error "Recursive calls are not allowed." + »a«(); + // $TEST$ error "Recursive calls are not allowed." + »b«(); + // $TEST$ error "Recursive calls are not allowed." + »c«(); + // $TEST$ no error "Recursive calls are not allowed." + »d«(); + // $TEST$ no error "Recursive calls are not allowed." + »f«(); + }; + + val lambda1 = () { + // $TEST$ no error "Recursive calls are not allowed." + »lambda1«(); + }; + + val lambda2 = () { + // $TEST$ no error "Recursive calls are not allowed." + »lambda3«(); + }; + + val lambda3 = () { + // $TEST$ no error "Recursive calls are not allowed." + »lambda2«(); + }; +} + +step b() { + // $TEST$ error "Recursive calls are not allowed." + »c«(); +} + +step c() { + // $TEST$ error "Recursive calls are not allowed." + »b«(); +} + +step d() {} diff --git a/tests/resources/validation/skip-old/schemaEffectArguments.sdstest b/tests/resources/validation/skip-old/schemaEffectArguments.sdstest new file mode 100644 index 000000000..c325a2ef5 --- /dev/null +++ b/tests/resources/validation/skip-old/schemaEffectArguments.sdstest @@ -0,0 +1,22 @@ +package tests.validation.typeChecking.schemaEffectArguments + +predicate schemaEffects (){ + + /* $ReadSchema ---------------------------------------------------------------------------------------------------*/ + // $TEST$ error "An argument of type 'Boolean' cannot be assigned to a parameter of type 'String'." + $readSchema(»false«), + + // $TEST$ no error "An argument of type 'String' cannot be assigned to a parameter of type 'String'." + $readSchema(»"datasetNameStr"«), + + /* $CheckColumn --------------------------------------------------------------------------------------------------*/ + // $TEST$ error "An argument of type 'Boolean' cannot be assigned to a parameter of type '::$SchemaType'." + // $TEST$ error "An argument of type 'Int' cannot be assigned to a parameter of type 'vararg'." + // $TEST$ no error "An argument of type 'safeds.lang.String' cannot be assigned to a parameter of type 'safeds.lang.String'." + $checkColumn(»false«, »0«, »"columnNameStr2"«), + + // $TEST$ no error "An argument of type '::$SchemaType' cannot be assigned to a parameter of type '::$SchemaType'." + // $TEST$ no error "An argument of type 'String' cannot be assigned to a parameter of type 'vararg'." + // $TEST$ no error "An argument of type 'String' cannot be assigned to a parameter of type 'String'." + $checkColumn(»::ASchema«, »"columnNameStr1"«, »"columnNameStr2"«) +} diff --git a/tests/resources/validation/skip-old/staticAnalysis/recursion.sdstest b/tests/resources/validation/skip-old/staticAnalysis/recursion.sdstest new file mode 100644 index 000000000..19e9248d8 --- /dev/null +++ b/tests/resources/validation/skip-old/staticAnalysis/recursion.sdstest @@ -0,0 +1,90 @@ +package tests.staticAnalysis.recursion + +// Positive examples ----------------------------------------------------------- + +annotation CallsShouldBeRecursive + +// Direct recursion + +@CallsShouldBeRecursive +step directRecursion(a: Any or directRecursion()) { + directRecursion(); + 1 + directRecursion(); + val a = directRecursion(); +} + +// Transitive recursion + +@CallsShouldBeRecursive +step transitiveRecursion1() { + transitiveRecursion2(); + val a = transitiveRecursion2(); +} + +@CallsShouldBeRecursive +step transitiveRecursion2() { + transitiveRecursion3(); + val a = transitiveRecursion3(); +} + +@CallsShouldBeRecursive +step transitiveRecursion3() { + transitiveRecursion2(); + val a = transitiveRecursion2(); +} + +// Deferred recursion in lambda + +@CallsShouldBeRecursive +step deferredRecursionInLambda() { + (() { directRecursion(); })(); + (() -> directRecursion())(); +} + +// Negative examples ----------------------------------------------------------- + +annotation CallsShouldNotBeRecursive + +// Normal calls + +@CallsShouldNotBeRecursive +step normalCall(f: () -> ()) { + f(); + (() {})(); + (() -> null)(); + + MyClass(); + MyEnum.Variant(); + myFun(); + myStep(); +} + +class MyClass() +enum MyEnum { + Variant() +} +fun myFun() +step myStep() {} + +// Uncalled lambda + +@CallsShouldNotBeRecursive +step uncalledLambda() { + () { uncalledLambda(); }; + () -> uncalledLambda(); +} + +// Lambda recursion (already handled by scoping) + +@CallsShouldNotBeRecursive +step lambdaRecursion() { + val a = () { a(); }; + val b = () -> b(); +} + +// Unresolved callable + +@CallsShouldNotBeRecursive +step unresolvedCallable() { + unresolved(); +} diff --git a/tests/resources/validation/skip-old/staticAnalysis/sideEffects.sdstest b/tests/resources/validation/skip-old/staticAnalysis/sideEffects.sdstest new file mode 100644 index 000000000..38ea9255a --- /dev/null +++ b/tests/resources/validation/skip-old/staticAnalysis/sideEffects.sdstest @@ -0,0 +1,147 @@ +package tests.staticAnalysis.sideEffects + +// Positive examples ----------------------------------------------------------- + +annotation ShouldHaveNoSideEffects + +// Call to class constructor + +class C() + +@ShouldHaveNoSideEffects +step callOfClassConstructor() { + C(); +} + +// Call to enum variant constructor + +enum MyEnum { + Variant +} + +@ShouldHaveNoSideEffects +step callOfEnumVariantConstructor() { + MyEnum.Variant(); +} + +// Function without side effects + +@Pure +fun pureFunction() + +@NoSideEffects +fun functionWithoutSideEffects() + +@ShouldHaveNoSideEffects +step callToPureFunction() { + pureFunction(); + functionWithoutSideEffects(); +} + +// Lambdas without side effects + +@ShouldHaveNoSideEffects +step callToPureLambdas() { + (() {})(); + (() -> null)(); + + () { + (() {})(); + }; + + () -> (() -> null)(); +} + +// Steps without side effects + +step pureStep() {} + +@ShouldHaveNoSideEffects +step callToPureSteps() { + pureStep(); +} + +// Uncalled lambdas + +step pureStepWithUncalledLambdas() { + () -> impureFunction(); +} + +@ShouldHaveNoSideEffects +step uncalledLambdas() { + pureStepWithUncalledLambdas(); +} + +// Function as result + +@ShouldHaveNoSideEffects +step pureFunctionAsResult() { + (() -> pureFunction)()(); +} + +// Negative examples ----------------------------------------------------------- + +annotation ShouldHaveSideEffects + +// Callable type + +@ShouldHaveSideEffects +step callToCallableType(f: () -> ()) { + f(); +} + +// Function with side effects + +fun impureFunction() + +@ShouldHaveSideEffects +step callToImpureFunction() { + impureFunction(); +} + +// Lambdas with side effects + +@ShouldHaveSideEffects +step callToImpureLambdas() { + (() { impureFunction(); })(); + (() -> impureFunction())(); + + () { + (() { impureFunction(); })(); + }; + + () -> (() -> impureFunction())(); +} + +// Steps with side effects + +step impureStep() { + impureFunction(); +} + +@ShouldHaveSideEffects +step callToImpureSteps() { + impureStep(); +} + +// Recursion + +@ShouldHaveSideEffects +step recursion() { + recursion(); +} + +// Unresolved callable + +@ShouldHaveSideEffects +step unresolvedCallable() { + unresolved(); +} + +// Function as parameter + +@ShouldHaveSideEffects +step impureFunctionAsParameter() { + ((f) -> f())(pureFunction); // This is actually pure, but we match in a conservative manner. Can be improved later. + ((f) -> f())(impureFunction); +} diff --git a/tests/resources/validation/skip-old/yields.sdstest b/tests/resources/validation/skip-old/yields.sdstest new file mode 100644 index 000000000..3cfeb4c78 --- /dev/null +++ b/tests/resources/validation/skip-old/yields.sdstest @@ -0,0 +1,13 @@ +package tests.validation.typeChecking.yields + +step myStep1() -> result: Int { + + // $TEST$ no error "A value of type 'Int' cannot be assigned to a result of type 'Int'." + yield result = »1«; +} + +step myStep2() -> result: Int { + + // $TEST$ error "A value of type 'String' cannot be assigned to a result of type 'Int'." + yield result = »""«; +}