diff --git a/img/safe-ds_logo_rounded.png b/img/safe-ds_logo_rounded.png new file mode 100644 index 000000000..cf515d7ab Binary files /dev/null and b/img/safe-ds_logo_rounded.png differ diff --git a/language-configuration.json b/language-configuration.json index 92d75bae8..2d0dd7986 100644 --- a/language-configuration.json +++ b/language-configuration.json @@ -4,26 +4,28 @@ "blockComment": ["/*", "*/"] }, "brackets": [ + ["(", ")"], ["{", "}"], ["[", "]"], - ["(", ")"], + ["<", ">"], ["»", "«"] ], "autoClosingPairs": [ + ["(", ")"], ["{", "}"], ["[", "]"], - ["(", ")"], - ["»", "«"], + ["<", ">"], ["\"", "\""], - ["`", "`"] + ["`", "`"], + ["»", "«"] ], "surroundingPairs": [ + ["(", ")"], ["{", "}"], ["[", "]"], - ["(", ")"], ["<", ">"], - ["»", "«"], ["\"", "\""], - ["`", "`"] + ["`", "`"], + ["»", "«"] ] } diff --git a/package.json b/package.json index d47911955..c7ff558fc 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,59 @@ { "name": "safe-ds", - "displayName": "safe-ds", - "description": "Statically checked Data Science programs.", "version": "0.1.0", + "preview": true, + "publisher": "Safe-DS", + "displayName": "Safe-DS", + "description": "Statically checked Data Science programs.", + "license": "MIT", + "categories": [ + "Programming Languages", + "Machine Learning", + "Data Science" + ], + "keywords": [ + "dsl", + "static checking" + ], + "galleryBanner": { + "color": "#e3e9e9" + }, + "icon": "img/safe-ds_logo_rounded.png", + "homepage": "https://dsl.safeds.com", + "qna": "https://github.com/orgs/Safe-DS/discussions", + "bugs": { + "url": "https://github.com/Safe-DS/DSL/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/Safe-DS/DSL.git" + }, + "badges": [ + { + "url": "https://github.com/Safe-DS/DSL/actions/workflows/main.yml/badge.svg", + "href": "https://github.com/Safe-DS/DSL/actions/workflows/main.yml", + "description": "Main" + }, + { + "url": "https://codecov.io/gh/Safe-DS/DSL/branch/main/graph/badge.svg?token=ma0ytglhO1", + "href": "https://codecov.io/gh/Safe-DS/DSL", + "description": "codecov" + } + ], "engines": { "vscode": "^1.82.0" }, - "categories": [ - "Programming Languages" - ], "contributes": { "languages": [ { "id": "safe-ds", "aliases": [ "Safe-DS", - "safe-ds" + "safe-ds", + "SafeDS", + "safeds", + "SDS", + "sds" ], "extensions": [ ".sdspipe", @@ -33,14 +71,14 @@ } ] }, + "type": "module", + "main": "out/extension/main.cjs", "files": [ "bin" ], - "type": "module", "bin": { "safe-ds-cli": "./bin/cli" }, - "main": "out/extension/main.cjs", "scripts": { "vscode:prepublish": "npm run build && npm run lint", "build": "tsc -b tsconfig.json && node esbuild.mjs", diff --git a/src/language/validation/other/declarations/placeholders.ts b/src/language/validation/other/declarations/placeholders.ts index 7453fb788..519f912db 100644 --- a/src/language/validation/other/declarations/placeholders.ts +++ b/src/language/validation/other/declarations/placeholders.ts @@ -1,11 +1,41 @@ -import { isSdsBlock, isSdsStatement, SdsPlaceholder } from '../../../generated/ast.js'; +import { + isSdsAssignment, + isSdsBlock, + isSdsParameter, + isSdsPlaceholder, + isSdsReference, + isSdsStatement, + SdsPlaceholder, +} from '../../../generated/ast.js'; import { getContainerOfType, ValidationAcceptor } from 'langium'; import { SafeDsServices } from '../../../safe-ds-module.js'; import { statementsOrEmpty } from '../../../helpers/nodeProperties.js'; import { last } from 'radash'; +export const CODE_PLACEHOLDER_ALIAS = 'placeholder/alias'; export const CODE_PLACEHOLDER_UNUSED = 'placeholder/unused'; +export const placeholdersMustNotBeAnAlias = (node: SdsPlaceholder, accept: ValidationAcceptor): void => { + if (node.$containerIndex ?? 0 > 0) { + return; + } + + const containingAssignment = getContainerOfType(node, isSdsAssignment); + const rhs = containingAssignment?.expression; + if (!isSdsReference(rhs)) { + return; + } + + const referenceTarget = rhs.target.ref; + if (isSdsParameter(referenceTarget) || isSdsPlaceholder(referenceTarget)) { + accept('error', 'Aliases are not allowed to provide a cleaner graphical view.', { + node, + property: 'name', + code: CODE_PLACEHOLDER_ALIAS, + }); + } +}; + export const placeholderShouldBeUsed = (services: SafeDsServices) => (node: SdsPlaceholder, accept: ValidationAcceptor) => { const usages = services.helpers.NodeMapper.placeholderToReferences(node); diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index d0845efd8..1644bb2e3 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -61,7 +61,7 @@ import { namedTypeDeclarationShouldNotBeExperimental, referenceTargetShouldNotExperimental, } from './builtins/experimental.js'; -import { placeholderShouldBeUsed } from './other/declarations/placeholders.js'; +import { placeholderShouldBeUsed, placeholdersMustNotBeAnAlias } from './other/declarations/placeholders.js'; import { segmentParameterShouldBeUsed, segmentResultMustBeAssignedExactlyOnce } from './other/declarations/segments.js'; import { lambdaParameterMustNotHaveConstModifier } from './other/expressions/lambdas.js'; import { indexedAccessesShouldBeUsedWithCaution } from './experimentalLanguageFeature.js'; @@ -139,7 +139,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { ], SdsParameterList: [parameterListMustNotHaveRequiredParametersAfterOptionalParameters], SdsPipeline: [pipelineMustContainUniqueNames], - SdsPlaceholder: [placeholderShouldBeUsed(services)], + SdsPlaceholder: [placeholdersMustNotBeAnAlias, placeholderShouldBeUsed(services)], SdsReference: [ referenceTargetMustNotBeAnnotationPipelineOrSchema, referenceTargetShouldNotBeDeprecated(services), diff --git a/tests/resources/validation/other/declarations/placeholders/alias/main.sdstest b/tests/resources/validation/other/declarations/placeholders/alias/main.sdstest new file mode 100644 index 000000000..fe1b02307 --- /dev/null +++ b/tests/resources/validation/other/declarations/placeholders/alias/main.sdstest @@ -0,0 +1,52 @@ +package tests.validation.other.placeholder.alias + +annotation MyAnnotation + +class MyClass { + static attr myAttribute: Int + + static fun myMethod() +} + +enum MyEnum { + MyEnumVariant +} + +fun myFunction() + +pipeline myPipeline {} + +schema MySchema {} + +segment mySegment1() {} + +segment mySegment2(myParameter: Int) { + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »myPlaceholder« = 1; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »a« = MyAnnotation; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »b« = MyClass.myAttribute; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »c« = MyClass; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »d« = MyEnum; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »e« = MyEnum.MyEnumVariant; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »f« = myFunction; + // $TEST$ error "Aliases are not allowed to provide a cleaner graphical view." + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »g1«, val »g2« = myParameter; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »h« = myPipeline; + // $TEST$ error "Aliases are not allowed to provide a cleaner graphical view." + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »i1«, val »i2« = myPlaceholder; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »j« = MySchema; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »k« = mySegment1; + // $TEST$ no error "Aliases are not allowed to provide a cleaner graphical view." + val »l« = unresolved; +}