Skip to content

Commit

Permalink
Moving functions from lsp-ide into wollok-ts (#233)
Browse files Browse the repository at this point in the history
* moving functions from lsp-ide into wollok-ts

* add unit test for projectPackages

* Fix method name and add tests

* Delete console info

* Fix linter

* Fix bad imported module

* Add tests for mayExecute

* Removing unused import

---------

Co-authored-by: Nahuel Palumbo <[email protected]>
  • Loading branch information
fdodino and PalumboN authored Apr 4, 2024
1 parent df495d4 commit 640709e
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 5 deletions.
22 changes: 21 additions & 1 deletion src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,24 @@ export const fqnRelativeToPackage =
export const workspacePackage = (environment: Environment): Package => environment.members[1]

export const targettingAt = <T extends Node>(aNode: T) => (anotherNode: Node): anotherNode is Reference<T> =>
anotherNode.is(Reference) && anotherNode.target === aNode
anotherNode.is(Reference) && anotherNode.target === aNode

export const projectPackages = (environment: Environment): Package[] =>
environment.members.slice(1)

export const isNotImportedIn = (importedPackage: Package, importingPackage: Package): boolean =>
importedPackage !== importingPackage &&
!importingPackage.imports.some(imported => imported.entity.target && belongsTo(imported.entity.target, importedPackage)) &&
!importedPackage.isGlobalPackage

export const belongsTo = (node: Node, mainPackage: Package): boolean =>
match(node)(
when(Package)((pkg) => pkg === mainPackage),
when(Node)((node) => node.parent === mainPackage),
)

export const mayExecute = (method: Method) => (node: Node): boolean =>
node.is(Send) &&
node.message === method.name &&
// exclude cases where a message is sent to a different singleton
!(node.receiver.is(Reference) && node.receiver.target?.is(Singleton) && node.receiver.target !== method.parent)
122 changes: 119 additions & 3 deletions test/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { should, use } from 'chai'
import sinonChai from 'sinon-chai'
import { BOOLEAN_MODULE, Body, Class, Evaluation, Interpreter, LIST_MODULE, Literal, Method, NUMBER_MODULE, OBJECT_MODULE, Package, Reference, STRING_MODULE, Singleton, WRENatives, allAvailableMethods, implicitImport, link, literalValueToClass, parentModule } from '../src'
import { BOOLEAN_MODULE, Body, Class, Environment, Evaluation, Import, Interpreter, LIST_MODULE, Literal, Method, NUMBER_MODULE, OBJECT_MODULE, Package, Reference, STRING_MODULE, Singleton, WRENatives, allAvailableMethods, implicitImport, isNotImportedIn, link, linkSentenceInNode, literalValueToClass, mayExecute, parentModule, parse, projectPackages } from '../src'
import { WREEnvironment, environmentWithEntities } from './utils'

use(sinonChai)
Expand All @@ -18,8 +18,8 @@ const basicEnvironmentWithSingleClass = () => link([new Package({
],
})], WREEnvironment)

const getLinkedEnvironment = () => {
const interpreter = new Interpreter(Evaluation.build(basicEnvironmentWithSingleClass(), WRENatives))
const getLinkedEnvironment = (baseEnvironment?: Environment) => {
const interpreter = new Interpreter(Evaluation.build(baseEnvironment ?? basicEnvironmentWithSingleClass(), WRENatives))
return interpreter.evaluation.environment
}

Expand Down Expand Up @@ -126,4 +126,120 @@ describe('Wollok helpers', () => {

})

describe('projectPackages', () => {

it('should return the right package from an environment', () => {
const environment = basicEnvironmentWithSingleClass()
const mainPackage = environment.getNodeByFQN('aves')
projectPackages(environment).should.deep.equal([mainPackage])
})

})

describe('isNotImportedIn', () => {

const MINIMAL_LANG = environmentWithEntities(OBJECT_MODULE)
const environment = getLinkedEnvironment(link([
new Package({
name: 'A',
imports: [
new Import({ isGeneric: false, entity: new Reference({ name: 'B.pepita' }) }),
new Import({ isGeneric: true, entity: new Reference({ name: 'D' }) }),
],
members: [
new Singleton({ name: 'entrenador' }),
],
}),
new Package({
name: 'B',
members: [
new Singleton(
{ name: 'pepita' }),
],
}),
new Package({
name: 'C',
members: [
new Singleton(
{ name: 'alpiste' }),
],
}),
new Package({
name: 'D',
members: [
new Singleton(
{ name: 'quilmes' }),
],
}),
], MINIMAL_LANG))

const packageA = environment.getNodeByFQN('A') as Package
const packageB = environment.getNodeByFQN('B') as Package
const packageC = environment.getNodeByFQN('C') as Package
const packageD = environment.getNodeByFQN('D') as Package

it('should return false if a definition is imported, using a specific import', () => {
isNotImportedIn(packageB, packageA).should.be.false
})

it('should return false if a definition is imported, use generic import', () => {
isNotImportedIn(packageD, packageA).should.be.false
})

it('should return true if a definition is not imported', () => {
isNotImportedIn(packageC, packageA).should.be.true
})

})

describe('mayExecute', () => {

let baseEnvironment: Environment
let testMethod: Method

beforeEach(() => {
const pepitaPackage: Package = new Package({
name: 'aves',
members: [
new Singleton({
name: 'pepita',
members: [
new Method({ name: 'volar', body: new Body() }),
new Method({ name: 'comer' }),
],
}),
],
})
const MINIMAL_LANG = environmentWithEntities(OBJECT_MODULE)
baseEnvironment = link([
pepitaPackage,
new Package({ name: 'repl' } ),
], MINIMAL_LANG)

const pepitaWKO = baseEnvironment.getNodeByFQN('aves.pepita') as Singleton
testMethod = pepitaWKO.lookupMethod('volar', 0)!
})

it('should not execute if second parameter is not a Send object', () => {
const assignmentForConst = parse.Variable.tryParse('const a = 1')
linkSentenceInNode(assignmentForConst, baseEnvironment.getNodeByFQN('repl'))

mayExecute(testMethod)(assignmentForConst).should.be.false
})

it('should not execute if method is different', () => {
const sendDifferentMethod = parse.Send.tryParse('aves.pepita.comer()')
linkSentenceInNode(sendDifferentMethod, baseEnvironment.getNodeByFQN('repl'))

mayExecute(testMethod)(sendDifferentMethod).should.be.false
})

it('should execute if node receiver is a singleton and is the same method', () => {
const sendOkSentence = parse.Send.tryParse('aves.pepita.volar()')
linkSentenceInNode(sendOkSentence, baseEnvironment.getNodeByFQN('repl'))

mayExecute(testMethod)(sendOkSentence).should.be.true
})

})
})
2 changes: 1 addition & 1 deletion test/interpreter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('Wollok Interpreter', () => {
const sentence = new Send({ receiver: new Reference({ name: 'p.o' }), message: 'm' })
const interpreter = new Interpreter(Evaluation.build(environment, {}))

interpreter.exec(sentence)!.innerNumber!.should.equal(5)
interpreter.exec(sentence)!.innerNumber!.should.equal(5)
})

it('should fail when executing a missing unlinked reference', () => {
Expand Down

0 comments on commit 640709e

Please sign in to comment.