Example #1
0
// FormatMappedECMASource parses and formats the given ECMAScript source code.
func FormatMappedECMASource(source string, sm *sourcemap.SourceMap) (string, *sourcemap.SourceMap, error) {
	// Parse the ES source.
	program, err := parser.ParseFile(nil, "", source, 0)
	if err != nil {
		return "", nil, err
	}

	// Reformat nicely.
	formatter := &sourceFormatter{
		file: program.File,

		indentationLevel: 0,
		hasNewline:       true,

		newlineCount:     0,
		charactersOnLine: 0,

		existingSourceMap:  sm,
		formattedSourceMap: sourcemap.NewSourceMap(sm.GeneratedFilePath(), sm.SourceRoot()),

		positionMapper: compilercommon.CreateSourcePositionMapper([]byte(source)),
	}

	formatter.formatProgram(program)
	return formatter.buf.String(), formatter.formattedSourceMap, nil
}
Example #2
0
// GenerateES5 produces ES5 code from the given scope graph.
func GenerateES5(sg *scopegraph.ScopeGraph, generatedFilePath string, sourceRoot string) (string, *sourcemap.SourceMap, error) {
	generated := generateModules(sg)

	// Order the modules by their paths.
	pather := shared.NewPather(sg.SourceGraph().Graph)
	modulePathMap := map[string]esbuilder.SourceBuilder{}

	var modulePathList = make([]string, 0)
	for module, _ := range generated {
		path := pather.GetModulePath(module)
		modulePathList = append(modulePathList, path)
		modulePathMap[path] = generated[module]
	}

	sort.Strings(modulePathList)

	// Collect the generated modules into their final source.
	ordered := ordered_map.NewOrderedMap()
	for _, modulePath := range modulePathList {
		ordered.Set(modulePath, modulePathMap[modulePath])
	}

	// Generate the unformatted code and source map.
	template := esbuilder.Template("es5", runtimeTemplate, ordered)

	sm := sourcemap.NewSourceMap(generatedFilePath, sourceRoot)
	unformatted := esbuilder.BuildSourceAndMap(template, sm)

	// Format the code.
	return escommon.FormatMappedECMASource(unformatted.String(), sm)
}
Example #3
0
func (builder templateBuilder) emitSource(sb *sourceBuilder) {
	var maps []offsetedSourceMap = make([]offsetedSourceMap, 0)
	var source bytes.Buffer

	// Register an `emit` function which does two things:
	//
	// 1) Builds and emits the source for the node at the place the function is called
	// 2) Saves the node's source map at the current template location for later appending
	emitNode := func(node SourceBuilder) string {
		if node == nil {
			return ""
		}

		if sb.sourcemap != nil {
			currentIndex := source.Len()
			sm := sourcemap.NewSourceMap("", "")
			buf := BuildSourceAndMap(node, sm)
			maps = append(maps, offsetedSourceMap{currentIndex, sm})
			return buf.String()
		} else {
			buf := BuildSource(node)
			return buf.String()
		}
	}

	funcMap := template.FuncMap{
		"emit": emitNode,
	}

	t := template.New(builder.name).Funcs(funcMap)
	parsed, err := t.Parse(builder.templateSource)
	if err != nil {
		panic(err)
	}

	// Execute the template.
	eerr := parsed.Execute(&source, builder.data)
	if eerr != nil {
		panic(eerr)
	}

	// Append the generated source to the builder.
	generatedSource := source.String()
	sb.append(generatedSource)

	// Append any offsetted source mappings.
	if sb.sourcemap != nil {
		for _, osm := range maps {
			sb.sourcemap.AppendMap(osm.sourcemap.OffsetBy(generatedSource[0:osm.offset]))
		}
	}
}
Example #4
0
// Build performs the build of the source, writing the result to the response writer.
func (dt *developTransaction) Build(w http.ResponseWriter, r *http.Request) {
	// Build a scope graph for the project. This will conduct parsing and type graph
	// construction on our behalf.
	scopeResult := scopegraph.ParseAndBuildScopeGraph(dt.rootSourceFilePath,
		dt.vcsDevelopmentDirectories,
		builder.CORE_LIBRARY)

	if !scopeResult.Status {
		dt.sourceMap = sourcemap.NewSourceMap(dt.name+".develop.js", "source/")

		for _, warning := range scopeResult.Warnings {
			dt.emitWarning(w, warning)
		}

		for _, err := range scopeResult.Errors {
			dt.emitError(w, err)
		}

		dt.emitInfo(w, "Build failed")
		dt.closeGroup(w)
	} else {
		// Generate the program's source.
		generated, sourceMap, err := es5.GenerateES5(scopeResult.Graph, dt.name+".develop.js", "source/")
		if err != nil {
			panic(err)
		}

		dt.sourceMap = sourceMap

		fmt.Fprint(w, generated)
		dt.emitInfo(w, "Build completed successfully")
		dt.closeGroup(w)

		dt.offsetCount = len(strings.Split(string(generated), "\n"))

		for _, warning := range scopeResult.Warnings {
			dt.emitWarning(w, warning)
		}
	}

	fmt.Fprintf(w, "//# sourceMappingURL=/%s.develop.js.map\n", dt.name)
}
Example #5
0
func TestGeneration(t *testing.T) {
	for _, test := range generationTests {
		sm := sourcemap.NewSourceMap("", "")
		buf := BuildSourceAndMap(test.node, sm)
		if !assert.Equal(t, buf.String(), test.expectedCode, "Mismatch on generation test %s", test.name) {
			continue
		}

		built := sm.Build()
		for _, expectedMapping := range test.expectedMappings {
			mapping, ok := built.LookupMapping(expectedMapping.lineNumber, expectedMapping.colPosition)
			if !assert.True(t, ok, "Expected mapping %v on test %s", expectedMapping, test.name) {
				continue
			}

			if !assert.Equal(t, expectedMapping.mapping, mapping, "Mapping mismatch on test %s", test.name) {
				continue
			}
		}
	}
}
Example #6
0
// FormatECMASource parses and formats the given ECMAScript source code.
func FormatECMASource(source string) (string, error) {
	formatted, _, err := FormatMappedECMASource(source, sourcemap.NewSourceMap("", ""))
	return formatted, err
}