private renderDeclarationEnd (
		code: MagicString,
		separatorString: string,
		lastSeparatorPos: number,
		actualContentEnd: number,
		renderedContentEnd: number,
		addSemicolon: boolean
	) {
		if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
			code.remove(this.end - 1, this.end);
		}
		if (addSemicolon) {
			separatorString += ';';
		}
		if (lastSeparatorPos !== null) {
			if (
				code.original.charCodeAt(actualContentEnd - 1) === 10 /*"\n"*/
				&& (code.original.charCodeAt(this.end) === 10 /*"\n"*/ || code.original.charCodeAt(this.end) === 13 /*"\r"*/)
			) {
				actualContentEnd--;
				if (code.original.charCodeAt(actualContentEnd) === 13 /*"\r"*/) {
					actualContentEnd--;
				}
			}
			if (actualContentEnd === lastSeparatorPos + 1) {
				code.overwrite(lastSeparatorPos, renderedContentEnd, separatorString);
			} else {
				code.overwrite(lastSeparatorPos, lastSeparatorPos + 1, separatorString);
				code.remove(actualContentEnd, renderedContentEnd);
			}
		} else {
			code.appendLeft(renderedContentEnd, separatorString);
		}
		return separatorString;
	}
Exemple #2
0
	render(code: MagicString, options: RenderOptions) {
		// Note that unknown test values are always included
		if (
			!this.test.included &&
			(this.testValue
				? this.alternate === null || !this.alternate.included
				: !this.consequent.included)
		) {
			const singleRetainedBranch = this.testValue ? this.consequent : this.alternate;
			code.remove(this.start, singleRetainedBranch.start);
			code.remove(singleRetainedBranch.end, this.end);
			removeAnnotations(this, code);
			singleRetainedBranch.render(code, options);
		} else {
			if (this.test.included) {
				this.test.render(code, options);
			} else {
				code.overwrite(this.test.start, this.test.end, this.testValue ? 'true' : 'false');
			}
			if (this.consequent.included) {
				this.consequent.render(code, options);
			} else {
				code.overwrite(this.consequent.start, this.consequent.end, ';');
			}
			if (this.alternate !== null) {
				if (this.alternate.included) {
					this.alternate.render(code, options);
				} else {
					code.remove(this.consequent.end, this.alternate.end);
				}
			}
		}
	}
	render (code: MagicString, options: RenderOptions) {
		if (!this.module.graph.treeshake) {
			super.render(code, options);
		} else {
			const last = this.expressions[this.expressions.length - 1];
			last.render(code, options);

			if (
				this.parent.type === NodeType.CallExpression &&
				last.type === NodeType.MemberExpression &&
				this.expressions.length > 1
			) {
				this.expressions[0].included = true;
			}

			const included = this.expressions
				.slice(0, this.expressions.length - 1)
				.filter(expression => expression.included);
			if (included.length === 0) {
				code.remove(this.start, last.start);
				code.remove(last.end, this.end);
			} else {
				let previousEnd = this.start;
				for (const expression of included) {
					expression.render(code, options);
					code.remove(previousEnd, expression.start);
					code.appendLeft(expression.end, ', ');
					previousEnd = expression.end;
				}

				code.remove(previousEnd, last.start);
				code.remove(last.end, this.end);
			}
		}
	}
	render (code: MagicString, options: RenderOptions) {
		if (this.declaration) {
			code.remove(this.start, this.declaration.start);
			this.declaration.render(code, options);
		} else {
			const start = this.leadingCommentStart || this.start;
			const end = this.next || this.end;
			code.remove(start, end);
		}
	}
