Skip to content

Commit

Permalink
subpackages, broken file support
Browse files Browse the repository at this point in the history
  • Loading branch information
marcellourbani committed Oct 24, 2018
1 parent df0a6a0 commit efa7675
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 35 deletions.
4 changes: 4 additions & 0 deletions src/adt/AbapObject.ts → src/abap/AbapObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export class AbapObject {
this.path = path
}

isLeaf() {
return true
}

getUri(base: Uri): Uri {
return base.with({ path: this.path })
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ObjectNode } from "./AdtParser"
import { ObjectNode } from "../adt/AdtParser"
import { AbapObject } from "./AbapObject"
import { AbapPackage } from "./AbapPackage"

Expand Down
3 changes: 3 additions & 0 deletions src/adt/AbapPackage.ts → src/abap/AbapPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { AbapObject } from "./AbapObject"
import { Uri } from "vscode"

export class AbapPackage extends AbapObject {
isLeaf() {
return false
}
getUri(base: Uri): Uri {
const ptype = encodeURIComponent(this.type)
const pname = encodeURIComponent(this.name)
Expand Down
12 changes: 3 additions & 9 deletions src/abapFsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,9 @@ export class AbapFsProvider implements vscode.FileSystemProvider {
throw new Error("Method not implemented.")
}
readFile(uri: vscode.Uri): Uint8Array | Thenable<Uint8Array> {
// if (uri.path === "/dummy.abap" && this.root) {
// return this.root.then(x => {
// const child = x.entries.get("dummy.abap")
// if (child && child instanceof AdtFile && child.data) {
// return child.data
// }
// })
// }
throw new Error("Method not implemented.")
const file = this._pathManager.find(uri)
if (file && file.body) return file.body
return new Uint8Array([])
}
writeFile(
uri: vscode.Uri,
Expand Down
15 changes: 12 additions & 3 deletions src/adt/AdtNode.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import { FileStat, FileType, Uri } from "vscode"
export class AdtNode implements FileStat {
type: FileType = FileType.Directory
type: FileType
ctime: number
mtime: number
size: number = 0
entries: Map<string, AdtNode>
uri: Uri
fetched: boolean
body: Buffer | undefined
needRefresh(): any {
return this.type === FileType.Directory && this.entries.size === 0
return !this.fetched
}
constructor(path: Uri) {
constructor(path: Uri, isDirectory: boolean, fetched: boolean) {
this.ctime = Date.now()
this.mtime = Date.now()
this.entries = new Map()
this.uri = path
this.type = isDirectory ? FileType.Directory : FileType.File
this.fetched = fetched
}

childPath(childname: string): string {
const sep = this.uri.path.match(/\/$/) || childname.match(/^\//) ? "" : "/"
return this.uri.path + sep + childname
}
setContents(body: Buffer): void {
this.body = body
this.size = body.length
this.fetched = true
}
}
57 changes: 41 additions & 16 deletions src/adt/AdtPathManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,64 @@ import { AdtNode } from "./AdtNode"
import { Response } from "request"
import { getNodeStructureTreeContent, ObjectNode } from "./AdtParser"
import { getServer, AdtServer } from "./AdtServer"
import { fromObjectNode } from "./AbapObjectFactory"
import { Uri } from "vscode"

const asPromise = (x: AdtNode) => new Promise<AdtNode>(resolve => resolve(x))
import { fromObjectNode } from "../abap/AbapObjectFactory"
import { Uri, FileSystemError, FileType } from "vscode"

export class AdtPathManager {
getDirectory(uri: Uri): AdtNode | undefined {
return getServer(uri.authority).getDirectory(uri.path)
}
find(uri: Uri): AdtNode | undefined {
const server = getServer(uri.authority)
let node = server.getDirectory(uri.path)
if (node) return node
const matches = uri.path.match(/(.*)\/([^\/]+)$/)
if (matches) {
const [dir, name] = matches.slice(1)
let parent = server.getDirectory(dir)
let node = parent && parent.entries.get(name)
if (node) return node
}
}

parse(uri: Uri, response: Response, server: AdtServer): Promise<AdtNode> {
return getNodeStructureTreeContent(response.body).then(
(children: ObjectNode[]) => {
const node = new AdtNode(uri)
server.addNodes(node, children.map(fromObjectNode))

return node
}
parse(
uri: Uri,
response: Response,
server: AdtServer,
node: AdtNode | undefined
): Promise<AdtNode> | AdtNode {
if (
response.request.uri.path &&
response.request.uri.path.match(/\/nodestructure/i)
)
return getNodeStructureTreeContent(response.body).then(
(children: ObjectNode[]) => {
if (node) node.entries.clear()
else node = new AdtNode(uri, true, true)
server.addNodes(node, children.map(fromObjectNode))
node.fetched = true
return node
}
)
else if (node && node.type === FileType.File) {
node.setContents(response.body)
return node
}
throw FileSystemError.FileNotFound(uri.path)
}

fetchFileOrDir(vsUrl: Uri): Promise<AdtNode> {
fetchFileOrDir(vsUrl: Uri): Promise<AdtNode> | AdtNode {
const server = getServer(vsUrl.authority)

const cached = server.getDirectory(vsUrl.path)
const cached = this.find(vsUrl)
if (cached && !cached.needRefresh()) {
return asPromise(cached)
return cached
}

const url = server.actualUri(vsUrl)

return server.connectionP
.then(conn => conn.request(url, "POST"))
.then(response => this.parse(vsUrl, response, server))
.then(response => this.parse(vsUrl, response, server, cached))
}
}
28 changes: 22 additions & 6 deletions src/adt/AdtServer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AdtConnectionManager } from "./AdtConnectionManager"
import { AdtConnection } from "./AdtConnection"
import { AdtNode } from "./AdtNode"
import { Uri, FileSystemError } from "vscode"
import { AbapObject } from "./AbapObject"
import { Uri, FileSystemError, FileType } from "vscode"
import { AbapObject } from "../abap/AbapObject"
// visual studio paths are hierarchic, adt ones aren't
// so we need a way to translate the hierarchic ones to the original ones
// this file is concerned with telling whether a path is a real ADT one or one from vscode
Expand All @@ -28,9 +28,14 @@ export class AdtServer {
private addChildrenToNs(node: AdtNode, objects: AbapObject[]) {
objects.forEach(object => {
const childname = node.childPath(object.nameinns())
const child = new AdtNode(node.uri.with({ path: childname }))
const child = new AdtNode(
node.uri.with({ path: childname }),
!object.isLeaf(),
false
)
node.entries.set(object.nameinns(), child)
this.objectUris.set(childname, object.getUri(node.uri))
if(child.type=== FileType.Directory)this.directories.set(childname,child)
})
}

Expand All @@ -52,16 +57,27 @@ export class AdtServer {
return map
}, new Map<string, AbapObject[]>())

//for every namespace create a node, add the children to it
// so package /foo/bar will be rendered in
// a namespace folder foo
// with a package bar inside
namespaces.forEach((objects, name) => {
if (name === "") this.addChildrenToNs(parent, objects)
else {
if (name !== "") {
const nodeName = parent.childPath(name)
const node = new AdtNode(parent.uri.with({ path: nodeName }))
const node = new AdtNode(
parent.uri.with({ path: nodeName }),
true,
true
)
parent.entries.set(name, node)
this.addChildrenToNs(node, objects)
this.directories.set(nodeName, node)
}
})
//add objects without a namespace
namespaces.forEach((objects, name) => {
if (name === "") this.addChildrenToNs(parent, objects)
})
}

getDirectory(name: string): AdtNode | undefined {
Expand Down

0 comments on commit efa7675

Please sign in to comment.