|  | // Copyright (c) 2018, Compiler Explorer Authors | 
|  | // All rights reserved. | 
|  | // | 
|  | // Redistribution and use in source and binary forms, with or without | 
|  | // modification, are permitted provided that the following conditions are met: | 
|  | // | 
|  | //     * Redistributions of source code must retain the above copyright notice, | 
|  | //       this list of conditions and the following disclaimer. | 
|  | //     * Redistributions in binary form must reproduce the above copyright | 
|  | //       notice, this list of conditions and the following disclaimer in the | 
|  | //       documentation and/or other materials provided with the distribution. | 
|  | // | 
|  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
|  | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
|  | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | 
|  | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
|  | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|  | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|  | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) , | 
|  | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
|  | // POSSIBILITY OF SUCH DAMAGE. | 
|  | "use strict"; | 
|  |  | 
|  | let ClientState = require('./clientstate'); | 
|  |  | 
|  | class ClientStateNormalizer { | 
|  | constructor() { | 
|  | this.normalized = new ClientState.State(); | 
|  | } | 
|  |  | 
|  | fromGoldenLayoutContent(content) { | 
|  | content.forEach((component) => { | 
|  | this.fromGoldenLayoutComponent(component); | 
|  | }); | 
|  | } | 
|  |  | 
|  | fromGoldenLayoutComponent(component) { | 
|  | if (component.componentName === "codeEditor") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.id); | 
|  | session.language = component.componentState.lang; | 
|  | session.source = component.componentState.source; | 
|  | } else if (component.componentName === "compiler") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.source); | 
|  |  | 
|  | const compiler = new ClientState.Compiler(); | 
|  | compiler.id = component.componentState.compiler; | 
|  | compiler.options = component.componentState.options; | 
|  | compiler.libs = component.componentState.libs; | 
|  | compiler.filters.binary = component.componentState.filters.binary; | 
|  | compiler.filters.labels = component.componentState.filters.labels; | 
|  | compiler.filters.directives = component.componentState.filters.directives; | 
|  | compiler.filters.commentOnly = component.componentState.filters.commentOnly; | 
|  | compiler.filters.trim = component.componentState.filters.trim; | 
|  | compiler.filters.intel = component.componentState.filters.intel; | 
|  | compiler.filters.demangle = component.componentState.filters.demangle; | 
|  |  | 
|  | session.compilers.push(compiler); | 
|  | } else if (component.componentName === "ast") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.editorid); | 
|  | const compiler = session.findOrCreateCompiler(component.componentState.id); | 
|  |  | 
|  | compiler.specialoutputs.push("ast"); | 
|  | } else if (component.componentName === "opt") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.editorid); | 
|  | const compiler = session.findOrCreateCompiler(component.componentState.id); | 
|  |  | 
|  | compiler.specialoutputs.push("opt"); | 
|  | } else if (component.componentName === "cfg") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.editorid); | 
|  | const compiler = session.findOrCreateCompiler(component.componentState.id); | 
|  |  | 
|  | compiler.specialoutputs.push("cfg"); | 
|  | } else if (component.componentName === "gccdump") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState._editorid); | 
|  | const compiler = session.findOrCreateCompiler(component.componentState._compilerid); | 
|  |  | 
|  | compiler.specialoutputs.push("gccdump"); | 
|  | } else if (component.componentName === "conformance") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.editorid); | 
|  | session.conformanceview = new ClientState.ConformanceView(component.componentState); | 
|  | } else if (component.componentName === "tool") { | 
|  | const session = this.normalized.findOrCreateSession(component.componentState.editor); | 
|  | const compiler = session.findOrCreateCompiler(component.componentState.compiler); | 
|  |  | 
|  | compiler.tools.push({ | 
|  | id: component.componentState.toolId, | 
|  | args: component.componentState.args | 
|  | }); | 
|  | } else if (component.content) { | 
|  | this.fromGoldenLayoutContent(component.content); | 
|  | } | 
|  | } | 
|  |  | 
|  | fromGoldenLayout(globj) { | 
|  | if (globj.content) { | 
|  | this.fromGoldenLayoutContent(globj.content); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class ClientStateGoldenifier { | 
|  | constructor() { | 
|  | this.golden = {}; | 
|  | } | 
|  |  | 
|  | newStackWithOneComponent(width, component) { | 
|  | return { | 
|  | type: "stack", | 
|  | width: width, | 
|  | content: [component] | 
|  | }; | 
|  | } | 
|  |  | 
|  | newSourceStackFromSession(session, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "codeEditor", | 
|  | componentState: { | 
|  | id: session.id, | 
|  | source: session.source, | 
|  | lang: session.language, | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newAstStackFromCompiler(session, compiler, compilerIndex, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "ast", | 
|  | componentState: { | 
|  | id: compilerIndex, | 
|  | editorid: session.id | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newOptStackFromCompiler(session, compiler, compilerIndex, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "opt", | 
|  | componentState: { | 
|  | id: compilerIndex, | 
|  | editorid: session.id | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newCfgStackFromCompiler(session, compiler, compilerIndex, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "opt", | 
|  | componentState: { | 
|  | id: compilerIndex, | 
|  | editorid: session.id, | 
|  | options: { | 
|  | navigation: false, | 
|  | physics: false | 
|  | } | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newGccDumpStackFromCompiler(session, compiler, compilerIndex, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "gccdump", | 
|  | componentState: { | 
|  | _compilerid: compilerIndex, | 
|  | _editorid: session.id | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newToolStackFromCompiler(session, compiler, compilerIndex, toolId, args, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "tool", | 
|  | componentState: { | 
|  | editor: session.id, | 
|  | compiler: compilerIndex, | 
|  | toolId: toolId, | 
|  | args: args | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newConformanceViewStack(session, width, conformanceview) { | 
|  | const stack = this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "conformance", | 
|  | componentState: { | 
|  | editorid: session.id, | 
|  | langId: session.language, | 
|  | compilers: [], | 
|  | libs: conformanceview.libs | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  |  | 
|  | conformanceview.compilers.forEach((compiler) => { | 
|  | const compjson = { | 
|  | compilerId: compiler.id, | 
|  | options: compiler.options | 
|  | }; | 
|  |  | 
|  | stack.content[0].componentState.compilers.push(compjson); | 
|  | }); | 
|  |  | 
|  | return stack; | 
|  | } | 
|  |  | 
|  | newCompilerStackFromSession(session, compiler, width) { | 
|  | return this.newStackWithOneComponent(width, | 
|  | { | 
|  | type: "component", | 
|  | componentName: "compiler", | 
|  | componentState: { | 
|  | compiler: compiler.id, | 
|  | source: session.id, | 
|  | options: compiler.options, | 
|  | filters: { | 
|  | binary: compiler.filters.binary, | 
|  | execute: compiler.filters.execute, | 
|  | labels: compiler.filters.labels, | 
|  | directives: compiler.filters.directives, | 
|  | commentOnly: compiler.filters.commentOnly, | 
|  | trim: compiler.filters.trim, | 
|  | intel: compiler.filters.intel, | 
|  | demangle: compiler.filters.demangle | 
|  | }, | 
|  | libs: compiler.libs, | 
|  | lang: session.language | 
|  | }, | 
|  | isClosable: true, | 
|  | reorderEnabled: true | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | newSpecialOutputStack(viewtype, session, compiler, idxCompiler, compilerWidth) { | 
|  | let stack = null; | 
|  | if (viewtype === "ast") { | 
|  | stack = this.newAstStackFromCompiler(session, compiler, idxCompiler+1, compilerWidth); | 
|  | } else if (viewtype === "opt") { | 
|  | stack = this.newOptStackFromCompiler(session, compiler, idxCompiler+1, compilerWidth); | 
|  | } else if (viewtype === "cfg") { | 
|  | stack = this.newCfgStackFromCompiler(session, compiler, idxCompiler+1, compilerWidth); | 
|  | } else if (viewtype === "gccdump") { | 
|  | stack = this.newGccDumpStackFromCompiler(session, compiler, idxCompiler+1, compilerWidth); | 
|  | } | 
|  |  | 
|  | return stack; | 
|  | } | 
|  |  | 
|  | fromClientState(state) { | 
|  | this.golden = { | 
|  | settings: { | 
|  | hasHeaders: true, | 
|  | constrainDragToContainer: false, | 
|  | reorderEnabled: true, | 
|  | selectionEnabled: false, | 
|  | popoutWholeStack: false, | 
|  | blockedPopoutsThrowError: true, | 
|  | closePopoutsOnUnload: true, | 
|  | showPopoutIcon: false, | 
|  | showMaximiseIcon: true, | 
|  | showCloseIcon: true, | 
|  | responsiveMode: "onload", | 
|  | tabOverlapAllowance: 0, | 
|  | reorderOnTabMenuClick: true, | 
|  | tabControlOffset: 10 | 
|  | }, | 
|  | dimensions: { | 
|  | borderWidth: 5, | 
|  | borderGrabWidth: 15, | 
|  | minItemHeight: 10, | 
|  | minItemWidth: 10, | 
|  | headerHeight: 20, | 
|  | dragProxyWidth: 300, | 
|  | dragProxyHeight: 200 | 
|  | }, | 
|  | labels: { | 
|  | close: "close", | 
|  | maximise: "maximise", | 
|  | minimise: "minimise", | 
|  | popout: "open in new window", | 
|  | popin: "pop in", | 
|  | tabDropdown: "additional tabs" | 
|  | }, | 
|  | content: [ | 
|  | { | 
|  | type: "row", | 
|  | content: [ | 
|  | ] | 
|  | } | 
|  | ] | 
|  | }; | 
|  |  | 
|  | if (state.sessions.length > 1) { | 
|  | const sessionWidth = 100.0 / state.sessions.length; | 
|  |  | 
|  | for (let idxSession = 0; idxSession < state.sessions.length; idxSession++) { | 
|  | const session = state.sessions[idxSession]; | 
|  |  | 
|  | this.golden.content[0].content[idxSession] = { | 
|  | type: "column", | 
|  | isClosable: true, | 
|  | reorderEnabled: true, | 
|  | width: sessionWidth, | 
|  | content: [ | 
|  | { | 
|  | type: "row", | 
|  | content: [ | 
|  | ] | 
|  | }, | 
|  | { | 
|  | type: "row", | 
|  | content: [ | 
|  | ] | 
|  | } | 
|  | ] | 
|  | }; | 
|  |  | 
|  | let stack = this.newSourceStackFromSession(session, 100.0); | 
|  | this.golden.content[0].content[idxSession].content[0].content.push(stack); | 
|  |  | 
|  | const compilerWidth = 100.0 / | 
|  | (1 + session.compilers.length + session.countNumberOfSpecialOutputsAndTools()); | 
|  |  | 
|  | if (session.conformanceview) { | 
|  | const stack = this.newConformanceViewStack(session, compilerWidth, session.conformanceview); | 
|  | this.golden.content[0].content[idxSession].content[1].content.push(stack); | 
|  | } | 
|  |  | 
|  | for (let idxCompiler = 0; idxCompiler < session.compilers.length; idxCompiler++) { | 
|  | const compiler = session.compilers[idxCompiler]; | 
|  | let stack = this.newCompilerStackFromSession(session, compiler, compilerWidth); | 
|  | this.golden.content[0].content[idxSession].content[1].content.push(stack); | 
|  |  | 
|  | compiler.specialoutputs.forEach((viewtype) => { | 
|  | let stack = this.newSpecialOutputStack(viewtype, session, compiler, idxCompiler, compilerWidth); | 
|  |  | 
|  | if (stack) { | 
|  | this.golden.content[0].content[idxSession].content[1].content.push(stack); | 
|  | } | 
|  | }); | 
|  |  | 
|  | compiler.tools.forEach((tool) => { | 
|  | let stack = this.newToolStackFromCompiler(session, compiler, idxCompiler + 1, | 
|  | tool.id, tool.args, compilerWidth); | 
|  | this.golden.content[0].content[idxSession].content[1].content.push(stack); | 
|  | }); | 
|  | } | 
|  | } | 
|  | } else if (state.sessions.length === 1) { | 
|  | const session = state.sessions[0]; | 
|  | this.golden.content[0] = { | 
|  | type: "row", | 
|  | content: [ | 
|  | ] | 
|  | }; | 
|  |  | 
|  | const width = 100.0 / (1 + session.compilers.length + session.countNumberOfSpecialOutputsAndTools()); | 
|  | this.golden.content[0].content.push(this.newSourceStackFromSession(session, width)); | 
|  |  | 
|  | if (session.conformanceview) { | 
|  | const stack = this.newConformanceViewStack(session, width, session.conformanceview); | 
|  | this.golden.content[0].content.push(stack); | 
|  | } | 
|  |  | 
|  | for (let idxCompiler = 0; idxCompiler < session.compilers.length; idxCompiler++) { | 
|  | const compiler = session.compilers[idxCompiler]; | 
|  | let stack = this.newCompilerStackFromSession(session, compiler, width); | 
|  | this.golden.content[0].content.push(stack); | 
|  |  | 
|  | compiler.specialoutputs.forEach((viewtype) => { | 
|  | let stack = this.newSpecialOutputStack(viewtype, session, compiler, idxCompiler, width); | 
|  |  | 
|  | if (stack) { | 
|  | this.golden.content[0].content.push(stack); | 
|  | } | 
|  | }); | 
|  |  | 
|  | compiler.tools.forEach((tool) => { | 
|  | let stack = this.newToolStackFromCompiler(session, compiler, idxCompiler + 1, | 
|  | tool.id, tool.args, width); | 
|  | this.golden.content[0].content.push(stack); | 
|  | }); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | module.exports = { | 
|  | ClientStateNormalizer: ClientStateNormalizer, | 
|  | ClientStateGoldenifier: ClientStateGoldenifier | 
|  | }; |