Exemple #5
0
export function treeshakeNode(node: Node, code: MagicString, start: number, end: number) {
	code.remove(start, end);
	if (node.annotations) {
		for (const annotation of node.annotations) {
			if (annotation.start < start) {
				code.remove(annotation.start, annotation.end);
			} else {
				return;
			}
		}
	}
}
Exemple #6
0
	render (code: MagicString, options: RenderOptions) {
		if (this.module.graph.treeshake) {
			if (this.testValue === UNKNOWN_VALUE) {
				super.render(code, options);
			} else {
				code.overwrite(
					this.test.start,
					this.test.end,
					JSON.stringify(this.testValue)
				);

				// TODO if no block-scoped declarations, remove enclosing
				// curlies and dedent block (if there is a block)

				if (this.hoistedVars) {
					const names = this.hoistedVars
						.map(name => {
							const variable = this.scope.findVariable(name);
							return variable.included ? variable.getName() : null;
						})
						.filter(Boolean);

					if (names.length > 0) {
						code.appendLeft(this.start, `var ${names.join(', ')};\n\n`);
					}
				}

				if (this.testValue) {
					code.remove(this.start, this.consequent.start);
					code.remove(this.consequent.end, this.end);
					this.consequent.render(code, options);
				} else {
					code.remove(
						this.start,
						this.alternate ? this.alternate.start : this.next || this.end
					);

					if (this.alternate) {
						this.alternate.render(code, options);
					} else if (statementsWithIfStatements.has(this.parent.type)) {
						code.prependRight(this.start, '{}');
					}
				}
			}
		} else {
			super.render(code, options);
		}
	}
Exemple #7
0
export function remove_indentation(code: MagicString, node: Node) {
	const indent = code.getIndentString();
	const pattern = new RegExp(`^${indent}`, 'gm');

	const excluded = [];

	walk(node, {
		enter(node) {
			if (node.type === 'TemplateElement') {
				excluded.push(node);
			}
		}
	});

	const str = code.original.slice(node.start, node.end);

	let match;
	while (match = pattern.exec(str)) {
		const index = node.start + match.index;
		while (excluded[0] && excluded[0].end < index) excluded.shift();
		if (excluded[0] && excluded[0].start < index) continue;

		code.remove(index, index + indent.length);
	}
}
Exemple #8
0
export function removeNode(code: MagicString, parent: Node, node: Node) {
	const key = keys[parent.type];
	const offset = offsets[parent.type];
	if (!key || !offset) throw new Error(`not implemented: ${parent.type}`);

	const list = parent[key];
	const i = list.indexOf(node);
	if (i === -1) throw new Error('node not in list');

	let a;
	let b;

	if (list.length === 1) {
		// remove everything, leave {}
		a = parent.start + offset[0];
		b = parent.end + offset[1];
	} else if (i === 0) {
		// remove everything before second node, including comments
		a = parent.start + offset[0];
		while (/\s/.test(code.original[a])) a += 1;

		b = list[i].end;
		while (/[\s,]/.test(code.original[b])) b += 1;
	} else {
		// remove the end of the previous node to the end of this one
		a = list[i - 1].end;
		b = node.end;
	}

	code.remove(a, b);
	list.splice(i, 1);
	return;
}
Exemple #9
0
export function renderStatementList (statements: Node[], code: MagicString, start: number, end: number, options: RenderOptions) {
	if (statements.length === 0) return;
	let currentNode, currentNodeStart, currentNodeNeedsBoundaries, nextNodeStart;
	let nextNode = statements[0];
	let nextNodeNeedsBoundaries = !nextNode.included || nextNode.needsBoundaries;
	if (nextNodeNeedsBoundaries) {
		nextNodeStart = start + findFirstLineBreakOutsideComment(code.original.slice(start, nextNode.start)) + 1;
	}

	for (let nextIndex = 1; nextIndex <= statements.length; nextIndex++) {
		currentNode = nextNode;
		currentNodeStart = nextNodeStart;
		currentNodeNeedsBoundaries = nextNodeNeedsBoundaries;
		nextNode = statements[nextIndex];
		nextNodeNeedsBoundaries = nextNode === undefined ? false : !nextNode.included || nextNode.needsBoundaries;
		if (currentNodeNeedsBoundaries || nextNodeNeedsBoundaries) {
			nextNodeStart = currentNode.end + findFirstLineBreakOutsideComment(
				code.original.slice(currentNode.end, nextNode === undefined ? end : nextNode.start)
			) + 1;
			if (currentNode.included) {
				currentNodeNeedsBoundaries
					? currentNode.render(code, options, { start: currentNodeStart, end: nextNodeStart })
					: currentNode.render(code, options);
			} else {
				code.remove(currentNodeStart, nextNodeStart);
			}
		} else {
			currentNode.render(code, options);
		}
	}
}
Exemple #10
0
 nodesToRemove.forEach(node => {
   // remove any trailing comma
   const end = (output.slice(node.getEnd(), node.getEnd() + 1) === ',') ?
       node.getEnd() + 1 :
       node.getEnd();
   output.remove(node.getFullStart(), end);
 });