@@ -266,6 +266,90 @@ export default class ASTCapabilities {
266266 this . scrollTo ( scrollInfo ) ;
267267 }
268268
269+ altN ( ) {
270+ this . negateExpression ( ) ;
271+ }
272+ // # Swap if and else blocks of a conditional
273+ negateExpression ( ) {
274+ const scrollInfo = this . scrollInfo ;
275+ let exitedEarly = false ;
276+
277+ const pathLocationsToSelect = [ ] ;
278+
279+ let transformed = this . sourceCode . transformAsAST ( ( { types : t , template } ) => ( {
280+ visitor : {
281+ Program : programPath => {
282+
283+ const negatableBinaryOperators = {
284+ "==" : "!=" ,
285+ "!=" : "==" ,
286+ "===" : "!==" ,
287+ "!==" : "===" ,
288+ "<" : ">=" ,
289+ "<=" : ">" ,
290+ ">" : "<=" ,
291+ ">=" : "<"
292+ } ;
293+
294+ const selectedPath = this . getInnermostPathContainingSelection ( programPath , this . firstSelection ) ;
295+
296+ let pathToNegate = selectedPath . find ( p => {
297+ const parentPath = p . parentPath ;
298+
299+ if ( ! parentPath ) {
300+ return false ;
301+ }
302+
303+ if ( parentPath . isIfStatement ( ) && p . parentKey === 'test' ) {
304+ return true ;
305+ }
306+
307+ if ( p . isBinaryExpression ( ) && negatableBinaryOperators [ p . node . operator ] ) {
308+ return true ;
309+ }
310+
311+ return false ;
312+ } ) ;
313+
314+ pathToNegate = pathToNegate || selectedPath . find ( p => {
315+ const parentPath = p . parentPath ;
316+ return parentPath && parentPath . isVariableDeclarator ( ) && p . parentKey === 'init' ;
317+ } ) ;
318+
319+ if ( ! pathToNegate ) {
320+ lively . warn ( 'not within a negatable node' ) ;
321+ exitedEarly = true ;
322+ return ;
323+ }
324+
325+ pathLocationsToSelect . push ( pathToNegate . getPathLocation ( ) ) ;
326+
327+ if ( pathToNegate . isUnaryExpression ( ) && pathToNegate . node . operator === '!' ) {
328+ pathToNegate . replaceWith ( pathToNegate . get ( 'argument' ) . node ) ;
329+ } else {
330+ const negatedOperator = negatableBinaryOperators [ pathToNegate . node . operator ] ;
331+ if ( pathToNegate . isBinaryExpression ( ) && negatedOperator ) {
332+ pathToNegate . node . operator = negatedOperator ;
333+ } else {
334+ pathToNegate . replaceWith ( t . unaryExpression ( "!" , pathToNegate . node ) ) ;
335+ }
336+ }
337+ }
338+ }
339+ } ) ) ;
340+
341+ if ( exitedEarly ) {
342+ return ;
343+ }
344+
345+ this . sourceCode = transformed . code ;
346+
347+ const pathsToSelect = this . pathLocationsToPathes ( pathLocationsToSelect ) ;
348+ this . selectPaths ( pathsToSelect ) ;
349+
350+ this . scrollTo ( scrollInfo ) ;
351+ }
352+
269353 /*MD ## Navigation MD*/
270354 /**
271355 * Get the root path
0 commit comments