Skip to content

Commit

Permalink
feat: scoping for inherited members
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-reimann committed Oct 30, 2023
1 parent 39d3aa5 commit ca08f90
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,16 @@ import {
getTypeParameters,
isStatic,
} from '../helpers/nodeProperties.js';
import { SafeDsNodeMapper } from '../helpers/safe-ds-node-mapper.js';
import { SafeDsServices } from '../safe-ds-module.js';
import { ClassType, EnumVariantType } from '../typing/model.js';
import type { SafeDsClassHierarchy } from '../typing/safe-ds-class-hierarchy.js';
import { SafeDsTypeComputer } from '../typing/safe-ds-type-computer.js';
import { SafeDsPackageManager } from '../workspace/safe-ds-package-manager.js';
import { SafeDsNodeMapper } from '../helpers/safe-ds-node-mapper.js';
import { ClassType, EnumVariantType } from '../typing/model.js';

export class SafeDsScopeProvider extends DefaultScopeProvider {
private readonly astReflection: AstReflection;
private readonly classHierarchy: SafeDsClassHierarchy;
private readonly nodeMapper: SafeDsNodeMapper;
private readonly packageManager: SafeDsPackageManager;
private readonly typeComputer: SafeDsTypeComputer;
Expand All @@ -79,6 +81,7 @@ export class SafeDsScopeProvider extends DefaultScopeProvider {
super(services);

this.astReflection = services.shared.AstReflection;
this.classHierarchy = services.types.ClassHierarchy;
this.nodeMapper = services.helpers.NodeMapper;
this.packageManager = services.workspace.PackageManager;
this.typeComputer = services.types.TypeComputer;
Expand Down Expand Up @@ -178,12 +181,9 @@ export class SafeDsScopeProvider extends DefaultScopeProvider {
const declaration = this.getUniqueReferencedDeclarationForExpression(node.receiver);
if (isSdsClass(declaration)) {
const ownStaticMembers = getMatchingClassMembers(declaration, isStatic);
// val superTypeMembers = receiverDeclaration.superClassMembers()
// .filter { it.isStatic() }
// .toList()
//
// return Scopes.scopeFor(ownStaticMembers, Scopes.scopeFor(superTypeMembers))
return this.createScopeForNodes(ownStaticMembers);
const superclassStaticMembers = this.classHierarchy.streamSuperclassMembers(declaration).filter(isStatic);

return this.createScopeForNodes(ownStaticMembers, this.createScopeForNodes(superclassStaticMembers));
} else if (isSdsEnum(declaration)) {
return this.createScopeForNodes(getEnumVariants(declaration));
}
Expand All @@ -208,12 +208,14 @@ export class SafeDsScopeProvider extends DefaultScopeProvider {

if (receiverType instanceof ClassType) {
const ownInstanceMembers = getMatchingClassMembers(receiverType.declaration, (it) => !isStatic(it));
// val superTypeMembers = type.sdsClass.superClassMembers()
// .filter { !it.isStatic() }
// .toList()
//
// Scopes.scopeFor(members, Scopes.scopeFor(superTypeMembers, resultScope))
return this.createScopeForNodes(ownInstanceMembers, resultScope);
const superclassInstanceMembers = this.classHierarchy
.streamSuperclassMembers(receiverType.declaration)
.filter((it) => !isStatic(it));

return this.createScopeForNodes(
ownInstanceMembers,
this.createScopeForNodes(superclassInstanceMembers, resultScope),
);
} else if (receiverType instanceof EnumVariantType) {
const parameters = getParameters(receiverType.declaration);
return this.createScopeForNodes(parameters, resultScope);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { SafeDsServices } from '../safe-ds-module.js';
import { SafeDsClasses } from '../builtins/safe-ds-classes.js';
import { SdsClass } from '../generated/ast.js';
import { EMPTY_STREAM, stream, Stream } from 'langium';
import { getParentTypes } from '../helpers/nodeProperties.js';
import { SafeDsTypeComputer } from './safe-ds-type-computer.js';
import { SafeDsClasses } from '../builtins/safe-ds-classes.js';
import { SdsClass, type SdsClassMember } from '../generated/ast.js';
import { getMatchingClassMembers, getParentTypes } from '../helpers/nodeProperties.js';
import { SafeDsServices } from '../safe-ds-module.js';
import { ClassType } from './model.js';
import { SafeDsTypeComputer } from './safe-ds-type-computer.js';

export class SafeDsClassHierarchy {
private readonly builtinClasses: SafeDsClasses;
Expand Down Expand Up @@ -60,6 +60,14 @@ export class SafeDsClassHierarchy {
}
}

streamSuperclassMembers(node: SdsClass | undefined): Stream<SdsClassMember> {
if (!node) {
return EMPTY_STREAM;
}

return this.streamSuperclasses(node).flatMap(getMatchingClassMembers);
}

/**
* Returns the parent class of the given class, or undefined if there is no parent class. Only the first parent
* type is considered, i.e. multiple inheritance is not supported.
Expand All @@ -74,22 +82,3 @@ export class SafeDsClassHierarchy {
return undefined;
}
}

// fun SdsClass.superClassMembers() =
// this.superClasses().flatMap { it.classMembersOrEmpty().asSequence() }
//
// // TODO only static methods can be hidden
// fun SdsFunction.hiddenFunction(): SdsFunction? {
// val containingClassOrInterface = closestAncestorOrNull<SdsClass>() ?: return null
// return containingClassOrInterface.superClassMembers()
// .filterIsInstance<SdsFunction>()
// .firstOrNull { it.name == name }
// }
//
// fun SdsClass?.inheritedNonStaticMembersOrEmpty(): Set<SdsAbstractDeclaration> {
// return this?.parentClassesOrEmpty()
// ?.flatMap { it.classMembersOrEmpty() }
// ?.filter { it is SdsAttribute && !it.isStatic || it is SdsFunction && !it.isStatic }
// ?.toSet()
// .orEmpty()
// }

0 comments on commit ca08f90

Please sign in to comment.