Skip to content

Commit

Permalink
Merge branch 'refactor'
Browse files Browse the repository at this point in the history
  • Loading branch information
marcellourbani committed Oct 27, 2018
2 parents 4b05e4c + 4ddffd3 commit 8458500
Show file tree
Hide file tree
Showing 21 changed files with 534 additions and 461 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# ABAP remote filesystem for visual studio code

Ideally one day this will allow you to edit your ABAP code directly in Visual studio code
Very early stages, for now it only displays some packages and a handful of object types, no local objects,subroutines in object lists...

Even things that do work need a big refactor
Very early stages, for now it only displays some packages and a handful of object types like programs, functions and classes

![anim](https://user-images.githubusercontent.com/2453277/47482169-ae0cc300-d82d-11e8-8d19-f55dd877c166.gif)
![image](https://user-images.githubusercontent.com/2453277/47466602-dd99dc00-d7e9-11e8-97ed-28e23dfd8f90.png)
Expand All @@ -15,16 +13,19 @@ Connect to your SAP server using the ADT interface

## setup

Too early to publish, there's a compiled extension you can run from source or install from the command line with
Too early to publish as an extension, there's a compiled extension you can run from source or install from the command line with

`code --install-extension vscode-abap-remote-fs-0.0.2.vsix`

`code --install-extension vscode-abap-remote-fs-0.0.1.vsix`
Once installed you'll need an ABAP system with the ADT (Abap Developer Tools for eclipse) installed and SICF node /sap/bc/adt activated:
![image](https://user-images.githubusercontent.com/2453277/47607084-5760de00-da13-11e8-9c51-7e04eeff4299.png)

You will need connection details in your settings:

```json
"abapfs.remote": {
"NPL": {
"url": "http://vhcalnplci.bti.local:8000",
"url": "https://vhcalnplci.bti.local:8000",
"username": "developer",
"password": "secret"
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-abap-remote-fs",
"displayName": "vscode_abap_remote_fs",
"description": "Work on your ABAP code straight from the server",
"version": "0.0.1",
"version": "0.0.2",
"publisher": "murbani",
"author": {
"email": "marcello.urbani@gmail.com",
Expand Down
26 changes: 25 additions & 1 deletion src/abap/AbapFunctionGroup.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
import { AbapObject, AbapObjectName } from "./AbapObject"
import { AbapObject, AbapObjectName, AbapComponents } from "./AbapObject"
import { Uri } from "vscode"
import { AdtConnection } from "../adt/AdtConnection"
import { pick } from "../functions"
import { parseNodeStructure } from "../adt/AdtNodeStructParser"

export class AbapFunctionGroup extends AbapObject {
isLeaf() {
return false
}

getChildren(connection: AdtConnection): Promise<AbapComponents> {
const ptype = encodeURIComponent(this.type)
const pname = encodeURIComponent(this.name)
const abapname = new AbapObjectName(this.name)
const techname = encodeURIComponent(
abapname.namespace === ""
? "SAPL" + abapname.name
: `/${abapname.namespace}/SAPL${abapname.name}`
)

const uri = Uri.parse("adt://" + connection.name).with({
path: "/sap/bc/adt/repository/nodestructure",
query: `parent_name=${pname}&parent_tech_name=${techname}&parent_type=${ptype}&withShortDescriptions=true`
})
return connection
.request(uri, "POST")
.then(pick("body"))
.then(parseNodeStructure)
}

getUri(base: Uri): Uri {
const ptype = encodeURIComponent(this.type)
const pname = encodeURIComponent(this.name)
Expand Down
8 changes: 0 additions & 8 deletions src/abap/AbapFunctionModule.ts

This file was deleted.

22 changes: 16 additions & 6 deletions src/abap/AbapObject.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Uri } from "vscode"
import { AdtConnection } from "../adt/AdtConnection"
import { pick } from "../functions"

export interface AbapObjectPart {
type: string
export const XML_EXTENSION = ".XML"
export type AbapComponents = Array<{
name: string
parent: AbapObject
}
types: Array<{ name: string; objects: Array<AbapObject> }>
}>

export class AbapObjectName {
namespace: string
name: string
Expand Down Expand Up @@ -46,11 +49,18 @@ export class AbapObject {
return this.name.replace(/\//g, "/") + this.getExtension()
}

getUri(base: Uri): Uri {
return base.with({ path: this.path + "/source/main" })
getContents(connection: AdtConnection): Promise<string> {
const suffix = this.getExtension() === XML_EXTENSION ? "" : "/source/main"
const uri = Uri.parse("adt://" + connection.name).with({
path: this.path + suffix
})
return connection.request(uri, "GET").then(pick("body"))
}

getExtension(): any {
return this.isLeaf() ? ".abap" : ""
}
getChildren(connection: AdtConnection): Promise<AbapComponents> {
throw new Error("Method not implemented.")
}
}
2 changes: 1 addition & 1 deletion src/abap/AbapObjectFactory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ObjectNode } from "../adt/AdtParser"
import { AbapObject } from "./AbapObject"
import { AbapPackage } from "./AbapPackage"
import { AbapFunctionGroup } from "./AbapFunctionGroup"
import { AbapSimpleObjectXml } from "./AbapSimpleObject"
import { ObjectNode } from "../adt/AdtNodeStructParser"

export function fromObjectNode(node: ObjectNode): AbapObject {
let objtype = AbapObject
Expand Down
17 changes: 13 additions & 4 deletions src/abap/AbapPackage.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { AbapObject } from "./AbapObject"
import { AbapObject, AbapComponents } from "./AbapObject"
import { Uri } from "vscode"
import { AdtConnection } from "../adt/AdtConnection"
import { parseNodeStructure } from "../adt/AdtNodeStructParser"
import { pick } from "../functions"

export class AbapPackage extends AbapObject {
isLeaf() {
return false
}
getUri(base: Uri): Uri {
getChildren(connection: AdtConnection): Promise<AbapComponents> {
const ptype = encodeURIComponent(this.type)
const pname = encodeURIComponent(this.name)
return base.with({
const query = `parent_name=${pname}&parent_tech_name=${pname}&parent_type=${ptype}&withShortDescriptions=true`

const uri = Uri.parse("adt://" + connection.name).with({
path: "/sap/bc/adt/repository/nodestructure",
query: `parent_name=${pname}&parent_tech_name=${pname}&parent_type=${ptype}&withShortDescriptions=true`
query: this.name ? query : "" //hack for root of object tree, modeled as a nameless package
})
return connection
.request(uri, "POST")
.then(pick("body"))
.then(parseNodeStructure)
}
}
11 changes: 3 additions & 8 deletions src/abap/AbapSimpleObject.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { AbapObject } from "./AbapObject"
import { Uri } from "vscode"
import { AbapObject, XML_EXTENSION } from "./AbapObject"

export class AbapSimpleObject extends AbapObject {
getUri(base: Uri): Uri {
return base.with({ path: this.path })
}
}
export class AbapSimpleObject extends AbapObject {}
export class AbapSimpleObjectXml extends AbapSimpleObject {
getExtension() {
return ".xml"
return XML_EXTENSION
}
}
33 changes: 0 additions & 33 deletions src/adt/AdtNode.ts

This file was deleted.

102 changes: 102 additions & 0 deletions src/adt/AdtNodeStructParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { getNode, recxml2js, parsetoPromise } from "./AdtParserBase"

import {
mapWidth,
ArrayToMap,
filterComplex,
defaultVal,
GroupArray,
selectMap
} from "../functions"
import { AbapComponents } from "../abap/AbapObject"
import { fromObjectNode } from "../abap/AbapObjectFactory"
import { convertableToString } from "xml2js"

export interface ObjectNode {
OBJECT_TYPE: string
OBJECT_NAME: string
TECH_NAME: string
OBJECT_URI: string
OBJECT_VIT_URI: string
EXPANDABLE: string
}

interface CategoryNode {
CATEGORY: string
CATEGORY_LABEL: string
}

interface ObjectTypeNode {
OBJECT_TYPE: string
CATEGORY_TAG: string
OBJECT_TYPE_LABEL: string
NODE_ID: string
}

const treecontentParser = defaultVal(
[],
getNode(
"asx:abap/asx:values/DATA/TREE_CONTENT/SEU_ADT_REPOSITORY_OBJ_NODE",
filterComplex(true),
mapWidth(recxml2js)
)
) as (xml: string) => Array<ObjectNode>
const categoryNodeParser: (a: string) => Map<string, CategoryNode> = defaultVal(
new Map(),
getNode(
"asx:abap/asx:values/DATA/CATEGORIES",
filterComplex(true),
"SEU_ADT_OBJECT_CATEGORY_INFO",
mapWidth(recxml2js),
ArrayToMap("CATEGORY")
)
)

const ObjectTypeParser: (a: string) => Map<string, ObjectTypeNode> = defaultVal(
new Map(),
getNode(
"asx:abap/asx:values/DATA/OBJECT_TYPES",
filterComplex(true),
"SEU_ADT_OBJECT_TYPE_INFO",
mapWidth(recxml2js),
ArrayToMap("OBJECT_TYPE")
)
)

export const parseNodeStructure: (
rawpayload: convertableToString
) => Promise<AbapComponents> = parsetoPromise((payload: any) => {
const nodes = treecontentParser(payload)
const categories = categoryNodeParser(payload)
const objectTypes = ObjectTypeParser(payload)

const catLabel = selectMap(categories, "CATEGORY_LABEL", "")
const typeLabel = selectMap(objectTypes, "OBJECT_TYPE_LABEL", "")

const types = GroupArray("OBJECT_TYPE")(nodes)
const catTypes = GroupArray("CATEGORY_TAG")([...objectTypes.values()])

const components: AbapComponents = []
for (const [category, ctypes] of catTypes) {
const cat = {
name: catLabel(category),
types: new Array<any>()
}
components.push(cat)
for (const ctype of ctypes) {
const typerec = types.get(ctype.OBJECT_TYPE)
if (typerec)
cat.types.push({
name: typeLabel(ctype.OBJECT_TYPE),
objects: typerec.map(fromObjectNode)
})
}
}
if (catTypes.size === 0)
components.push({
name: "",
types: [{ name: "", objects: nodes.map(fromObjectNode) }]
})

return components
})
Loading

0 comments on commit 8458500

Please sign in to comment.