@@ -177,7 +177,27 @@ class ServiceInstanceFromConstructor extends ServiceInstance {
177177}
178178
179179/**
180- * A read to `this` variable which represents the service whose definition encloses this variable access.
180+ * A read to `this` variable which represents the service whose definition encloses
181+ * this variable access.
182+ * e.g.1. Given this code:
183+ * ``` javascript
184+ * const cds = require("@sap/cds");
185+ * module.exports = class SomeService extends cds.ApplicationService {
186+ * init() {
187+ * this.on("SomeEvent", (req) => { ... } )
188+ * }
189+ * }
190+ * ```
191+ * This class captures the access to the `this` variable as in `this.on(...)`.
192+ *
193+ * e.g.2. Given this code:
194+ * ``` javascript
195+ * const cds = require('@sap/cds');
196+ * module.exports = cds.service.impl (function() {
197+ * this.on("SomeEvent", (req) => { ... })
198+ * })
199+ * ```
200+ * This class captures the access to the `this` variable as in `this.on(...)`.
181201 */
182202class ServiceInstanceFromThisNode extends ServiceInstance , ThisNode {
183203 UserDefinedApplicationService userDefinedApplicationService ;
@@ -294,12 +314,56 @@ class DbServiceInstanceFromCdsConnectTo extends ServiceInstanceFromCdsConnectTo,
294314 override UserDefinedApplicationService getDefinition ( ) { none ( ) }
295315}
296316
317+ /**
318+ * The 0-th parameter of an exported closure that represents the service being implemented. e.g.
319+ * ``` javascript
320+ * const cds = require('@sap/cds')
321+ * module.exports = (srv) => {
322+ * srv.on("SomeEvent1", (req) => { ... })
323+ * }
324+ * ```
325+ * This class captures the `srv` parameter of the exported arrow function. Also see
326+ * `ServiceInstanceFromImplMethodCallClosureParameter` which is similar to this.
327+ */
328+ class ServiceInstanceFromExportedClosureParameter extends ServiceInstance , ParameterNode {
329+ ExportedClosureApplicationServiceDefinition exportedClosure ;
330+
331+ ServiceInstanceFromExportedClosureParameter ( ) { this = exportedClosure .getParameter ( 0 ) }
332+
333+ override UserDefinedApplicationService getDefinition ( ) { result = exportedClosure }
334+ }
335+
336+ /**
337+ * The 0-th parameter of a callback (usually an arrow function) passed to `cds.service.impl` that
338+ * represents the service being implemented. e.g.
339+ * ``` javascript
340+ * const cds = require('@sap/cds')
341+ * module.exports = cds.service.impl((srv) => {
342+ * srv.on("SomeEvent1", (req) => { ... })
343+ * })
344+ * ```
345+ * This class captures the `srv` parameter of the exported arrow function. Also see
346+ * `ServiceInstanceFromExportedClosureParameter` which is similar to this.
347+ */
348+ class ServiceInstanceFromImplMethodCallClosureParameter extends ServiceInstance , ParameterNode {
349+ ImplMethodCallApplicationServiceDefinition implMethodCallApplicationServiceDefinition ;
350+
351+ ServiceInstanceFromImplMethodCallClosureParameter ( ) {
352+ this = implMethodCallApplicationServiceDefinition .getInitFunction ( ) .getParameter ( 0 )
353+ }
354+
355+ override UserDefinedApplicationService getDefinition ( ) {
356+ result = implMethodCallApplicationServiceDefinition
357+ }
358+ }
359+
297360/**
298361 * A call to `before`, `on`, or `after` on an `cds.ApplicationService`.
299362 * It registers an handler to be executed when an event is fired,
300363 * to do something with the incoming request or event as its parameter.
301364 */
302365class HandlerRegistration extends MethodCallNode {
366+ /** The instance of the service a handler is registered on. */
303367 ServiceInstance srv ;
304368 string methodName ;
305369
@@ -308,6 +372,9 @@ class HandlerRegistration extends MethodCallNode {
308372 methodName = [ "before" , "on" , "after" ]
309373 }
310374
375+ /**
376+ * Gets the instance of the service a handler is registered on.
377+ */
311378 ServiceInstance getService ( ) { result = srv }
312379
313380 /**
@@ -347,7 +414,7 @@ class HandlerRegistration extends MethodCallNode {
347414
348415/**
349416 * The first parameter of a handler, representing the request object received either directly
350- * from a user, or from another service that may be internal (defined in the same application)
417+ * from a user, or from another service that may be internal (defined in the same application)
351418 * or external (defined in another application, or even served from a different server).
352419 * e.g.
353420 * ``` javascript
@@ -356,14 +423,15 @@ class HandlerRegistration extends MethodCallNode {
356423 * this.before("SomeEvent", "SomeEntity", (req, next) => { ... });
357424 * this.after("SomeEvent", "SomeEntity", (req, next) => { ... });
358425 * }
359- * ```
360- * All parameters named `req` above are captured. Also see `HandlerParameterOfExposedService`
426+ * ```
427+ * All parameters named `req` above are captured. Also see
428+ * `RemoteflowSources::HandlerParameterOfExposedService`
361429 * for a subset of this class that is only about handlers exposed to some protocol.
362430 */
363431class HandlerParameter extends ParameterNode {
364432 Handler handler ;
365433
366- HandlerParameter ( ) { this = handler . getParameter ( 0 ) }
434+ HandlerParameter ( ) { this = isHandlerParameter ( handler ) }
367435
368436 Handler getHandler ( ) { result = handler }
369437}
@@ -506,7 +574,7 @@ abstract class UserDefinedApplicationService extends UserDefinedService {
506574 /**
507575 * Holds if this service supports access from the outside through any kind of protocol.
508576 */
509- predicate isExposed ( ) { not this .isInternal ( ) }
577+ predicate isExposed ( ) { exists ( this . getCdsDeclaration ( ) ) and not this .isInternal ( ) }
510578
511579 /**
512580 * Holds if this service does not support access from the outside through any kind of protocol, thus being internal only.
@@ -539,9 +607,21 @@ class ES6ApplicationServiceDefinition extends ClassNode, UserDefinedApplicationS
539607
540608/**
541609 * Subclassing `cds.ApplicationService` via a call to `cds.service.impl`.
542- * ```js
610+ * e.g.1. Given this code:
611+ * ``` javascript
612+ * const cds = require('@sap/cds')
613+ * module.exports = cds.service.impl (function() {
614+ * this.on("SomeEvent1", (req) => { ... })
615+ * })
616+ * ```
617+ * This class captures the call `cds.service.impl (function() { ... })`.
618+ *
619+ * e.g.2. Given this code:
620+ * ``` javascript
543621 * const cds = require('@sap/cds')
544- * module.exports = cds.service.impl (function() { ... })
622+ * module.exports = cds.service.impl ((srv) => {
623+ * srv.on("SomeEvent1", (req) => { ... })
624+ * })
545625 * ```
546626 */
547627class ImplMethodCallApplicationServiceDefinition extends MethodCallNode ,
@@ -554,6 +634,40 @@ class ImplMethodCallApplicationServiceDefinition extends MethodCallNode,
554634 override FunctionNode getInitFunction ( ) { result = this .getArgument ( 0 ) }
555635}
556636
637+ /**
638+ * A user-defined application service that comes in a form of an exported
639+ * closure. e.g. Given the below code,
640+ * ``` javascript
641+ * const cds = require("@sap/cds");
642+ *
643+ * module.exports = (srv) => {
644+ * srv.before("SomeEvent1", "SomeEntity", (req, res) => { ... })
645+ * srv.on("SomeEvent2", (req) => { ... } )
646+ * srv.after("SomeEvent3", (req) => { ... } )
647+ * }
648+ * ```
649+ * This class captures the entire `(srv) => { ... }` function that is
650+ * exported.
651+ */
652+ class ExportedClosureApplicationServiceDefinition extends FunctionNode ,
653+ UserDefinedApplicationService
654+ {
655+ ExportedClosureApplicationServiceDefinition ( ) {
656+ /*
657+ * ==================== HACK ====================
658+ * See issue #221.
659+ */
660+
661+ exists ( PropWrite moduleExports |
662+ moduleExports .getBase ( ) .asExpr ( ) .( VarAccess ) .getName ( ) = "module" and
663+ moduleExports .getPropertyName ( ) = "exports" and
664+ this = moduleExports .getRhs ( )
665+ )
666+ }
667+
668+ override FunctionNode getInitFunction ( ) { result = this }
669+ }
670+
557671abstract class InterServiceCommunicationMethodCall extends MethodCallNode {
558672 string name ;
559673 ServiceInstance recipient ;
0 commit comments